[Wayland]: Add support for xdg-toplevel-icon-v1
This commit is contained in:
parent
7cffc6bb60
commit
6c7b648570
|
@ -241,6 +241,8 @@ gfx/common/wayland/content-type-v1.h
|
|||
gfx/common/wayland/content-type-v1.c
|
||||
gfx/common/wayland/single-pixel-buffer-v1.h
|
||||
gfx/common/wayland/single-pixel-buffer-v1.c
|
||||
gfx/common/wayland/xdg-toplevel-icon-v1.h
|
||||
gfx/common/wayland/xdg-toplevel-icon-v1.c
|
||||
|
||||
# libretro-common samples
|
||||
libretro-common/samples/streams/rzip/rzip
|
||||
|
|
|
@ -1284,6 +1284,7 @@ ifeq ($(HAVE_WAYLAND), 1)
|
|||
gfx/common/wayland_common.o \
|
||||
gfx/common/wayland/fractional-scale-v1.o \
|
||||
gfx/common/wayland/viewporter.o \
|
||||
gfx/common/wayland/xdg-toplevel-icon-v1.o \
|
||||
gfx/common/wayland/xdg-shell.o \
|
||||
gfx/common/wayland/idle-inhibit-unstable-v1.o \
|
||||
gfx/common/wayland/xdg-decoration-unstable-v1.o \
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
xdg_toplevel_icon protocol
|
||||
|
||||
Maintainers:
|
||||
Matthias Klumpp <matthias@tenstral.net> (@mak)
|
|
@ -0,0 +1,205 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="xdg_toplevel_icon_v1">
|
||||
|
||||
<copyright>
|
||||
Copyright © 2023-2024 Matthias Klumpp
|
||||
Copyright © 2024 David Edmundson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<description summary="protocol to assign icons to toplevels">
|
||||
This protocol allows clients to set icons for their toplevel surfaces
|
||||
either via the XDG icon stock (using an icon name), or from pixel data.
|
||||
|
||||
A toplevel icon represents the individual toplevel (unlike the application
|
||||
or launcher icon, which represents the application as a whole), and may be
|
||||
shown in window switchers, window overviews and taskbars that list
|
||||
individual windows.
|
||||
|
||||
This document adheres to RFC 2119 when using words like "must",
|
||||
"should", "may", etc.
|
||||
|
||||
Warning! The protocol described in this file is currently in the testing
|
||||
phase. Backward compatible changes may be added together with the
|
||||
corresponding interface version bump. Backward incompatible changes can
|
||||
only be done by creating a new major version of the extension.
|
||||
</description>
|
||||
|
||||
<interface name="xdg_toplevel_icon_manager_v1" version="1">
|
||||
<description summary="interface to manage toplevel icons">
|
||||
This interface allows clients to create toplevel window icons and set
|
||||
them on toplevel windows to be displayed to the user.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the toplevel icon manager">
|
||||
Destroy the toplevel icon manager.
|
||||
This does not destroy objects created with the manager.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="create_icon">
|
||||
<description summary="create a new icon instance">
|
||||
Creates a new icon object. This icon can then be attached to a
|
||||
xdg_toplevel via the 'set_icon' request.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="xdg_toplevel_icon_v1"/>
|
||||
</request>
|
||||
|
||||
<request name="set_icon">
|
||||
<description summary="set an icon on a toplevel window">
|
||||
This request assigns the icon 'icon' to 'toplevel', or clears the
|
||||
toplevel icon if 'icon' was null.
|
||||
This state is double-buffered and is applied on the next
|
||||
wl_surface.commit of the toplevel.
|
||||
|
||||
After making this call, the xdg_toplevel_icon_v1 provided as 'icon'
|
||||
can be destroyed by the client without 'toplevel' losing its icon.
|
||||
The xdg_toplevel_icon_v1 is immutable from this point, and any
|
||||
future attempts to change it must raise the
|
||||
'xdg_toplevel_icon_v1.immutable' protocol error.
|
||||
|
||||
The compositor must set the toplevel icon from either the pixel data
|
||||
the icon provides, or by loading a stock icon using the icon name.
|
||||
See the description of 'xdg_toplevel_icon_v1' for details.
|
||||
|
||||
If 'icon' is set to null, the icon of the respective toplevel is reset
|
||||
to its default icon (usually the icon of the application, derived from
|
||||
its desktop-entry file, or a placeholder icon).
|
||||
If this request is passed an icon with no pixel buffers or icon name
|
||||
assigned, the icon must be reset just like if 'icon' was null.
|
||||
</description>
|
||||
<arg name="toplevel" type="object" interface="xdg_toplevel" summary="the toplevel to act on"/>
|
||||
<arg name="icon" type="object" interface="xdg_toplevel_icon_v1" allow-null="true"/>
|
||||
</request>
|
||||
|
||||
<event name="icon_size">
|
||||
<description summary="describes a supported & preferred icon size">
|
||||
This event indicates an icon size the compositor prefers to be
|
||||
available if the client has scalable icons and can render to any size.
|
||||
|
||||
When the 'xdg_toplevel_icon_manager_v1' object is created, the
|
||||
compositor may send one or more 'icon_size' events to describe the list
|
||||
of preferred icon sizes. If the compositor has no size preference, it
|
||||
may not send any 'icon_size' event, and it is up to the client to
|
||||
decide a suitable icon size.
|
||||
|
||||
A sequence of 'icon_size' events must be finished with a 'done' event.
|
||||
If the compositor has no size preferences, it must still send the
|
||||
'done' event, without any preceding 'icon_size' events.
|
||||
</description>
|
||||
<arg name="size" type="int"
|
||||
summary="the edge size of the square icon in surface-local coordinates, e.g. 64"/>
|
||||
</event>
|
||||
|
||||
<event name="done">
|
||||
<description summary="all information has been sent">
|
||||
This event is sent after all 'icon_size' events have been sent.
|
||||
</description>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="xdg_toplevel_icon_v1" version="1">
|
||||
<description summary="a toplevel window icon">
|
||||
This interface defines a toplevel icon.
|
||||
An icon can have a name, and multiple buffers.
|
||||
In order to be applied, the icon must have either a name, or at least
|
||||
one buffer assigned. Applying an empty icon (with no buffer or name) to
|
||||
a toplevel should reset its icon to the default icon.
|
||||
|
||||
It is up to compositor policy whether to prefer using a buffer or loading
|
||||
an icon via its name. See 'set_name' and 'add_buffer' for details.
|
||||
</description>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="invalid_buffer"
|
||||
summary="the provided buffer does not satisfy requirements"
|
||||
value="1"/>
|
||||
<entry name="immutable"
|
||||
summary="the icon has already been assigned to a toplevel and must not be changed"
|
||||
value="2"/>
|
||||
<entry name="no_buffer"
|
||||
summary="the provided buffer has been destroyed before the toplevel icon"
|
||||
value="3"/>
|
||||
</enum>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the icon object">
|
||||
Destroys the 'xdg_toplevel_icon_v1' object.
|
||||
The icon must still remain set on every toplevel it was assigned to,
|
||||
until the toplevel icon is reset explicitly.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="set_name">
|
||||
<description summary="set an icon name">
|
||||
This request assigns an icon name to this icon.
|
||||
Any previously set name is overridden.
|
||||
|
||||
The compositor must resolve 'icon_name' according to the lookup rules
|
||||
described in the XDG icon theme specification[1] using the
|
||||
environment's current icon theme.
|
||||
|
||||
If the compositor does not support icon names or cannot resolve
|
||||
'icon_name' according to the XDG icon theme specification it must
|
||||
fall back to using pixel buffer data instead.
|
||||
|
||||
If this request is made after the icon has been assigned to a toplevel
|
||||
via 'set_icon', a 'immutable' error must be raised.
|
||||
|
||||
[1]: https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html
|
||||
</description>
|
||||
<arg name="icon_name" type="string"/>
|
||||
</request>
|
||||
|
||||
<request name="add_buffer">
|
||||
<description summary="add icon data from a pixel buffer">
|
||||
This request adds pixel data supplied as wl_buffer to the icon.
|
||||
|
||||
The client should add pixel data for all icon sizes and scales that
|
||||
it can provide, or which are explicitly requested by the compositor
|
||||
via 'icon_size' events on xdg_toplevel_icon_manager_v1.
|
||||
|
||||
The wl_buffer supplying pixel data as 'buffer' must be backed by wl_shm
|
||||
and must be a square (width and height being equal).
|
||||
If any of these buffer requirements are not fulfilled, a 'invalid_buffer'
|
||||
error must be raised.
|
||||
|
||||
If this icon instance already has a buffer of the same size and scale
|
||||
from a previous 'add_buffer' request, data from the last request
|
||||
overrides the preexisting pixel data.
|
||||
|
||||
The wl_buffer must be kept alive for as long as the xdg_toplevel_icon
|
||||
it is associated with is not destroyed, otherwise a 'no_buffer' error
|
||||
is raised. The buffer contents must not be modified after it was
|
||||
assigned to the icon. As a result, the region of the wl_shm_pool's
|
||||
backing storage used for the wl_buffer must not be modified after this
|
||||
request is sent. The wl_buffer.release event is unused.
|
||||
|
||||
If this request is made after the icon has been assigned to a toplevel
|
||||
via 'set_icon', a 'immutable' error must be raised.
|
||||
</description>
|
||||
<arg name="buffer" type="object" interface="wl_buffer"/>
|
||||
<arg name="scale" type="int"
|
||||
summary="the scaling factor of the icon, e.g. 1"/>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
|
@ -73,3 +73,4 @@ generate_source 'staging/cursor-shape' 'cursor-shape-v1'
|
|||
generate_source 'unstable/tablet' 'tablet-unstable-v2'
|
||||
generate_source 'staging/content-type' 'content-type-v1'
|
||||
generate_source 'staging/single-pixel-buffer' 'single-pixel-buffer-v1'
|
||||
generate_source 'staging/xdg-toplevel-icon' 'xdg-toplevel-icon-v1'
|
||||
|
|
|
@ -295,6 +295,10 @@ void gfx_ctx_wl_destroy_resources_common(gfx_ctx_wayland_data_t *wl)
|
|||
zxdg_toplevel_decoration_v1_destroy(wl->deco);
|
||||
if (wl->xdg_toplevel)
|
||||
xdg_toplevel_destroy(wl->xdg_toplevel);
|
||||
if (wl->xdg_toplevel_icon_manager)
|
||||
xdg_toplevel_icon_manager_v1_destroy(wl->xdg_toplevel_icon_manager);
|
||||
if (wl->xdg_toplevel_icon)
|
||||
xdg_toplevel_icon_v1_destroy(wl->xdg_toplevel_icon);
|
||||
if (wl->xdg_surface)
|
||||
xdg_surface_destroy(wl->xdg_surface);
|
||||
if (wl->surface)
|
||||
|
@ -363,30 +367,32 @@ void gfx_ctx_wl_destroy_resources_common(gfx_ctx_wayland_data_t *wl)
|
|||
wl_display_disconnect(wl->input.dpy);
|
||||
}
|
||||
|
||||
wl->input.dpy = NULL;
|
||||
wl->registry = NULL;
|
||||
wl->compositor = NULL;
|
||||
wl->shm = NULL;
|
||||
wl->data_device_manager = NULL;
|
||||
wl->xdg_shell = NULL;
|
||||
wl->seat = NULL;
|
||||
wl->relative_pointer_manager = NULL;
|
||||
wl->pointer_constraints = NULL;
|
||||
wl->content_type = NULL;
|
||||
wl->content_type_manager = NULL;
|
||||
wl->cursor_shape_manager = NULL;
|
||||
wl->cursor_shape_device = NULL;
|
||||
wl->idle_inhibit_manager = NULL;
|
||||
wl->deco_manager = NULL;
|
||||
wl->single_pixel_manager = NULL;
|
||||
wl->surface = NULL;
|
||||
wl->xdg_surface = NULL;
|
||||
wl->xdg_toplevel = NULL;
|
||||
wl->deco = NULL;
|
||||
wl->idle_inhibitor = NULL;
|
||||
wl->wl_touch = NULL;
|
||||
wl->wl_pointer = NULL;
|
||||
wl->wl_keyboard = NULL;
|
||||
wl->input.dpy = NULL;
|
||||
wl->registry = NULL;
|
||||
wl->compositor = NULL;
|
||||
wl->shm = NULL;
|
||||
wl->data_device_manager = NULL;
|
||||
wl->xdg_shell = NULL;
|
||||
wl->seat = NULL;
|
||||
wl->relative_pointer_manager = NULL;
|
||||
wl->pointer_constraints = NULL;
|
||||
wl->content_type = NULL;
|
||||
wl->content_type_manager = NULL;
|
||||
wl->cursor_shape_manager = NULL;
|
||||
wl->cursor_shape_device = NULL;
|
||||
wl->idle_inhibit_manager = NULL;
|
||||
wl->deco_manager = NULL;
|
||||
wl->single_pixel_manager = NULL;
|
||||
wl->surface = NULL;
|
||||
wl->xdg_surface = NULL;
|
||||
wl->xdg_toplevel = NULL;
|
||||
wl->xdg_toplevel_icon = NULL;
|
||||
wl->xdg_toplevel_icon_manager = NULL;
|
||||
wl->deco = NULL;
|
||||
wl->idle_inhibitor = NULL;
|
||||
wl->wl_touch = NULL;
|
||||
wl->wl_pointer = NULL;
|
||||
wl->wl_keyboard = NULL;
|
||||
|
||||
wl->width = 0;
|
||||
wl->height = 0;
|
||||
|
@ -586,6 +592,29 @@ static void shm_buffer_paint_icon(
|
|||
}
|
||||
}
|
||||
|
||||
static bool wl_create_toplevel_icon(gfx_ctx_wayland_data_t *wl)
|
||||
{
|
||||
wl->xdg_toplevel_icon = xdg_toplevel_icon_manager_v1_create_icon(
|
||||
wl->xdg_toplevel_icon_manager);
|
||||
xdg_toplevel_icon_v1_set_name(wl->xdg_toplevel_icon, WAYLAND_APP_ID);
|
||||
|
||||
const int icon_size = wl->buffer_scale > 1 ? 128 : 64;
|
||||
shm_buffer_t *icon_buffer = create_shm_buffer(wl,
|
||||
icon_size, icon_size, WL_SHM_FORMAT_ARGB8888);
|
||||
|
||||
if (icon_buffer)
|
||||
{
|
||||
shm_buffer_paint_icon(icon_buffer, icon_size, icon_size, 1, icon_size / 16);
|
||||
xdg_toplevel_icon_v1_add_buffer(
|
||||
wl->xdg_toplevel_icon, icon_buffer->wl_buffer, 1);
|
||||
}
|
||||
|
||||
xdg_toplevel_icon_manager_v1_set_icon(
|
||||
wl->xdg_toplevel_icon_manager, wl->xdg_toplevel, wl->xdg_toplevel_icon);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void shm_buffer_paint_checkerboard(
|
||||
shm_buffer_t *buffer,
|
||||
int width, int height, int scale,
|
||||
|
@ -778,6 +807,11 @@ bool gfx_ctx_wl_init_common(
|
|||
RARCH_LOG("[Wayland]: Compositor doesn't support the %s protocol!\n", wp_single_pixel_buffer_manager_v1_interface.name);
|
||||
}
|
||||
|
||||
if (!wl->xdg_toplevel_icon_manager)
|
||||
{
|
||||
RARCH_LOG("[Wayland]: Compositor doesn't support the %s protocol!\n", xdg_toplevel_icon_manager_v1_interface.name);
|
||||
}
|
||||
|
||||
wl->surface = wl_compositor_create_surface(wl->compositor);
|
||||
if (wl->viewporter)
|
||||
wl->viewport = wp_viewporter_get_viewport(wl->viewporter, wl->surface);
|
||||
|
@ -842,6 +876,9 @@ bool gfx_ctx_wl_init_common(
|
|||
wl->deco = zxdg_decoration_manager_v1_get_toplevel_decoration(
|
||||
wl->deco_manager, wl->xdg_toplevel);
|
||||
|
||||
if (wl->xdg_toplevel_icon_manager)
|
||||
wl_create_toplevel_icon(wl);
|
||||
|
||||
/* Waiting for xdg_toplevel to be configured before starting to draw */
|
||||
wl_surface_commit(wl->surface);
|
||||
wl->configured = true;
|
||||
|
|
|
@ -806,6 +806,10 @@ static void wl_registry_handle_global(void *data, struct wl_registry *reg,
|
|||
wl->single_pixel_manager = (struct wp_single_pixel_buffer_manager_v1*)
|
||||
wl_registry_bind(
|
||||
reg, id, &wp_single_pixel_buffer_manager_v1_interface, MIN(version, 1));
|
||||
else if (string_is_equal(interface, xdg_toplevel_icon_manager_v1_interface.name) && found++)
|
||||
wl->xdg_toplevel_icon_manager = (struct xdg_toplevel_icon_manager_v1*)
|
||||
wl_registry_bind(
|
||||
reg, id, &xdg_toplevel_icon_manager_v1_interface, MIN(version, 1));
|
||||
|
||||
if (found > 1)
|
||||
RARCH_LOG("[Wayland]: Registered interface %s at version %u\n",
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "../../gfx/common/wayland/viewporter.h"
|
||||
#include "../../gfx/common/wayland/xdg-decoration-unstable-v1.h"
|
||||
#include "../../gfx/common/wayland/xdg-shell.h"
|
||||
#include "../../gfx/common/wayland/xdg-toplevel-icon-v1.h"
|
||||
|
||||
#define FRACTIONAL_SCALE_V1_DEN 120
|
||||
#define FRACTIONAL_SCALE_MULT(v, scale_num) \
|
||||
|
@ -159,6 +160,8 @@ typedef struct gfx_ctx_wayland_data
|
|||
struct wp_fractional_scale_v1 *fractional_scale;
|
||||
struct xdg_wm_base *xdg_shell;
|
||||
struct xdg_toplevel *xdg_toplevel;
|
||||
struct xdg_toplevel_icon_v1 *xdg_toplevel_icon;
|
||||
struct xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager;
|
||||
struct wl_keyboard *wl_keyboard;
|
||||
struct wl_pointer *wl_pointer;
|
||||
struct zwp_relative_pointer_v1 *wl_relative_pointer;
|
||||
|
|
Loading…
Reference in New Issue