Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve IME area reporting and set IME area in TextArea #785

Merged
merged 3 commits into from
Dec 11, 2024

Conversation

tomcur
Copy link
Member

@tomcur tomcur commented Dec 11, 2024

This adds the required context methods for (re)setting the IME area. These are added to the mutable context types, which I believe is the right place.

TextArea now uses PlainEditor::ime_cursor_area to report its IME area.

Note Masonry currently reports new IME cursor areas only when the widget itself moves or the focus changes to a new widget, but Parley's PlainEditor determines the IME cursor area based on the selection and preedit state of the editor, meaning the area can change based on events as well. Other widgets may choose to have different behavior still.

(It appears Masonry currently doesn't account for the IME area potentially changing based on relayout, which may be a bug.)

This replaces the old IME area reporting with a check at the end of the rewrite pass to see if IME is active, and if it is, whether the IME area has moved. If it has, the new area is reported to the platform.

This also adds the required context methods for (re)setting the IME
area. These are added to the mutable context types, which I believe is
the right place.

Note Masonry currently reports new IME cursor areas only when the widget
itself moves or the focus changes to a new widget, but Parley's
`PlainEditor` determines the IME cursor area based on the selection and
preedit state of the editor, meaning the area can change based on events
as well. Other widgets may choose to have different behavior still.

(It appears Masonry currently doesn't account for the IME area
potentially changing based on relayout, which may be a bug.)

This replaces the old IME area reporting with a check at the end of the
rewrite pass to see if IME is active, and if it is, whether the IME area
has moved. If it has, the new area is reported to the platform.
Comment on lines +502 to +513
if self.global_state.is_ime_active {
let widget = self
.global_state
.focused_widget
.expect("IME is active without a focused widget");
let ime_area = self.widget_arena.get_state(widget).item.get_ime_area();
if self.global_state.last_sent_ime_area != ime_area {
self.global_state.last_sent_ime_area = ime_area;
self.global_state
.emit_signal(RenderRootSignal::new_ime_moved_signal(ime_area));
}
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that these rewrite passes are intended to make the state consistent, so Masonry will know the correct IME area once this has been done. Some other signals are emitted to the platform here as well. While I believe it makes sense to add this here, I can certainly be convinced otherwise.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems valid to me.

Copy link
Member

@DJMcNab DJMcNab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is an improvement. A few peripheral suggestions, and a potential refactor which might be more idiomatic

masonry/src/render_root.rs Show resolved Hide resolved
/// Get the IME area from the editor, accounting for padding.
///
/// This should only be called when the editor layout is available.
fn ime_area(&self) -> Rect {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This being repeated so often to me suggests that it should be a method on Widget, so that there is only one source of truth needed. That would be a bit of a bigger change to wire up, and I don't have all the specifics.

That is, this is a non-blocking conern

Comment on lines +502 to +513
if self.global_state.is_ime_active {
let widget = self
.global_state
.focused_widget
.expect("IME is active without a focused widget");
let ime_area = self.widget_arena.get_state(widget).item.get_ime_area();
if self.global_state.last_sent_ime_area != ime_area {
self.global_state.last_sent_ime_area = ime_area;
self.global_state
.emit_signal(RenderRootSignal::new_ime_moved_signal(ime_area));
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems valid to me.

.global_state
.focused_widget
.expect("IME is active without a focused widget");
let ime_area = self.widget_arena.get_state(widget).item.get_ime_area();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's conceivable that you have enough context to call a Widget method with a QueryCtx here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that probably is possible. Hmm, my main concern with both using QueryCtx and removing the repeated calls to set the IME area that you mentioned on TextArea::ime_area, would be that the results aren't cached. In general, calculating the area can be a somewhat expensive operation – and certainly in the case of PlainEditor it is somewhat expensive.

I believe the question is then whether WidgetState stores the IME area, which is what Masonry currently does, or whether that field should be removed in favor of a query method on Widget, which moves the responsibility of caching when necessary to the widget. This doesn't solve the issue of the repeated TextArea::ime_area calls.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, that's true, and it's probably too messy. Without having a new invalidation method, it doesn't really work.

---------

Co-authored-by: Daniel McNab <[email protected]>
@tomcur tomcur changed the title Use the Parley-reported IME cursor area in TextArea Improve IME area reporting and set IME area in TextArea Dec 11, 2024
@tomcur tomcur added this pull request to the merge queue Dec 11, 2024
@tomcur tomcur removed this pull request from the merge queue due to a manual request Dec 11, 2024
@tomcur tomcur added this pull request to the merge queue Dec 11, 2024
@tomcur
Copy link
Member Author

tomcur commented Dec 11, 2024

I've gone ahead and merged, but am happy to revisit your comments about the source of truth.

Merged via the queue into linebender:main with commit 806946b Dec 11, 2024
17 checks passed
@tomcur tomcur deleted the ime-area branch December 11, 2024 16:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants