mirror of
https://github.com/fltk/fltk.git
synced 2026-05-30 13:05:35 +08:00
Fix: Wayland crashes when dragging window from 100% to 200% scale factors (#1428)
This commit is contained in:
@@ -42,6 +42,7 @@ public:
|
||||
struct wl_buffer *wl_buffer;
|
||||
void *data;
|
||||
struct wl_shm_pool *shm_pool;
|
||||
int allowed_wld_scale; // the wld_scale active when this buffer was sized
|
||||
bool draw_buffer_needs_commit;
|
||||
bool in_use; // true while being committed
|
||||
bool released; // true after buffer_release() was called
|
||||
@@ -57,7 +58,7 @@ public:
|
||||
void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen osrc,
|
||||
int srcx, int srcy) FL_OVERRIDE;
|
||||
void cache_size(Fl_Image *img, int &width, int &height) FL_OVERRIDE;
|
||||
static struct wld_buffer *create_wld_buffer(int width, int height, bool with_shm = true);
|
||||
static struct wld_buffer *create_wld_buffer(int width, int height, bool with_shm, int wld_s);
|
||||
static void create_shm_buffer(wld_buffer *buffer);
|
||||
static void buffer_release(struct wld_window *window);
|
||||
static void buffer_commit(struct wld_window *window, cairo_region_t *r = NULL);
|
||||
@@ -66,7 +67,7 @@ public:
|
||||
// used by class Fl_Wayland_Gl_Window_Driver
|
||||
static FL_EXPORT struct draw_buffer *offscreen_buffer(Fl_Offscreen);
|
||||
static const cairo_user_data_key_t key;
|
||||
static Fl_Image_Surface *custom_offscreen(int w, int h, struct wld_buffer **buffer);
|
||||
static Fl_Image_Surface *custom_offscreen(int w, int h, struct wld_buffer **buffer, int scale);
|
||||
};
|
||||
|
||||
#endif // FL_WAYLAND_GRAPHICS_DRIVER_H
|
||||
|
||||
@@ -108,12 +108,13 @@ void Fl_Wayland_Graphics_Driver::create_shm_buffer(Fl_Wayland_Graphics_Driver::w
|
||||
|
||||
|
||||
struct Fl_Wayland_Graphics_Driver::wld_buffer *
|
||||
Fl_Wayland_Graphics_Driver::create_wld_buffer(int width, int height, bool with_shm) {
|
||||
Fl_Wayland_Graphics_Driver::create_wld_buffer(int width, int height, bool with_shm, int wld_s) {
|
||||
struct wld_buffer *buffer = (struct wld_buffer*)calloc(1, sizeof(struct wld_buffer));
|
||||
int stride = cairo_format_stride_for_width(cairo_format, width);
|
||||
cairo_init(&buffer->draw_buffer, width, height, stride, cairo_format);
|
||||
buffer->draw_buffer_needs_commit = true;
|
||||
if (with_shm) create_shm_buffer(buffer);
|
||||
buffer->allowed_wld_scale = wld_s;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@@ -173,6 +174,17 @@ static void copy_region(struct wld_window *window, cairo_region_t *r) {
|
||||
void Fl_Wayland_Graphics_Driver::buffer_commit(struct wld_window *window, cairo_region_t *r)
|
||||
{
|
||||
if (!window->buffer->wl_buffer) create_shm_buffer(window->buffer);
|
||||
|
||||
if (window->buffer->allowed_wld_scale != Fl_Wayland_Window_Driver::driver(window->fl_win)->wld_scale()) {
|
||||
// surface_enter has updated wld_scale() but the buffer was sized for the
|
||||
// old scale. Committing now would violate the Wayland protocol (buffer
|
||||
// dimensions must be multiples of buffer_scale). Let delayed_rescale
|
||||
// rebuild the buffer at the correct size first. (#1428)
|
||||
buffer_release(window);
|
||||
window->fl_win->redraw();
|
||||
return;
|
||||
}
|
||||
|
||||
cairo_surface_t *surf = cairo_get_target(window->buffer->draw_buffer.cairo_);
|
||||
cairo_surface_flush(surf);
|
||||
if (r) copy_region(window, r);
|
||||
@@ -295,8 +307,8 @@ Fl_Wayland_Graphics_Driver::offscreen_buffer(Fl_Offscreen offscreen) {
|
||||
|
||||
|
||||
Fl_Image_Surface *Fl_Wayland_Graphics_Driver::custom_offscreen(int w, int h,
|
||||
struct Fl_Wayland_Graphics_Driver::wld_buffer **p_off) {
|
||||
struct wld_buffer *off = create_wld_buffer(w, h);
|
||||
struct Fl_Wayland_Graphics_Driver::wld_buffer **p_off, int scale) {
|
||||
struct wld_buffer *off = create_wld_buffer(w, h, true, scale);
|
||||
*p_off = off;
|
||||
cairo_set_user_data(off->draw_buffer.cairo_, &key, &off->draw_buffer, NULL);
|
||||
return new Fl_Image_Surface(w, h, 0, (Fl_Offscreen)off->draw_buffer.cairo_);
|
||||
|
||||
@@ -370,7 +370,7 @@ void Fl_Wayland_Window_Driver::make_current() {
|
||||
int wld_s = wld_scale();
|
||||
if (!window->buffer) {
|
||||
window->buffer = Fl_Wayland_Graphics_Driver::create_wld_buffer(
|
||||
int(pWindow->w() * f) * wld_s, int(pWindow->h() * f) * wld_s, false);
|
||||
int(pWindow->w() * f) * wld_s, int(pWindow->h() * f) * wld_s, false, wld_s);
|
||||
((Fl_Cairo_Graphics_Driver*)fl_graphics_driver)->needs_commit_tag(
|
||||
&window->buffer->draw_buffer_needs_commit);
|
||||
}
|
||||
@@ -1872,7 +1872,7 @@ int Fl_Wayland_Window_Driver::set_cursor_4args(const Fl_RGB_Image *rgb, int hotx
|
||||
//create a Wayland buffer and have it used as an image of the new cursor
|
||||
struct Fl_Wayland_Graphics_Driver::wld_buffer *offscreen;
|
||||
Fl_Image_Surface *img_surf = Fl_Wayland_Graphics_Driver::custom_offscreen(
|
||||
new_image->image.width, new_image->image.height, &offscreen);
|
||||
new_image->image.width, new_image->image.height, &offscreen, scale);
|
||||
new_image->buffer = offscreen->wl_buffer;
|
||||
wl_buffer_set_user_data(new_image->buffer, offscreen);
|
||||
new_cursor->image_count = 1;
|
||||
|
||||
@@ -215,7 +215,7 @@ static struct Fl_Wayland_Graphics_Driver::wld_buffer *offscreen_from_text(const
|
||||
height = ceil(height/float(scale)) * scale;
|
||||
struct Fl_Wayland_Graphics_Driver::wld_buffer *off;
|
||||
Fl_Image_Surface *surf = Fl_Wayland_Graphics_Driver::custom_offscreen(
|
||||
width, height, &off);
|
||||
width, height, &off, scale);
|
||||
Fl_Surface_Device::push_current(surf);
|
||||
p = text;
|
||||
fl_font(FL_HELVETICA, 10 * scale);
|
||||
|
||||
Reference in New Issue
Block a user