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
This commit is contained in:
ManoloFLTK
2023-10-23 11:15:04 +02:00
parent 17baeceb7a
commit 39a157a7dd
3 changed files with 23 additions and 25 deletions
+12 -6
View File
@@ -390,14 +390,14 @@ struct WinAndTracker {
static void del_transient_window(WinAndTracker *data) { static void del_transient_window(WinAndTracker *data) {
delete (Fl_Image*)data->win->shape(); delete (Fl_Image*)data->win->shape();
Fl::delete_widget(data->win); delete data->win;
if (data->tracker) { if (data->tracker) {
if (data->tracker->exists()) { if (data->tracker->exists()) {
data->tracker->widget()->take_focus(); data->tracker->widget()->take_focus();
} }
delete data->tracker; delete data->tracker;
} }
delete data; data->win = NULL;
} }
void Fl_Screen_Driver::transient_scale_display(float f, int nscreen) 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(); win->set_non_modal();
Fl_Window_Driver::driver(win)->screen_num(nscreen); Fl_Window_Driver::driver(win)->screen_num(nscreen);
Fl_Window_Driver::driver(win)->force_position(1); Fl_Window_Driver::driver(win)->force_position(1);
WinAndTracker *data = new WinAndTracker; static WinAndTracker data = {NULL, NULL};
data->win = win; if (data.win) {
Fl::remove_timeout((Fl_Timeout_Handler)del_transient_window);
delete data.win;
}
data.win = win;
Fl_Widget *widget = Fl::focus(); 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(); 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 // respond to Ctrl-'+' and Ctrl-'-' and Ctrl-'0' (Ctrl-'=' is same as Ctrl-'+') by rescaling all windows
+2 -1
View File
@@ -3144,7 +3144,8 @@ void Fl_Cocoa_Window_Driver::makeWindow()
if (w->modal()) Fl::modal_ = w; if (w->modal()) Fl::modal_ = w;
w->set_visible(); 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]]; [cw setDelegate:[FLWindowDelegate singleInstance]];
if (show_iconic()) { if (show_iconic()) {
show_iconic(0); show_iconic(0);
@@ -1161,17 +1161,6 @@ static const struct xdg_popup_listener popup_listener = {
bool Fl_Wayland_Window_Driver::in_flush_ = false; bool Fl_Wayland_Window_Driver::in_flush_ = false;
// Compute the parent window of the transient scale window
static Fl_Window *calc_transient_parent(int &center_x, int &center_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() { static const char *get_prog_name() {
pid_t pid = getpid(); pid_t pid = getpid();
char fname[100]; 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. 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) { bool Fl_Wayland_Window_Driver::process_menu_or_tooltip(struct wld_window *new_window) {
// a menu window or tooltip // a menu window or tooltip
new_window->kind = Fl_Wayland_Window_Driver::POPUP; 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_Window_Driver::menu_title(pWindow);
} }
Fl_Widget *target = (pWindow->tooltip_window() ? Fl_Tooltip::current() : NULL); 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_Window_Driver::menu_parent();
if (!target) target = Fl::belowmouse(); if (!target) target = Fl::belowmouse();
if (!target) target = Fl::first_window(); 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 && if (pWindow->user_data() == &Fl_Screen_Driver::transient_scale_display &&
Fl::first_window()) { Fl::first_window()) {
// put transient scale win at center of top window by making it a child of top // put transient scale win at center of top window by making it a tooltip of top
int center_x, center_y; transient_parent = Fl::first_window();
Fl_Window *top = calc_transient_parent(center_x, center_y); pWindow->set_tooltip_window();
if (top) { pWindow->position((transient_parent->w() - pWindow->w())/2 ,
top->add(pWindow); (transient_parent->h() - pWindow->h())/2);
pWindow->position(center_x - pWindow->w()/2 , center_y - pWindow->h()/2);
}
} }
if (pWindow->menu_window() || pWindow->tooltip_window()) { // a menu window or tooltip if (pWindow->menu_window() || pWindow->tooltip_window()) { // a menu window or tooltip