diff options
| author | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2024-04-25 08:49:08 +0200 |
|---|---|---|
| committer | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2024-04-25 08:49:08 +0200 |
| commit | 38c9ebc29d7d590280ed2487bb88031c6542f903 (patch) | |
| tree | c599b6e08e0fcaf5b727887c7c95e5ed54bfabfa /src/drivers | |
| parent | 00b603fa09027ae7ce3203786d942f625ef83cf8 (diff) | |
Substantial fix for "IME problem under wayland" in fltk-rs
see: fltk-rs/fltk-rs#1539
Diffstat (limited to 'src/drivers')
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx | 105 |
1 files changed, 78 insertions, 27 deletions
diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx index 19ab37d01..115f9765c 100644 --- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx +++ b/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; } } |
