From 39a157a7dd83e1626c9f67e0b09d6deb23aa7c76 Mon Sep 17 00:00:00 2001 From: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> Date: Mon, 23 Oct 2023 11:15:04 +0200 Subject: [PATCH] Wayland: implement transient scale factor windows as popups as discussed in issue #794. Also, fix for macOS the use of the FL_FOCUS event for these transient windows --- src/Fl_Screen_Driver.cxx | 18 ++++++++----- src/Fl_cocoa.mm | 3 ++- .../Wayland/Fl_Wayland_Window_Driver.cxx | 27 +++++++------------ 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/Fl_Screen_Driver.cxx b/src/Fl_Screen_Driver.cxx index 78d598d13..1bcd54727 100644 --- a/src/Fl_Screen_Driver.cxx +++ b/src/Fl_Screen_Driver.cxx @@ -390,14 +390,14 @@ struct WinAndTracker { static void del_transient_window(WinAndTracker *data) { delete (Fl_Image*)data->win->shape(); - Fl::delete_widget(data->win); + delete data->win; if (data->tracker) { if (data->tracker->exists()) { data->tracker->widget()->take_focus(); } delete data->tracker; } - delete data; + data->win = NULL; } void Fl_Screen_Driver::transient_scale_display(float f, int nscreen) @@ -440,12 +440,18 @@ void Fl_Screen_Driver::transient_scale_display(float f, int nscreen) win->set_non_modal(); Fl_Window_Driver::driver(win)->screen_num(nscreen); Fl_Window_Driver::driver(win)->force_position(1); - WinAndTracker *data = new WinAndTracker; - data->win = win; + static WinAndTracker data = {NULL, NULL}; + if (data.win) { + Fl::remove_timeout((Fl_Timeout_Handler)del_transient_window); + delete data.win; + } + data.win = win; Fl_Widget *widget = Fl::focus(); - data->tracker = (widget ? new Fl_Widget_Tracker(widget) : NULL); + if (!widget) widget = Fl::first_window(); + data.tracker = (widget ? new Fl_Widget_Tracker(widget) : NULL); win->show(); - Fl::add_timeout(1, (Fl_Timeout_Handler)del_transient_window, data); // delete after 1 sec + // delete transient win after 1 sec + Fl::add_timeout(1, (Fl_Timeout_Handler)del_transient_window, &data); } // respond to Ctrl-'+' and Ctrl-'-' and Ctrl-'0' (Ctrl-'=' is same as Ctrl-'+') by rescaling all windows diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm index 76753d4f9..fbbe6aebf 100644 --- a/src/Fl_cocoa.mm +++ b/src/Fl_cocoa.mm @@ -3144,7 +3144,8 @@ void Fl_Cocoa_Window_Driver::makeWindow() if (w->modal()) Fl::modal_ = w; w->set_visible(); - if ( w->border() || (!w->modal() && !w->tooltip_window()) ) Fl::handle(FL_FOCUS, w); + if ( w->border() || (!w->modal() && !w->tooltip_window() && + w->user_data() != &Fl_Screen_Driver::transient_scale_display) ) Fl::handle(FL_FOCUS, w); [cw setDelegate:[FLWindowDelegate singleInstance]]; if (show_iconic()) { show_iconic(0); diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx index 07bb5230d..bbd372797 100644 --- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx @@ -1161,17 +1161,6 @@ static const struct xdg_popup_listener popup_listener = { bool Fl_Wayland_Window_Driver::in_flush_ = false; -// Compute the parent window of the transient scale window -static Fl_Window *calc_transient_parent(int ¢er_x, int ¢er_y) { - // Find top, the topmost window, but not a transient window itself - Fl_Window *top = Fl::first_window()->top_window(); - while (top && top->user_data() == &Fl_Screen_Driver::transient_scale_display) - top = Fl::next_window(top); - center_x = top->w()/2; center_y = top->h()/2; - return top; -} - - static const char *get_prog_name() { pid_t pid = getpid(); char fname[100]; @@ -1255,6 +1244,8 @@ static const char *get_prog_name() { item, when there's one, is visible immediately after the tall popup is mapped on display. */ +static Fl_Window *transient_parent = NULL; // used for transient scale windows + bool Fl_Wayland_Window_Driver::process_menu_or_tooltip(struct wld_window *new_window) { // a menu window or tooltip new_window->kind = Fl_Wayland_Window_Driver::POPUP; @@ -1274,6 +1265,8 @@ bool Fl_Wayland_Window_Driver::process_menu_or_tooltip(struct wld_window *new_wi Fl_Window_Driver::menu_title(pWindow); } Fl_Widget *target = (pWindow->tooltip_window() ? Fl_Tooltip::current() : NULL); + if (pWindow->user_data() == &Fl_Screen_Driver::transient_scale_display && + transient_parent) target = transient_parent; if (!target) target = Fl_Window_Driver::menu_parent(); if (!target) target = Fl::belowmouse(); if (!target) target = Fl::first_window(); @@ -1375,13 +1368,11 @@ void Fl_Wayland_Window_Driver::makeWindow() if (pWindow->user_data() == &Fl_Screen_Driver::transient_scale_display && Fl::first_window()) { - // put transient scale win at center of top window by making it a child of top - int center_x, center_y; - Fl_Window *top = calc_transient_parent(center_x, center_y); - if (top) { - top->add(pWindow); - pWindow->position(center_x - pWindow->w()/2 , center_y - pWindow->h()/2); - } + // put transient scale win at center of top window by making it a tooltip of top + transient_parent = Fl::first_window(); + pWindow->set_tooltip_window(); + pWindow->position((transient_parent->w() - pWindow->w())/2 , + (transient_parent->h() - pWindow->h())/2); } if (pWindow->menu_window() || pWindow->tooltip_window()) { // a menu window or tooltip