mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-10-26 12:27:44 +00:00
wayland: Clean up gesture support
The gesture capability is tied to the pointer capability, not touch, and may not always be exposed by the compositor.
This commit is contained in:
@@ -46,6 +46,8 @@
|
||||
#include "primary-selection-unstable-v1-client-protocol.h"
|
||||
#include "input-timestamps-unstable-v1-client-protocol.h"
|
||||
#include "pointer-gestures-unstable-v1-client-protocol.h"
|
||||
#include "cursor-shape-v1-client-protocol.h"
|
||||
#include "viewporter-client-protocol.h"
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
#include <libdecor.h>
|
||||
@@ -67,8 +69,6 @@
|
||||
#include <unistd.h>
|
||||
#include <xkbcommon/xkbcommon-compose.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include "cursor-shape-v1-client-protocol.h"
|
||||
#include "viewporter-client-protocol.h"
|
||||
|
||||
// Weston uses a ratio of 10 units per scroll tick
|
||||
#define WAYLAND_WHEEL_AXIS_UNIT 10
|
||||
@@ -289,6 +289,71 @@ void Wayland_DisplayInitInputTimestampManager(SDL_VideoData *display)
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_pinch_begin(void *data, struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, struct wl_surface *surface, uint32_t fingers)
|
||||
{
|
||||
if (!surface) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_WindowData *wind = Wayland_GetWindowDataForOwnedSurface(surface);
|
||||
if (wind) {
|
||||
SDL_WaylandSeat *seat = (SDL_WaylandSeat *)data;
|
||||
seat->pointer.gesture_focus = wind;
|
||||
|
||||
const Uint64 timestamp = Wayland_GetPointerTimestamp(seat, time);
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_BEGIN, timestamp, wind->sdlwindow, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_pinch_update(void *data, struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, uint32_t time,
|
||||
wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t scale, wl_fixed_t rotation)
|
||||
{
|
||||
SDL_WaylandSeat *seat = (SDL_WaylandSeat *)data;
|
||||
|
||||
if (seat->pointer.gesture_focus) {
|
||||
const Uint64 timestamp = Wayland_GetPointerTimestamp(seat, time);
|
||||
const float s = (float)wl_fixed_to_double(scale);
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_UPDATE, timestamp, seat->pointer.gesture_focus->sdlwindow, s);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_pinch_end(void *data, struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, int32_t cancelled)
|
||||
{
|
||||
SDL_WaylandSeat *seat = (SDL_WaylandSeat *)data;
|
||||
|
||||
if (seat->pointer.gesture_focus) {
|
||||
const Uint64 timestamp = Wayland_GetPointerTimestamp(seat, time);
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_END, timestamp, seat->pointer.gesture_focus->sdlwindow, 0.0f);
|
||||
|
||||
seat->pointer.gesture_focus = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct zwp_pointer_gesture_pinch_v1_listener gesture_pinch_listener = {
|
||||
handle_pinch_begin,
|
||||
handle_pinch_update,
|
||||
handle_pinch_end
|
||||
};
|
||||
|
||||
static void Wayland_SeatCreatePointerGestures(SDL_WaylandSeat *seat)
|
||||
{
|
||||
if (seat->display->zwp_pointer_gestures) {
|
||||
if (seat->pointer.wl_pointer && !seat->pointer.gesture_pinch) {
|
||||
seat->pointer.gesture_pinch = zwp_pointer_gestures_v1_get_pinch_gesture(seat->display->zwp_pointer_gestures, seat->pointer.wl_pointer);
|
||||
zwp_pointer_gesture_pinch_v1_set_user_data(seat->pointer.gesture_pinch, seat);
|
||||
zwp_pointer_gesture_pinch_v1_add_listener(seat->pointer.gesture_pinch, &gesture_pinch_listener, seat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Wayland_DisplayInitPointerGestureManager(SDL_VideoData *display)
|
||||
{
|
||||
SDL_WaylandSeat *seat;
|
||||
wl_list_for_each (seat, &display->seat_list, link) {
|
||||
Wayland_SeatCreatePointerGestures(seat);
|
||||
}
|
||||
}
|
||||
|
||||
static void Wayland_SeatCreateCursorShape(SDL_WaylandSeat *seat)
|
||||
{
|
||||
if (seat->display->cursor_shape_manager) {
|
||||
@@ -1417,43 +1482,6 @@ static const struct wl_touch_listener touch_listener = {
|
||||
touch_handler_orientation // Version 6
|
||||
};
|
||||
|
||||
void pinch_begin(void *data,
|
||||
struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1,
|
||||
uint32_t serial,
|
||||
uint32_t time,
|
||||
struct wl_surface *surface,
|
||||
uint32_t fingers)
|
||||
{
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_BEGIN, 0, NULL, 0);
|
||||
}
|
||||
void pinch_update(void *data,
|
||||
struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1,
|
||||
uint32_t time,
|
||||
wl_fixed_t dx,
|
||||
wl_fixed_t dy,
|
||||
wl_fixed_t scale,
|
||||
wl_fixed_t rotation)
|
||||
{
|
||||
|
||||
float s = (float)(wl_fixed_to_double(scale));
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_UPDATE, 0, NULL, s);
|
||||
}
|
||||
|
||||
void pinch_end(void *data,
|
||||
struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1,
|
||||
uint32_t serial,
|
||||
uint32_t time,
|
||||
int32_t cancelled)
|
||||
{
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_END, 0, NULL, 0);
|
||||
}
|
||||
|
||||
static const struct zwp_pointer_gesture_pinch_v1_listener gesture_pinch_listener = {
|
||||
pinch_begin,
|
||||
pinch_update,
|
||||
pinch_end
|
||||
};
|
||||
|
||||
// Fallback for xkb_keymap_key_get_mods_for_level(), which is only available from 1.0.0, while the SDL minimum is 0.5.0.
|
||||
#if !SDL_XKBCOMMON_CHECK_VERSION(1, 0, 0)
|
||||
static size_t xkb_legacy_get_mods_for_level(SDL_WaylandSeat *seat, xkb_keycode_t key, xkb_layout_index_t layout, xkb_level_index_t level, xkb_mod_mask_t *masks_out, size_t masks_size)
|
||||
@@ -2296,6 +2324,11 @@ static const struct wl_keyboard_listener keyboard_listener = {
|
||||
|
||||
static void Wayland_SeatDestroyPointer(SDL_WaylandSeat *seat, bool send_event)
|
||||
{
|
||||
// End any active gestures.
|
||||
if (seat->pointer.gesture_focus) {
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_END, 0, seat->pointer.gesture_focus->sdlwindow, 0.0f);
|
||||
}
|
||||
|
||||
// Make sure focus is removed from a surface before the pointer is destroyed.
|
||||
if (seat->pointer.focus) {
|
||||
pointer_handle_leave(seat, seat->pointer.wl_pointer, 0, seat->pointer.focus->surface);
|
||||
@@ -2319,6 +2352,10 @@ static void Wayland_SeatDestroyPointer(SDL_WaylandSeat *seat, bool send_event)
|
||||
zwp_input_timestamps_v1_destroy(seat->pointer.timestamps);
|
||||
}
|
||||
|
||||
if (seat->pointer.gesture_pinch) {
|
||||
zwp_pointer_gesture_pinch_v1_destroy(seat->pointer.gesture_pinch);
|
||||
}
|
||||
|
||||
if (seat->pointer.cursor_state.frame_callback) {
|
||||
wl_callback_destroy(seat->pointer.cursor_state.frame_callback);
|
||||
}
|
||||
@@ -2425,10 +2462,6 @@ static void Wayland_SeatDestroyTouch(SDL_WaylandSeat *seat)
|
||||
}
|
||||
}
|
||||
|
||||
if (seat->touch.gesture_pinch) {
|
||||
zwp_pointer_gesture_pinch_v1_destroy(seat->touch.gesture_pinch);
|
||||
}
|
||||
|
||||
SDL_zero(seat->touch);
|
||||
WAYLAND_wl_list_init(&seat->touch.points);
|
||||
}
|
||||
@@ -2447,6 +2480,9 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, enum w
|
||||
wl_pointer_set_user_data(seat->pointer.wl_pointer, seat);
|
||||
wl_pointer_add_listener(seat->pointer.wl_pointer, &pointer_listener, seat);
|
||||
|
||||
// Pointer gestures
|
||||
Wayland_SeatCreatePointerGestures(seat);
|
||||
|
||||
seat->pointer.sdl_id = SDL_GetNextObjectID();
|
||||
|
||||
if (seat->name) {
|
||||
@@ -2472,12 +2508,6 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, enum w
|
||||
}
|
||||
|
||||
SDL_AddTouch((SDL_TouchID)(uintptr_t)seat->touch.wl_touch, SDL_TOUCH_DEVICE_DIRECT, name_fmt);
|
||||
|
||||
/* Pinch gesture */
|
||||
seat->touch.gesture_pinch = zwp_pointer_gestures_v1_get_pinch_gesture(seat->display->zwp_pointer_gestures, seat->pointer.wl_pointer);
|
||||
zwp_pointer_gesture_pinch_v1_set_user_data(seat->touch.gesture_pinch, seat);
|
||||
zwp_pointer_gesture_pinch_v1_add_listener(seat->touch.gesture_pinch, &gesture_pinch_listener, seat);
|
||||
|
||||
} else if (!(capabilities & WL_SEAT_CAPABILITY_TOUCH) && seat->touch.wl_touch) {
|
||||
Wayland_SeatDestroyTouch(seat);
|
||||
}
|
||||
|
||||
@@ -123,10 +123,14 @@ typedef struct SDL_WaylandSeat
|
||||
struct wp_cursor_shape_device_v1 *cursor_shape;
|
||||
struct zwp_locked_pointer_v1 *locked_pointer;
|
||||
struct zwp_confined_pointer_v1 *confined_pointer;
|
||||
struct zwp_pointer_gesture_pinch_v1 *gesture_pinch;
|
||||
|
||||
SDL_WindowData *focus;
|
||||
SDL_CursorData *current_cursor;
|
||||
|
||||
// According to the spec, a seat can only have one active gesture of any type at a time.
|
||||
SDL_WindowData *gesture_focus;
|
||||
|
||||
Uint64 highres_timestamp_ns;
|
||||
Uint32 enter_serial;
|
||||
SDL_MouseButtonFlags buttons_pressed;
|
||||
@@ -192,7 +196,6 @@ typedef struct SDL_WaylandSeat
|
||||
struct zwp_input_timestamps_v1 *timestamps;
|
||||
Uint64 highres_timestamp_ns;
|
||||
struct wl_list points;
|
||||
struct zwp_pointer_gesture_pinch_v1 *gesture_pinch;
|
||||
} touch;
|
||||
|
||||
struct
|
||||
@@ -220,6 +223,7 @@ extern int Wayland_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS);
|
||||
|
||||
extern void Wayland_DisplayInitInputTimestampManager(SDL_VideoData *display);
|
||||
extern void Wayland_DisplayInitCursorShapeManager(SDL_VideoData *display);
|
||||
extern void Wayland_DisplayInitPointerGestureManager(SDL_VideoData *display);
|
||||
extern void Wayland_DisplayInitTabletManager(SDL_VideoData *display);
|
||||
extern void Wayland_DisplayInitDataDeviceManager(SDL_VideoData *display);
|
||||
extern void Wayland_DisplayInitPrimarySelectionDeviceManager(SDL_VideoData *display);
|
||||
|
||||
@@ -1324,7 +1324,8 @@ static void handle_registry_global(void *data, struct wl_registry *registry, uin
|
||||
} else if (SDL_strcmp(interface, "wp_pointer_warp_v1") == 0) {
|
||||
d->wp_pointer_warp_v1 = wl_registry_bind(d->registry, id, &wp_pointer_warp_v1_interface, 1);
|
||||
} else if (SDL_strcmp(interface, "zwp_pointer_gestures_v1") == 0) {
|
||||
d->zwp_pointer_gestures = wl_registry_bind(d->registry, id, &zwp_pointer_gestures_v1_interface, 1);
|
||||
d->zwp_pointer_gestures = wl_registry_bind(d->registry, id, &zwp_pointer_gestures_v1_interface, SDL_min(version, 3));
|
||||
Wayland_DisplayInitPointerGestureManager(d);
|
||||
}
|
||||
#ifdef SDL_WL_FIXES_VERSION
|
||||
else if (SDL_strcmp(interface, "wl_fixes") == 0) {
|
||||
@@ -1649,7 +1650,11 @@ static void Wayland_VideoCleanup(SDL_VideoDevice *_this)
|
||||
}
|
||||
|
||||
if (data->zwp_pointer_gestures) {
|
||||
zwp_pointer_gestures_v1_destroy(data->zwp_pointer_gestures);
|
||||
if (zwp_pointer_gestures_v1_get_version(data->zwp_pointer_gestures) >= ZWP_POINTER_GESTURES_V1_RELEASE_SINCE_VERSION) {
|
||||
zwp_pointer_gestures_v1_release(data->zwp_pointer_gestures);
|
||||
} else {
|
||||
zwp_pointer_gestures_v1_destroy(data->zwp_pointer_gestures);
|
||||
}
|
||||
data->zwp_pointer_gestures = NULL;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user