
Look up the MetaWaylandTabletTool from the correct wl_resource. Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/4004 Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4367>
289 lines
11 KiB
C
289 lines
11 KiB
C
/*
|
|
* Copyright 2024 Red Hat, Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "wayland/meta-wayland-cursor-shape.h"
|
|
|
|
#include "core/window-private.h"
|
|
#include "wayland/meta-wayland-private.h"
|
|
#include "wayland/meta-wayland-xdg-shell.h"
|
|
#include "wayland/meta-wayland-versions.h"
|
|
|
|
#include "cursor-shape-v1-server-protocol.h"
|
|
|
|
typedef enum _MetaWaylandCursorShapeDeviceType
|
|
{
|
|
META_WAYLAND_CURSOR_SHAPE_DEVICE_TYPE_POINTER,
|
|
META_WAYLAND_CURSOR_SHAPE_DEVICE_TYPE_TOOL,
|
|
} MetaWaylandCursorShapeDeviceType;
|
|
|
|
typedef struct _MetaWaylandCursorShapeDevice
|
|
{
|
|
MetaWaylandCursorShapeDeviceType type;
|
|
union {
|
|
MetaWaylandPointer *pointer;
|
|
MetaWaylandTabletTool *tool;
|
|
};
|
|
} MetaWaylandCursorShapeDevice;
|
|
|
|
static const MetaCursor
|
|
shape_map[] = {
|
|
/* version 1 */
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT] = META_CURSOR_DEFAULT,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CONTEXT_MENU] = META_CURSOR_CONTEXT_MENU,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_HELP] = META_CURSOR_HELP,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER] = META_CURSOR_POINTER,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_PROGRESS] = META_CURSOR_PROGRESS,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_WAIT] = META_CURSOR_WAIT,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CELL] = META_CURSOR_CELL,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CROSSHAIR] = META_CURSOR_CROSSHAIR,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT] = META_CURSOR_TEXT,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_VERTICAL_TEXT] = META_CURSOR_VERTICAL_TEXT,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALIAS] = META_CURSOR_ALIAS,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_COPY] = META_CURSOR_COPY,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_MOVE] = META_CURSOR_MOVE,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NO_DROP] = META_CURSOR_NO_DROP,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NOT_ALLOWED] = META_CURSOR_NOT_ALLOWED,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRAB] = META_CURSOR_GRAB,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRABBING] = META_CURSOR_GRABBING,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_E_RESIZE] = META_CURSOR_E_RESIZE,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_N_RESIZE] = META_CURSOR_N_RESIZE,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NE_RESIZE] = META_CURSOR_NE_RESIZE,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NW_RESIZE] = META_CURSOR_NW_RESIZE,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_S_RESIZE] = META_CURSOR_S_RESIZE,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SE_RESIZE] = META_CURSOR_SE_RESIZE,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SW_RESIZE] = META_CURSOR_SW_RESIZE,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_W_RESIZE] = META_CURSOR_W_RESIZE,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_EW_RESIZE] = META_CURSOR_EW_RESIZE,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NS_RESIZE] = META_CURSOR_NS_RESIZE,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NESW_RESIZE] = META_CURSOR_NESW_RESIZE,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NWSE_RESIZE] = META_CURSOR_NWSE_RESIZE,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_COL_RESIZE] = META_CURSOR_COL_RESIZE,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ROW_RESIZE] = META_CURSOR_ROW_RESIZE,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_SCROLL] = META_CURSOR_ALL_SCROLL,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ZOOM_IN] = META_CURSOR_ZOOM_IN,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ZOOM_OUT] = META_CURSOR_ZOOM_OUT,
|
|
/* version 2 */
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DND_ASK] = META_CURSOR_DND_ASK,
|
|
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_RESIZE] = META_CURSOR_ALL_RESIZE,
|
|
};
|
|
|
|
static MetaCursor
|
|
cursor_from_shape (enum wp_cursor_shape_device_v1_shape shape,
|
|
int version)
|
|
{
|
|
if (shape < WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT)
|
|
return META_CURSOR_INVALID;
|
|
|
|
if (version <= 1 && shape > WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ZOOM_OUT)
|
|
return META_CURSOR_INVALID;
|
|
|
|
if (shape >= G_N_ELEMENTS (shape_map))
|
|
return META_CURSOR_INVALID;
|
|
|
|
return shape_map[shape];
|
|
}
|
|
|
|
static MetaWaylandCursorShapeDevice *
|
|
meta_wayland_cursor_shape_device_new_pointer (MetaWaylandPointer *pointer)
|
|
{
|
|
MetaWaylandCursorShapeDevice *cursor_shape_device =
|
|
g_new0 (MetaWaylandCursorShapeDevice, 1);
|
|
|
|
cursor_shape_device->type = META_WAYLAND_CURSOR_SHAPE_DEVICE_TYPE_POINTER;
|
|
cursor_shape_device->pointer = pointer;
|
|
g_object_add_weak_pointer (G_OBJECT (pointer),
|
|
(gpointer *) &cursor_shape_device->pointer);
|
|
|
|
return cursor_shape_device;
|
|
}
|
|
|
|
|
|
static MetaWaylandCursorShapeDevice *
|
|
meta_wayland_cursor_shape_device_new_tool (MetaWaylandTabletTool *tool)
|
|
{
|
|
MetaWaylandCursorShapeDevice *cursor_shape_device =
|
|
g_new0 (MetaWaylandCursorShapeDevice, 1);
|
|
|
|
cursor_shape_device->type = META_WAYLAND_CURSOR_SHAPE_DEVICE_TYPE_TOOL;
|
|
cursor_shape_device->tool = tool;
|
|
|
|
return cursor_shape_device;
|
|
}
|
|
|
|
static void
|
|
meta_wayland_cursor_shape_device_free (MetaWaylandCursorShapeDevice *cursor_shape_device)
|
|
{
|
|
if (cursor_shape_device->type == META_WAYLAND_CURSOR_SHAPE_DEVICE_TYPE_POINTER)
|
|
g_clear_weak_pointer ((gpointer *) &cursor_shape_device->pointer);
|
|
|
|
g_free (cursor_shape_device);
|
|
}
|
|
|
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaWaylandCursorShapeDevice,
|
|
meta_wayland_cursor_shape_device_free)
|
|
|
|
static void
|
|
cursor_shape_device_destructor (struct wl_resource *resource)
|
|
{
|
|
MetaWaylandCursorShapeDevice *cursor_shape_device =
|
|
wl_resource_get_user_data (resource);
|
|
|
|
meta_wayland_cursor_shape_device_free (cursor_shape_device);
|
|
}
|
|
|
|
static void
|
|
cursor_shape_device_destroy (struct wl_client *client,
|
|
struct wl_resource *resource)
|
|
{
|
|
wl_resource_destroy (resource);
|
|
}
|
|
|
|
static void
|
|
cursor_shape_device_set_shape (struct wl_client *client,
|
|
struct wl_resource *resource,
|
|
uint32_t serial,
|
|
enum wp_cursor_shape_device_v1_shape shape)
|
|
{
|
|
MetaWaylandCursorShapeDevice *cursor_shape_device =
|
|
wl_resource_get_user_data (resource);
|
|
MetaCursor cursor = cursor_from_shape (shape,
|
|
wl_resource_get_version (resource));
|
|
|
|
if (cursor == META_CURSOR_INVALID)
|
|
{
|
|
wl_resource_post_error (resource,
|
|
WP_CURSOR_SHAPE_DEVICE_V1_ERROR_INVALID_SHAPE,
|
|
"wp_cursor_shape_device_v1@%d: "
|
|
"the specified shape value is invalid",
|
|
wl_resource_get_id (resource));
|
|
return;
|
|
}
|
|
|
|
if (cursor_shape_device->type == META_WAYLAND_CURSOR_SHAPE_DEVICE_TYPE_POINTER &&
|
|
cursor_shape_device->pointer)
|
|
{
|
|
MetaWaylandPointer *pointer = cursor_shape_device->pointer;
|
|
|
|
if (!meta_wayland_pointer_check_focus_serial (pointer, client, serial))
|
|
return;
|
|
|
|
meta_wayland_pointer_set_cursor_shape (pointer, cursor);
|
|
}
|
|
|
|
if (cursor_shape_device->type == META_WAYLAND_CURSOR_SHAPE_DEVICE_TYPE_TOOL &&
|
|
cursor_shape_device->tool)
|
|
{
|
|
MetaWaylandTabletTool *tool = cursor_shape_device->tool;
|
|
|
|
if (!meta_wayland_tablet_tool_check_focus_serial (tool, client, serial))
|
|
return;
|
|
|
|
meta_wayland_tablet_tool_set_cursor_shape (tool, cursor);
|
|
}
|
|
}
|
|
|
|
static const struct wp_cursor_shape_device_v1_interface cursor_shape_device_interface = {
|
|
cursor_shape_device_destroy,
|
|
cursor_shape_device_set_shape,
|
|
};
|
|
|
|
static void
|
|
cursor_manager_destroy (struct wl_client *client,
|
|
struct wl_resource *resource)
|
|
{
|
|
wl_resource_destroy (resource);
|
|
}
|
|
|
|
static void
|
|
cursor_manager_get_pointer (struct wl_client *client,
|
|
struct wl_resource *resource,
|
|
uint32_t id,
|
|
struct wl_resource *pointer_resource)
|
|
{
|
|
MetaWaylandPointer *pointer = wl_resource_get_user_data (pointer_resource);
|
|
g_autoptr (MetaWaylandCursorShapeDevice) cursor_shape_device = NULL;
|
|
struct wl_resource *shape_device_resource;
|
|
|
|
cursor_shape_device = meta_wayland_cursor_shape_device_new_pointer (pointer);
|
|
|
|
shape_device_resource =
|
|
wl_resource_create (client,
|
|
&wp_cursor_shape_device_v1_interface,
|
|
wl_resource_get_version (resource),
|
|
id);
|
|
wl_resource_set_implementation (shape_device_resource,
|
|
&cursor_shape_device_interface,
|
|
g_steal_pointer (&cursor_shape_device),
|
|
cursor_shape_device_destructor);
|
|
}
|
|
|
|
static void
|
|
cursor_manager_get_tablet_tool_v2 (struct wl_client *client,
|
|
struct wl_resource *resource,
|
|
uint32_t id,
|
|
struct wl_resource *tool_resource)
|
|
{
|
|
MetaWaylandTabletTool *tool = wl_resource_get_user_data (tool_resource);
|
|
g_autoptr (MetaWaylandCursorShapeDevice) cursor_shape_device = NULL;
|
|
struct wl_resource *shape_device_resource;
|
|
|
|
cursor_shape_device = meta_wayland_cursor_shape_device_new_tool (tool);
|
|
|
|
shape_device_resource =
|
|
wl_resource_create (client,
|
|
&wp_cursor_shape_device_v1_interface,
|
|
wl_resource_get_version (resource),
|
|
id);
|
|
wl_resource_set_implementation (shape_device_resource,
|
|
&cursor_shape_device_interface,
|
|
g_steal_pointer (&cursor_shape_device),
|
|
cursor_shape_device_destructor);
|
|
}
|
|
|
|
static const struct wp_cursor_shape_manager_v1_interface cursor_shape_manager_interface = {
|
|
cursor_manager_destroy,
|
|
cursor_manager_get_pointer,
|
|
cursor_manager_get_tablet_tool_v2,
|
|
};
|
|
|
|
static void
|
|
bind_cursor_shape (struct wl_client *client,
|
|
void *data,
|
|
uint32_t version,
|
|
uint32_t id)
|
|
{
|
|
struct wl_resource *resource;
|
|
|
|
resource = wl_resource_create (client, &wp_cursor_shape_manager_v1_interface,
|
|
version, id);
|
|
wl_resource_set_implementation (resource, &cursor_shape_manager_interface,
|
|
NULL, NULL);
|
|
}
|
|
|
|
void
|
|
meta_wayland_init_cursor_shape (MetaWaylandCompositor *compositor)
|
|
{
|
|
if (wl_global_create (compositor->wayland_display,
|
|
&wp_cursor_shape_manager_v1_interface,
|
|
META_WP_CURSOR_SHAPE_VERSION,
|
|
NULL, bind_cursor_shape) == NULL)
|
|
g_error ("Failed to register a global cursor-shape object");
|
|
}
|