mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-10-16 23:06:03 +00:00
wayland: Add support for setting window icons via the xdg-toplevel-icon-v1 protocol
This commit is contained in:
@@ -63,6 +63,7 @@
|
||||
#include "xdg-foreign-unstable-v2-client-protocol.h"
|
||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||
#include "xdg-shell-client-protocol.h"
|
||||
#include "xdg-toplevel-icon-v1-client-protocol.h"
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
#include <libdecor.h>
|
||||
@@ -549,6 +550,7 @@ static SDL_VideoDevice *Wayland_CreateDevice(bool require_preferred_protocols)
|
||||
device->SetWindowModalFor = Wayland_SetWindowModalFor;
|
||||
device->SetWindowOpacity = Wayland_SetWindowOpacity;
|
||||
device->SetWindowTitle = Wayland_SetWindowTitle;
|
||||
device->SetWindowIcon = Wayland_SetWindowIcon;
|
||||
device->GetWindowSizeInPixels = Wayland_GetWindowSizeInPixels;
|
||||
device->GetDisplayForWindow = Wayland_GetDisplayForWindow;
|
||||
device->DestroyWindow = Wayland_DestroyWindow;
|
||||
@@ -1191,6 +1193,8 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint
|
||||
d->xdg_wm_dialog_v1 = wl_registry_bind(d->registry, id, &xdg_wm_dialog_v1_interface, 1);
|
||||
} else if (SDL_strcmp(interface, "wp_alpha_modifier_v1") == 0) {
|
||||
d->wp_alpha_modifier_v1 = wl_registry_bind(d->registry, id, &wp_alpha_modifier_v1_interface, 1);
|
||||
} else if (SDL_strcmp(interface, "xdg_toplevel_icon_manager_v1") == 0) {
|
||||
d->xdg_toplevel_icon_manager_v1 = wl_registry_bind(d->registry, id, &xdg_toplevel_icon_manager_v1_interface, 1);
|
||||
} else if (SDL_strcmp(interface, "kde_output_order_v1") == 0) {
|
||||
d->kde_output_order = wl_registry_bind(d->registry, id, &kde_output_order_v1_interface, 1);
|
||||
kde_output_order_v1_add_listener(d->kde_output_order, &kde_output_order_listener, d);
|
||||
@@ -1460,6 +1464,11 @@ static void Wayland_VideoCleanup(SDL_VideoDevice *_this)
|
||||
data->wp_alpha_modifier_v1 = NULL;
|
||||
}
|
||||
|
||||
if (data->xdg_toplevel_icon_manager_v1) {
|
||||
xdg_toplevel_icon_manager_v1_destroy(data->xdg_toplevel_icon_manager_v1);
|
||||
data->xdg_toplevel_icon_manager_v1 = NULL;
|
||||
}
|
||||
|
||||
if (data->kde_output_order) {
|
||||
Wayland_FlushOutputOrder(data);
|
||||
kde_output_order_v1_destroy(data->kde_output_order);
|
||||
|
@@ -81,6 +81,7 @@ struct SDL_VideoData
|
||||
struct zxdg_exporter_v2 *zxdg_exporter_v2;
|
||||
struct xdg_wm_dialog_v1 *xdg_wm_dialog_v1;
|
||||
struct wp_alpha_modifier_v1 *wp_alpha_modifier_v1;
|
||||
struct xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager_v1;
|
||||
struct kde_output_order_v1 *kde_output_order;
|
||||
struct frog_color_management_factory_v1 *frog_color_management_factory_v1;
|
||||
struct zwp_tablet_manager_v2 *tablet_manager;
|
||||
|
@@ -42,6 +42,7 @@
|
||||
#include "xdg-foreign-unstable-v2-client-protocol.h"
|
||||
#include "xdg-dialog-v1-client-protocol.h"
|
||||
#include "frog-color-management-v1-client-protocol.h"
|
||||
#include "xdg-toplevel-icon-v1-client-protocol.h"
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
#include <libdecor.h>
|
||||
@@ -1722,6 +1723,12 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
zxdg_exported_v2_add_listener(data->exported, &exported_v2_listener, data);
|
||||
}
|
||||
|
||||
if (c->xdg_toplevel_icon_manager_v1 && data->xdg_toplevel_icon_v1) {
|
||||
xdg_toplevel_icon_manager_v1_set_icon(_this->internal->xdg_toplevel_icon_manager_v1,
|
||||
libdecor_frame_get_xdg_toplevel(data->shell_surface.libdecor.frame),
|
||||
data->xdg_toplevel_icon_v1);
|
||||
}
|
||||
|
||||
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_SURFACE_POINTER, libdecor_frame_get_xdg_surface(data->shell_surface.libdecor.frame));
|
||||
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, libdecor_frame_get_xdg_toplevel(data->shell_surface.libdecor.frame));
|
||||
}
|
||||
@@ -1802,6 +1809,12 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
zxdg_exported_v2_add_listener(data->exported, &exported_v2_listener, data);
|
||||
}
|
||||
|
||||
if (c->xdg_toplevel_icon_manager_v1 && data->xdg_toplevel_icon_v1) {
|
||||
xdg_toplevel_icon_manager_v1_set_icon(_this->internal->xdg_toplevel_icon_manager_v1,
|
||||
data->shell_surface.xdg.roleobj.toplevel,
|
||||
data->xdg_toplevel_icon_v1);
|
||||
}
|
||||
|
||||
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, data->shell_surface.xdg.roleobj.toplevel);
|
||||
}
|
||||
}
|
||||
@@ -2666,6 +2679,51 @@ void Wayland_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
}
|
||||
}
|
||||
|
||||
bool Wayland_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon)
|
||||
{
|
||||
SDL_WindowData *wind = window->internal;
|
||||
struct xdg_toplevel *toplevel = NULL;
|
||||
|
||||
if (!_this->internal->xdg_toplevel_icon_manager_v1) {
|
||||
return SDL_SetError("wayland: cannot set icon; xdg_toplevel_icon_v1 protocol not supported");
|
||||
}
|
||||
|
||||
if (icon->w != icon->h) {
|
||||
return SDL_SetError("wayland: icon width and height must be equal, got %ix%i", icon->w, icon->h);
|
||||
}
|
||||
|
||||
if (wind->xdg_toplevel_icon_v1) {
|
||||
xdg_toplevel_icon_v1_destroy(wind->xdg_toplevel_icon_v1);
|
||||
wind->xdg_toplevel_icon_v1 = NULL;
|
||||
}
|
||||
|
||||
// TODO: Add high-DPI icon support
|
||||
Wayland_ReleaseSHMBuffer(&wind->icon);
|
||||
if (Wayland_AllocSHMBuffer(icon->w, icon->h, &wind->icon) != 0) {
|
||||
return SDL_SetError("wayland: failed to allocate SHM buffer for the icon");
|
||||
}
|
||||
|
||||
SDL_PremultiplyAlpha(icon->w, icon->h, icon->format, icon->pixels, icon->pitch, SDL_PIXELFORMAT_ARGB8888, wind->icon.shm_data, icon->w * 4, SDL_TRUE);
|
||||
|
||||
wind->xdg_toplevel_icon_v1 = xdg_toplevel_icon_manager_v1_create_icon(_this->internal->xdg_toplevel_icon_manager_v1);
|
||||
xdg_toplevel_icon_v1_add_buffer(wind->xdg_toplevel_icon_v1, wind->icon.wl_buffer, 1);
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR && wind->shell_surface.libdecor.frame) {
|
||||
toplevel = libdecor_frame_get_xdg_toplevel(wind->shell_surface.libdecor.frame);
|
||||
} else
|
||||
#endif
|
||||
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL && wind->shell_surface.xdg.roleobj.toplevel) {
|
||||
toplevel = wind->shell_surface.xdg.roleobj.toplevel;
|
||||
}
|
||||
|
||||
if (toplevel) {
|
||||
xdg_toplevel_icon_manager_v1_set_icon(_this->internal->xdg_toplevel_icon_manager_v1, toplevel, wind->xdg_toplevel_icon_v1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Wayland_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *wind = window->internal;
|
||||
@@ -2803,6 +2861,12 @@ void Wayland_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
Wayland_RemoveWindowDataFromExternalList(wind);
|
||||
}
|
||||
|
||||
if (wind->xdg_toplevel_icon_v1) {
|
||||
xdg_toplevel_icon_v1_destroy(wind->xdg_toplevel_icon_v1);
|
||||
}
|
||||
|
||||
Wayland_ReleaseSHMBuffer(&wind->icon);
|
||||
|
||||
SDL_free(wind);
|
||||
WAYLAND_wl_display_flush(data->display);
|
||||
}
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "../../events/SDL_touch_c.h"
|
||||
|
||||
#include "SDL_waylandvideo.h"
|
||||
#include "SDL_waylandshmbuffer.h"
|
||||
|
||||
struct SDL_WaylandInput;
|
||||
|
||||
@@ -98,6 +99,7 @@ struct SDL_WindowData
|
||||
struct zxdg_exported_v2 *exported;
|
||||
struct xdg_dialog_v1 *xdg_dialog_v1;
|
||||
struct wp_alpha_modifier_surface_v1 *wp_alpha_modifier_surface_v1;
|
||||
struct xdg_toplevel_icon_v1 *xdg_toplevel_icon_v1;
|
||||
struct frog_color_managed_surface *frog_color_managed_surface;
|
||||
|
||||
SDL_AtomicInt swap_interval_ready;
|
||||
@@ -110,6 +112,8 @@ struct SDL_WindowData
|
||||
char *app_id;
|
||||
float windowed_scale_factor;
|
||||
|
||||
struct Wayland_SHMBuffer icon;
|
||||
|
||||
struct
|
||||
{
|
||||
float x;
|
||||
@@ -202,6 +206,7 @@ extern void Wayland_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void Wayland_ShowWindowSystemMenu(SDL_Window *window, int x, int y);
|
||||
extern void Wayland_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern bool Wayland_SuspendScreenSaver(SDL_VideoDevice *_this);
|
||||
extern bool Wayland_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon);
|
||||
|
||||
extern bool Wayland_SetWindowHitTest(SDL_Window *window, bool enabled);
|
||||
extern bool Wayland_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation);
|
||||
|
Reference in New Issue
Block a user