summaryrefslogtreecommitdiff
path: root/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2025-03-14 12:29:17 +0100
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2025-03-14 13:04:31 +0100
commit24aec69f27aedeead49ed629b7d434b8846826d3 (patch)
tree96dc21c0ecbcc77a6b50fe8983975527d2ccd2e6 /src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
parentc18c39071a4dc0ace4fc5e23c61f3aa7ddd8c679 (diff)
Wayland: simplify handling of tall menu windows
Diffstat (limited to 'src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx')
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx109
1 files changed, 26 insertions, 83 deletions
diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
index c9a0cbbf8..75d3f05b7 100644
--- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
+++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
@@ -1347,13 +1347,20 @@ bool Fl_Wayland_Window_Driver::process_menu_or_tooltip(struct wld_window *new_wi
xdg_positioner_set_anchor_rect(positioner, popup_x, 0, 1, 1);
popup_y++;
}
- int V, screen_H;
- Fl::screen_work_area(V, V, V, screen_H, origin_win->screen_num());
- // Under KWIN, we need to have in screen_H the size of the current screen's work-area.
- // We get this exactly only when there's a single screen. Otherwise, we get the screen height.
- bool tall_kde = (pWindow->h() > screen_H) &&
- (Fl_Wayland_Screen_Driver::compositor == Fl_Wayland_Screen_Driver::KWIN);
- xdg_positioner_set_size(positioner, pWindow->w() * f , (tall_kde ? screen_H : pWindow->h()) * f );
+ int positioner_H = pWindow->h();
+ if (Fl_Wayland_Screen_Driver::compositor == Fl_Wayland_Screen_Driver::KWIN) {
+ // Under KWIN, limiting the height of the positioner to the work area height
+ // results in tall popup windows starting at the top of the screen, what we want.
+ // Unfortunately, we know the work area height exactly only for single-screen systems,
+ // otherwise FLTK returns work area height == screen height. In that case we estimate
+ // work area height ≈ screen height - 40.
+ int V, work_area_H, screen_H;
+ Fl::screen_work_area(V, V, V, work_area_H, origin_win->screen_num());
+ Fl::screen_xywh(V, V, V, screen_H, origin_win->screen_num());
+ if (work_area_H == screen_H) work_area_H -= 40;
+ if (positioner_H > work_area_H) positioner_H = work_area_H;
+ }
+ xdg_positioner_set_size(positioner, pWindow->w() * f , positioner_H * f );
xdg_positioner_set_anchor(positioner, XDG_POSITIONER_ANCHOR_BOTTOM_LEFT);
xdg_positioner_set_gravity(positioner, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT);
// prevent menuwindow from expanding beyond display limits
@@ -2012,83 +2019,19 @@ void Fl_Wayland_Window_Driver::subRect(cairo_rectangle_int_t *r) {
void Fl_Wayland_Window_Driver::reposition_menu_window(int x, int y) {
if (y == pWindow->y()) return;
- if (Fl_Wayland_Screen_Driver::compositor == Fl_Wayland_Screen_Driver::KWIN) {
- // The KWin compositor refuses to position a popup such that it extends above
- // the top of the screen. That's no longer true with version 6 of KWIN.
- // Instead of sliding the popup window
- // on the display, we slide the drawing inside the fixed popup via
- // member variable offset_y of the menuwindow class, and we redraw the popup
- // content. It's also useful to make such tall popup window transparent.
- *Fl_Window_Driver::menu_offset_y(pWindow) += (y - pWindow->y());
- struct wld_window *xid = fl_wl_xid(pWindow);
- wl_surface_set_opaque_region(xid->wl_surface, NULL);
- if (xid->buffer) memset(xid->buffer->draw_buffer.buffer, 0,
- xid->buffer->draw_buffer.data_size);
- //printf("offset_y=%d\n", *Fl_Window_Driver::menu_offset_y(pWindow));
- this->y(y);
- pWindow->redraw();
- return;
- }
- struct wld_window * xid_menu = fl_wl_xid(pWindow);
-//printf("reposition %dx%d[cur=%d] menu->state=%d\n", x, y, pWindow->y(), xid_menu->state);
- struct xdg_popup *old_popup = xid_menu->xdg_popup;
- struct xdg_surface *old_xdg = xid_menu->xdg_surface;
- struct wl_surface *old_surface = xid_menu->wl_surface;
- // menu_origin will be the parent of the processed menu window
- Fl_Window *menu_origin = Fl_Window_Driver::menu_title(pWindow);
- if (!menu_origin) menu_origin = Fl_Window_Driver::menu_leftorigin(pWindow);
- if (!menu_origin) menu_origin = Fl_Window_Driver::menu_parent();
- if (Fl_Window_Driver::menu_title(pWindow) && !Fl_Window_Driver::menu_bartitle(pWindow) &&
- !Fl_Window_Driver::menu_leftorigin(pWindow)) {
- // occurs with tall popup menu
- menu_origin = Fl_Window_Driver::menu_parent();
- }
- // create a new popup at position (x,y) and display it above the current one
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- xid_menu->wl_surface = wl_compositor_create_surface(scr_driver->wl_compositor);
- wl_surface_add_listener(xid_menu->wl_surface, &surface_listener, xid_menu);
- xid_menu->xdg_surface = xdg_wm_base_get_xdg_surface(scr_driver->xdg_wm_base,
- xid_menu->wl_surface);
- xdg_surface_add_listener(xid_menu->xdg_surface, &xdg_surface_listener, xid_menu);
- struct xdg_positioner *positioner = xdg_wm_base_create_positioner(scr_driver->xdg_wm_base);
- struct wld_window * parent_xid = fl_wl_xid(menu_origin);
- float f = Fl::screen_scale(Fl_Window_Driver::menu_parent()->screen_num());
- int popup_x = x * f, popup_y = y * f + xid_menu->state;
- if (menu_origin->menu_window() && driver(menu_origin)->popup_window()) {
- popup_x -= menu_origin->x() * f;
- popup_y -= menu_origin->y() * f;
- }
- if (popup_x >= menu_origin->w() * f) popup_x = menu_origin->w() * f - 1;
- if (parent_xid->kind == DECORATED) {
- libdecor_frame_translate_coordinate(parent_xid->frame, popup_x, popup_y,
- &popup_x, &popup_y);
- }
- xdg_positioner_set_anchor_rect(positioner, popup_x, 0, 1, 1);
- xdg_positioner_set_size(positioner, pWindow->w() * f , pWindow->h() * f );
- xdg_positioner_set_anchor(positioner, XDG_POSITIONER_ANCHOR_TOP_LEFT);
- xdg_positioner_set_gravity(positioner, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT);
- xdg_positioner_set_constraint_adjustment(positioner,
- XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X);
- xdg_positioner_set_offset(positioner, 0, popup_y);
- xid_menu->xdg_popup = xdg_surface_get_popup(xid_menu->xdg_surface, parent_xid->xdg_surface,
- positioner);
- xdg_positioner_destroy(positioner);
- struct win_positioner *win_pos = new struct win_positioner;
- win_pos->window = xid_menu;
- win_pos->x = popup_x;
- win_pos->y = popup_y;
- win_pos->child_popup = NULL;
- xdg_popup_add_listener(xid_menu->xdg_popup, &popup_listener, win_pos);
- wl_surface_commit(xid_menu->wl_surface);
- wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display); // necessary with sway
- // delete the previous popup
- struct win_positioner *old_win_pos =
- (struct win_positioner*)xdg_popup_get_user_data(old_popup);
- xdg_popup_destroy(old_popup);
- delete old_win_pos;
- xdg_surface_destroy(old_xdg);
- destroy_surface_caution_pointer_focus(old_surface, scr_driver->seat);
+ // The top of the tall popup window was positioned at the top of the screen
+ // Instead of sliding up the popup window on the display, we slide up the
+ // drawing inside the fixed popup via member variable offset_y of the
+ // menuwindow class, and we redraw the popup content.
+ // It's also useful to make such tall popup window transparent.
+ *Fl_Window_Driver::menu_offset_y(pWindow) += (y - pWindow->y());
+ struct wld_window *xid = fl_wl_xid(pWindow);
+ wl_surface_set_opaque_region(xid->wl_surface, NULL);
+ if (xid->buffer) memset(xid->buffer->draw_buffer.buffer, 0,
+ xid->buffer->draw_buffer.data_size);
+ //printf("offset_y=%d\n", *Fl_Window_Driver::menu_offset_y(pWindow));
this->y(y);
+ pWindow->redraw();
}