From 47f0d63f194d6fe3a164061e2fe70b1057575168 Mon Sep 17 00:00:00 2001 From: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> Date: Wed, 29 Jun 2022 18:02:11 +0200 Subject: [PATCH] Wayland platform: send FL_ENTER/LEAVE/MOVE events to top-level windows only. --- .../Wayland/Fl_Wayland_Screen_Driver.cxx | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx index 9f48d197f..ce050dd36 100644 --- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx @@ -239,6 +239,25 @@ Fl_Window *Fl_Wayland_Screen_Driver::surface_to_window(struct wl_surface *surfac } +static Fl_Window *event_coords_from_surface(struct wl_surface *surface, + wl_fixed_t surface_x, wl_fixed_t surface_y) { + Fl_Window *win = Fl_Wayland_Screen_Driver::surface_to_window(surface); + if (!win) return NULL; + int delta_x = 0, delta_y = 0; + while (win->parent()) { + delta_x += win->x(); + delta_y += win->y(); + win = win->window(); + } + float f = Fl::screen_scale(win->screen_num()); + Fl::e_x = wl_fixed_to_int(surface_x) / f + delta_x; + Fl::e_x_root = Fl::e_x + win->x(); + Fl::e_y = wl_fixed_to_int(surface_y) / f + delta_y; + Fl::e_y_root = Fl::e_y + win->y(); + return win; +} + + static void pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, @@ -246,24 +265,15 @@ static void pointer_enter(void *data, wl_fixed_t surface_x, wl_fixed_t surface_y) { - Fl_Window *win = Fl_Wayland_Screen_Driver::surface_to_window(surface); + Fl_Window *win = event_coords_from_surface(surface, surface_x, surface_y); if (!win) return; Fl_Wayland_Window_Driver *driver = Fl_Wayland_Window_Driver::driver(win); struct wl_cursor *cursor = driver->cursor(); // use custom cursor if present - if (win->parent() && !cursor) { - driver = Fl_Wayland_Window_Driver::driver(win->top_window()); - cursor = driver->cursor(); - } struct seat *seat = (struct seat*)data; do_set_cursor(seat, cursor); seat->serial = serial; - float f = Fl::screen_scale(win->screen_num()); - Fl::e_x = wl_fixed_to_int(surface_x) / f; - Fl::e_x_root = Fl::e_x + win->x(); - Fl::e_y = wl_fixed_to_int(surface_y) / f; - Fl::e_y_root = Fl::e_y + win->y(); set_event_xy(win); - Fl::handle(FL_ENTER, win->top_window()); + Fl::handle(FL_ENTER, win); //fprintf(stderr, "pointer_enter window=%p\n", win); seat->pointer_focus = surface; } @@ -293,18 +303,13 @@ static void pointer_motion(void *data, wl_fixed_t surface_y) { struct seat *seat = (struct seat*)data; - Fl_Window *win = Fl_Wayland_Screen_Driver::surface_to_window(seat->pointer_focus); + Fl_Window *win = event_coords_from_surface(seat->pointer_focus, surface_x, surface_y); if (!win) return; - float f = Fl::screen_scale(win->screen_num()); - Fl::e_x = wl_fixed_to_int(surface_x) / f; - Fl::e_x_root = Fl::e_x + win->x(); // If there's an active grab() and the pointer is in a window other than the grab(), // make e_x_root too large to be in any window if (Fl::grab() && !Fl::grab()->menu_window() && Fl::grab() != win) { Fl::e_x_root = 1000000; } - Fl::e_y = wl_fixed_to_int(surface_y) / f; - Fl::e_y_root = Fl::e_y + win->y(); //fprintf(stderr, "FL_MOVE on win=%p to x:%dx%d root:%dx%d\n", win, Fl::e_x, Fl::e_y, Fl::e_x_root, Fl::e_y_root); wld_event_time = time; set_event_xy(win); @@ -325,6 +330,7 @@ static void pointer_button(void *data, int event = 0; Fl_Window *win = Fl_Wayland_Screen_Driver::surface_to_window(seat->pointer_focus); if (!win) return; + win = win->top_window(); wld_event_time = time; if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED && seat->pointer_focus == NULL && fl_xid(win)->kind == Fl_Wayland_Window_Driver::DECORATED) {