Wayland.dox: add "Menu windows and other popups" and miscellaneous

This commit is contained in:
ManoloFLTK 2023-05-28 19:55:50 +02:00
parent 4c057c57ae
commit 1abf1dd712

View File

@ -45,18 +45,14 @@ below).
Wayland differs noticeably from X11 in that the position of a window in the display is
completely hidden to the client app. This prevents function \c Fl_Window::position() from having
any effect on a top-level window. Wayland also prevents a client app from knowing whether
a window is minimized: \c Fl_Window::show() has no effect on an already mapped window.
a window is minimized: \c Fl_Window::show() has no effect on a minimized window.
Subwindows can be positioned as usual relatively to their
parent window. FLTK uses that for the small, yellow windows that display
the new scale factor value when it's changed: these are created as short-lived subwindows
centered above \c Fl::first_window().
Wayland allows to create popup windows positioned relatively to a previously mapped other
window, with the sole restriction that any popup must intersect or at least touch that other
window.
This allows FLTK to create menus and tooltips, but it seriously complicates the algorithm
to pilot menus, because the previous algorithm conceived for other platforms assumes
the position of a window in the display to be known to the client app, which is wrong
under Wayland.
window. This allows FLTK to position adequately menu and tooltip windows, see
\ref menu-windows.
Wayland uses a trick of its own to handle lists of linked records. It defines the opaque type
<tt>struct wl_list</tt> and a few macros (\c wl_list_init(), \c wl_list_for_each(), \c wl_list_insert(),
@ -70,7 +66,7 @@ Macro <tt>wl_list_for_each(arg1, arg2, arg3)</tt> allows to run through all list
- \c arg3 is the name of the member variable of these elements used to link them together.
For example, \c wl_list_for_each() can be used as follows to scan the linked list
of all displays of the system (see \ref output):
of all displays of the system (see \ref wayland-output "Fl_Wayland_Screen_Driver::output"):
\code
Fl_Wayland_Screen_Driver::output *output;
Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
@ -88,8 +84,8 @@ The names of these functions begin with \c wl_, \c xkb_ or \c libdecor_.
the socket.
The core protocol defines also a number of mostly opaque structures whose names begin with \c wl_.
The names of symbols and types defined by the other protocols FLTK uses begin with \c xdg_ and
\c zwp_text_input_v3.
The names of symbols and types defined by the other protocols FLTK uses begin with \c xdg_,
\c zwp_text_input_v3 and \c zxdg_toplevel_decoration_.
FLTK defines a few structures holding Wayland-related data.
The names of FLTK-defined structures don't begin with \c wl_. For example,
<tt>struct wld_window</tt> (see \ref wld_window) is used to store all Wayland-specific data associated
@ -102,9 +98,12 @@ Classes \c Fl_Wayland_Window_Driver, \c Fl_Wayland_Screen_Driver, \c Fl_Wayland_
\c Fl_Wayland_Copy_Surface_Driver, \c Fl_Wayland_Image_Surface_Driver and
\c Fl_Wayland_Gl_Window_Driver contain all the Wayland-specific code of the FLTK library.
This code is located at \c src/drivers/Wayland/ in the FLTK source tree.
Furthermore, class \c Fl_Unix_System_Driver is used by both the Wayland and the X11 FLTK platforms,
so that a specially important element of the FLTK library, the event loop, is nearly completely
identical in X11 and in Wayland.
A single C++ source file generally contains all the code of a given class.
The code related to copy, paste and drag-and-drop operations, however,
is gathered in file \c fl_wayland_clipboard_dnd.cxx and contains a few
member functions of class \c Fl_Wayland_Screen_Driver.
Furthermore, class \c Fl_Unix_System_Driver is used by both the Wayland and the X11
FLTK platforms.
The public C API to Wayland, xkb and libdecor libraries are obtained with
\code
@ -171,59 +170,6 @@ This is achieved building FLTK with <tt>cmake -DOPTION_WAYLAND_ONLY=on</tt> or w
The rest of this chapter describes what happens when the Wayland leg has been chosen.
\section wayland-connection Opening a Wayland connection
Establishing a Wayland connection requires environment variable \c XDG_RUNTIME_DIR to be
defined and to point to a directory containing a socket connected to a Wayland
compositor. This variable is usually set by the login procedure of Wayland-friendly desktops.
The name of the Wayland socket is determined as follows:
- the client may call <tt>Fl::display(const char *display_name)</tt> before
\c fl_open_display() runs or use the \c -display command line argument and transmit there the
socket name;
- environment variable \c WAYLAND_DISPLAY can be defined to the socket name;
- otherwise, \c "wayland-0" is used.
What socket is selected determines what compositor will be used by the client application.
Function \c Fl_Wayland_Screen_Driver::open_display_platform() establishes the connection to the
Wayland socket identified above calling \c wl_display_connect(NULL) which returns a
<tt>struct wl_display</tt> pointer or NULL in case of failure. Such NULL return is the hint
that allows the FLTK display opening procedure of the Wayland/X11 hybrid to recognize when Wayland
access is not possible and to fallback to X11.
Then, function \c wl_registry_add_listener() associates a 2-member listener, whose 1st member,
\c registry_handle_global(), will be called by Wayland a number of times to indicate each time a protocol
supported by the compositor or a system feature such as displays and keyboards.
The prototype of this function is:
\code
static void registry_handle_global(void *user_data, struct wl_registry *wl_registry,
uint32_t id, const char *interface, uint32_t version)
\endcode
Each time Wayland calls \c registry_handle_global(), \c interface and \c version give the name
and version of a component or feature of the Wayland system. It's necessary to call each time function
\c wl_registry_bind() which returns a pointer to a Wayland structure that will be the client's access
point to the corresponding Wayland protocol or system feature. This pointer is stored in a dedicated
member variable of the unique \c Fl_Wayland_Screen_Driver object of an FLTK app, or of another object
accessible from this object.
For example, when \c interface equals "wl_compositor", \c the value returned by wl_registry_bind() is
stored as member \c wl_compositor of the \c Fl_Wayland_Screen_Driver object.
\c registry_handle_global() also identifies whether the Mutter, Weston, or KDE compositor is connected
and stores this information in static member variable \c Fl_Wayland_Screen_Driver::compositor.
Finally, function \c wl_display_get_fd() is called to obtain the file descriptor of the Wayland socket
and a call to Fl::add_fd() makes FLTK listen to this descriptor in \c FL_READ mode and associates
function \c wayland_socket_callback() from file \c Fl_Wayland_Screen_Driver.cxx with it.
This function calls \c wl_display_dispatch() which reads and interprets data available from the
file descriptor, and calls corresponding listeners.
The \c wl_display_dispatch() call is repeated as long as data are available for reading.
The event loop is run by function \c Fl_Unix_System_Driver::wait() which is used by both
the Wayland and X11 FLTK backends. Among various tasks, this function waits for data arriving
on the file descriptors FLTK is listening. Overall, the event loop of the Wayland backend
is nearly exactly the
same as that used by the X11 backend. The Wayland backend differs only in the callback function
called to handle data read from the Wayland connection socket, which is Wayland-specific.
\section wayland-listeners Listeners
A Wayland 'listener' is a small array of pointers to FLTK-defined callback functions
@ -258,12 +204,100 @@ uses this possibility calling <tt>wl_proxy_get_listener( (struct wl_proxy *)wl_s
for any object of type <tt>struct wl_surface</tt>: if that object was created as in the
example above, this call returns a pointer to FLTK's \c surface_listener static variable.
\section wayland-connection Opening a Wayland connection
Establishing a Wayland connection requires environment variable \c XDG_RUNTIME_DIR to be
defined and to point to a directory containing a socket connected to a Wayland
compositor. This variable is usually set by the login procedure of Wayland-friendly desktops.
The name of the Wayland socket is determined as follows:
- the client may call <tt>Fl::display(const char *display_name)</tt> before
\c fl_open_display() runs or use the \c -display command line argument and transmit there the
socket name;
- environment variable \c WAYLAND_DISPLAY can be defined to the socket name;
- otherwise, \c "wayland-0" is used.
What socket is selected determines what compositor will be used by the client application.
Function \c Fl_Wayland_Screen_Driver::open_display_platform() establishes the connection to the
Wayland socket identified above calling \c wl_display_connect(NULL) which returns a
<tt>struct wl_display</tt> pointer or NULL in case of failure. Such NULL return is the hint
that allows the FLTK display opening procedure of the Wayland/X11 hybrid to recognize when Wayland
access is not possible and to fallback to X11.
Then, function \c wl_registry_add_listener() associates a 2-member listener, whose 1st member,
\c registry_handle_global(), will be called by Wayland a number of times to indicate each time a protocol
supported by the compositor or a system feature such as displays and keyboards.
This code allows to run the client until all calls to \c registry_handle_global() have
occurred:
\code
static const struct wl_callback_listener sync_listener = {
sync_done
};
struct wl_callback *registry_cb = wl_display_sync(wl_display);
wl_callback_add_listener(registry_cb, &sync_listener, &registry_cb);
while (registry_cb) wl_display_dispatch(wl_display);
\endcode
A pointer to an object of type <tt>struct wl_callback</tt> created by function
\c wl_display_sync() is assigned to variable \c registry_cb.
Then a 1-member listener is attached to this object. Wayland will run this listener's
member function, \c sync_done(), after all calls to \c registry_handle_global() have
occurred. Function \c sync_done() sets to null variable \c registry_cb.
Finally, function \c wl_display_dispatch() is called as long as variable \c registry_cb is
not null. This makes Wayland process all its pending requests until \c sync_done() runs.
The prototype of function \c registry_handle_global is:
\code
static void registry_handle_global(void *user_data, struct wl_registry *wl_registry,
uint32_t id, const char *interface, uint32_t version)
\endcode
Each time Wayland calls \c registry_handle_global(), \c interface and \c version give the name
and version of a component or feature of the Wayland system. It's necessary to call each time function
\c wl_registry_bind() which returns a pointer to a Wayland structure that will be the client's access
point to the corresponding Wayland protocol or system feature. This pointer is stored in a dedicated
member variable of the unique \c Fl_Wayland_Screen_Driver object of an FLTK app, or of another object
accessible from this object.
For example, when \c interface equals "wl_compositor", \c the value returned by wl_registry_bind() is
stored as member \c wl_compositor of the \c Fl_Wayland_Screen_Driver object.
\c registry_handle_global() also identifies whether the Mutter, Weston, or KDE compositor is connected
and stores this information in static member variable \c Fl_Wayland_Screen_Driver::compositor.
Wayland calls \c registry_handle_global() with its parameter \c interface equals to
"wl_output" once for each screen connected to the system. Each time, an object of type
<tt>struct wl_output</tt> is created, to which a 4-member listener is associated by function
\c wl_output_add_listener(). The 3rd member of this 4-function listener, \c output_done(),
runs after all initialization steps of the screen have completed and turns to \c true
member \c done of a record of type
\c struct \ref wayland-output "Fl_Wayland_Screen_Driver::output" associated to the
screen. Function \c sync_done() mentioned above therefore also calls \c wl_display_dispatch()
until the \c done member of all \c Fl_Wayland_Screen_Driver::output records are \c true.
Overall, after return from function \c sync_done(), FLTK has been made aware of all
optional protocols and features of its connected Wayland compositor, and has initialized
all screens of the system.
Finally, function \c wl_display_get_fd() is called to obtain the file descriptor of the Wayland socket
and a call to Fl::add_fd() makes FLTK listen to this descriptor in \c FL_READ mode and associates
function \c wayland_socket_callback() from file \c Fl_Wayland_Screen_Driver.cxx with it.
This function calls \c wl_display_dispatch() which reads and interprets data available from the
file descriptor, and calls corresponding listeners.
The \c wl_display_dispatch() call is repeated as long as data are available for reading.
The event loop is run by function \c Fl_Unix_System_Driver::wait() which is used by both
the Wayland and X11 FLTK backends. Among various tasks, this function waits for data arriving
on the file descriptors FLTK is listening. Overall, the event loop of the Wayland backend
is nearly exactly the
same as that used by the X11 backend. The Wayland backend differs only in the callback function
called to handle data read from the Wayland connection socket, which is Wayland-specific.
\section wayland-surface Wayland windows and surfaces
Wayland defines objects called surfaces of type <tt>struct wl_surface</tt>. A Wayland surface
"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 below). FLTK makes no use of local coordinate systems. FLTK creates a surface
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.
Static member function <tt>Fl_Wayland_Window_Driver::surface_to_window(struct wl_surface *)</tt>
gives the \c Fl_Window* corresponding to the surface given in argument.
@ -276,16 +310,20 @@ and tooltips, SUBWINDOW to an Fl_Window embedded in another Fl_Window. Function
type <tt>struct wld_window</tt> (see \ref wld_window), and stores the window kind in
member variable \c kind of this record. Member variable \c xid of the window's \c Fl_X record stores
the adress of this record.
Except for SUBWINDOW's, each surface needs a Wayland object of type <tt>struct xdg_surface</tt>
used to make it become a mapped window and stored in member \c xdg_surface of the window's
\ref wld_window record. Finally, each surface is also associated to one more Wayland object whose type
\ref wld_window record. For DECORATED windows, this object is created inside libdecor
and transmitted to FLTK by function \c libdecor_frame_get_xdg_surface(). For UNFRAMED
and POPUP windows, it's created by function \c xdg_wm_base_get_xdg_surface().
Finally, each surface is also associated to one more Wayland object whose type
varies with the window's kind. These explain this part of the \ref wld_window record:
\code
union {
struct libdecor_frame *frame; // used when kind == DECORATED
struct wl_subsurface *subsurface; // used when kind == SUBWINDOW
struct xdg_popup *xdg_popup; // used when kind == POPUP
struct xdg_toplevel *xdg_toplevel; // used when kind == UNFRAMED
struct libdecor_frame *frame; // created for DECORATED by libdecor_decorate()
struct wl_subsurface *subsurface; // created for SUBWINDOW by wl_subcompositor_get_subsurface()
struct xdg_popup *xdg_popup; // created for POPUP by xdg_surface_get_popup()
struct xdg_toplevel *xdg_toplevel; // created for UNFRAMED by xdg_surface_get_toplevel()
};
\endcode
@ -298,11 +336,12 @@ FLTK distinguishes the first from the second run of \c handle_configure() by loo
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() and \c xdg_toplevel_configure().
They transmit effective window size information to FLTK. Also, these 'configure' functions 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
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
\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().
When a decorated window changes size, whatever the cause of it, Wayland calls
@ -319,6 +358,90 @@ to detect that Wayland needs be informed of the desired size change, which gets
to \c libdecor_frame_commit(). Wayland later calls \c handle_configure() and events described
above unfold.
\section menu-windows Menu windows and other popups
Menu windows, tiny menu title windows, and tooltip windows are implemented using Wayland's
popup mechanism which allows to position a popup window relatively to a previously mapped
window, itself a popup or another kind of window, with the restriction that any popup
must overlap or at least touch that other window.
Member function \c Fl_Wayland_Window_Driver::makeWindow calls member function
\c Fl_Wayland_Window_Driver::process_menu_or_tooltip to create all popups.
This function gets called after FLTK has computed using a given algorithm the desired \c (x,y)
position of the popup window's top-left corner, using coordinates centered on the top-left
corner of the toplevel window from which the popup originates.
This algorithm is able to prevent popups from
being positioned beyond the screen borders under the assumption that the position of a
toplevel window inside a screen is known. While this assumption holds for other
platforms, it does not for the Wayland platform. The FLTK code for the Wayland platform
therefore modifies the algorithm that FLTK uses to compute the position of menu windows.
The key information used by this algorithm is obtained by member function
\c Fl_Window_Driver::menu_window_area which computes the coordinates of the rectangle where
menu windows are allowed to be positioned. Under other platforms, this function just returns
the origin and size of the work area of the screen in use.
In contrast, the Wayland platform handles two situations differently :
- For menu windows that are not taller than the display in use, the
Wayland-overridden member function \c Fl_Wayland_Window_Driver::menu_window_area returns
large negative origin and large width and height values. This lets the standard FLTK
algorithm position the menu relatively to its window of origin without concern about screen
limits, and relies on Wayland's constraint mechanism described below to prevent the menu from
going beyond these limits, without FLTK having to know where they are.
- Menu windows taller than the screen where they are mapped need special handling
described in detail in a comment above the source code of function
\c Fl_Wayland_Window_Driver::process_menu_or_tooltip.
Function \c Fl_Wayland_Window_Driver::process_menu_or_tooltip
first computes \c origin_win, pointer to the \c Fl_Window relatively to which the popup is to
be positioned. Window \c origin_win is the parent menu window when the popup is a sub-menu;
it's the tiny windowtitle when the popup is a menu with a title; otherwise, it's the window
containing the point of origin of the popup.
An object of type <tt>struct xdg_positioner</tt> created by function
\c xdg_wm_base_create_positioner() is used to express the rules that will determine the
popup position relatively to \c origin_win as follows:
- Function \c xdg_positioner_set_anchor_rect() determines a rectangle in \c origin_win
relatively to which the popup is to be positioned. When the popup to be created is a menu
window spawned by an Fl_Menu_Bar, that rectangle is the full area of the menu title window.
Otherwise, that rectangle is an adequately located point.
- Function \c xdg_positioner_set_size() sets the popup size.
- The <tt>xdg_positioner_set_anchor(positioner, XDG_POSITIONER_ANCHOR_BOTTOM_LEFT);</tt>
and <tt>xdg_positioner_set_gravity(positioner, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT);</tt>
calls position the popup so that its top-left corner is initially below and at right of
the bottom-left corner of the \c origin_win 's anchor rectangle.
- The call to \c xdg_positioner_set_offset() further changes the popup vertical position.
- The call to \c xdg_positioner_set_constraint_adjustment() uses constraint flags
\c XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X and
\c XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y which mean that the compositor will move
the popup horizontally and vertically if its initial position would make it expand beyond
the edges of the screen. Furthermore, flag XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y is
added when the popup is a menu window spawned by an Fl_Menu_Bar; this has the popup flipped
above the Fl_Menu_Bar if there's not enough screen room below it for the popup.
- Finally, a call to function \c xdg_surface_get_popup() creates the popup accounting for
position rules listed above. The positioner is then deleted
by \c xdg_positioner_destroy(), a listener is associated to the popup surface with
\c xdg_popup_add_listener(), and a call to \c wl_surface_commit() triggers the mapping
of the popup on the display.
Overall, the expected coordinates of the top-left corner of the popup relatively to
\c origin_win are <tt>popup_x, popup_y</tt>. They are memorized in a record of FLTK-defined
type <tt>struct win_positioner</tt> that's associated to the popup listener.
When the compositor maps the popup, function
\c popup_configure, the first element of the popup listener, runs and receives as arguments
the coordinates of the popup top left and its size. These values account for the positioning
constraints of the popup which may have moved it to avoid screen borders. This function
can therefore detect whether constraints applied have modified the effective popup location
in comparison to the expected coordinates which are available as member variables of the
<tt>struct win_positioner</tt> record mentioned above. That's key to the handling by FLTK
of tall menu windows.
Groups of popups containing a menutitle, the associated menuwindow, and optionally
a submenu window and that don't belong to an Fl_Menu_Bar are mapped in a different order:
the menuwindow is mapped first, and the menutitle is mapped second above it as a child popup.
Function \c Fl_Window_Driver::is_floating_title() detects when such a menutitle is created,
static member variable \c previous_floatingtitle is assigned the value of this menutitle, and
the menutitle is mapped only after the menuwindow has been mapped, as a child of it.
This positions better the popup group in the display relatively to where the popup
was created.
\section wayland-graphics-driver Fl_Wayland_Graphics_Driver and Fl_Cairo_Graphics_Driver
The Wayland platform of FLTK uses an \c Fl_Wayland_Graphics_Driver object for all its on-screen
@ -364,7 +487,7 @@ destined to contain the Fl_Window's graphics. The Cairo surface object is where
The Wayland buffer is what Wayland maps on the display. FLTK copies the Cairo surface's byte array
to the Wayland buffer's byte array before beginning the mapping operation.
Section "Buffer factories" below details how FLTK creates \c wl_buffer objects.
Section \ref wayland-buffer-factory below details how FLTK creates \c wl_buffer objects.
FLTK associates to each surface a <tt>struct fl_wld_buffer</tt> (see \ref fl_wld_buffer) containing
a pointer to the byte array of the Cairo image surface (member \c draw_buffer), information about the
@ -436,7 +559,7 @@ it. This file lives in RAM because it is created by function \c memfd_create().
FLTK initially sets this file size to \c pool_size = 10 MB. This size will be increased when and
if necessary.
FLTK stores in variable \c pool_memory the address of the beginning of the mmap'ed memory structure.
- Wayland function \c wl_shm_create_pool() has this mmap'ed memory shared with the
- Wayland function \c wl_shm_create_pool() shares this mmap'ed memory with the
Wayland compositor and returns an object of type <tt>struct wl_shm_pool</tt> which encapsulates
this memory. FLTK initializes
to 0 a variable called \c chunk_offset that represents the offset inside the mmap'ed memory available
@ -462,8 +585,8 @@ If <tt>chunk_offset + size > pool_size</tt> holds when function \c create_shm_bu
create a new \c wl_buffer object, \c chunk_offset is reset to 0,
function \c wl_shm_pool_destroy() is called to destroy
the current \c wl_shm_pool object, and a new \c wl_shm_pool object is created and used by FLTK's
"buffer factory". If <tt>size > pool_size</tt> holds at that step, the value of \c pool_size if
increased to <tt>2 * size</tt>. This mechanism allows to access new mmap'ed memory when
"buffer factory". If <tt>size > pool_size</tt> holds at that step, the value of \c pool_size
is increased to <tt>2 * size</tt>. This mechanism allows to access new mmap'ed memory when
\c chunk_offset reaches the end of the previous mmap'ed section, and to enlarge the size of the
mmap'ed memory when necessary.
@ -472,7 +595,8 @@ freed when all \c wl_buffer objects which encapsulate sections of this mmap'ed m
destroyed.
Wayland uses also \c wl_buffer objects to support cursors, and
FLTK uses the "buffer factory" described here also when creating custom cursors (see below) with
FLTK uses the "buffer factory" described here also when creating custom cursors (see
\ref custom-cursor) with
function <tt>Fl_Wayland_Window_Driver::set_cursor(const Fl_RGB_Image *,…)</tt> because
\c create_shm_buffer() runs as well. In contrast, standard shaped-cursors (e.g., FL_CURSOR_INSERT)
use their own "buffer factory" inside Wayland functions such as \c wl_cursor_theme_get_cursor().
@ -495,11 +619,12 @@ This function also associates a listener to each display connected to the system
by calling function \c wl_output_add_listener(). This listener is an array of callback function
pointers among which one (\c output_mode) runs when the display is resized and another
(\c output_scale) when the Wayland scale factor (see below) is changed.
FLTK defines type <tt>struct Fl_Wayland_Screen_Driver::output</tt> (see \ref output)
FLTK defines type \c struct \ref wayland-output "Fl_Wayland_Screen_Driver::output"
to store display size and scaling information.
One such record is created for each display. FLTK uses 2 distinct scaling parameters for each display:
- <tt>int wld_scale;</tt>. This member variable of
<tt>struct Fl_Wayland_Screen_Driver::output</tt> typically equals 1 for standard, and 2 for
- <tt>int wld_scale;</tt>. This member variable of the
\c struct \ref wayland-output "Fl_Wayland_Screen_Driver::output" record
typically equals 1 for standard, and 2 for
HighDPI displays. Its value is set by the Wayland compositor for each display with the effect
that 1 Wayland graphics unit represents a block of \c nxn pixels when the value is \c n.
Another effect is that a drawing buffer for a surface of size WxH units contains
@ -520,11 +645,12 @@ Overall, an FLTK object, say an Fl_Window, of size \c WxH FLTK units occupies
<h3>Fractional scaling</h3>
The KDE compositor, and gnome too if specially set, allow to use <em>fractional scaling</em>
that can take values between 100% and 200%. Wayland implements this rendering all
that can take intermediate values between 100% and 200%. Wayland implements this rendering all
<tt>wl_surface</tt>'s as if the scaling was at 200%, and downsizing them
to the desired fractional scale value at the compositing stage.
Seen from FLTK, everything runs as when <tt>wld_scale = 2</tt>. These commands make gnome
accept fractional scaling, and turn that off:
Seen from FLTK, everything runs as when <tt>wld_scale = 2</tt>.
These commands make gnome accept fractional scaling, and turn that off:
\code
gsettings set org.gnome.mutter experimental-features "['scale-monitor-framebuffer']"
gsettings reset org.gnome.mutter experimental-features
@ -567,7 +693,8 @@ cursor-related data.
FLTK uses function \c init_cursors() from file \c Fl_Wayland_Screen_Driver.cxx to obtain the
'cursor theme' name using function \c libdecor_get_cursor_settings() of library \c libdecor.
Function \c wl_cursor_theme_load() then returns a pointer to an object of type
<tt>struct wl_cursor_theme</tt> stored in member variable \c cursor_theme of the \ref seat record.
<tt>struct wl_cursor_theme</tt> stored in member variable \c cursor_theme of the
\ref wayland-seat "Fl_Wayland_Screen_Driver::seat" record.
Function \c init_cursors() is itself called by a 'listener' called \c seat_capabilities()
installed when function \c registry_handle_global() receives a \c "wl_seat" interface, at program
startup. It is also called when the value of the Wayland scaling factor changes:
@ -585,14 +712,16 @@ where \c XXXX is the 'gnome cursor theme' (default= Adwaita). For example, what
\c FL_CURSOR_INSERT corresponds to file \c xterm therein. The full correspondance between
\c Fl_Cursor values and names of files therein is found in function
\c Fl_Wayland_Window_Driver::set_cursor(Fl_Cursor). FLTK stores in member variable
\c default_cursor of the \ref seat record, a pointer to the currently used \c wl_cursor object,
and the current \c Fl_Cursor value in member \c standard_cursor_ of the \c Fl_Wayland_Window_Driver
object.
\c default_cursor of the \ref wayland-seat "Fl_Wayland_Screen_Driver::seat" record a pointer
to the currently used \c wl_cursor object,
and the current \c Fl_Cursor value in member \c standard_cursor_ of the
\c Fl_Wayland_Window_Driver object.
Finally, function do_set_cursor() of file \c Fl_Wayland_Screen_Driver.cxx makes the system pointer use
the current \c wl_cursor object to draw its shape on screen. That's done with a call to
\c wl_pointer_set_cursor() and a few other functions.
\anchor custom-cursor
<h3>Custom cursor shapes</h3>
To support custom cursors, FLTK presently uses a <u>non-public type</u>,
<tt>struct cursor_image</tt>, defined in file \c Fl_Wayland_Window_Driver.cxx as follows:
@ -650,14 +779,15 @@ gets associated to a standard cursor or to a new custom cursor.
The "Mouse handling" section above mentionned function \c seat_capabilities() that Wayland calls when
the app discovers its "seat". Presence of flag \c WL_SEAT_CAPABILITY_KEYBOARD in argument
\c capabilities of this function indicates that a keyboard is available. In that case, a call to
\c wl_seat_get_keyboard() returns a pointer stored in member \c wl_keyboard of the \ref seat object,
\c capabilities of this function indicates that a keyboard is available. In that case, a call
to \c wl_seat_get_keyboard() returns a pointer stored in member \c wl_keyboard of the
\ref wayland-seat "Fl_Wayland_Screen_Driver::seat" object,
and a call to \c wl_keyboard_add_listener() installs a 6-member listener of type
<tt>struct wl_keyboard_listener</tt>. These 6 FLTK-defined, callback functions are used as follows.
Function \c wl_keyboard_keymap() runs once and allows initialization of access to this keyboard.
Noticeably, member \c xkb_state of type <tt>struct xkb_state*</tt> of the current \ref seat record
is adequately initialized.
Noticeably, member \c xkb_state of type <tt>struct xkb_state*</tt> of the current
\ref wayland-seat "Fl_Wayland_Screen_Driver::seat" record is adequately initialized.
Functions \c wl_keyboard_enter() and \c wl_keyboard_leave(), called when focus enters and
leaves a surface, send \c FL_FOCUS and \c FL_UNFOCUS events to the \c Fl_Window object corresponding
@ -690,7 +820,8 @@ pointer to type <tt>struct zwp_text_input_manager_v3</tt> that is stored as memb
Later, when function \c seat_capabilities() runs, \c text_input_base is found not NULL, which triggers
a call to function \c zwp_text_input_manager_v3_get_text_input() returning a value of type
<tt>struct zwp_text_input_v3 *</tt> and stored as member \c text_input of the \ref seat object.
<tt>struct zwp_text_input_v3 *</tt> and stored as member \c text_input of the
\ref wayland-seat "Fl_Wayland_Screen_Driver::seat" object.
Next, a call to \c zwp_text_input_v3_add_listener() associates this \c text_input with a 6-member
listener of type <tt>struct zwp_text_input_v3_listener</tt>. These 6 FLTK-defined, callback functions
are used as follows.
@ -809,8 +940,8 @@ FLTK follows the procedure that is very well described in item "Wayland clipboar
drop" of the \ref wayland-doc. All corresponding source code is in file
\c src/drivers/Wayland/fl_wayland_clipboard_dnd.cxx.
This part of \ref seat records stores pointers to Wayland objects used for clipboard and D-n-D
operations:
This part of the \ref wayland-seat "Fl_Wayland_Screen_Driver::seat" record stores pointers to
Wayland objects used for clipboard and D-n-D operations:
\code
struct wl_data_device_manager *data_device_manager;
struct wl_data_device *data_device;
@ -854,7 +985,8 @@ Function \c fl_wl_xid(Fl_Window*) returns a pointer to the <tt>struct wld_window
<pre>
struct wld_window {
Fl_Window *fl_win;
struct Fl_Wayland_Screen_Driver::output *output; // the display where win is mapped (see \ref output)
// the display where win is mapped (see \ref wayland-output "Fl_Wayland_Screen_Driver::output")
struct Fl_Wayland_Screen_Driver::output *output;
struct wl_surface *wl_surface; // the window's surface
struct fl_wld_buffer *buffer; // see \ref fl_wld_buffer
struct xdg_surface *xdg_surface;
@ -900,10 +1032,10 @@ struct fl_wld_buffer {
};
</pre>
\anchor output
\anchor wayland-output
<h3>struct Fl_Wayland_Screen_Driver::output</h3>
One such record is
created for each display of the system by function \c registry_handle_global() when it receives a
Defined in Fl_Wayland_Screen_Driver.H. One such record is created for each display of the
system by function \c registry_handle_global() when it receives a
\c "wl_output" interface. These records are kept in a linked list of them all, and
an identifier of this linked list is stored in member \c outputs of the unique
\c Fl_Wayland_Screen_Driver object FLTK uses. Thus,
@ -931,7 +1063,7 @@ Wayland-associated object for the same display, say <tt>struct wl_output *wl_out
by this call:
<tt>(struct Fl_Wayland_Screen_Driver::output *)wl_output_get_user_data(wl_output)</tt>.
\anchor seat
\anchor wayland-seat
<h3>struct Fl_Wayland_Screen_Driver::seat</h3>
Defined in file \c Fl_Wayland_Screen_Driver.H. One record is created by
function \c registry_handle_global() when it receives a \c "wl_seat" or