|
commit 38c9ebc29d7d590280ed2487bb88031c6542f903
Author: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
AuthorDate: Thu Apr 25 08:49:08 2024 +0200
Commit: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
CommitDate: Thu Apr 25 08:49:08 2024 +0200
Substantial fix for "IME problem under wayland" in fltk-rs
see: fltk-rs/fltk-rs#1539
src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx | 105 +++++++++++++++++------
1 file changed, 78 insertions(+), 27 deletions(-)
diff --git src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx
index 19ab37d..115f976 100644
--- src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx
+++ src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx
@@ -611,12 +611,31 @@ int Fl_Wayland_Screen_Driver::insertion_point_width = 0;
int Fl_Wayland_Screen_Driver::insertion_point_height = 0;
bool Fl_Wayland_Screen_Driver::insertion_point_location_is_valid = false;
+static int previous_cursor_x = 0, previous_cursor_y = 0, previous_cursor_h = 0;
+static uint32_t commit_serial = 0;
+static char *current_pre_edit = NULL;
+static char *pending_pre_edit = NULL;
+static char *pending_commit = NULL;
+
+
+static void send_commit() {
+ Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
+ if (scr_driver->seat->text_input) {
+ zwp_text_input_v3_commit(scr_driver->seat->text_input);
+ commit_serial++;
+ }
+}
+
// inform TIM about location of the insertion point, and memorize this info.
void Fl_Wayland_Screen_Driver::insertion_point_location(int x, int y, int height) {
//printf("insertion_point_location %dx%d\n",x,y);
Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- if (scr_driver->seat->text_input) {
+ if (scr_driver->seat->text_input && !current_pre_edit &&
+ (x != previous_cursor_x || y != previous_cursor_y || height != previous_cursor_h)) {
+ previous_cursor_x = x;
+ previous_cursor_y = y;
+ previous_cursor_h = height;
if (Fl::focus()) {
Fl_Widget *focuswin = Fl::focus()->window();
while (focuswin && focuswin->parent()) {
@@ -632,9 +651,9 @@ void Fl_Wayland_Screen_Driver::insertion_point_location(int x, int y, int height
insertion_point_height = s*height;
if (zwp_text_input_v3_get_user_data(scr_driver->seat->text_input) ) {
zwp_text_input_v3_set_cursor_rectangle(scr_driver->seat->text_input,
- insertion_point_x, insertion_point_y,
- insertion_point_width, insertion_point_height);
- zwp_text_input_v3_commit(scr_driver->seat->text_input);
+ insertion_point_x, insertion_point_y,
+ insertion_point_width, insertion_point_height);
+ send_commit();
}
}
}
@@ -753,7 +772,7 @@ static void wl_keyboard_key(void *data, struct wl_keyboard *wl_keyboard,
remove_int_vector(key_vector, for_key_vector);
}
Fl::e_text = buf;
- Fl::e_length = strlen(buf);
+ Fl::e_length = (int)strlen(buf);
// Process dead keys and compose sequences :
enum xkb_compose_status status = XKB_COMPOSE_NOTHING;
// This part is useful only if the compositor doesn't support protocol text-input-unstable-v3
@@ -769,7 +788,7 @@ static void wl_keyboard_key(void *data, struct wl_keyboard *wl_keyboard,
}
if (i < dead_key_count) strcpy(buf, dead_keys[i].marked_text);
else buf[0] = 0;
- Fl::e_length = strlen(buf);
+ Fl::e_length = (int)strlen(buf);
Fl::compose_state = 0;
}
Fl_Wayland_Screen_Driver::next_marked_length = Fl::e_length;
@@ -868,12 +887,12 @@ void text_input_enter(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
//puts("text_input_enter");
zwp_text_input_v3_set_user_data(zwp_text_input_v3, surface);
zwp_text_input_v3_enable(zwp_text_input_v3);
+ zwp_text_input_v3_set_content_type(zwp_text_input_v3, ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE, ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL);
int x, y, width, height;
if (Fl_Wayland_Screen_Driver::insertion_point_location(&x, &y, &width, &height)) {
zwp_text_input_v3_set_cursor_rectangle(zwp_text_input_v3, x, y, width, height);
}
- zwp_text_input_v3_commit(zwp_text_input_v3);
- wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display);
+ send_commit();
}
@@ -882,39 +901,49 @@ void text_input_leave(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
//puts("text_input_leave");
zwp_text_input_v3_disable(zwp_text_input_v3);
zwp_text_input_v3_set_user_data(zwp_text_input_v3, NULL);
- zwp_text_input_v3_commit(zwp_text_input_v3);
+ send_commit();
+ free(pending_pre_edit); pending_pre_edit = NULL;
+ free(current_pre_edit); current_pre_edit = NULL;
+ free(pending_commit); pending_commit = NULL;
}
-void text_input_preedit_string(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
- const char *text, int32_t cursor_begin, int32_t cursor_end) {
-//printf("text_input_preedit_string %s cursor_begin=%d cursor_end=%d\n",text, cursor_begin, cursor_end);
- // goes to widget as marked text
- Fl_Wayland_Screen_Driver::next_marked_length = text ? strlen(text) : 0;
+static void send_text_to_fltk(const char *text, bool is_marked, struct wl_surface *current_surface) {
+//printf("send_text_to_fltk(%s, %d)\n",text,is_marked);
+ Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(current_surface);
Fl::e_text = text ? (char*)text : (char*)"";
- Fl::e_length = text ? strlen(text) : 0;
+ Fl::e_length = text ? (int)strlen(text) : 0;
Fl::e_keysym = 'a'; // fake a simple key
- struct wl_surface *surface = (struct wl_surface*)data;
- Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(surface);
set_event_xy(win);
Fl::e_is_click = 0;
- Fl::handle(FL_KEYDOWN, win);
+ if (is_marked) { // goes to widget as marked text
+ Fl::handle(FL_KEYDOWN, win);
+ } else if (text) {
+ Fl_Wayland_Screen_Driver::next_marked_length = 0;
+ Fl::handle(FL_KEYDOWN, win);
+ Fl::compose_state = 0;
+ } else {
+ Fl_Wayland_Screen_Driver::next_marked_length = 0;
+ Fl::handle(FL_KEYDOWN, win);
+ }
+}
+
+
+void text_input_preedit_string(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
+ const char *text, int32_t cursor_begin, int32_t cursor_end) {
+//printf("text_input_preedit_string %s cursor_begin=%d cursor_end=%d\n",text, cursor_begin, cursor_end);
+ free(pending_pre_edit);
+ pending_pre_edit = text ? strdup(text) : NULL;
+ Fl_Wayland_Screen_Driver::next_marked_length = text ? (int)strlen(text) : 0;
}
void text_input_commit_string(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
const char *text) {
//printf("text_input_commit_string %s\n",text);
- Fl::e_text = (char*)text;
- Fl::e_length = strlen(text);
- struct wl_surface *surface = (struct wl_surface*)data;
- Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(surface);
- set_event_xy(win);
- Fl::e_is_click = 0;
+ free(pending_commit);
+ pending_commit = text ? strdup(text) : NULL;
Fl_Wayland_Screen_Driver::next_marked_length = 0;
- Fl::handle(FL_KEYDOWN, win);
- zwp_text_input_v3_commit(zwp_text_input_v3);
- Fl::compose_state = 0;
}
@@ -929,6 +958,25 @@ void text_input_delete_surrounding_text(void *data,
void text_input_done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
uint32_t serial) {
//puts("text_input_done");
+ struct wl_surface *current_surface = (struct wl_surface*)data;
+ const bool bad_event = (serial != commit_serial);
+ if ((pending_pre_edit == NULL && current_pre_edit == NULL) ||
+ (pending_pre_edit && current_pre_edit && strcmp(pending_pre_edit, current_pre_edit) == 0)) {
+ free(pending_pre_edit); pending_pre_edit = NULL;
+ } else {
+ free(current_pre_edit);
+ current_pre_edit = pending_pre_edit;
+ pending_pre_edit = NULL;
+ if (current_pre_edit) {
+ send_text_to_fltk(current_pre_edit, !bad_event, current_surface);
+ } else {
+ send_text_to_fltk(NULL, false, current_surface);
+ }
+ }
+ if (pending_commit) {
+ send_text_to_fltk(pending_commit, false, current_surface);
+ free(pending_commit); pending_commit = NULL;
+ }
}
@@ -958,6 +1006,9 @@ void Fl_Wayland_Screen_Driver::disable_im() {
zwp_text_input_v3_commit(seat->text_input);
zwp_text_input_v3_destroy(seat->text_input);
seat->text_input = NULL;
+ free(pending_pre_edit); pending_pre_edit = NULL;
+ free(current_pre_edit); current_pre_edit = NULL;
+ free(pending_commit); pending_commit = NULL;
}
}
[ Direct Link to Message ] | |