mirror of
				https://github.com/libsdl-org/SDL.git
				synced 2025-10-26 12:27:44 +00:00 
			
		
		
		
	wayland: Clean up cursor scaling
Handle named and custom cursor scaling in a cleaner manner, and account for edge cases where named cursor sizes may not exactly match the required size.
This commit is contained in:
		| @@ -48,18 +48,16 @@ static bool Wayland_SetRelativeMouseMode(bool enabled); | |||||||
| typedef struct | typedef struct | ||||||
| { | { | ||||||
|     struct Wayland_SHMBuffer shmBuffer; |     struct Wayland_SHMBuffer shmBuffer; | ||||||
|  |  | ||||||
|     int dst_width; |  | ||||||
|     int dst_height; |  | ||||||
|     double scale; |     double scale; | ||||||
|  |  | ||||||
|     struct wl_list node; |     struct wl_list node; | ||||||
| } Wayland_CachedCustomCursor; | } Wayland_ScaledCustomCursor; | ||||||
|  |  | ||||||
| typedef struct | typedef struct | ||||||
| { | { | ||||||
|     SDL_Surface *sdl_cursor_surface; |     SDL_Surface *sdl_cursor_surface; | ||||||
|     struct wl_list cursor_cache; |     int hot_x; | ||||||
|  |     int hot_y; | ||||||
|  |     struct wl_list scaled_cursor_cache; | ||||||
| } Wayland_CustomCursor; | } Wayland_CustomCursor; | ||||||
|  |  | ||||||
| typedef struct | typedef struct | ||||||
| @@ -91,8 +89,6 @@ struct SDL_CursorData | |||||||
|     struct wl_surface *surface; |     struct wl_surface *surface; | ||||||
|     struct wp_viewport *viewport; |     struct wp_viewport *viewport; | ||||||
|  |  | ||||||
|     int hot_x, hot_y; |  | ||||||
|  |  | ||||||
|     bool is_system_cursor; |     bool is_system_cursor; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -338,39 +334,35 @@ static void cursor_frame_done(void *data, struct wl_callback *cb, uint32_t time) | |||||||
|     wl_surface_commit(c->surface); |     wl_surface_commit(c->surface); | ||||||
| } | } | ||||||
|  |  | ||||||
| static bool wayland_get_system_cursor(SDL_VideoData *vdata, SDL_CursorData *cdata, double *scale) | static bool Wayland_GetSystemCursor(SDL_VideoData *vdata, SDL_CursorData *cdata, int *scale, int *dst_size, int *hot_x, int *hot_y) | ||||||
| { | { | ||||||
|     struct wl_cursor_theme *theme = NULL; |     struct wl_cursor_theme *theme = NULL; | ||||||
|     struct wl_cursor *cursor; |     struct wl_cursor *cursor; | ||||||
|     const char *css_name = "default"; |     const char *css_name = "default"; | ||||||
|     const char *fallback_name = NULL; |     const char *fallback_name = NULL; | ||||||
|  |     double scale_factor = 1.0; | ||||||
|     int size = dbus_cursor_size; |     int theme_size = dbus_cursor_size; | ||||||
|  |  | ||||||
|     SDL_Window *focus; |  | ||||||
|  |  | ||||||
|     // Fallback envvar if the DBus properties don't exist |     // Fallback envvar if the DBus properties don't exist | ||||||
|     if (size <= 0) { |     if (theme_size <= 0) { | ||||||
|         const char *xcursor_size = SDL_getenv("XCURSOR_SIZE"); |         const char *xcursor_size = SDL_getenv("XCURSOR_SIZE"); | ||||||
|         if (xcursor_size) { |         if (xcursor_size) { | ||||||
|             size = SDL_atoi(xcursor_size); |             theme_size = SDL_atoi(xcursor_size); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if (size <= 0) { |     if (theme_size <= 0) { | ||||||
|         size = 24; |         theme_size = 24; | ||||||
|     } |     } | ||||||
|     // First, find the appropriate theme based on the current scale... |     // First, find the appropriate theme based on the current scale... | ||||||
|     focus = SDL_GetMouse()->focus; |     SDL_Window *focus = SDL_GetMouse()->focus; | ||||||
|     if (focus) { |     if (focus) { | ||||||
|         // TODO: Use the fractional scale once GNOME supports viewports on cursor surfaces. |         // TODO: Use the fractional scale once GNOME supports viewports on cursor surfaces. | ||||||
|         *scale = SDL_ceil(focus->internal->scale_factor); |         scale_factor = SDL_ceil(focus->internal->scale_factor); | ||||||
|     } else { |  | ||||||
|         *scale = 1.0; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     size *= (int)*scale; |     const int scaled_size = (int)SDL_lround(theme_size * scale_factor); | ||||||
|     for (int i = 0; i < vdata->num_cursor_themes; ++i) { |     for (int i = 0; i < vdata->num_cursor_themes; ++i) { | ||||||
|         if (vdata->cursor_themes[i].size == size) { |         if (vdata->cursor_themes[i].size == scaled_size) { | ||||||
|             theme = vdata->cursor_themes[i].theme; |             theme = vdata->cursor_themes[i].theme; | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| @@ -390,8 +382,8 @@ static bool wayland_get_system_cursor(SDL_VideoData *vdata, SDL_CursorData *cdat | |||||||
|             xcursor_theme = SDL_getenv("XCURSOR_THEME"); |             xcursor_theme = SDL_getenv("XCURSOR_THEME"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         theme = WAYLAND_wl_cursor_theme_load(xcursor_theme, size, vdata->shm); |         theme = WAYLAND_wl_cursor_theme_load(xcursor_theme, scaled_size, vdata->shm); | ||||||
|         vdata->cursor_themes[vdata->num_cursor_themes].size = size; |         vdata->cursor_themes[vdata->num_cursor_themes].size = scaled_size; | ||||||
|         vdata->cursor_themes[vdata->num_cursor_themes++].theme = theme; |         vdata->cursor_themes[vdata->num_cursor_themes++].theme = theme; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -429,48 +421,67 @@ static bool wayland_get_system_cursor(SDL_VideoData *vdata, SDL_CursorData *cdat | |||||||
|         cdata->cursor_data.system.frames[i].duration = cursor->images[i]->delay; |         cdata->cursor_data.system.frames[i].duration = cursor->images[i]->delay; | ||||||
|         cdata->cursor_data.system.total_duration += cursor->images[i]->delay; |         cdata->cursor_data.system.total_duration += cursor->images[i]->delay; | ||||||
|     } |     } | ||||||
|     cdata->hot_x = cursor->images[0]->hotspot_x; |  | ||||||
|     cdata->hot_y = cursor->images[0]->hotspot_y; |     *scale = SDL_ceil(scale_factor) == scale_factor ? (int)scale_factor : 0; | ||||||
|  |     *dst_size = theme_size; | ||||||
|  |  | ||||||
|  |     // Calculate the hotspot offset if the cursor is being scaled. | ||||||
|  |     if (scaled_size == cursor->images[0]->width) { | ||||||
|  |         // If the theme has an exact size match, just divide by the scale. | ||||||
|  |         *hot_x = (int)SDL_lround(cursor->images[0]->hotspot_x / scale_factor); | ||||||
|  |         *hot_y = (int)SDL_lround(cursor->images[0]->hotspot_y / scale_factor); | ||||||
|  |     } else { | ||||||
|  |         if (vdata->viewporter) { | ||||||
|  |             // Use a viewport if no exact size match is found to avoid a potential "buffer size is not divisible by scale" protocol error. | ||||||
|  |             *scale = 0; | ||||||
|  |  | ||||||
|  |             // Map the hotspot coordinates from the source to destination sizes. | ||||||
|  |             const double hotspot_scale = (double)theme_size / (double)cursor->images[0]->width; | ||||||
|  |             *hot_x = (int)SDL_lround(hotspot_scale * cursor->images[0]->hotspot_x); | ||||||
|  |             *hot_y = (int)SDL_lround(hotspot_scale * cursor->images[0]->hotspot_y); | ||||||
|  |         } else { | ||||||
|  |             // No exact match, and viewports are unsupported. Find a safe integer scale. | ||||||
|  |             for (; *scale > 1; --*scale) { | ||||||
|  |                 if (cursor->images[0]->width % *scale == 0) { | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             *hot_x = cursor->images[0]->hotspot_x / *scale; | ||||||
|  |             *hot_y = cursor->images[0]->hotspot_y / *scale; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| static Wayland_CachedCustomCursor *Wayland_GetCachedCustomCursor(SDL_Cursor *cursor) | static Wayland_ScaledCustomCursor *Wayland_CacheScaledCustomCursor(SDL_CursorData *cdata, double scale) | ||||||
| { | { | ||||||
|     SDL_VideoDevice *vd = SDL_GetVideoDevice(); |     Wayland_ScaledCustomCursor *cache = NULL; | ||||||
|     SDL_VideoData *wd = vd->internal; |  | ||||||
|     SDL_CursorData *data = cursor->internal; |  | ||||||
|     Wayland_CachedCustomCursor *cache; |  | ||||||
|     SDL_Window *focus = SDL_GetMouseFocus(); |  | ||||||
|     double scale = 1.0; |  | ||||||
|  |  | ||||||
|     if (focus && SDL_SurfaceHasAlternateImages(data->cursor_data.custom.sdl_cursor_surface)) { |  | ||||||
|         scale = focus->internal->scale_factor; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Only use fractional scale values if viewports are available. |  | ||||||
|     if (!wd->viewporter) { |  | ||||||
|         scale = SDL_ceil(scale); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Is this cursor already cached at the target scale? |     // Is this cursor already cached at the target scale? | ||||||
|     wl_list_for_each(cache, &data->cursor_data.custom.cursor_cache, node) { |     if (!WAYLAND_wl_list_empty(&cdata->cursor_data.custom.scaled_cursor_cache)) { | ||||||
|         if (cache->scale == scale) { |         Wayland_ScaledCustomCursor *c = NULL; | ||||||
|             return cache; |         wl_list_for_each (c, &cdata->cursor_data.custom.scaled_cursor_cache, node) { | ||||||
|  |             if (c->scale == scale) { | ||||||
|  |                 cache = c; | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     cache = SDL_calloc(1, sizeof(Wayland_CachedCustomCursor)); |     if (!cache) { | ||||||
|  |         cache = SDL_calloc(1, sizeof(Wayland_ScaledCustomCursor)); | ||||||
|         if (!cache) { |         if (!cache) { | ||||||
|             return NULL; |             return NULL; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     SDL_Surface *surface = SDL_GetSurfaceImage(data->cursor_data.custom.sdl_cursor_surface, (float)scale); |         SDL_Surface *surface = SDL_GetSurfaceImage(cdata->cursor_data.custom.sdl_cursor_surface, (float)scale); | ||||||
|         if (!surface) { |         if (!surface) { | ||||||
|             SDL_free(cache); |             SDL_free(cache); | ||||||
|             return NULL; |             return NULL; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     // Allocate shared memory buffer for this cursor |         // Allocate the shared memory buffer for this cursor. | ||||||
|         if (!Wayland_AllocSHMBuffer(surface->w, surface->h, &cache->shmBuffer)) { |         if (!Wayland_AllocSHMBuffer(surface->w, surface->h, &cache->shmBuffer)) { | ||||||
|             SDL_free(cache); |             SDL_free(cache); | ||||||
|             SDL_DestroySurface(surface); |             SDL_DestroySurface(surface); | ||||||
| @@ -482,15 +493,46 @@ static Wayland_CachedCustomCursor *Wayland_GetCachedCustomCursor(SDL_Cursor *cur | |||||||
|                              surface->format, surface->pixels, surface->pitch, |                              surface->format, surface->pixels, surface->pitch, | ||||||
|                              SDL_PIXELFORMAT_ARGB8888, cache->shmBuffer.shm_data, surface->w * 4, true); |                              SDL_PIXELFORMAT_ARGB8888, cache->shmBuffer.shm_data, surface->w * 4, true); | ||||||
|  |  | ||||||
|     cache->dst_width = data->cursor_data.custom.sdl_cursor_surface->w; |  | ||||||
|     cache->dst_height = data->cursor_data.custom.sdl_cursor_surface->h; |  | ||||||
|         cache->scale = scale; |         cache->scale = scale; | ||||||
|     WAYLAND_wl_list_insert(&data->cursor_data.custom.cursor_cache, &cache->node); |         WAYLAND_wl_list_insert(&cdata->cursor_data.custom.scaled_cursor_cache, &cache->node); | ||||||
|         SDL_DestroySurface(surface); |         SDL_DestroySurface(surface); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return cache; |     return cache; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static bool Wayland_GetCustomCursor(SDL_Cursor *cursor, struct wl_buffer **buffer, int *scale, int *dst_width, int *dst_height, int *hot_x, int *hot_y) | ||||||
|  | { | ||||||
|  |     SDL_VideoDevice *vd = SDL_GetVideoDevice(); | ||||||
|  |     SDL_VideoData *wd = vd->internal; | ||||||
|  |     SDL_CursorData *data = cursor->internal; | ||||||
|  |     SDL_Window *focus = SDL_GetMouseFocus(); | ||||||
|  |     double scale_factor = 1.0; | ||||||
|  |  | ||||||
|  |     if (focus && SDL_SurfaceHasAlternateImages(data->cursor_data.custom.sdl_cursor_surface)) { | ||||||
|  |         scale_factor = focus->internal->scale_factor; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Only use fractional scale values if viewports are available. | ||||||
|  |     if (!wd->viewporter) { | ||||||
|  |         scale_factor = SDL_ceil(scale_factor); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     Wayland_ScaledCustomCursor *c = Wayland_CacheScaledCustomCursor(data, scale_factor); | ||||||
|  |     if (!c) { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     *buffer = c->shmBuffer.wl_buffer; | ||||||
|  |     *scale = SDL_ceil(scale_factor) == scale_factor ? (int)scale_factor : 0; | ||||||
|  |     *dst_width = data->cursor_data.custom.sdl_cursor_surface->w; | ||||||
|  |     *dst_height = data->cursor_data.custom.sdl_cursor_surface->h; | ||||||
|  |     *hot_x = data->cursor_data.custom.hot_x; | ||||||
|  |     *hot_y = data->cursor_data.custom.hot_y; | ||||||
|  |  | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  |  | ||||||
| static SDL_Cursor *Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) | static SDL_Cursor *Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) | ||||||
| { | { | ||||||
|     SDL_VideoDevice *vd = SDL_GetVideoDevice(); |     SDL_VideoDevice *vd = SDL_GetVideoDevice(); | ||||||
| @@ -504,18 +546,17 @@ static SDL_Cursor *Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot | |||||||
|             return NULL; |             return NULL; | ||||||
|         } |         } | ||||||
|         cursor->internal = data; |         cursor->internal = data; | ||||||
|         WAYLAND_wl_list_init(&data->cursor_data.custom.cursor_cache); |         WAYLAND_wl_list_init(&data->cursor_data.custom.scaled_cursor_cache); | ||||||
|         data->hot_x = hot_x; |         data->cursor_data.custom.hot_x = hot_x; | ||||||
|         data->hot_y = hot_y; |         data->cursor_data.custom.hot_y = hot_y; | ||||||
|         data->surface = wl_compositor_create_surface(wd->compositor); |         data->surface = wl_compositor_create_surface(wd->compositor); | ||||||
|         wl_surface_set_user_data(data->surface, NULL); |  | ||||||
|  |  | ||||||
|         data->cursor_data.custom.sdl_cursor_surface = surface; |         data->cursor_data.custom.sdl_cursor_surface = surface; | ||||||
|         ++surface->refcount; |         ++surface->refcount; | ||||||
|  |  | ||||||
|         // If the cursor has only one size, just prepare it now. |         // If the cursor has only one size, just prepare it now. | ||||||
|         if (!SDL_SurfaceHasAlternateImages(surface)) { |         if (!SDL_SurfaceHasAlternateImages(surface)) { | ||||||
|             Wayland_GetCachedCustomCursor(cursor); |             Wayland_CacheScaledCustomCursor(data, 1.0); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -565,8 +606,8 @@ static void Wayland_FreeCursorData(SDL_CursorData *d) | |||||||
|         } |         } | ||||||
|         SDL_free(d->cursor_data.system.frames); |         SDL_free(d->cursor_data.system.frames); | ||||||
|     } else { |     } else { | ||||||
|         Wayland_CachedCustomCursor *c, *temp; |         Wayland_ScaledCustomCursor *c, *temp; | ||||||
|         wl_list_for_each_safe(c, temp, &d->cursor_data.custom.cursor_cache, node) { |         wl_list_for_each_safe(c, temp, &d->cursor_data.custom.scaled_cursor_cache, node) { | ||||||
|             Wayland_ReleaseSHMBuffer(&c->shmBuffer); |             Wayland_ReleaseSHMBuffer(&c->shmBuffer); | ||||||
|             SDL_free(c); |             SDL_free(c); | ||||||
|         } |         } | ||||||
| @@ -681,9 +722,12 @@ static bool Wayland_ShowCursor(SDL_Cursor *cursor) | |||||||
|     SDL_VideoData *d = vd->internal; |     SDL_VideoData *d = vd->internal; | ||||||
|     struct SDL_WaylandInput *input = d->input; |     struct SDL_WaylandInput *input = d->input; | ||||||
|     struct wl_pointer *pointer = d->pointer; |     struct wl_pointer *pointer = d->pointer; | ||||||
|     double scale = 1.0; |     struct wl_buffer *buffer = NULL; | ||||||
|  |     int scale = 1; | ||||||
|     int dst_width = 0; |     int dst_width = 0; | ||||||
|     int dst_height = 0; |     int dst_height = 0; | ||||||
|  |     int hot_x; | ||||||
|  |     int hot_y; | ||||||
|  |  | ||||||
|     if (!pointer) { |     if (!pointer) { | ||||||
|         return false; |         return false; | ||||||
| @@ -700,19 +744,18 @@ static bool Wayland_ShowCursor(SDL_Cursor *cursor) | |||||||
|         SDL_CursorData *data = cursor->internal; |         SDL_CursorData *data = cursor->internal; | ||||||
|  |  | ||||||
|         if (data->is_system_cursor) { |         if (data->is_system_cursor) { | ||||||
|  |             // If the cursor shape protocol is supported, the compositor will draw nicely scaled cursors for us, so nothing more to do. | ||||||
|             if (input->cursor_shape) { |             if (input->cursor_shape) { | ||||||
|                 Wayland_SetSystemCursorShape(input, data->cursor_data.system.id); |                 Wayland_SetSystemCursorShape(input, data->cursor_data.system.id); | ||||||
|                 input->current_cursor = data; |                 input->current_cursor = data; | ||||||
|  |  | ||||||
|                 return true; |                 return true; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (!wayland_get_system_cursor(d, data, &scale)) { |             if (!Wayland_GetSystemCursor(d, data, &scale, &dst_width, &hot_x, &hot_y)) { | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (data->is_system_cursor) { |             dst_height = dst_width; | ||||||
|             wl_surface_attach(data->surface, data->cursor_data.system.frames[0].wl_buffer, 0, 0); |             wl_surface_attach(data->surface, data->cursor_data.system.frames[0].wl_buffer, 0, 0); | ||||||
|  |  | ||||||
|             // If more than one frame is available, create a frame callback to run the animation. |             // If more than one frame is available, create a frame callback to run the animation. | ||||||
| @@ -724,34 +767,31 @@ static bool Wayland_ShowCursor(SDL_Cursor *cursor) | |||||||
|                 wl_callback_add_listener(data->cursor_data.system.frame_callback, &cursor_frame_listener, data); |                 wl_callback_add_listener(data->cursor_data.system.frame_callback, &cursor_frame_listener, data); | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             Wayland_CachedCustomCursor *cached = Wayland_GetCachedCustomCursor(cursor); |             if (!Wayland_GetCustomCursor(cursor, &buffer, &scale, &dst_width, &dst_height, &hot_x, &hot_y)) { | ||||||
|             if (!cached) { |  | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|             dst_width = cached->dst_width; |  | ||||||
|             dst_height = cached->dst_height; |             wl_surface_attach(data->surface, buffer, 0, 0); | ||||||
|             scale = cached->scale; |  | ||||||
|             wl_surface_attach(data->surface, cached->shmBuffer.wl_buffer, 0, 0); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // TODO: Make the viewport path the default in all cases once GNOME finally supports viewports on cursor surfaces. |         // A scale value of 0 indicates that a viewport with the returned destination size should be used. | ||||||
|         if (SDL_ceil(scale) != scale && d->viewporter) { |         if (!scale) { | ||||||
|             if (!data->viewport) { |             if (!data->viewport) { | ||||||
|                 data->viewport = wp_viewporter_get_viewport(d->viewporter, data->surface); |                 data->viewport = wp_viewporter_get_viewport(d->viewporter, data->surface); | ||||||
|             } |             } | ||||||
|             wl_surface_set_buffer_scale(data->surface, 1); |             wl_surface_set_buffer_scale(data->surface, 1); | ||||||
|             wp_viewport_set_source(data->viewport, wl_fixed_from_int(-1), wl_fixed_from_int(-1), wl_fixed_from_int(-1), wl_fixed_from_int(-1)); |             wp_viewport_set_source(data->viewport, wl_fixed_from_int(-1), wl_fixed_from_int(-1), wl_fixed_from_int(-1), wl_fixed_from_int(-1)); | ||||||
|             wp_viewport_set_destination(data->viewport, dst_width, dst_height); |             wp_viewport_set_destination(data->viewport, dst_width, dst_height); | ||||||
|             wl_pointer_set_cursor(pointer, input->pointer_enter_serial, data->surface, data->hot_x, data->hot_y); |  | ||||||
|         } else { |         } else { | ||||||
|             if (data->viewport) { |             if (data->viewport) { | ||||||
|                 wp_viewport_destroy(data->viewport); |                 wp_viewport_destroy(data->viewport); | ||||||
|                 data->viewport = NULL; |                 data->viewport = NULL; | ||||||
|             } |             } | ||||||
|             wl_surface_set_buffer_scale(data->surface, (int32_t)scale); |             wl_surface_set_buffer_scale(data->surface, scale); | ||||||
|             wl_pointer_set_cursor(pointer, input->pointer_enter_serial, data->surface, (int32_t)(data->hot_x / scale), (int32_t)(data->hot_y / scale)); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         wl_pointer_set_cursor(pointer, input->pointer_enter_serial, data->surface, hot_x, hot_y); | ||||||
|  |  | ||||||
|         if (wl_surface_get_version(data->surface) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION) { |         if (wl_surface_get_version(data->surface) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION) { | ||||||
|             wl_surface_damage_buffer(data->surface, 0, 0, SDL_MAX_SINT32, SDL_MAX_SINT32); |             wl_surface_damage_buffer(data->surface, 0, 0, SDL_MAX_SINT32, SDL_MAX_SINT32); | ||||||
|         } else { |         } else { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Frank Praznik
					Frank Praznik