From c43cf2f19243057fe8b02410bb11669a720e2ca8 Mon Sep 17 00:00:00 2001 From: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> Date: Mon, 19 Jun 2023 17:48:37 +0200 Subject: Wayland: improve support of multi-display setups --- documentation/src/wayland.dox | 84 ++++++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 25 deletions(-) (limited to 'documentation/src') diff --git a/documentation/src/wayland.dox b/documentation/src/wayland.dox index cad7cd66f..bbd1ae242 100644 --- a/documentation/src/wayland.dox +++ b/documentation/src/wayland.dox @@ -71,7 +71,7 @@ of all displays of the system (see \ref wayland-output "Fl_Wayland_Screen_Driver Fl_Wayland_Screen_Driver::output *output; Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); wl_list_for_each(output, &(scr_driver->outputs), link) { - // … work with output, a member of the linked list of all displays in the system … + // … work with output, an item of the linked list of all displays in the system … } \endcode @@ -298,11 +298,10 @@ Wayland defines objects called surfaces of type struct wl_surface. A Wa "has a rectangular area which may be displayed on zero or more displays, present buffers, receive user input, and define a local coordinate system". Buffers allow the client app to draw to surfaces (see \ref wayland-buffer). FLTK creates a surface -with function \c wl_compositor_create_surface() each time an Fl_Window is show()'n. +each time an Fl_Window is show()'n. Static member function Fl_Wayland_Window_Driver::surface_to_window(struct wl_surface *) gives the \c Fl_Window* corresponding to the surface given in argument. -Function \c wl_surface_add_listener() associates the surface with a listener which allows to -associate each surface with the display where it is mapped. FLTK recognizes 4 distinct +FLTK recognizes 4 distinct kinds of surfaces named DECORATED, UNFRAMED, POPUP and SUBWINDOW. DECORATED are toplevel windows with a titlebar. UNFRAMED have no titlebar. POPUP correspond to menus and tooltips, SUBWINDOW to an Fl_Window embedded in another Fl_Window. Function @@ -327,19 +326,25 @@ varies with the window's kind. These explain this part of the \ref wld_window re }; \endcode -Except for SUBWINDOW's, each surface is associated to a 'configure' function that Wayland calls one or -more times when the window is going to be mapped on the display. -The 'configure' function of DECORATED surfaces is \c handle_configure(). Wayland calls it -twice when mapping a DECORATED surface. The first \c handle_configure() run allows to set -the window's \c xdg_surface object which is returned by function \c libdecor_frame_get_xdg_surface(). +Except for SUBWINDOW's, each surface is associated to a 'configure' function that Wayland +calls one or more times when the window is going to be mapped on the display. +The 'configure' function of DECORATED surfaces is \c handle_configure() which is the 1st +member of a 4-member listener named \c libdecor_frame_iface associated to a decorated window +when it's created calling \c libdecor_decorate(). Finally, a call to \c libdecor_frame_map() +triggers the process of mapping the newly created DECORATED surface on a display. +Wayland calls \c handle_configure() twice during this process. +The first \c handle_configure() run allows to set the window's \c xdg_surface object +which is returned by function \c libdecor_frame_get_xdg_surface(). FLTK distinguishes the first from the second run of \c handle_configure() by looking at the \c xdg_surface member variable that's NULL at the beginning of the 1st run and not NULL later. Wayland calls \c handle_configure() also during operations such as resizing, minimizing (see below). With the help of a few calls to libdecor functions, FLTK obtains in this function -all needed information about the size and state of the mapped window. The 'configure' -functions of UNFRAMED and POPUP surfaces are \c xdg_surface_configure(), -\c xdg_toplevel_configure() and \c popup_configure(). They transmit effective window size -information to FLTK. Also, these 'configure' functions are where the window's +all needed information about the size and state of the mapped window. +The 'configure' functions of UNFRAMED and POPUP surfaces are \c xdg_surface_configure(), +\c xdg_toplevel_configure() and \c popup_configure(). The mapping process of these surfaces +is triggered by a call to \c wl_surface_commit(). +These 'configure' functions transmit effective window size +information to FLTK. Also, they are where the window's \c Fl_Window_Driver::wait_for_expose_value member variable is set to 0 to indicate that the window has been mapped to display. \b Caution: there are some small differences between how and when the various Wayland compositors call \c handle_configure(). @@ -640,12 +645,17 @@ displays, which Wayland calls outputs, of type struct wl_outputstruct wl_list accessible from member \c outputs of the single +\c Fl_Wayland_Screen_Driver object. + +FLTK uses 2 distinct scaling parameters for each display: - int wld_scale;. This member variable of the \c struct \ref wayland-output "Fl_Wayland_Screen_Driver::output" record typically equals 1 for standard, and 2 for @@ -667,6 +677,27 @@ that scales the graphics driver by this factor with \c cairo_scale(). Overall, an FLTK object, say an Fl_Window, of size \c WxH FLTK units occupies W * wld_scale * gui_scale x H * wld_scale * gui_scale pixels on the display. +When an \c Fl_Window is to be show()'n, \c Fl_Wayland_Window_Driver::makeWindow() creates +a struct wl_surface with \c wl_compositor_create_surface() and associates it +calling \c wl_surface_add_listener() with a 2-member listener called \c surface_listener +encharged of managing as follows the list of displays where this \c wl_surface will map. +The \c Fl_Window possesses an initially empty linked list of displays accessible at +member \c outputs of the window's \ref wld_window record. +When the \c Fl_Window, or more exactly its associated struct wl_surface is mapped +on a display, member \c surface_enter() of \c surface_listener runs. +This function adds the display where the surface belongs to the end of the linked +list of displays for this surface. +When a surface is dragged or enlarged across the edge of a display +in a multi-display system and expands on a second display, \c surface_enter() runs again, +and this surface's list of displays contains 2 items. +When a surface leaves a display, member \c surface_leave() of \c surface_listener runs. +It removes that display from the surface's list of displays. +Each time the first item of a surface's list of displays +changes, function \c change_scale() is called and applies that display's \c gui_scale +value to that surface calling \c Fl_Window_Driver::screen_num(int). When a window +is unmapped by function \c Fl_Wayland_Window_Driver::hide(), the surface's list of displays +is emptied. +
struct wld_window {
Fl_Window *fl_win;
- // the display where win is mapped (see \ref wayland-output "Fl_Wayland_Screen_Driver::output")
- struct Fl_Wayland_Screen_Driver::output *output;
+ struct wl_list outputs; // linked list of displays where part or whole of window maps
struct wl_surface *wl_surface; // the window's surface
struct fl_wld_buffer *buffer; // see \ref fl_wld_buffer
struct xdg_surface *xdg_surface;
--
cgit v1.2.3