Wayland: improve support of multi-display setups
This commit is contained in:
parent
742af8a31a
commit
c43cf2f192
@ -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 <tt>struct wl_surface</tt>. 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 <tt>Fl_Wayland_Window_Driver::surface_to_window(struct wl_surface *)</tt>
|
||||
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 <em>outputs</em>, of type <tt>struct wl_output</tt
|
||||
|
||||
As written above, function \c registry_handle_global() discovers the available seat at start-up time.
|
||||
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.
|
||||
by calling function \c wl_output_add_listener(). This listener's member functions run
|
||||
at program startup when Wayland discovers its displays (see \ref wayland-connection).
|
||||
Member \c output_mode runs also when the display is resized and member
|
||||
\c output_scale also when the Wayland scale factor (see below) is changed.
|
||||
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:
|
||||
One such record is created for each display. These records are put in a
|
||||
<tt>struct wl_list</tt> accessible from member \c outputs of the single
|
||||
\c Fl_Wayland_Screen_Driver object.
|
||||
|
||||
FLTK uses 2 distinct scaling parameters for each display:
|
||||
- <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
|
||||
@ -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
|
||||
<tt>W * wld_scale * gui_scale x H * wld_scale * gui_scale</tt> pixels on the display.
|
||||
|
||||
When an \c Fl_Window is to be show()'n, \c Fl_Wayland_Window_Driver::makeWindow() creates
|
||||
a <tt>struct wl_surface</tt> 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 <tt>struct wl_surface</tt> is mapped
|
||||
on a display, member \c surface_enter() of \c surface_listener runs.
|
||||
This function adds the display where the surface belongs to <u>the end</u> 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 <u>the first</u> 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.
|
||||
|
||||
<h3>Fractional scaling</h3>
|
||||
The KDE compositor, and gnome too if specially set, allow to use <em>fractional scaling</em>
|
||||
that can take intermediate values between 100% and 200%. Wayland implements this rendering all
|
||||
@ -809,7 +840,8 @@ to \c wl_seat_get_keyboard() returns a pointer stored in member \c wl_keyboard o
|
||||
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.
|
||||
Function \c wl_keyboard_keymap() runs when the app starts and also if the keyboard layout
|
||||
is changed during run-time. It allows initialization of access to this keyboard.
|
||||
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.
|
||||
|
||||
@ -883,11 +915,14 @@ text input method about the position of the insertion point.
|
||||
|
||||
\section wayland-libdecor Interface with libdecor
|
||||
|
||||
FLTK uses a library called \c libdecor to determine whether the Wayland compositor uses CSD or SSD mode,
|
||||
and also to draw window titlebars when in CSD mode (see \ref bundled-libdecor). \c Libdecor is
|
||||
conceived to load at run-time a plugin present in a shared library in the system and
|
||||
expected to draw titlebars in a way that best matches the Desktop. As of early 2023, two plugins
|
||||
are available:
|
||||
FLTK uses a library called
|
||||
<a href= https://gitlab.freedesktop.org/libdecor/libdecor/-/blob/master/README.md>
|
||||
libdecor</a> to determine whether the Wayland compositor uses CSD or SSD mode,
|
||||
and also to draw window titlebars when in CSD mode (see \ref bundled-libdecor).
|
||||
\c Libdecor is conceived to be present in a shared library linked to the Wayland
|
||||
client application which itself, and if the running Wayland compositor uses CSD mode,
|
||||
loads another shared library intended to draw titlebars in a way that best matches the
|
||||
Desktop. As of early 2023, two titlebar-drawing \c libdecor plugins are available:
|
||||
- \c libdecor-gtk intended for the Gnome desktop;
|
||||
- \c libdecor-cairo for other situations.
|
||||
|
||||
@ -1009,8 +1044,7 @@ Function \c fl_wl_xid(Fl_Window*) returns a pointer to the <tt>struct wld_window
|
||||
<pre>
|
||||
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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user