mirror of
https://github.com/shadps4-emu/ext-SDL.git
synced 2026-01-31 00:55:22 +01:00
Add SDL Pinch events (#9445)
This commit is contained in:
@@ -1084,6 +1084,9 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
public static native boolean nativeAllowRecreateActivity();
|
||||
public static native int nativeCheckSDLThreadCounter();
|
||||
public static native void onNativeFileDialog(int requestCode, String[] filelist, int filter);
|
||||
public static native void onNativePinchStart();
|
||||
public static native void onNativePinchUpdate(float scale);
|
||||
public static native void onNativePinchEnd();
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.view.View;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import android.view.ScaleGestureDetector;
|
||||
|
||||
/**
|
||||
SDLSurface. This is what we draw on, so we need to know when it's created
|
||||
@@ -31,7 +32,8 @@ import android.view.WindowManager;
|
||||
Because of this, that's where we set up the SDL thread
|
||||
*/
|
||||
public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||
View.OnApplyWindowInsetsListener, View.OnKeyListener, View.OnTouchListener, SensorEventListener {
|
||||
View.OnApplyWindowInsetsListener, View.OnKeyListener, View.OnTouchListener,
|
||||
SensorEventListener, ScaleGestureDetector.OnScaleGestureListener {
|
||||
|
||||
// Sensors
|
||||
protected SensorManager mSensorManager;
|
||||
@@ -43,11 +45,16 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||
// Is SurfaceView ready for rendering
|
||||
protected boolean mIsSurfaceReady;
|
||||
|
||||
// Pinch events
|
||||
private final ScaleGestureDetector scaleGestureDetector;
|
||||
|
||||
// Startup
|
||||
protected SDLSurface(Context context) {
|
||||
super(context);
|
||||
getHolder().addCallback(this);
|
||||
|
||||
scaleGestureDetector = new ScaleGestureDetector(context, this);
|
||||
|
||||
setFocusable(true);
|
||||
setFocusableInTouchMode(true);
|
||||
requestFocus();
|
||||
@@ -294,6 +301,8 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||
break;
|
||||
} while (++i < pointerCount);
|
||||
|
||||
scaleGestureDetector.onTouchEvent(event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -415,4 +424,23 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScale(ScaleGestureDetector detector) {
|
||||
float scale = detector.getScaleFactor();
|
||||
SDLActivity.onNativePinchUpdate(scale);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScaleBegin(ScaleGestureDetector detector) {
|
||||
SDLActivity.onNativePinchStart();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScaleEnd(ScaleGestureDetector detector) {
|
||||
SDLActivity.onNativePinchEnd();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -441,6 +441,23 @@ macro(CheckX11)
|
||||
if(HAVE_XINPUT2_MULTITOUCH)
|
||||
set(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH 1)
|
||||
endif()
|
||||
|
||||
# Check for gesture
|
||||
check_c_source_compiles("
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/extensions/XInput2.h>
|
||||
int event_type = XI_GesturePinchBegin;
|
||||
XITouchClassInfo *t;
|
||||
Status XIAllowTouchEvents(Display *a,int b,unsigned int c,Window d,int f) {
|
||||
return (Status)0;
|
||||
}
|
||||
int main(int argc, char **argv) { return 0; }" HAVE_XINPUT2_GESTURE)
|
||||
if(HAVE_XINPUT2_GESTURE)
|
||||
set(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_GESTURE 1)
|
||||
endif()
|
||||
|
||||
|
||||
endif()
|
||||
|
||||
# check along with XInput2.h because we use Xfixes with XIBarrierReleasePointer
|
||||
|
||||
@@ -218,6 +218,11 @@ typedef enum SDL_EventType
|
||||
SDL_EVENT_FINGER_MOTION,
|
||||
SDL_EVENT_FINGER_CANCELED,
|
||||
|
||||
/* Pinch events */
|
||||
SDL_EVENT_PINCH_BEGIN = 0x710, /**< Pinch gesture started */
|
||||
SDL_EVENT_PINCH_UPDATE, /**< Pinch gesture updated */
|
||||
SDL_EVENT_PINCH_END, /**< Pinch gesture ended */
|
||||
|
||||
/* 0x800, 0x801, and 0x802 were the Gesture events from SDL2. Do not reuse these values! sdl2-compat needs them! */
|
||||
|
||||
/* Clipboard events */
|
||||
@@ -788,6 +793,18 @@ typedef struct SDL_TouchFingerEvent
|
||||
SDL_WindowID windowID; /**< The window underneath the finger, if any */
|
||||
} SDL_TouchFingerEvent;
|
||||
|
||||
/**
|
||||
* Pinch event structure (event.pinch.*)
|
||||
*/
|
||||
typedef struct SDL_PinchFingerEvent
|
||||
{
|
||||
SDL_EventType type; /**< ::SDL_EVENT_PINCH_BEGIN or ::SDL_EVENT_PINCH_UPDATE or ::SDL_EVENT_PINCH_END */
|
||||
Uint32 reserved;
|
||||
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
|
||||
float scale; /**< The scale change since the last SDL_EVENT_PINCH_UPDATE. Scale < 1 is "zoom out". Scale > 1 is "zoom in". */
|
||||
SDL_WindowID windowID; /**< The window underneath the finger, if any */
|
||||
} SDL_PinchFingerEvent;
|
||||
|
||||
/**
|
||||
* Pressure-sensitive pen proximity event structure (event.pproximity.*)
|
||||
*
|
||||
@@ -1025,6 +1042,7 @@ typedef union SDL_Event
|
||||
SDL_QuitEvent quit; /**< Quit request event data */
|
||||
SDL_UserEvent user; /**< Custom event data */
|
||||
SDL_TouchFingerEvent tfinger; /**< Touch finger event data */
|
||||
SDL_PinchFingerEvent pinch; /**< Pinch event data */
|
||||
SDL_PenProximityEvent pproximity; /**< Pen proximity event data */
|
||||
SDL_PenTouchEvent ptouch; /**< Pen tip touching event data */
|
||||
SDL_PenMotionEvent pmotion; /**< Pen motion event data */
|
||||
|
||||
@@ -436,6 +436,7 @@
|
||||
#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2 1
|
||||
#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH 1
|
||||
#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO 1
|
||||
#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_GESTURE @SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_GESTURE@
|
||||
#cmakedefine SDL_VIDEO_DRIVER_X11_XRANDR 1
|
||||
#cmakedefine SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1
|
||||
#cmakedefine SDL_VIDEO_DRIVER_X11_XSHAPE 1
|
||||
|
||||
@@ -121,6 +121,16 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeTouch)(
|
||||
jint touch_device_id_in, jint pointer_finger_id_in,
|
||||
jint action, jfloat x, jfloat y, jfloat p);
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativePinchStart)(
|
||||
JNIEnv *env, jclass jcls);
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativePinchUpdate)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
jfloat scale);
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativePinchEnd)(
|
||||
JNIEnv *env, jclass jcls);
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeMouse)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
jint button, jint action, jfloat x, jfloat y, jboolean relative);
|
||||
@@ -221,6 +231,9 @@ static JNINativeMethod SDLActivity_tab[] = {
|
||||
{ "onNativeSoftReturnKey", "()Z", SDL_JAVA_INTERFACE(onNativeSoftReturnKey) },
|
||||
{ "onNativeKeyboardFocusLost", "()V", SDL_JAVA_INTERFACE(onNativeKeyboardFocusLost) },
|
||||
{ "onNativeTouch", "(IIIFFF)V", SDL_JAVA_INTERFACE(onNativeTouch) },
|
||||
{ "onNativePinchStart", "()V", SDL_JAVA_INTERFACE(onNativePinchStart) },
|
||||
{ "onNativePinchUpdate", "(F)V", SDL_JAVA_INTERFACE(onNativePinchUpdate) },
|
||||
{ "onNativePinchEnd", "()V", SDL_JAVA_INTERFACE(onNativePinchEnd) },
|
||||
{ "onNativeMouse", "(IIFFZ)V", SDL_JAVA_INTERFACE(onNativeMouse) },
|
||||
{ "onNativePen", "(IIIFFF)V", SDL_JAVA_INTERFACE(onNativePen) },
|
||||
{ "onNativeAccel", "(FFF)V", SDL_JAVA_INTERFACE(onNativeAccel) },
|
||||
@@ -1366,6 +1379,43 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeTouch)(
|
||||
SDL_UnlockMutex(Android_ActivityMutex);
|
||||
}
|
||||
|
||||
// Pinch
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativePinchStart)(
|
||||
JNIEnv *env, jclass jcls)
|
||||
{
|
||||
SDL_LockMutex(Android_ActivityMutex);
|
||||
|
||||
if (Android_Window) {
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_BEGIN, 0, Android_Window, 0);
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(Android_ActivityMutex);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativePinchUpdate)(
|
||||
JNIEnv *env, jclass jcls, jfloat scale)
|
||||
{
|
||||
SDL_LockMutex(Android_ActivityMutex);
|
||||
|
||||
if (Android_Window) {
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_UPDATE, 0, Android_Window, scale);
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(Android_ActivityMutex);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativePinchEnd)(
|
||||
JNIEnv *env, jclass jcls)
|
||||
{
|
||||
SDL_LockMutex(Android_ActivityMutex);
|
||||
|
||||
if (Android_Window) {
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_END, 0, Android_Window, 0);
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(Android_ActivityMutex);
|
||||
}
|
||||
|
||||
// Mouse
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeMouse)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
|
||||
@@ -770,6 +770,20 @@ int SDL_GetEventDescription(const SDL_Event *event, char *buf, int buflen)
|
||||
break;
|
||||
#undef PRINT_FINGER_EVENT
|
||||
|
||||
#define PRINT_PINCH_EVENT(event) \
|
||||
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u scale=%f)", \
|
||||
(uint)event->pinch.timestamp, event->pinch.scale)
|
||||
SDL_EVENT_CASE(SDL_EVENT_PINCH_BEGIN)
|
||||
PRINT_PINCH_EVENT(event);
|
||||
break;
|
||||
SDL_EVENT_CASE(SDL_EVENT_PINCH_UPDATE)
|
||||
PRINT_PINCH_EVENT(event);
|
||||
break;
|
||||
SDL_EVENT_CASE(SDL_EVENT_PINCH_END)
|
||||
PRINT_PINCH_EVENT(event);
|
||||
break;
|
||||
#undef PRINT_PINCH_EVENT
|
||||
|
||||
#define PRINT_PTOUCH_EVENT(event) \
|
||||
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u pen_state=%u x=%g y=%g eraser=%s state=%s)", \
|
||||
(uint)event->ptouch.timestamp, (uint)event->ptouch.windowID, (uint)event->ptouch.which, (uint)event->ptouch.pen_state, event->ptouch.x, event->ptouch.y, \
|
||||
@@ -902,12 +916,13 @@ static void SDL_LogEvent(const SDL_Event *event)
|
||||
return;
|
||||
}
|
||||
|
||||
// sensor/mouse/pen/finger motion are spammy, ignore these if they aren't demanded.
|
||||
// sensor/mouse/pen/finger/pinch motion are spammy, ignore these if they aren't demanded.
|
||||
if ((SDL_EventLoggingVerbosity < 2) &&
|
||||
((event->type == SDL_EVENT_MOUSE_MOTION) ||
|
||||
(event->type == SDL_EVENT_FINGER_MOTION) ||
|
||||
(event->type == SDL_EVENT_PEN_AXIS) ||
|
||||
(event->type == SDL_EVENT_PEN_MOTION) ||
|
||||
(event->type == SDL_EVENT_PINCH_UPDATE) ||
|
||||
(event->type == SDL_EVENT_GAMEPAD_AXIS_MOTION) ||
|
||||
(event->type == SDL_EVENT_GAMEPAD_SENSOR_UPDATE) ||
|
||||
(event->type == SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION) ||
|
||||
|
||||
@@ -500,3 +500,19 @@ void SDL_QuitTouch(void)
|
||||
SDL_free(SDL_touchDevices);
|
||||
SDL_touchDevices = NULL;
|
||||
}
|
||||
|
||||
int SDL_SendPinch(SDL_EventType type, Uint64 timestamp, SDL_Window *window, float scale)
|
||||
{
|
||||
/* Post the event, if desired */
|
||||
int posted = 0;
|
||||
if (SDL_EventEnabled(type)) {
|
||||
SDL_Event event;
|
||||
event.type = type;
|
||||
event.common.timestamp = timestamp;
|
||||
event.pinch.scale = scale;
|
||||
event.pinch.windowID = window ? SDL_GetWindowID(window) : 0;
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
return posted;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,4 +57,7 @@ extern void SDL_DelTouch(SDL_TouchID id);
|
||||
// Shutdown the touch subsystem
|
||||
extern void SDL_QuitTouch(void);
|
||||
|
||||
// Send Gesture events
|
||||
extern int SDL_SendPinch(SDL_EventType type, Uint64 timestamp, SDL_Window *window, float scale);
|
||||
|
||||
#endif // SDL_touch_c_h_
|
||||
|
||||
@@ -1928,6 +1928,16 @@ void SDLTest_PrintEvent(const SDL_Event *event)
|
||||
event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure);
|
||||
break;
|
||||
|
||||
case SDL_EVENT_PINCH_BEGIN:
|
||||
SDL_Log("SDL EVENT: Pinch Begin");
|
||||
break;
|
||||
case SDL_EVENT_PINCH_UPDATE:
|
||||
SDL_Log("SDL EVENT: Pinch Update, scale=%f", event->pinch.scale);
|
||||
break;
|
||||
case SDL_EVENT_PINCH_END:
|
||||
SDL_Log("SDL EVENT: Pinch End");
|
||||
break;
|
||||
|
||||
case SDL_EVENT_RENDER_TARGETS_RESET:
|
||||
SDL_Log("SDL EVENT: render targets reset in window %" SDL_PRIu32, event->render.windowID);
|
||||
break;
|
||||
@@ -2238,6 +2248,7 @@ SDL_AppResult SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const
|
||||
event->type != SDL_EVENT_FINGER_MOTION &&
|
||||
event->type != SDL_EVENT_PEN_MOTION &&
|
||||
event->type != SDL_EVENT_PEN_AXIS &&
|
||||
event->type != SDL_EVENT_PINCH_UPDATE &&
|
||||
event->type != SDL_EVENT_JOYSTICK_AXIS_MOTION) ||
|
||||
(state->verbose & VERBOSE_MOTION)) {
|
||||
SDLTest_PrintEvent(event);
|
||||
|
||||
@@ -122,6 +122,7 @@ typedef enum
|
||||
- (void)touchesMovedWithEvent:(NSEvent *)theEvent;
|
||||
- (void)touchesEndedWithEvent:(NSEvent *)theEvent;
|
||||
- (void)touchesCancelledWithEvent:(NSEvent *)theEvent;
|
||||
- (void)magnifyWithEvent:(NSEvent *) theEvent;
|
||||
|
||||
// Touch event handling
|
||||
- (void)handleTouches:(NSTouchPhase)phase withEvent:(NSEvent *)theEvent;
|
||||
|
||||
@@ -1990,6 +1990,27 @@ static void Cocoa_SendMouseButtonClicks(SDL_Mouse *mouse, NSEvent *theEvent, SDL
|
||||
[self handleTouches:NSTouchPhaseCancelled withEvent:theEvent];
|
||||
}
|
||||
|
||||
- (void)magnifyWithEvent:(NSEvent *)theEvent
|
||||
{
|
||||
switch ([theEvent phase]) {
|
||||
case NSEventPhaseBegan:
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_BEGIN, Cocoa_GetEventTimestamp([theEvent timestamp]), NULL, 0);
|
||||
break;
|
||||
case NSEventPhaseChanged:
|
||||
{
|
||||
CGFloat scale = 1.0f + [theEvent magnification];
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_UPDATE, Cocoa_GetEventTimestamp([theEvent timestamp]), NULL, scale);
|
||||
}
|
||||
break;
|
||||
case NSEventPhaseEnded:
|
||||
case NSEventPhaseCancelled:
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_END, Cocoa_GetEventTimestamp([theEvent timestamp]), NULL, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleTouches:(NSTouchPhase)phase withEvent:(NSEvent *)theEvent
|
||||
{
|
||||
NSSet *touches = [theEvent touchesMatchingPhase:phase inView:nil];
|
||||
|
||||
@@ -46,6 +46,9 @@
|
||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
|
||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
|
||||
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
|
||||
#if !defined(SDL_PLATFORM_TVOS)
|
||||
- (IBAction)sdlPinchGesture:(UIPinchGestureRecognizer *)sender;
|
||||
#endif
|
||||
|
||||
- (void)safeAreaInsetsDidChange;
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick;
|
||||
|
||||
SDL_TouchID directTouchId;
|
||||
SDL_TouchID indirectTouchId;
|
||||
float pinch_scale;
|
||||
|
||||
#if !defined(SDL_PLATFORM_TVOS)
|
||||
UIPointerInteraction *indirectPointerInteraction API_AVAILABLE(ios(13.4));
|
||||
@@ -76,6 +77,15 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick;
|
||||
[self addGestureRecognizer:swipeRight];
|
||||
#endif
|
||||
|
||||
#if !defined(SDL_PLATFORM_TVOS)
|
||||
/* Pinch gestures */
|
||||
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(sdlPinchGesture:)];
|
||||
pinchGesture.cancelsTouchesInView = NO;
|
||||
pinchGesture.delaysTouchesBegan = NO;
|
||||
pinchGesture.delaysTouchesEnded = NO;
|
||||
[self addGestureRecognizer:pinchGesture];
|
||||
#endif
|
||||
|
||||
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
self.autoresizesSubviews = YES;
|
||||
|
||||
@@ -470,6 +480,39 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick;
|
||||
(int)SDL_ceilf(self.safeAreaInsets.bottom));
|
||||
}
|
||||
|
||||
#if !defined(SDL_PLATFORM_TVOS)
|
||||
- (IBAction)sdlPinchGesture:(UIPinchGestureRecognizer *)sender
|
||||
{
|
||||
CGFloat scale = sender.scale;
|
||||
UIGestureRecognizerState state = sender.state;
|
||||
|
||||
switch (state) {
|
||||
|
||||
case UIGestureRecognizerStateBegan:
|
||||
pinch_scale = 1.0f;
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_BEGIN, 0, sdlwindow, 0);
|
||||
break;
|
||||
|
||||
case UIGestureRecognizerStateChanged:
|
||||
if (pinch_scale > 0.0f) {
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_UPDATE, 0, sdlwindow, scale / pinch_scale);
|
||||
}
|
||||
pinch_scale = scale;
|
||||
break;
|
||||
|
||||
case UIGestureRecognizerStateFailed:
|
||||
case UIGestureRecognizerStateEnded:
|
||||
case UIGestureRecognizerStateCancelled:
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_END, 0, sdlwindow, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
- (SDL_Scancode)scancodeFromPress:(UIPress *)press
|
||||
{
|
||||
if (press.key != nil) {
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "tablet-v2-client-protocol.h"
|
||||
#include "primary-selection-unstable-v1-client-protocol.h"
|
||||
#include "input-timestamps-unstable-v1-client-protocol.h"
|
||||
#include "pointer-gestures-unstable-v1-client-protocol.h"
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
#include <libdecor.h>
|
||||
@@ -1416,6 +1417,43 @@ 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)
|
||||
@@ -2387,6 +2425,10 @@ 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);
|
||||
}
|
||||
@@ -2430,6 +2472,12 @@ 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);
|
||||
}
|
||||
|
||||
@@ -192,6 +192,7 @@ 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
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
#include "xdg-toplevel-icon-v1-client-protocol.h"
|
||||
#include "color-management-v1-client-protocol.h"
|
||||
#include "pointer-warp-v1-client-protocol.h"
|
||||
#include "pointer-gestures-unstable-v1-client-protocol.h"
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
#include <libdecor.h>
|
||||
@@ -1322,6 +1323,8 @@ static void handle_registry_global(void *data, struct wl_registry *registry, uin
|
||||
Wayland_InitColorManager(d);
|
||||
} 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);
|
||||
}
|
||||
#ifdef SDL_WL_FIXES_VERSION
|
||||
else if (SDL_strcmp(interface, "wl_fixes") == 0) {
|
||||
@@ -1645,6 +1648,11 @@ static void Wayland_VideoCleanup(SDL_VideoDevice *_this)
|
||||
data->wp_pointer_warp_v1 = NULL;
|
||||
}
|
||||
|
||||
if (data->zwp_pointer_gestures) {
|
||||
zwp_pointer_gestures_v1_destroy(data->zwp_pointer_gestures);
|
||||
data->zwp_pointer_gestures = NULL;
|
||||
}
|
||||
|
||||
if (data->compositor) {
|
||||
wl_compositor_destroy(data->compositor);
|
||||
data->compositor = NULL;
|
||||
|
||||
@@ -86,6 +86,7 @@ struct SDL_VideoData
|
||||
struct wp_color_manager_v1 *wp_color_manager_v1;
|
||||
struct zwp_tablet_manager_v2 *tablet_manager;
|
||||
struct wl_fixes *wl_fixes;
|
||||
struct zwp_pointer_gestures_v1 *zwp_pointer_gestures;
|
||||
|
||||
struct xkb_context *xkb_context;
|
||||
|
||||
|
||||
@@ -38,6 +38,11 @@ static bool xinput2_initialized;
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||
static bool xinput2_multitouch_supported;
|
||||
#endif
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_GESTURE
|
||||
static int xinput2_gesture_supported = 0;
|
||||
#endif
|
||||
|
||||
static int X11_Xinput2IsGestureSupported(void);
|
||||
|
||||
/* Opcode returned X11_XQueryExtension
|
||||
* It will be used in event processing
|
||||
@@ -272,8 +277,8 @@ bool X11_InitXinput2(SDL_VideoDevice *_this)
|
||||
return false; // X server does not have XInput at all
|
||||
}
|
||||
|
||||
// We need at least 2.2 for Multitouch, 2.0 otherwise.
|
||||
version = query_xinput2_version(data->display, 2, 2);
|
||||
// We need at least 2.4 for Gesture, 2.2 for Multitouch, 2.0 otherwise.
|
||||
version = query_xinput2_version(data->display, 2, 4);
|
||||
if (!xinput2_version_atleast(version, 2, 0)) {
|
||||
return false; // X server does not support the version we want at all.
|
||||
}
|
||||
@@ -287,6 +292,9 @@ bool X11_InitXinput2(SDL_VideoDevice *_this)
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH // Multitouch needs XInput 2.2
|
||||
xinput2_multitouch_supported = xinput2_version_atleast(version, 2, 2);
|
||||
#endif
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_GESTURE // Gesture needs XInput 2.4
|
||||
xinput2_gesture_supported = xinput2_version_atleast(version, 2, 4);
|
||||
#endif
|
||||
|
||||
// Populate the atoms for finding relative axes
|
||||
xinput2_rel_x_atom = X11_XInternAtom(data->display, "Rel X", False);
|
||||
@@ -735,6 +743,28 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
|
||||
SDL_SendTouchMotion(0, xev->sourceid, xev->detail, window, x, y, 1.0);
|
||||
} break;
|
||||
#endif // SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_GESTURE
|
||||
case XI_GesturePinchBegin:
|
||||
case XI_GesturePinchUpdate:
|
||||
case XI_GesturePinchEnd:
|
||||
{
|
||||
const XIGesturePinchEvent *xev = (const XIGesturePinchEvent *)cookie->data;
|
||||
float x, y;
|
||||
SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
|
||||
xinput2_normalize_touch_coordinates(window, xev->event_x, xev->event_y, &x, &y);
|
||||
|
||||
if (cookie->evtype == XI_GesturePinchBegin) {
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_BEGIN, 0, window, 0);
|
||||
} else if (cookie->evtype == XI_GesturePinchUpdate) {
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_UPDATE, 0, window, (float)xev->scale);
|
||||
} else {
|
||||
SDL_SendPinch(SDL_EVENT_PINCH_END, 0, window, 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
#endif // SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_GESTURE
|
||||
|
||||
}
|
||||
#endif // SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||
}
|
||||
@@ -774,6 +804,14 @@ void X11_Xinput2Select(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
XISetMask(mask, XI_Motion);
|
||||
}
|
||||
|
||||
if (X11_Xinput2IsGestureSupported()) {
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_GESTURE
|
||||
XISetMask(mask, XI_GesturePinchBegin);
|
||||
XISetMask(mask, XI_GesturePinchUpdate);
|
||||
XISetMask(mask, XI_GesturePinchEnd);
|
||||
#endif
|
||||
}
|
||||
|
||||
X11_XISelectEvents(data->display, window_data->xwindow, &eventmask, 1);
|
||||
#endif
|
||||
}
|
||||
@@ -836,6 +874,15 @@ bool X11_Xinput2SelectMouseAndKeyboard(SDL_VideoDevice *_this, SDL_Window *windo
|
||||
return false;
|
||||
}
|
||||
|
||||
int X11_Xinput2IsGestureSupported(void)
|
||||
{
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_GESTURE
|
||||
return xinput2_initialized && xinput2_gesture_supported;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void X11_Xinput2GrabTouch(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||
|
||||
@@ -30,6 +30,7 @@ static SDL_BlendMode blendMode = SDL_BLENDMODE_NONE;
|
||||
static float angle = 0.0f;
|
||||
static int translate_cx = 0;
|
||||
static int translate_cy = 0;
|
||||
static float pinch_scale = 1.0f;
|
||||
|
||||
static int done;
|
||||
|
||||
@@ -103,11 +104,14 @@ static void loop(void)
|
||||
} else if (event.key.key == SDLK_DOWN) {
|
||||
translate_cy += 1;
|
||||
} else {
|
||||
SDLTest_CommonEvent(state, &event, &done);
|
||||
|
||||
}
|
||||
} else {
|
||||
SDLTest_CommonEvent(state, &event, &done);
|
||||
} else if (event.type == SDL_EVENT_PINCH_BEGIN) {
|
||||
} else if (event.type == SDL_EVENT_PINCH_UPDATE) {
|
||||
pinch_scale *= event.pinch.scale;
|
||||
} else if (event.type == SDL_EVENT_PINCH_END) {
|
||||
}
|
||||
SDLTest_CommonEvent(state, &event, &done);
|
||||
}
|
||||
|
||||
for (i = 0; i < state->num_windows; ++i) {
|
||||
@@ -136,24 +140,24 @@ static void loop(void)
|
||||
cy += translate_cy;
|
||||
|
||||
a = (angle * SDL_PI_F) / 180.0f;
|
||||
verts[0].position.x = cx + d * SDL_cosf(a);
|
||||
verts[0].position.y = cy + d * SDL_sinf(a);
|
||||
verts[0].position.x = cx + (d * SDL_cosf(a)) * pinch_scale;
|
||||
verts[0].position.y = cy + (d * SDL_sinf(a)) * pinch_scale;
|
||||
verts[0].color.r = 1.0f;
|
||||
verts[0].color.g = 0;
|
||||
verts[0].color.b = 0;
|
||||
verts[0].color.a = 1.0f;
|
||||
|
||||
a = ((angle + 120) * SDL_PI_F) / 180.0f;
|
||||
verts[1].position.x = cx + d * SDL_cosf(a);
|
||||
verts[1].position.y = cy + d * SDL_sinf(a);
|
||||
verts[1].position.x = cx + (d * SDL_cosf(a)) * pinch_scale;
|
||||
verts[1].position.y = cy + (d * SDL_sinf(a)) * pinch_scale;
|
||||
verts[1].color.r = 0;
|
||||
verts[1].color.g = 1.0f;
|
||||
verts[1].color.b = 0;
|
||||
verts[1].color.a = 1.0f;
|
||||
|
||||
a = ((angle + 240) * SDL_PI_F) / 180.0f;
|
||||
verts[2].position.x = cx + d * SDL_cosf(a);
|
||||
verts[2].position.y = cy + d * SDL_sinf(a);
|
||||
verts[2].position.x = cx + (d * SDL_cosf(a)) * pinch_scale;
|
||||
verts[2].position.y = cy + (d * SDL_sinf(a)) * pinch_scale;
|
||||
verts[2].color.r = 0;
|
||||
verts[2].color.g = 0;
|
||||
verts[2].color.b = 1.0f;
|
||||
|
||||
253
wayland-protocols/pointer-gestures-unstable-v1.xml
Normal file
253
wayland-protocols/pointer-gestures-unstable-v1.xml
Normal file
@@ -0,0 +1,253 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="pointer_gestures_unstable_v1">
|
||||
|
||||
<interface name="zwp_pointer_gestures_v1" version="3">
|
||||
<description summary="touchpad gestures">
|
||||
A global interface to provide semantic touchpad gestures for a given
|
||||
pointer.
|
||||
|
||||
Three gestures are currently supported: swipe, pinch, and hold.
|
||||
Pinch and swipe gestures follow a three-stage cycle: begin, update,
|
||||
end, hold gestures follow a two-stage cycle: begin and end. All
|
||||
gestures are identified by a unique id.
|
||||
|
||||
Warning! The protocol described in this file is experimental and
|
||||
backward incompatible changes may be made. Backward compatible changes
|
||||
may be added together with the corresponding interface version bump.
|
||||
Backward incompatible changes are done by bumping the version number in
|
||||
the protocol and interface names and resetting the interface version.
|
||||
Once the protocol is to be declared stable, the 'z' prefix and the
|
||||
version number in the protocol and interface names are removed and the
|
||||
interface version number is reset.
|
||||
</description>
|
||||
|
||||
<request name="get_swipe_gesture">
|
||||
<description summary="get swipe gesture">
|
||||
Create a swipe gesture object. See the
|
||||
wl_pointer_gesture_swipe interface for details.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwp_pointer_gesture_swipe_v1"/>
|
||||
<arg name="pointer" type="object" interface="wl_pointer"/>
|
||||
</request>
|
||||
|
||||
<request name="get_pinch_gesture">
|
||||
<description summary="get pinch gesture">
|
||||
Create a pinch gesture object. See the
|
||||
wl_pointer_gesture_pinch interface for details.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwp_pointer_gesture_pinch_v1"/>
|
||||
<arg name="pointer" type="object" interface="wl_pointer"/>
|
||||
</request>
|
||||
|
||||
<!-- Version 2 additions -->
|
||||
|
||||
<request name="release" type="destructor" since="2">
|
||||
<description summary="destroy the pointer gesture object">
|
||||
Destroy the pointer gesture object. Swipe, pinch and hold objects
|
||||
created via this gesture object remain valid.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<!-- Version 3 additions -->
|
||||
|
||||
<request name="get_hold_gesture" since="3">
|
||||
<description summary="get hold gesture">
|
||||
Create a hold gesture object. See the
|
||||
wl_pointer_gesture_hold interface for details.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwp_pointer_gesture_hold_v1"/>
|
||||
<arg name="pointer" type="object" interface="wl_pointer"/>
|
||||
</request>
|
||||
|
||||
</interface>
|
||||
|
||||
<interface name="zwp_pointer_gesture_swipe_v1" version="2">
|
||||
<description summary="a swipe gesture object">
|
||||
A swipe gesture object notifies a client about a multi-finger swipe
|
||||
gesture detected on an indirect input device such as a touchpad.
|
||||
The gesture is usually initiated by multiple fingers moving in the
|
||||
same direction but once initiated the direction may change.
|
||||
The precise conditions of when such a gesture is detected are
|
||||
implementation-dependent.
|
||||
|
||||
A gesture consists of three stages: begin, update (optional) and end.
|
||||
There cannot be multiple simultaneous hold, pinch or swipe gestures on a
|
||||
same pointer/seat, how compositors prevent these situations is
|
||||
implementation-dependent.
|
||||
|
||||
A gesture may be cancelled by the compositor or the hardware.
|
||||
Clients should not consider performing permanent or irreversible
|
||||
actions until the end of a gesture has been received.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the pointer swipe gesture object"/>
|
||||
</request>
|
||||
|
||||
<event name="begin">
|
||||
<description summary="multi-finger swipe begin">
|
||||
This event is sent when a multi-finger swipe gesture is detected
|
||||
on the device.
|
||||
</description>
|
||||
<arg name="serial" type="uint"/>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
<arg name="fingers" type="uint" summary="number of fingers"/>
|
||||
</event>
|
||||
|
||||
<event name="update">
|
||||
<description summary="multi-finger swipe motion">
|
||||
This event is sent when a multi-finger swipe gesture changes the
|
||||
position of the logical center.
|
||||
|
||||
The dx and dy coordinates are relative coordinates of the logical
|
||||
center of the gesture compared to the previous event.
|
||||
</description>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="dx" type="fixed" summary="delta x coordinate in surface coordinate space"/>
|
||||
<arg name="dy" type="fixed" summary="delta y coordinate in surface coordinate space"/>
|
||||
</event>
|
||||
|
||||
<event name="end">
|
||||
<description summary="multi-finger swipe end">
|
||||
This event is sent when a multi-finger swipe gesture ceases to
|
||||
be valid. This may happen when one or more fingers are lifted or
|
||||
the gesture is cancelled.
|
||||
|
||||
When a gesture is cancelled, the client should undo state changes
|
||||
caused by this gesture. What causes a gesture to be cancelled is
|
||||
implementation-dependent.
|
||||
</description>
|
||||
<arg name="serial" type="uint"/>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="cancelled" type="int" summary="1 if the gesture was cancelled, 0 otherwise"/>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="zwp_pointer_gesture_pinch_v1" version="2">
|
||||
<description summary="a pinch gesture object">
|
||||
A pinch gesture object notifies a client about a multi-finger pinch
|
||||
gesture detected on an indirect input device such as a touchpad.
|
||||
The gesture is usually initiated by multiple fingers moving towards
|
||||
each other or away from each other, or by two or more fingers rotating
|
||||
around a logical center of gravity. The precise conditions of when
|
||||
such a gesture is detected are implementation-dependent.
|
||||
|
||||
A gesture consists of three stages: begin, update (optional) and end.
|
||||
There cannot be multiple simultaneous hold, pinch or swipe gestures on a
|
||||
same pointer/seat, how compositors prevent these situations is
|
||||
implementation-dependent.
|
||||
|
||||
A gesture may be cancelled by the compositor or the hardware.
|
||||
Clients should not consider performing permanent or irreversible
|
||||
actions until the end of a gesture has been received.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the pinch gesture object"/>
|
||||
</request>
|
||||
|
||||
<event name="begin">
|
||||
<description summary="multi-finger pinch begin">
|
||||
This event is sent when a multi-finger pinch gesture is detected
|
||||
on the device.
|
||||
</description>
|
||||
<arg name="serial" type="uint"/>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
<arg name="fingers" type="uint" summary="number of fingers"/>
|
||||
</event>
|
||||
|
||||
<event name="update">
|
||||
<description summary="multi-finger pinch motion">
|
||||
This event is sent when a multi-finger pinch gesture changes the
|
||||
position of the logical center, the rotation or the relative scale.
|
||||
|
||||
The dx and dy coordinates are relative coordinates in the
|
||||
surface coordinate space of the logical center of the gesture.
|
||||
|
||||
The scale factor is an absolute scale compared to the
|
||||
pointer_gesture_pinch.begin event, e.g. a scale of 2 means the fingers
|
||||
are now twice as far apart as on pointer_gesture_pinch.begin.
|
||||
|
||||
The rotation is the relative angle in degrees clockwise compared to the previous
|
||||
pointer_gesture_pinch.begin or pointer_gesture_pinch.update event.
|
||||
</description>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="dx" type="fixed" summary="delta x coordinate in surface coordinate space"/>
|
||||
<arg name="dy" type="fixed" summary="delta y coordinate in surface coordinate space"/>
|
||||
<arg name="scale" type="fixed" summary="scale relative to the initial finger position"/>
|
||||
<arg name="rotation" type="fixed" summary="angle in degrees cw relative to the previous event"/>
|
||||
</event>
|
||||
|
||||
<event name="end">
|
||||
<description summary="multi-finger pinch end">
|
||||
This event is sent when a multi-finger pinch gesture ceases to
|
||||
be valid. This may happen when one or more fingers are lifted or
|
||||
the gesture is cancelled.
|
||||
|
||||
When a gesture is cancelled, the client should undo state changes
|
||||
caused by this gesture. What causes a gesture to be cancelled is
|
||||
implementation-dependent.
|
||||
</description>
|
||||
<arg name="serial" type="uint"/>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="cancelled" type="int" summary="1 if the gesture was cancelled, 0 otherwise"/>
|
||||
</event>
|
||||
|
||||
</interface>
|
||||
|
||||
<interface name="zwp_pointer_gesture_hold_v1" version="3">
|
||||
<description summary="a hold gesture object">
|
||||
A hold gesture object notifies a client about a single- or
|
||||
multi-finger hold gesture detected on an indirect input device such as
|
||||
a touchpad. The gesture is usually initiated by one or more fingers
|
||||
being held down without significant movement. The precise conditions
|
||||
of when such a gesture is detected are implementation-dependent.
|
||||
|
||||
In particular, this gesture may be used to cancel kinetic scrolling.
|
||||
|
||||
A hold gesture consists of two stages: begin and end. Unlike pinch and
|
||||
swipe there is no update stage.
|
||||
There cannot be multiple simultaneous hold, pinch or swipe gestures on a
|
||||
same pointer/seat, how compositors prevent these situations is
|
||||
implementation-dependent.
|
||||
|
||||
A gesture may be cancelled by the compositor or the hardware.
|
||||
Clients should not consider performing permanent or irreversible
|
||||
actions until the end of a gesture has been received.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor" since="3">
|
||||
<description summary="destroy the hold gesture object"/>
|
||||
</request>
|
||||
|
||||
<event name="begin" since="3">
|
||||
<description summary="multi-finger hold begin">
|
||||
This event is sent when a hold gesture is detected on the device.
|
||||
</description>
|
||||
<arg name="serial" type="uint"/>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
<arg name="fingers" type="uint" summary="number of fingers"/>
|
||||
</event>
|
||||
|
||||
<event name="end" since="3">
|
||||
<description summary="multi-finger hold end">
|
||||
This event is sent when a hold gesture ceases to
|
||||
be valid. This may happen when the holding fingers are lifted or
|
||||
the gesture is cancelled, for example if the fingers move past an
|
||||
implementation-defined threshold, the finger count changes or the hold
|
||||
gesture changes into a different type of gesture.
|
||||
|
||||
When a gesture is cancelled, the client may need to undo state changes
|
||||
caused by this gesture. What causes a gesture to be cancelled is
|
||||
implementation-dependent.
|
||||
</description>
|
||||
<arg name="serial" type="uint"/>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="cancelled" type="int" summary="1 if the gesture was cancelled, 0 otherwise"/>
|
||||
</event>
|
||||
|
||||
</interface>
|
||||
</protocol>
|
||||
Reference in New Issue
Block a user