Skip to content
This repository has been archived by the owner on Jul 15, 2024. It is now read-only.

Commit

Permalink
Fix some lingering bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
DJMcNab committed Aug 4, 2023
1 parent b126fc2 commit 6f2015b
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 23 deletions.
40 changes: 23 additions & 17 deletions src/backend/wayland/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ pub(super) struct SeatInfo {
text_field_owner: TextFieldOwner,
}

#[derive(Copy, Clone)]
enum TextFieldOwner {
Keyboard,
TextInput,
Expand Down Expand Up @@ -167,13 +168,14 @@ impl SeatInfo {
// However, we need to update our state
self.force_release_preedit(None);
}
self.keyboard_focused = None;
}
}

fn update_active_text_input(
&mut self,
TextFieldDetails(handler, props_cell): &mut TextFieldDetails,
force: bool,
mut force: bool,
should_update_text_input: bool,
) {
let handler = &mut **handler;
Expand All @@ -198,6 +200,7 @@ impl SeatInfo {
}
}
if props.active_text_field_updated || force {
force = false;
if !focus_changed {
self.force_release_preedit(props.active_text_field.map(|it| FutureInputLock {
handler,
Expand All @@ -214,9 +217,10 @@ impl SeatInfo {
if should_update_text_input {
if let Some(input_state) = self.input_state.as_mut() {
// In force_release_preedit, which has definitely been called, we
// cleared the field and disabled the text input.
// might have cleared the field and disabled the text input, if it had any state
// See the comment there for explanation
input_state.set_field(field);
input_state.set_field_if_needed(field);

let mut ime = handler.acquire_input_lock(field, false);
input_state
.sync_state(&mut *ime, zwp_text_input_v3::ChangeCause::Other);
Expand Down Expand Up @@ -311,26 +315,26 @@ impl SeatInfo {
// However, we choose not to do that for reasons discussed below
ime.set_composition_range(None);
handler.release_input_lock(token);
if let Some(ime_state) = self.input_state.as_mut() {
// We believe that GNOME's implementation of the text input protocol is not ideal.
// It carries the same IME state between text fields and applications, until the IME is
// complete or the otherwise cancelled.
// Additionally, the design of our IME interface gives no opportunity for the IME to proactively
// intercept e.g. a click event to reset the preedit content.
// Because of these conditions, we are forced into one of two choices. If you are typing e.g.
// `this is a [test]` (where test is the preedit text), then click at ` i|s `, we can either get
// the result `this i[test]s a test`, or `this i|s a test`.
// We choose the former, as it doesn't litter pre-edit text, or relayout the text. A valid alternative
// choice would be `this i[test]s a`, which is implemented by GTK apps. However, this doesn't work
// due to our method of reporting updates from the application.
ime_state.remove_field();
}
}
}
TextFieldOwner::Neither => {
// If there is no preedit text, we don't need to reset the preedit text
}
}
if let Some(ime_state) = self.input_state.as_mut() {
// We believe that GNOME's implementation of the text input protocol is not ideal.
// It carries the same IME state between text fields and applications, until the IME is
// complete or the otherwise cancelled.
// Additionally, the design of our IME interface gives no opportunity for the IME to proactively
// intercept e.g. a click event to reset the preedit content.
// Because of these conditions, we are forced into one of two choices. If you are typing e.g.
// `this is a [test]` (where test is the preedit text), then click at ` i|s `, we can either get
// the result `this i[test]s a test`, or `this i|s a test`.
// We choose the former, as it doesn't litter pre-edit text, or relayout the text. A valid alternative
// choice would be `this i[test]s a`, which is implemented by GTK apps. However, this doesn't work
// due to our method of reporting updates from the application.
ime_state.remove_field();
}
// Release ownership of the field
self.text_field_owner = TextFieldOwner::Neither;
}
Expand Down Expand Up @@ -456,6 +460,8 @@ impl SeatInfo {
let has_preedit = op(self.input_state.as_mut().unwrap(), ime);
if has_preedit {
self.text_field_owner = TextFieldOwner::TextInput;
} else {
self.text_field_owner = TextFieldOwner::Neither;
}
handler.release_input_lock(field);
}
Expand Down
16 changes: 10 additions & 6 deletions src/backend/wayland/input/text_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,20 @@ impl InputState {
self.buffer_start = None;
}

pub(super) fn set_field(&mut self, token: TextFieldToken) {
debug_assert!(self.token.is_none());
self.reset();
self.token = Some(token);
pub(super) fn set_field_if_needed(&mut self, token: TextFieldToken) {
if self.token.is_none() {
self.reset();
self.token = Some(token);

self.text_input.enable();
// Don't commit the enabling
self.text_input.enable();
tracing::warn!("enabling text input");
} else {
debug_assert!(self.token == Some(token))
}
}

pub(super) fn remove_field(&mut self) {
tracing::warn!("disabling text input");
self.token = None;
self.text_input.disable();
self.commit();
Expand Down
1 change: 1 addition & 0 deletions src/backend/wayland/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ impl WindowHandle {
let mut updated = false;
if props.active_text_field.is_some_and(|it| it == token) {
props.active_text_field = None;
props.active_text_field_updated = true;
updated = true;
}
if props.next_text_field.is_some_and(|it| it == token) {
Expand Down

0 comments on commit 6f2015b

Please sign in to comment.