mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-10 04:27:45 -05:00
cursor-shape: add support for server side cursor shapes
This implements support for the new cursor-shape-v1 protocol. When available, we use it, instead of client-side cursor surfaces, to select the xcursor shape. Note that we still need to keep client side pointers, for: * backward compatibility * to be able to "hide" the cursor Closes #1379
This commit is contained in:
parent
ee794a121e
commit
c8e13ad393
8 changed files with 280 additions and 20 deletions
|
|
@ -53,6 +53,10 @@
|
|||
* Support for the new fractional-scaling-v1 Wayland protocol. This
|
||||
brings true fractional scaling to Wayland in general, and with this
|
||||
release, foot.
|
||||
* Support for the new `cursor-shape-v1` Wayland protocol, i.e. server
|
||||
side cursor shapes ([#1379][1379]).
|
||||
|
||||
[1379]: https://codeberg.org/dnkl/foot/issues/1379
|
||||
|
||||
|
||||
### Changed
|
||||
|
|
|
|||
147
cursor-shape-v1.xml
Normal file
147
cursor-shape-v1.xml
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="cursor_shape_v1">
|
||||
<copyright>
|
||||
Copyright 2018 The Chromium Authors
|
||||
Copyright 2023 Simon Ser
|
||||
|
||||
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>
|
||||
|
||||
<interface name="wp_cursor_shape_manager_v1" version="1">
|
||||
<description summary="cursor shape manager">
|
||||
This global offers an alternative, optional way to set cursor images. This
|
||||
new way uses enumerated cursors instead of a wl_surface like
|
||||
wl_pointer.set_cursor does.
|
||||
|
||||
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>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the manager">
|
||||
Destroy the cursor shape manager.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="get_pointer">
|
||||
<description summary="manage the cursor shape of a pointer device">
|
||||
Obtain a wp_cursor_shape_device_v1 for a wl_pointer object.
|
||||
</description>
|
||||
<arg name="cursor_shape_device" type="new_id" interface="wp_cursor_shape_device_v1"/>
|
||||
<arg name="pointer" type="object" interface="wl_pointer"/>
|
||||
</request>
|
||||
|
||||
<request name="get_tablet_tool_v2">
|
||||
<description summary="manage the cursor shape of a tablet tool device">
|
||||
Obtain a wp_cursor_shape_device_v1 for a zwp_tablet_tool_v2 object.
|
||||
</description>
|
||||
<arg name="cursor_shape_device" type="new_id" interface="wp_cursor_shape_device_v1"/>
|
||||
<arg name="tablet_tool" type="object" interface="zwp_tablet_tool_v2"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="wp_cursor_shape_device_v1" version="1">
|
||||
<description summary="cursor shape for a device">
|
||||
This interface advertises the list of supported cursor shapes for a
|
||||
device, and allows clients to set the cursor shape.
|
||||
</description>
|
||||
|
||||
<enum name="shape">
|
||||
<description summary="cursor shapes">
|
||||
This enum describes cursor shapes.
|
||||
|
||||
The names are taken from the CSS W3C specification:
|
||||
https://w3c.github.io/csswg-drafts/css-ui/#cursor
|
||||
</description>
|
||||
<entry name="default" value="1" summary="default cursor"/>
|
||||
<entry name="context_menu" value="2" summary="a context menu is available for the object under the cursor"/>
|
||||
<entry name="help" value="3" summary="help is available for the object under the cursor"/>
|
||||
<entry name="pointer" value="4" summary="pointer that indicates a link or another interactive element"/>
|
||||
<entry name="progress" value="5" summary="progress indicator"/>
|
||||
<entry name="wait" value="6" summary="program is busy, user should wait"/>
|
||||
<entry name="cell" value="7" summary="a cell or set of cells may be selected"/>
|
||||
<entry name="crosshair" value="8" summary="simple crosshair"/>
|
||||
<entry name="text" value="9" summary="text may be selected"/>
|
||||
<entry name="vertical_text" value="10" summary="vertical text may be selected"/>
|
||||
<entry name="alias" value="11" summary="drag-and-drop: alias of/shortcut to something is to be created"/>
|
||||
<entry name="copy" value="12" summary="drag-and-drop: something is to be copied"/>
|
||||
<entry name="move" value="13" summary="drag-and-drop: something is to be moved"/>
|
||||
<entry name="no_drop" value="14" summary="drag-and-drop: the dragged item cannot be dropped at the current cursor location"/>
|
||||
<entry name="not_allowed" value="15" summary="drag-and-drop: the requested action will not be carried out"/>
|
||||
<entry name="grab" value="16" summary="drag-and-drop: something can be grabbed"/>
|
||||
<entry name="grabbing" value="17" summary="drag-and-drop: something is being grabbed"/>
|
||||
<entry name="e_resize" value="18" summary="resizing: the east border is to be moved"/>
|
||||
<entry name="n_resize" value="19" summary="resizing: the north border is to be moved"/>
|
||||
<entry name="ne_resize" value="20" summary="resizing: the north-east corner is to be moved"/>
|
||||
<entry name="nw_resize" value="21" summary="resizing: the north-west corner is to be moved"/>
|
||||
<entry name="s_resize" value="22" summary="resizing: the south border is to be moved"/>
|
||||
<entry name="se_resize" value="23" summary="resizing: the south-east corner is to be moved"/>
|
||||
<entry name="sw_resize" value="24" summary="resizing: the south-west corner is to be moved"/>
|
||||
<entry name="w_resize" value="25" summary="resizing: the west border is to be moved"/>
|
||||
<entry name="ew_resize" value="26" summary="resizing: the east and west borders are to be moved"/>
|
||||
<entry name="ns_resize" value="27" summary="resizing: the north and south borders are to be moved"/>
|
||||
<entry name="nesw_resize" value="28" summary="resizing: the north-east and south-west corners are to be moved"/>
|
||||
<entry name="nwse_resize" value="29" summary="resizing: the north-west and south-east corners are to be moved"/>
|
||||
<entry name="col_resize" value="30" summary="resizing: that the item/column can be resized horizontally"/>
|
||||
<entry name="row_resize" value="31" summary="resizing: that the item/row can be resized vertically"/>
|
||||
<entry name="all_scroll" value="32" summary="something can be scrolled in any direction"/>
|
||||
<entry name="zoom_in" value="33" summary="something can be zoomed in"/>
|
||||
<entry name="zoom_out" value="34" summary="something can be zoomed out"/>
|
||||
</enum>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="invalid_shape" value="1"
|
||||
summary="the specified shape value is invalid"/>
|
||||
</enum>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the cursor shape device">
|
||||
Destroy the cursor shape device.
|
||||
|
||||
The device cursor shape remains unchanged.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="set_shape">
|
||||
<description summary="set device cursor to the shape">
|
||||
Sets the device cursor to the specified shape. The compositor will
|
||||
change the cursor image based on the specified shape.
|
||||
|
||||
The cursor actually changes only if the input device focus is one of
|
||||
the requesting client's surfaces. If any, the previous cursor image
|
||||
(surface or shape) is replaced.
|
||||
|
||||
The "shape" argument must be a valid enum entry, otherwise the
|
||||
invalid_shape protocol error is raised.
|
||||
|
||||
This is similar to the wl_pointer.set_cursor and
|
||||
zwp_tablet_tool_v2.set_cursor requests, but this request accepts a
|
||||
shape instead of contents in the form of a surface. Clients can mix
|
||||
set_cursor and set_shape requests.
|
||||
|
||||
The serial parameter must match the latest wl_pointer.enter or
|
||||
zwp_tablet_tool_v2.proximity_in serial number sent to the client.
|
||||
Otherwise the request will be ignored.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial number of the enter event"/>
|
||||
<arg name="shape" type="uint" enum="shape"/>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
const char *
|
||||
cursor_shape_to_string(enum cursor_shape shape)
|
||||
{
|
||||
static const char *const table[] = {
|
||||
static const char *const table[CURSOR_SHAPE_COUNT] = {
|
||||
[CURSOR_SHAPE_NONE] = NULL,
|
||||
[CURSOR_SHAPE_HIDDEN] = "hidden",
|
||||
[CURSOR_SHAPE_LEFT_PTR] = "left_ptr",
|
||||
|
|
@ -27,3 +27,26 @@ cursor_shape_to_string(enum cursor_shape shape)
|
|||
xassert(shape <= ALEN(table));
|
||||
return table[shape];
|
||||
}
|
||||
|
||||
#if defined(HAVE_CURSOR_SHAPE)
|
||||
enum wp_cursor_shape_device_v1_shape
|
||||
cursor_shape_to_server_shape(enum cursor_shape shape)
|
||||
{
|
||||
static const enum wp_cursor_shape_device_v1_shape table[CURSOR_SHAPE_COUNT] = {
|
||||
[CURSOR_SHAPE_LEFT_PTR] = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT,
|
||||
[CURSOR_SHAPE_TEXT] = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT,
|
||||
[CURSOR_SHAPE_TEXT_FALLBACK] = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT,
|
||||
[CURSOR_SHAPE_TOP_LEFT_CORNER] = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NW_RESIZE,
|
||||
[CURSOR_SHAPE_TOP_RIGHT_CORNER] = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NE_RESIZE,
|
||||
[CURSOR_SHAPE_BOTTOM_LEFT_CORNER] = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SW_RESIZE,
|
||||
[CURSOR_SHAPE_BOTTOM_RIGHT_CORNER] = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SE_RESIZE,
|
||||
[CURSOR_SHAPE_LEFT_SIDE] = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_W_RESIZE,
|
||||
[CURSOR_SHAPE_RIGHT_SIDE] = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_E_RESIZE,
|
||||
[CURSOR_SHAPE_TOP_SIDE] = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_N_RESIZE,
|
||||
[CURSOR_SHAPE_BOTTOM_SIDE] = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_S_RESIZE,
|
||||
};
|
||||
|
||||
xassert(shape <= ALEN(table));
|
||||
return table[shape];
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#if defined(HAVE_CURSOR_SHAPE)
|
||||
#include <cursor-shape-v1.h>
|
||||
#endif
|
||||
|
||||
enum cursor_shape {
|
||||
CURSOR_SHAPE_NONE,
|
||||
CURSOR_SHAPE_CUSTOM,
|
||||
|
||||
CURSOR_SHAPE_HIDDEN,
|
||||
|
||||
CURSOR_SHAPE_LEFT_PTR,
|
||||
CURSOR_SHAPE_TEXT,
|
||||
CURSOR_SHAPE_TEXT_FALLBACK,
|
||||
|
|
@ -16,6 +20,13 @@ enum cursor_shape {
|
|||
CURSOR_SHAPE_RIGHT_SIDE,
|
||||
CURSOR_SHAPE_TOP_SIDE,
|
||||
CURSOR_SHAPE_BOTTOM_SIDE,
|
||||
|
||||
CURSOR_SHAPE_COUNT,
|
||||
};
|
||||
|
||||
const char *cursor_shape_to_string(enum cursor_shape shape);
|
||||
|
||||
#if defined(HAVE_CURSOR_SHAPE)
|
||||
enum wp_cursor_shape_device_v1_shape cursor_shape_to_server_shape(
|
||||
enum cursor_shape shape);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -170,6 +170,12 @@ else
|
|||
fractional_scale = false
|
||||
endif
|
||||
|
||||
# TODO: check wayland-protocols version
|
||||
wl_proto_xml += [wayland_protocols_datadir + '/unstable/tablet/tablet-unstable-v2.xml', # required by cursor-shape-v1
|
||||
'cursor-shape-v1.xml', # TODO: use wayland-protocols
|
||||
]
|
||||
add_project_arguments('-DHAVE_CURSOR_SHAPE', language: 'c')
|
||||
|
||||
foreach prot : wl_proto_xml
|
||||
wl_proto_headers += custom_target(
|
||||
prot.underscorify() + '-client-header',
|
||||
|
|
|
|||
47
render.c
47
render.c
|
|
@ -31,6 +31,7 @@
|
|||
#include "box-drawing.h"
|
||||
#include "char32.h"
|
||||
#include "config.h"
|
||||
#include "cursor-shape.h"
|
||||
#include "grid.h"
|
||||
#include "hsl.h"
|
||||
#include "ime.h"
|
||||
|
|
@ -4259,35 +4260,46 @@ render_xcursor_update(struct seat *seat)
|
|||
if (seat->pointer.shape == CURSOR_SHAPE_HIDDEN) {
|
||||
/* Hide cursor */
|
||||
wl_surface_attach(seat->pointer.surface.surf, NULL, 0, 0);
|
||||
wl_pointer_set_cursor(
|
||||
seat->wl_pointer, seat->pointer.serial, seat->pointer.surface.surf,
|
||||
0, 0);
|
||||
wl_surface_commit(seat->pointer.surface.surf);
|
||||
return;
|
||||
}
|
||||
|
||||
xassert(seat->pointer.cursor != NULL);
|
||||
|
||||
const float scale = seat->pointer.scale;
|
||||
struct wl_cursor_image *image = seat->pointer.cursor->images[0];
|
||||
struct wl_buffer *buf = wl_cursor_image_get_buffer(image);
|
||||
#if defined(HAVE_CURSOR_SHAPE)
|
||||
if (seat->pointer.shape_device != NULL) {
|
||||
wp_cursor_shape_device_v1_set_shape(
|
||||
seat->pointer.shape_device,
|
||||
seat->pointer.serial,
|
||||
cursor_shape_to_server_shape(seat->pointer.shape));
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
const int scale = seat->pointer.scale;
|
||||
struct wl_cursor_image *image = seat->pointer.cursor->images[0];
|
||||
|
||||
wayl_surface_scale_explicit_width_height(
|
||||
seat->mouse_focus->window,
|
||||
&seat->pointer.surface, image->width, image->height, scale);
|
||||
wl_surface_attach(
|
||||
seat->pointer.surface.surf, wl_cursor_image_get_buffer(image), 0, 0);
|
||||
|
||||
wl_surface_attach(seat->pointer.surface.surf, buf, 0, 0);
|
||||
wl_pointer_set_cursor(
|
||||
seat->wl_pointer, seat->pointer.serial,
|
||||
seat->pointer.surface.surf,
|
||||
image->hotspot_x / scale, image->hotspot_y / scale);
|
||||
|
||||
wl_pointer_set_cursor(
|
||||
seat->wl_pointer, seat->pointer.serial,
|
||||
seat->pointer.surface.surf,
|
||||
image->hotspot_x / scale, image->hotspot_y / scale);
|
||||
wl_surface_damage_buffer(
|
||||
seat->pointer.surface.surf, 0, 0, INT32_MAX, INT32_MAX);
|
||||
|
||||
wl_surface_damage_buffer(
|
||||
seat->pointer.surface.surf, 0, 0, INT32_MAX, INT32_MAX);
|
||||
wl_surface_set_buffer_scale(seat->pointer.surface.surf, scale);
|
||||
|
||||
xassert(seat->pointer.xcursor_callback == NULL);
|
||||
seat->pointer.xcursor_callback = wl_surface_frame(seat->pointer.surface.surf);
|
||||
wl_callback_add_listener(seat->pointer.xcursor_callback, &xcursor_listener, seat);
|
||||
xassert(seat->pointer.xcursor_callback == NULL);
|
||||
seat->pointer.xcursor_callback = wl_surface_frame(seat->pointer.surface.surf);
|
||||
wl_callback_add_listener(seat->pointer.xcursor_callback, &xcursor_listener, seat);
|
||||
|
||||
wl_surface_commit(seat->pointer.surface.surf);
|
||||
wl_surface_commit(seat->pointer.surface.surf);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -4452,6 +4464,7 @@ render_xcursor_set(struct seat *seat, struct terminal *term, enum cursor_shape s
|
|||
if (seat->pointer.shape == shape)
|
||||
return true;
|
||||
|
||||
/* TODO: skip this when using server-side cursors */
|
||||
if (shape != CURSOR_SHAPE_HIDDEN) {
|
||||
const char *const xcursor = cursor_shape_to_string(shape);
|
||||
const char *const fallback =
|
||||
|
|
|
|||
46
wayland.c
46
wayland.c
|
|
@ -14,6 +14,10 @@
|
|||
#include <wayland-cursor.h>
|
||||
#include <xkbcommon/xkbcommon-compose.h>
|
||||
|
||||
#if defined(HAVE_CURSOR_SHAPE)
|
||||
#include <cursor-shape-v1.h>
|
||||
#endif
|
||||
|
||||
#include <tllist.h>
|
||||
|
||||
#define LOG_MODULE "wayland"
|
||||
|
|
@ -209,6 +213,11 @@ seat_destroy(struct seat *seat)
|
|||
if (seat->data_device != NULL)
|
||||
wl_data_device_release(seat->data_device);
|
||||
|
||||
#if defined(HAVE_CURSOR_SHAPE)
|
||||
if (seat->pointer.shape_device != NULL)
|
||||
wp_cursor_shape_device_v1_destroy(seat->pointer.shape_device);
|
||||
#endif
|
||||
|
||||
if (seat->wl_keyboard != NULL)
|
||||
wl_keyboard_release(seat->wl_keyboard);
|
||||
if (seat->wl_pointer != NULL)
|
||||
|
|
@ -316,9 +325,22 @@ seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
|
|||
|
||||
seat->wl_pointer = wl_seat_get_pointer(wl_seat);
|
||||
wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat);
|
||||
|
||||
#if defined(HAVE_CURSOR_SHAPE)
|
||||
if (seat->wayl->cursor_shape_manager != NULL) {
|
||||
xassert(seat->pointer.shape_device == NULL);
|
||||
seat->pointer.shape_device = wp_cursor_shape_manager_v1_get_pointer(
|
||||
seat->wayl->cursor_shape_manager, seat->wl_pointer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
if (seat->wl_pointer != NULL) {
|
||||
#if defined(HAVE_CURSOR_SHAPE)
|
||||
wp_cursor_shape_device_v1_destroy(seat->pointer.shape_device);
|
||||
seat->pointer.shape_device = NULL;
|
||||
#endif
|
||||
|
||||
wl_pointer_release(seat->wl_pointer);
|
||||
wl_surface_destroy(seat->pointer.surface.surf);
|
||||
|
||||
|
|
@ -1167,6 +1189,17 @@ handle_global(void *data, struct wl_registry *registry,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CURSOR_SHAPE)
|
||||
else if (strcmp(interface, wp_cursor_shape_manager_v1_interface.name) == 0) {
|
||||
const uint32_t required = 1;
|
||||
if (!verify_iface_version(interface, version, required))
|
||||
return;
|
||||
|
||||
wayl->cursor_shape_manager = wl_registry_bind(
|
||||
wayl->registry, name, &wp_cursor_shape_manager_v1_interface, required);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
else if (strcmp(interface, zwp_text_input_manager_v3_interface.name) == 0) {
|
||||
const uint32_t required = 1;
|
||||
|
|
@ -1401,6 +1434,15 @@ wayl_init(struct fdm *fdm, struct key_binding_manager *key_binding_manager,
|
|||
LOG_WARN("fractional scaling not available");
|
||||
}
|
||||
|
||||
#if defined(HAVE_CURSOR_SHAPE)
|
||||
if (wayl->cursor_shape_manager == NULL) {
|
||||
#else
|
||||
if (true) {
|
||||
#endif
|
||||
LOG_WARN("no server-side cursors available, "
|
||||
"falling back to client-side cursors");
|
||||
}
|
||||
|
||||
if (presentation_timings && wayl->presentation == NULL) {
|
||||
LOG_ERR("presentation time interface not implemented by compositor");
|
||||
goto out;
|
||||
|
|
@ -1495,6 +1537,10 @@ wayl_destroy(struct wayland *wayl)
|
|||
if (wayl->viewporter != NULL)
|
||||
wp_viewporter_destroy(wayl->viewporter);
|
||||
#endif
|
||||
#if defined(HAVE_CURSOR_SHAPE)
|
||||
if (wayl->cursor_shape_manager != NULL)
|
||||
wp_cursor_shape_manager_v1_destroy(wayl->cursor_shape_manager);
|
||||
#endif
|
||||
#if defined(HAVE_XDG_ACTIVATION)
|
||||
if (wayl->xdg_activation != NULL)
|
||||
xdg_activation_v1_destroy(wayl->xdg_activation);
|
||||
|
|
|
|||
12
wayland.h
12
wayland.h
|
|
@ -146,12 +146,18 @@ struct seat {
|
|||
struct {
|
||||
uint32_t serial;
|
||||
|
||||
/* Client-side cursor */
|
||||
struct wayl_surface surface;
|
||||
struct wl_cursor_theme *theme;
|
||||
struct wl_cursor *cursor;
|
||||
|
||||
/* Server-side cursor */
|
||||
#if defined(HAVE_CURSOR_SHAPE)
|
||||
struct wp_cursor_shape_device_v1 *shape_device;
|
||||
#endif
|
||||
|
||||
float scale;
|
||||
bool hidden;
|
||||
|
||||
enum cursor_shape shape;
|
||||
struct wl_callback *xcursor_callback;
|
||||
bool xcursor_pending;
|
||||
|
|
@ -426,6 +432,10 @@ struct wayland {
|
|||
struct xdg_activation_v1 *xdg_activation;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CURSOR_SHAPE)
|
||||
struct wp_cursor_shape_manager_v1 *cursor_shape_manager;
|
||||
#endif
|
||||
|
||||
bool presentation_timings;
|
||||
struct wp_presentation *presentation;
|
||||
uint32_t presentation_clock_id;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue