Add Fl_Wayland_Window_Driver::wld_scale() member function

This commit is contained in:
ManoloFLTK 2023-03-02 11:36:26 +01:00
parent 2626962dd3
commit 86c238c000
9 changed files with 81 additions and 109 deletions

View File

@ -2,7 +2,7 @@
// A base class for platform specific window handling code
// for the Fast Light Tool Kit (FLTK).
//
// Copyright 2010-2022 by Bill Spitzak and others.
// Copyright 2010-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -100,6 +100,7 @@ public:
int aspect();
unsigned char size_range_set();
int is_resizable() { return pWindow->is_resizable(); }
void is_a_rescale(bool b) { is_a_rescale_ = b;}
int fullscreen_screen_top();
int fullscreen_screen_bottom();
int fullscreen_screen_left();

View File

@ -1,7 +1,7 @@
//
// Copy-to-clipboard code for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2021 by Bill Spitzak and others.
// Copyright 1998-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -24,7 +24,9 @@
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->scale : 1);
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);
img_surf = new Fl_Image_Surface(w * os_scale, h * os_scale);
driver(img_surf->driver());
driver()->scale(os_scale);

View File

@ -1,7 +1,7 @@
//
// Class Fl_Wayland_Gl_Window_Driver for the Fast Light Tool Kit (FLTK).
//
// Copyright 2021-2022 by Bill Spitzak and others.
// Copyright 2021-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -298,7 +298,8 @@ void Fl_Wayland_Gl_Window_Driver::make_current_before() {
Fl_Wayland_Gl_Choice *g = (Fl_Wayland_Gl_Choice*)this->g();
egl_surface = eglCreateWindowSurface(egl_display, g->egl_conf, egl_window, NULL);
//fprintf(stderr, "Created egl surface=%p at scale=%d\n", egl_surface, win->scale);
wl_surface_set_buffer_scale(surface, win->scale);
wl_surface_set_buffer_scale(surface,
Fl_Wayland_Window_Driver::driver(pWindow)->wld_scale());
// Tested apps: shape, glpuzzle, cube, fractals, gl_overlay, fullscreen, unittests,
// OpenGL3-glut-test, OpenGL3test.
// Tested wayland compositors: mutter, kde-plasma, weston, sway on FreeBSD.
@ -311,7 +312,8 @@ void Fl_Wayland_Gl_Window_Driver::make_current_before() {
float Fl_Wayland_Gl_Window_Driver::pixels_per_unit()
{
int ns = pWindow->screen_num();
int wld_scale = pWindow->shown() ? fl_wl_xid(pWindow)->scale : 1;
int wld_scale = (pWindow->shown() ?
Fl_Wayland_Window_Driver::driver(pWindow)->wld_scale() : 1);
return wld_scale * Fl::screen_driver()->scale(ns);
}
@ -403,8 +405,9 @@ void Fl_Wayland_Gl_Window_Driver::resize(int is_a_resize, int W, int H) {
if (!egl_window) return;
struct wld_window *win = fl_wl_xid(pWindow);
float f = Fl::screen_scale(pWindow->screen_num());
W = (W * win->scale) * f;
H = (H * win->scale) * f;
int s = Fl_Wayland_Window_Driver::driver(pWindow)->wld_scale();
W = (W * s) * f;
H = (H * s) * f;
int W2, H2;
wl_egl_window_get_attached_size(egl_window, &W2, &H2);
if (W2 != W || H2 != H) {

View File

@ -1,7 +1,7 @@
//
// Implementation of the Wayland graphics driver.
//
// Copyright 2021-2022 by Bill Spitzak and others.
// Copyright 2021-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -99,7 +99,8 @@ void Fl_Wayland_Graphics_Driver::buffer_commit(struct wld_window *window, bool n
cairo_surface_flush(surf);
memcpy(window->buffer->data, window->buffer->draw_buffer, window->buffer->data_size);
wl_surface_attach(window->wl_surface, window->buffer->wl_buffer, 0, 0);
wl_surface_set_buffer_scale(window->wl_surface, window->scale);
wl_surface_set_buffer_scale(window->wl_surface,
Fl_Wayland_Window_Driver::driver(window->fl_win)->wld_scale());
window->buffer->cb = wl_surface_frame(window->wl_surface);
if (need_damage) wl_surface_damage_buffer(window->wl_surface, 0, 0, 1000000, 1000000);
wl_callback_add_listener(window->buffer->cb, &surface_frame_listener, window);

View File

@ -1,7 +1,7 @@
//
// Draw-to-image code for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2021 by Bill Spitzak and others.
// Copyright 1998-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -25,8 +25,8 @@ Fl_Wayland_Image_Surface_Driver::Fl_Wayland_Image_Surface_Driver(int w, int h, i
float d = 1;
if (!off) {
fl_open_display();
if (Fl_Wayland_Window_Driver::wld_window) {
d = Fl_Wayland_Window_Driver::wld_window->scale;
if (Fl_Wayland_Window_Driver::wld_window && Fl_Wayland_Window_Driver::wld_window->output) {
d = Fl_Wayland_Window_Driver::wld_window->output->wld_scale;
}
d *= fl_graphics_driver->scale();
if (d != 1 && high_res) {

View File

@ -1,7 +1,7 @@
//
// Implementation of Wayland Screen interface
//
// Copyright 1998-2022 by Bill Spitzak and others.
// Copyright 1998-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -105,11 +105,6 @@ struct pointer_output {
struct wl_list link;
};
struct Fl_Wayland_Window_Driver::window_output { // FLTK defined
Fl_Wayland_Screen_Driver::output* output;
struct wl_list link;
}
The unique Fl_Wayland_Screen_Driver object contains a member
"outputs" of type struct wl_list = list of Fl_Wayland_Screen_Driver::output records
- this list is initialised by open-display
@ -119,15 +114,11 @@ struct pointer_output {
(outputs member of the Fl_Wayland_Screen_Driver) and the list of struct output objects attached
to each window.
Each Fl_Wayland_Window_Driver object contains a member
"outputs" of type struct wl_list = list of Fl_Wayland_Window_Driver::window_output records
- this list is fed by surface_enter() (when a surface is mapped)
- these records contain:
window_output->output = (Fl_Wayland_Screen_Driver::output*)wl_output_get_user_data(wl_output);
where wl_output is received from OS by surface_enter()
- surface_leave() removes the adequate record from the list
- hide() empties the list
- Fl_Wayland_Window_Driver::update_scale() sets the scale info of the records for a given window
Each struct wld_window object contains a member
"output" of type pter to Fl_Wayland_Screen_Driver::output
- this pointer is set by surface_enter() (when a surface is mapped)
- surface_leave() sets it to NULL
- hide() sets it to NULL
*/
static Fl_Int_Vector key_vector; // used by Fl_Wayland_Screen_Driver::event_key()
@ -937,17 +928,24 @@ static void output_mode(void *data, struct wl_output *wl_output, uint32_t flags,
static void output_done(void *data, struct wl_output *wl_output)
{
// Runs at startup and when desktop scale factor is changed
Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)data;
Fl_Wayland_Window_Driver::window_output *window_output;
//fprintf(stderr, "output_done output=%p\n",output);
Fl_X *xp = Fl_X::first;
while (xp) { // all mapped windows
struct wld_window *win = (struct wld_window*)xp->xid;
wl_list_for_each(window_output, &(win->outputs), link) { // all Fl_Wayland_Window_Driver::window_output for this window
if (window_output->output == output) {
Fl_Wayland_Window_Driver *win_driver = Fl_Wayland_Window_Driver::driver(win->fl_win);
if (output->wld_scale != win->scale) win_driver->update_scale();
Fl_Window *W = win->fl_win;
if (win->buffer || W->as_gl_window()) {
if (W->as_gl_window()) {
wl_surface_set_buffer_scale(win->wl_surface, output->wld_scale);
Fl_Window_Driver::driver(W)->is_a_rescale(true);
W->resize(W->x(), W->y(), W->w(), W->h());
Fl_Window_Driver::driver(W)->is_a_rescale(false);
} else {
Fl_Wayland_Graphics_Driver::buffer_release(win);
}
W->redraw();
Fl_Window_Driver::driver(W)->flush();
}
xp = xp->next;
}
@ -1069,7 +1067,6 @@ 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)
{//TODO to be tested
Fl_Wayland_Screen_Driver::output *output;
Fl_Wayland_Window_Driver::window_output *window_output, *tmp;
//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();
wl_list_for_each(output, &(scr_driver->outputs), link) { // all screens of the system
@ -1077,12 +1074,9 @@ 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;
wl_list_for_each_safe(window_output, tmp, &(win->outputs), link) { // all Fl_Wayland_Window_Driver::window_output for this window
if (window_output->output == output) {
wl_list_remove(&window_output->link);
free(window_output);
if (win->output == output) {
win->output = NULL;
}
}
xp = xp->next;
}
wl_list_remove(&output->link);
@ -1353,7 +1347,8 @@ Fl_RGB_Image *Fl_Wayland_Screen_Driver::read_win_rectangle(int X, int Y, int w,
bool ignore, bool *p_ignore) {
struct wld_window* xid = win ? fl_wl_xid(win) : NULL;
struct fl_wld_buffer *buffer = win ? xid->buffer : (struct fl_wld_buffer *)Fl_Surface_Device::surface()->driver()->gc();
float s = win ? xid->scale * scale(win->screen_num()) :
float s = win ?
Fl_Wayland_Window_Driver::driver(win)->wld_scale() * scale(win->screen_num()) :
Fl_Surface_Device::surface()->driver()->scale();
int Xs, Ys, ws, hs;
if (s == 1) {

View File

@ -65,10 +65,6 @@ private:
public:
inline Fl_Cursor standard_cursor() { return standard_cursor_; };
bool in_handle_configure; // distinguish OS and user window resize
struct window_output {
Fl_Wayland_Screen_Driver::output* output;
struct wl_list link;
};
// --- support for screen-specific scaling factors
struct type_for_resize_window_between_screens {
int screen;
@ -78,7 +74,7 @@ public:
void decorated_win_size(int &w, int &h);
void shape_bitmap_(Fl_Image* b);
void shape_alpha_(Fl_Image* img, int offset) FL_OVERRIDE;
void update_scale();
int wld_scale();
cairo_rectangle_int_t *subRect() { return subRect_; } // getter
void subRect(cairo_rectangle_int_t *r); // setter
void checkSubwindowFrame();
@ -136,7 +132,7 @@ public:
struct wld_window {
Fl_Window *fl_win;
struct wl_list outputs;
struct Fl_Wayland_Screen_Driver::output *output; // the display where win is mapped
struct wl_surface *wl_surface;
struct fl_wld_buffer *buffer;
struct xdg_surface *xdg_surface;
@ -152,7 +148,6 @@ struct wld_window {
int configured_height;
int floating_width;
int floating_height;
int scale;
int state;
};

View File

@ -197,7 +197,8 @@ void Fl_Wayland_Window_Driver::flush_overlay()
}
if (overlay() == oWindow) oWindow->draw_overlay();
struct wld_window * xid = fl_wl_xid(pWindow);
wl_surface_damage_buffer(xid->wl_surface, 0, 0, pWindow->w() * xid->scale, pWindow->h() * xid->scale);
int s = wld_scale();
wl_surface_damage_buffer(xid->wl_surface, 0, 0, pWindow->w() * s, pWindow->h() * s);
}
@ -350,7 +351,7 @@ void Fl_Wayland_Window_Driver::make_current() {
Fl_Wayland_Window_Driver::wld_window = window;
fl_window = (Window)window;
float scale = Fl::screen_scale(pWindow->screen_num()) * window->scale;
float scale = Fl::screen_scale(pWindow->screen_num()) * wld_scale();
if (!window->buffer) {
window->buffer = Fl_Wayland_Graphics_Driver::create_shm_buffer(
pWindow->w() * scale, pWindow->h() * scale);
@ -392,20 +393,20 @@ void Fl_Wayland_Window_Driver::flush() {
Fl_X *ip = Fl_X::flx(pWindow);
struct flCairoRegion* r = (struct flCairoRegion*)ip->region;
float f = Fl::screen_scale(pWindow->screen_num());
float f = Fl::screen_scale(pWindow->screen_num()) * wld_scale();
if (r && window->buffer) {
for (int i = 0; i < r->count; i++) {
int left = r->rects[i].x * window->scale * f;
int top = r->rects[i].y * window->scale * f;
int width = r->rects[i].width * window->scale * f;
int height = r->rects[i].height * window->scale * f;
int left = r->rects[i].x * f;
int top = r->rects[i].y * f;
int width = r->rects[i].width * f;
int height = r->rects[i].height * f;
wl_surface_damage_buffer(window->wl_surface, left, top, width, height);
//fprintf(stderr, "damage %dx%d %dx%d\n", left, top, width, height);
}
} else {
wl_surface_damage_buffer(window->wl_surface, 0, 0,
pWindow->w() * window->scale * f, pWindow->h() * window->scale * f);
//fprintf(stderr, "damage 0x0 %dx%d\n", pWindow->w() * window->scale, pWindow->h() * window->scale);
pWindow->w() * f, pWindow->h() * f);
//fprintf(stderr, "damage 0x0 %dx%d\n", pWindow->w() * f, pWindow->h() * f);
}
Fl_Wayland_Window_Driver::in_flush = true;
@ -473,11 +474,7 @@ void Fl_Wayland_Window_Driver::hide() {
wld_win->wl_surface = NULL;
}
if (wld_win->custom_cursor) delete_cursor_(wld_win);
Fl_Wayland_Window_Driver::window_output *window_output, *tmp;
wl_list_for_each_safe(window_output, tmp, &wld_win->outputs, link) {
wl_list_remove(&window_output->link);
free(window_output);
}
wld_win->output = NULL;
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);
@ -506,7 +503,6 @@ void Fl_Wayland_Window_Driver::map() {
wl_subsurface_place_above(wl_win->subsurface, parent->wl_surface);
wl_win->configured_width = pWindow->w();
wl_win->configured_height = pWindow->h();
wl_win->scale = parent->scale;
wait_for_expose_value = 0;
pWindow->redraw();
}
@ -583,7 +579,7 @@ int Fl_Wayland_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h,
{
struct wld_window * xid = fl_wl_xid(pWindow);
struct fl_wld_buffer *buffer = xid->buffer;
float s = xid->scale * fl_graphics_driver->scale();
float s = wld_scale() * fl_graphics_driver->scale();
if (s != 1) {
src_x = src_x * s;
src_y = src_y * s;
@ -633,7 +629,6 @@ static struct libdecor_interface libdecor_iface = {
static void surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output)
{
struct wld_window *window = (struct wld_window*)data;
Fl_Wayland_Window_Driver::window_output *window_output;
if (!Fl_Wayland_Screen_Driver::own_output(wl_output))
return;
@ -642,11 +637,8 @@ static void surface_enter(void *data, struct wl_surface *wl_surface, struct wl_o
if (output == NULL)
return;
window_output = (Fl_Wayland_Window_Driver::window_output*)calloc(1, sizeof *window_output);
window_output->output = output;
wl_list_insert(&window->outputs, &window_output->link);
window->output = output;
Fl_Wayland_Window_Driver *win_driver = Fl_Wayland_Window_Driver::driver(window->fl_win);
win_driver->update_scale();
if (!window->fl_win->parent()) { // for top-level, set its screen number
Fl_Wayland_Screen_Driver::output *running_output;
Fl_Wayland_Screen_Driver *scr_dr = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
@ -666,16 +658,8 @@ static void surface_leave(void *data, struct wl_surface *wl_surface, struct wl_o
{
struct wld_window *window = (struct wld_window*)data;
if (! window->wl_surface) return;
Fl_Wayland_Window_Driver::window_output *window_output;
wl_list_for_each(window_output, &window->outputs, link) {
if (window_output->output->wl_output == wl_output) {
wl_list_remove(&window_output->link);
free(window_output);
Fl_Wayland_Window_Driver *win_driver = Fl_Wayland_Window_Driver::driver(window->fl_win);
win_driver->update_scale();
break;
}
if (window->output->wl_output == wl_output) {
window->output = NULL;
}
}
@ -1124,7 +1108,6 @@ void Fl_Wayland_Window_Driver::makeWindow()
{
struct wld_window *new_window;
bool is_floatingtitle = false;
Fl_Wayland_Screen_Driver::output *output;
wait_for_expose_value = 1;
if (pWindow->parent() && !pWindow->window()) return;
@ -1132,12 +1115,7 @@ void Fl_Wayland_Window_Driver::makeWindow()
new_window = (struct wld_window *)calloc(1, sizeof *new_window);
new_window->fl_win = pWindow;
new_window->scale = 1;
Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
wl_list_for_each(output, &(scr_driver->outputs), link) {
new_window->scale = MAX(new_window->scale, output->wld_scale);
}
wl_list_init(&new_window->outputs);
new_window->wl_surface = wl_compositor_create_surface(scr_driver->wl_compositor);
//Fl::warning("makeWindow:%p wayland-scale=%d user-scale=%.2f\n", pWindow, new_window->scale, Fl::screen_scale(0));
@ -1413,26 +1391,6 @@ int Fl_Wayland_Window_Driver::set_cursor(Fl_Cursor c) {
}
void Fl_Wayland_Window_Driver::update_scale()
{
struct wld_window *window = fl_wl_xid(pWindow);
int scale = 0;
Fl_Wayland_Window_Driver::window_output *window_output;
wl_list_for_each(window_output, &window->outputs, link) {
scale = fl_max(scale, window_output->output->wld_scale);
}
if (scale && scale != window->scale) {
window->scale = scale;
if (window->buffer || window->fl_win->as_gl_window()) {
Fl_Wayland_Graphics_Driver::buffer_release(window);
window->fl_win->damage(FL_DAMAGE_ALL);
Fl_Window_Driver::driver(window->fl_win)->flush();
}
}
}
void Fl_Wayland_Window_Driver::use_border() {
if (!shown() || pWindow->parent()) return;
pWindow->wait_for_expose(); // useful for border(0) just after show()
@ -1499,7 +1457,7 @@ int Fl_Wayland_Window_Driver::set_cursor(const Fl_RGB_Image *rgb, int hotx, int
struct wld_window *xid = (struct wld_window *)Fl_Window_Driver::xid(pWindow);
struct wl_cursor *new_cursor = (struct wl_cursor*)malloc(sizeof(struct wl_cursor));
struct cursor_image *new_image = (struct cursor_image*)calloc(1, sizeof(struct cursor_image));
int scale = xid->scale;
int scale = wld_scale();
new_image->image.width = rgb->w() * scale;
new_image->image.height = rgb->h() * scale;
new_image->image.hotspot_x = hotx * scale;
@ -1783,6 +1741,20 @@ void Fl_Wayland_Window_Driver::menu_window_area(int &X, int &Y, int &W, int &H,
}
int Fl_Wayland_Window_Driver::wld_scale() {
if (!wld_window || !wld_window->output) {
Fl_Wayland_Screen_Driver::output *output;
int scale = 1;
Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
wl_list_for_each(output, &(scr_driver->outputs), link) {
scale = fl_max(scale, output->wld_scale);
}
return scale;
}
return wld_window->output->wld_scale;
}
FL_EXPORT struct wl_surface *fl_wl_surface(struct wld_window *xid) {
return xid->wl_surface;
}

View File

@ -236,7 +236,7 @@ int Fl_Wayland_Screen_Driver::dnd(int use_selection) {
if (use_selection) {
// use the text as dragging icon
Fl_Widget *current = Fl::pushed() ? Fl::pushed() : Fl::first_window();
s = fl_wl_xid(current->top_window())->scale;
s = Fl_Wayland_Window_Driver::driver(current->top_window())->wld_scale();
off = (struct fl_wld_buffer *)offscreen_from_text(fl_selection_buffer[0], s);
dnd_icon = wl_compositor_create_surface(scr_driver->wl_compositor);
} else dnd_icon = NULL;
@ -576,9 +576,12 @@ void Fl_Wayland_Screen_Driver::paste(Fl_Widget &receiver, int clipboard, const c
} else if (type == Fl::clipboard_image && clipboard_contains(Fl::clipboard_image)) {
if (get_clipboard_image()) return;
struct wld_window * xid = fl_wl_xid(receiver.top_window());
if (xid && xid->scale > 1) {
Fl_RGB_Image *rgb = (Fl_RGB_Image*)Fl::e_clipboard_data;
rgb->scale(rgb->data_w() / xid->scale, rgb->data_h() / xid->scale);
if (xid) {
int s = Fl_Wayland_Window_Driver::driver(receiver.top_window())->wld_scale();
if ( s > 1) {
Fl_RGB_Image *rgb = (Fl_RGB_Image*)Fl::e_clipboard_data;
rgb->scale(rgb->data_w() / s, rgb->data_h() / s);
}
}
int done = receiver.handle(FL_PASTE);
Fl::e_clipboard_type = "";