summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2025-03-16 09:10:14 +0100
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2025-03-17 14:49:17 +0100
commit6b9fb46b966f8c134004f75ec1b386ba7c6ef586 (patch)
tree399ff4be352fc328750dc40905c29f578162bf7e /src/drivers
parented4fded9d94f05b8f4e55c818de5b21ffd885278 (diff)
Wayland: improve support of addition/removal of displays while FLTK runs
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx36
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx21
2 files changed, 22 insertions, 35 deletions
diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx
index 304395936..534d70bb5 100644
--- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx
+++ b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx
@@ -1114,11 +1114,6 @@ static void output_mode(void *data, struct wl_output *wl_output, uint32_t flags,
}
-static bool compute_full_and_maximized_areas(Fl_Wayland_Screen_Driver::output *output,
- int& Wfullscreen, int& Hfullscreen,
- int& Wworkarea, int& Hworkarea);
-
-
static void output_done(void *data, struct wl_output *wl_output)
{
// Runs at startup and when desktop scale factor is changed or screen added
@@ -1147,13 +1142,7 @@ static void output_done(void *data, struct wl_output *wl_output)
Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
if (scr_driver->screen_count_get() > 0) { // true when output_done runs after initial screen dectection
scr_driver->screen_count_set( wl_list_length(&(scr_driver->outputs)) );
- int Wfullscreen, Hfullscreen, Wworkarea, Hworkarea;
- compute_full_and_maximized_areas(output, Wfullscreen, Hfullscreen, Wworkarea, Hworkarea);
- if (Wfullscreen && Hfullscreen) {
- output->width = Wfullscreen * output->wld_scale; // pixels
- output->height = Hfullscreen * output->wld_scale; // pixels
- }
- Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL);
+ scr_driver->init_workarea();
}
}
@@ -1290,7 +1279,11 @@ static void registry_handle_global(void *user_data, struct wl_registry *wl_regis
wl_list_for_each(elt, &scr_driver->outputs, link) {
if (elt == output) found = true;
}
- if (!found) wl_list_insert(&(scr_driver->outputs), &output->link);
+ if (!found) { // add to end of the linked list of displays
+ struct wl_list *e = &scr_driver->outputs;
+ while (e->next != &scr_driver->outputs) e = e->next; // move e to end of linked list
+ wl_list_insert(e, &output->link);
+ }
//fprintf(stderr, "wl_output: id=%d wl_output=%p \n", id, output->wl_output);
} else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
@@ -1333,25 +1326,12 @@ static void registry_handle_global(void *user_data, struct wl_registry *wl_regis
static void registry_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {
- Fl_Wayland_Screen_Driver::output *output, *tmp;
+ Fl_Wayland_Screen_Driver::output *output;
//fprintf(stderr, "registry_handle_global_remove data=%p id=%u\n", data, name);
Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
bool has_removed_screen = false;
- wl_list_for_each_safe(output, tmp, &(scr_driver->outputs), link) { // all screens
+ wl_list_for_each(output, &(scr_driver->outputs), link) { // all screens
if (output->id == name) { // the screen being removed
- again:
- Fl_X *xp = Fl_X::first;
- while (xp) { // all mapped windows
- struct wld_window *win = (struct wld_window*)xp->xid;
- struct Fl_Wayland_Window_Driver::surface_output *s_output;
- wl_list_for_each(s_output, &win->outputs, link) {
- if (output == s_output->output) {
- delete win->fl_win;
- goto again;
- }
- }
- xp = xp->next;
- }
wl_list_remove(&output->link);
wl_output_destroy(output->wl_output);
free(output);
diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
index 75d3f05b7..8e12091ba 100644
--- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
+++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
@@ -658,6 +658,14 @@ static struct libdecor_interface libdecor_iface = {
};
+
+static void delayed_rescale(Fl_Window *win) {
+ Fl_Window_Driver::driver(win)->is_a_rescale(true);
+ win->size(win->w(), win->h());
+ Fl_Window_Driver::driver(win)->is_a_rescale(false);
+}
+
+
void change_scale(Fl_Wayland_Screen_Driver::output *output, struct wld_window *window,
float pre_scale) {
Fl_Wayland_Window_Driver *win_driver = Fl_Wayland_Window_Driver::driver(window->fl_win);
@@ -681,9 +689,8 @@ void change_scale(Fl_Wayland_Screen_Driver::output *output, struct wld_window *w
Fl_Wayland_Graphics_Driver::buffer_release(window);
window->fl_win->redraw();
} else {
- win_driver->is_a_rescale(true);
- window->fl_win->size(window->fl_win->w(), window->fl_win->h());
- win_driver->is_a_rescale(false);
+ // delaying the rescaling is necessary to set first the window's size_range according to the new screen
+ Fl::add_timeout(0, (Fl_Timeout_Handler)delayed_rescale, window->fl_win);
}
}
if (window->fl_win->as_gl_window())
@@ -715,7 +722,7 @@ static void surface_enter(void *data, struct wl_surface *wl_surface,
while (e->next != &window->outputs) e = e->next; // move e to end of linked list
wl_list_insert(e, &surface_output->link);
//printf("window %p enters screen id=%d length=%d\n", window->fl_win, output->id, wl_list_length(&window->outputs));
- if (list_was_empty) {
+ if (list_was_empty && !window->fl_win->parent()) {
change_scale(output, window, pre_scale);
}
}
@@ -741,7 +748,7 @@ static void surface_leave(void *data, struct wl_surface *wl_surface,
break;
}
}
- if (count == 1 && !wl_list_empty(&window->outputs)) {
+ if (count == 1 && !wl_list_empty(&window->outputs) && !window->fl_win->parent()) {
s_output = wl_container_of(window->outputs.next, s_output, link);
change_scale(s_output->output, window, pre_scale);
}
@@ -1353,11 +1360,11 @@ bool Fl_Wayland_Window_Driver::process_menu_or_tooltip(struct wld_window *new_wi
// 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.
+ // work area height ≈ screen height - 44.
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 (work_area_H == screen_H) work_area_H -= 44;
if (positioner_H > work_area_H) positioner_H = work_area_H;
}
xdg_positioner_set_size(positioner, pWindow->w() * f , positioner_H * f );