mirror of
https://github.com/fltk/fltk.git
synced 2026-05-30 21:25:30 +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;
|
struct wl_buffer *wl_buffer;
|
||||||
void *data;
|
void *data;
|
||||||
struct wl_shm_pool *shm_pool;
|
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 draw_buffer_needs_commit;
|
||||||
bool in_use; // true while being committed
|
bool in_use; // true while being committed
|
||||||
bool released; // true after buffer_release() was called
|
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,
|
void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen osrc,
|
||||||
int srcx, int srcy) FL_OVERRIDE;
|
int srcx, int srcy) FL_OVERRIDE;
|
||||||
void cache_size(Fl_Image *img, int &width, int &height) 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 create_shm_buffer(wld_buffer *buffer);
|
||||||
static void buffer_release(struct wld_window *window);
|
static void buffer_release(struct wld_window *window);
|
||||||
static void buffer_commit(struct wld_window *window, cairo_region_t *r = NULL);
|
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
|
// used by class Fl_Wayland_Gl_Window_Driver
|
||||||
static FL_EXPORT struct draw_buffer *offscreen_buffer(Fl_Offscreen);
|
static FL_EXPORT struct draw_buffer *offscreen_buffer(Fl_Offscreen);
|
||||||
static const cairo_user_data_key_t key;
|
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
|
#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 *
|
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));
|
struct wld_buffer *buffer = (struct wld_buffer*)calloc(1, sizeof(struct wld_buffer));
|
||||||
int stride = cairo_format_stride_for_width(cairo_format, width);
|
int stride = cairo_format_stride_for_width(cairo_format, width);
|
||||||
cairo_init(&buffer->draw_buffer, width, height, stride, cairo_format);
|
cairo_init(&buffer->draw_buffer, width, height, stride, cairo_format);
|
||||||
buffer->draw_buffer_needs_commit = true;
|
buffer->draw_buffer_needs_commit = true;
|
||||||
if (with_shm) create_shm_buffer(buffer);
|
if (with_shm) create_shm_buffer(buffer);
|
||||||
|
buffer->allowed_wld_scale = wld_s;
|
||||||
return buffer;
|
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)
|
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->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_t *surf = cairo_get_target(window->buffer->draw_buffer.cairo_);
|
||||||
cairo_surface_flush(surf);
|
cairo_surface_flush(surf);
|
||||||
if (r) copy_region(window, r);
|
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,
|
Fl_Image_Surface *Fl_Wayland_Graphics_Driver::custom_offscreen(int w, int h,
|
||||||
struct Fl_Wayland_Graphics_Driver::wld_buffer **p_off) {
|
struct Fl_Wayland_Graphics_Driver::wld_buffer **p_off, int scale) {
|
||||||
struct wld_buffer *off = create_wld_buffer(w, h);
|
struct wld_buffer *off = create_wld_buffer(w, h, true, scale);
|
||||||
*p_off = off;
|
*p_off = off;
|
||||||
cairo_set_user_data(off->draw_buffer.cairo_, &key, &off->draw_buffer, NULL);
|
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_);
|
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();
|
int wld_s = wld_scale();
|
||||||
if (!window->buffer) {
|
if (!window->buffer) {
|
||||||
window->buffer = Fl_Wayland_Graphics_Driver::create_wld_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(
|
((Fl_Cairo_Graphics_Driver*)fl_graphics_driver)->needs_commit_tag(
|
||||||
&window->buffer->draw_buffer_needs_commit);
|
&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
|
//create a Wayland buffer and have it used as an image of the new cursor
|
||||||
struct Fl_Wayland_Graphics_Driver::wld_buffer *offscreen;
|
struct Fl_Wayland_Graphics_Driver::wld_buffer *offscreen;
|
||||||
Fl_Image_Surface *img_surf = Fl_Wayland_Graphics_Driver::custom_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;
|
new_image->buffer = offscreen->wl_buffer;
|
||||||
wl_buffer_set_user_data(new_image->buffer, offscreen);
|
wl_buffer_set_user_data(new_image->buffer, offscreen);
|
||||||
new_cursor->image_count = 1;
|
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;
|
height = ceil(height/float(scale)) * scale;
|
||||||
struct Fl_Wayland_Graphics_Driver::wld_buffer *off;
|
struct Fl_Wayland_Graphics_Driver::wld_buffer *off;
|
||||||
Fl_Image_Surface *surf = Fl_Wayland_Graphics_Driver::custom_offscreen(
|
Fl_Image_Surface *surf = Fl_Wayland_Graphics_Driver::custom_offscreen(
|
||||||
width, height, &off);
|
width, height, &off, scale);
|
||||||
Fl_Surface_Device::push_current(surf);
|
Fl_Surface_Device::push_current(surf);
|
||||||
p = text;
|
p = text;
|
||||||
fl_font(FL_HELVETICA, 10 * scale);
|
fl_font(FL_HELVETICA, 10 * scale);
|
||||||
|
|||||||
Reference in New Issue
Block a user