diff options
Diffstat (limited to 'src/drivers')
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.cxx | 9 | ||||
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx | 10 | ||||
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Window_Driver.H | 6 | ||||
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx | 107 |
4 files changed, 91 insertions, 41 deletions
diff --git a/src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.cxx index c3d8a977c..b1c34b2ec 100644 --- a/src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.cxx @@ -22,9 +22,12 @@ Fl_Wayland_Copy_Surface_Driver::Fl_Wayland_Copy_Surface_Driver(int w, int h) : Fl_Copy_Surface_Driver(w, h) { - int os_scale = - (Fl_Wayland_Window_Driver::wld_window && Fl_Wayland_Window_Driver::wld_window->output ? - Fl_Wayland_Window_Driver::wld_window->output->wld_scale : 1); + struct Fl_Wayland_Window_Driver::surface_output *s_output = NULL; + if (Fl_Wayland_Window_Driver::wld_window && + !wl_list_empty(&Fl_Wayland_Window_Driver::wld_window->outputs)) { + s_output = wl_container_of(Fl_Wayland_Window_Driver::wld_window->outputs.next, s_output, link); + } + int os_scale = (s_output ? s_output->output->wld_scale : 1); img_surf = new Fl_Image_Surface(w * os_scale, h * os_scale); driver(img_surf->driver()); driver()->scale(os_scale); diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx index 653fc646d..cac300567 100644 --- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx @@ -996,7 +996,10 @@ static void output_scale(void *data, struct wl_output *wl_output, int32_t factor Fl_Window *win = Fl::first_window(); while (win) { struct wld_window *xid = fl_wl_xid(win); - if (xid->custom_cursor && output == xid->output) { + struct Fl_Wayland_Window_Driver::surface_output *s_output; + // get 1st screen where window appears + s_output = wl_container_of(xid->outputs.next, s_output, link); + if (xid->custom_cursor && output == s_output->output) { Fl_Wayland_Window_Driver *driver = Fl_Wayland_Window_Driver::driver(win); driver->set_cursor_4args(xid->custom_cursor->rgb, xid->custom_cursor->hotx, xid->custom_cursor->hoty, false); @@ -1131,10 +1134,13 @@ static void registry_handle_global_remove(void *data, struct wl_registry *regist Fl_X *xp = Fl_X::first; while (xp) { // all mapped windows struct wld_window *win = (struct wld_window*)xp->xid; - if (win->output == output) { + 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); diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.H b/src/drivers/Wayland/Fl_Wayland_Window_Driver.H index ebcdfea5f..985d7bfe2 100644 --- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.H +++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.H @@ -68,6 +68,10 @@ public: int screen; bool busy; }; + struct surface_output { // for linked list of displays where a surface maps + struct Fl_Wayland_Screen_Driver::output *output; + struct wl_list link; + }; static type_for_resize_window_between_screens data_for_resize_window_between_screens_; void decorated_win_size(int &w, int &h); void shape_bitmap_(Fl_Image* b); @@ -131,7 +135,7 @@ public: struct wld_window { Fl_Window *fl_win; - struct Fl_Wayland_Screen_Driver::output *output; // the display where win is mapped + struct wl_list outputs; // linked list of displays where part or whole of window maps struct wl_surface *wl_surface; struct fl_wld_buffer *buffer; struct xdg_surface *xdg_surface; diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx index eec088e6c..97b8f5252 100644 --- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx @@ -117,10 +117,6 @@ void Fl_Wayland_Window_Driver::decorated_win_size(int &w, int &h) Fl_Window *win = pWindow; w = win->w(); h = win->h(); - // needed until libdecor_plugin_fallback_frame_get_border_size() is corrected upstream - if (((Fl_Wayland_Screen_Driver*)Fl::screen_driver())->compositor == - Fl_Wayland_Screen_Driver::OWL) return; - if (!win->shown() || win->parent() || !win->border() || !win->visible()) return; int X, titlebar_height; libdecor_frame_translate_coordinate(fl_wl_xid(win)->frame, 0, 0, &X, &titlebar_height); @@ -475,7 +471,12 @@ void Fl_Wayland_Window_Driver::hide() { wld_win->wl_surface = NULL; } if (wld_win->custom_cursor) delete_cursor_(wld_win); - wld_win->output = NULL; + while (!wl_list_empty(&wld_win->outputs)) { // remove from screens where it belongs + struct surface_output *s_output; + s_output = wl_container_of(wld_win->outputs.next, s_output, link); + wl_list_remove(&s_output->link); + free(s_output); + } if (Fl_Wayland_Window_Driver::wld_window == wld_win) Fl_Wayland_Window_Driver::wld_window = NULL; //fprintf(stderr, "After hide: sub=%p frame=%p xdg=%p top=%p pop=%p surf=%p\n", wld_win->subsurface, wld_win->frame, wld_win->xdg_surface, wld_win->xdg_toplevel, wld_win->xdg_popup, wld_win->wl_surface); free(wld_win); @@ -638,37 +639,25 @@ static void delayed_redraw(Fl_Window *win) { } -static void surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) -{ - struct wld_window *window = (struct wld_window*)data; - - if (!Fl_Wayland_Screen_Driver::own_output(wl_output)) - return; - - Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)wl_output_get_user_data(wl_output); - if (output == NULL) - return; - -//printf("surface_enter win=%p wl_output=%p wld_scale=%d\n", window->fl_win, wl_output, output->wld_scale); +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); - float pre_scale = Fl::screen_scale(win_driver->screen_num()) * win_driver->wld_scale(); - window->output = output; - if (!window->fl_win->parent()) { // for top-level, set its screen number + if (!window->fl_win->parent()) { + // for top-level, set its screen number when the 1st screen for this surface changes Fl_Wayland_Screen_Driver::output *running_output; Fl_Wayland_Screen_Driver *scr_dr = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); int i = 0; wl_list_for_each(running_output, &scr_dr->outputs, link) { // each screen of the system if (running_output == output) { // we've found our screen of the system win_driver->screen_num(i); -//fprintf(stderr,"window %p is on screen #%d\n", window->fl_win, i); break; } i++; } } float post_scale = Fl::screen_scale(win_driver->screen_num()) * output->wld_scale; - //printf("pre_scale=%.1f post_scale=%.1f\n", pre_scale, post_scale); - if (window->fl_win->as_gl_window() || post_scale != pre_scale) { +//printf("pre_scale=%.1f post_scale=%.1f\n", pre_scale, post_scale); + if (post_scale != pre_scale) { if (window->kind == Fl_Wayland_Window_Driver::POPUP) { Fl_Wayland_Graphics_Driver::buffer_release(window); window->fl_win->redraw(); @@ -682,23 +671,67 @@ static void surface_enter(void *data, struct wl_surface *wl_surface, struct wl_o Fl::add_timeout(0.01, (Fl_Timeout_Handler)delayed_redraw, window->fl_win); } } - } else if (window->buffer) { - if (!window->buffer->cb) { - Fl_Wayland_Graphics_Driver::buffer_commit(window); - } } if (window->fl_win->as_gl_window()) wl_surface_set_buffer_scale(window->wl_surface, output->wld_scale); } -static void surface_leave(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) -{ - // Do nothing because surface_leave old display arrives **after** surface_enter new display - //struct wld_window *window = (struct wld_window*)data; - //printf("surface_leave win=%p wl_output=%p\n", window->fl_win, wl_output); +static void surface_enter(void *data, struct wl_surface *wl_surface, + struct wl_output *wl_output) { + struct wld_window *window = (struct wld_window*)data; + + if (!Fl_Wayland_Screen_Driver::own_output(wl_output)) + return; + + Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)wl_output_get_user_data(wl_output); + if (output == NULL) + return; + + Fl_Wayland_Window_Driver *win_driver = Fl_Wayland_Window_Driver::driver(window->fl_win); + float pre_scale = Fl::screen_scale(win_driver->screen_num()) * win_driver->wld_scale(); + bool list_was_empty = wl_list_empty(&window->outputs); + struct Fl_Wayland_Window_Driver::surface_output *surface_output = + (struct Fl_Wayland_Window_Driver::surface_output*)malloc( + sizeof(struct Fl_Wayland_Window_Driver::surface_output)); + surface_output->output = output; + // add to end of the linked list of displays of this surface + struct wl_list *e = &window->outputs; + 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) { + change_scale(output, window, pre_scale); + } } + +static void surface_leave(void *data, struct wl_surface *wl_surface, + struct wl_output *wl_output) { + if (!Fl_Wayland_Screen_Driver::own_output(wl_output)) + return; + struct wld_window *window = (struct wld_window*)data; + Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)wl_output_get_user_data(wl_output); + Fl_Wayland_Window_Driver *win_driver = Fl_Wayland_Window_Driver::driver(window->fl_win); + float pre_scale = Fl::screen_scale(win_driver->screen_num()) * win_driver->wld_scale(); + struct Fl_Wayland_Window_Driver::surface_output *s_output; + int count = 0; + wl_list_for_each(s_output, &window->outputs, link) { + count++; + if (s_output->output == output) { + wl_list_remove(&s_output->link); + free(s_output); +//printf("window %p leaves screen id=%d length=%d\n", window->fl_win, output->id, wl_list_length(&window->outputs)); + break; + } + } + if (count == 1 && !wl_list_empty(&window->outputs)) { + s_output = wl_container_of(window->outputs.next, s_output, link); + change_scale(s_output->output, window, pre_scale); + } +} + + static struct wl_surface_listener surface_listener = { surface_enter, surface_leave, @@ -1189,6 +1222,7 @@ void Fl_Wayland_Window_Driver::makeWindow() new_window = (struct wld_window *)calloc(1, sizeof *new_window); new_window->fl_win = pWindow; + wl_list_init(&new_window->outputs); Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); new_window->wl_surface = wl_compositor_create_surface(scr_driver->wl_compositor); @@ -1612,6 +1646,7 @@ void Fl_Wayland_Window_Driver::resize(int X, int Y, int W, int H) { if (fl_win && fl_win->kind == DECORATED && !xdg_toplevel()) { pWindow->wait_for_expose(); } + if (!pWindow->parent()) X = Y = 0; // toplevel windows must have origin at 0,0 int is_a_move = (X != x() || Y != y()); bool true_rescale = Fl_Window::is_a_rescale(); if (fl_win && fl_win->buffer) { @@ -1865,16 +1900,18 @@ void Fl_Wayland_Window_Driver::menu_window_area(int &X, int &Y, int &W, int &H, int Fl_Wayland_Window_Driver::wld_scale() { struct wld_window *xid = (struct wld_window *)Fl_X::flx(pWindow)->xid; - if (!xid->output) { - Fl_Wayland_Screen_Driver::output *output; + if (wl_list_empty(&xid->outputs)) { int scale = 1; Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); + Fl_Wayland_Screen_Driver::output *output; wl_list_for_each(output, &(scr_driver->outputs), link) { scale = fl_max(scale, output->wld_scale); } return scale; } - return xid->output->wld_scale; + struct surface_output *s_output; + s_output = wl_container_of(xid->outputs.next, s_output, link); + return s_output->output->wld_scale; } |
