Skip to content

Commit 04f5aac

Browse files
committed
Add SDL Pinch events.
backend: x11/wayland/macosx/ios/Android
1 parent 463984e commit 04f5aac

File tree

20 files changed

+606
-19
lines changed

20 files changed

+606
-19
lines changed

android-project/app/src/main/java/org/libsdl/app/SDLActivity.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,10 @@ public static native void onNativeTouch(int touchDevId, int pointerFingerId,
10641064
public static native boolean nativeAllowRecreateActivity();
10651065
public static native int nativeCheckSDLThreadCounter();
10661066
public static native void onNativeFileDialog(int requestCode, String[] filelist, int filter);
1067+
public static native void onNativePinchStart();
1068+
public static native void onNativePinchUpdate(float scale);
1069+
public static native void onNativePinchEnd();
1070+
10671071

10681072
/**
10691073
* This method is called by SDL using JNI.

android-project/app/src/main/java/org/libsdl/app/SDLSurface.java

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import android.view.View;
2121
import android.view.WindowManager;
2222

23+
import android.view.ScaleGestureDetector;
2324

2425
/**
2526
SDLSurface. This is what we draw on, so we need to know when it's created
@@ -28,7 +29,9 @@
2829
Because of this, that's where we set up the SDL thread
2930
*/
3031
public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
31-
View.OnKeyListener, View.OnTouchListener, SensorEventListener {
32+
View.OnKeyListener, View.OnTouchListener, SensorEventListener,
33+
ScaleGestureDetector.OnScaleGestureListener
34+
{
3235

3336
// Sensors
3437
protected SensorManager mSensorManager;
@@ -40,11 +43,16 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
4043
// Is SurfaceView ready for rendering
4144
public boolean mIsSurfaceReady;
4245

46+
// Pinch events
47+
private final ScaleGestureDetector scaleGestureDetector;
48+
4349
// Startup
4450
public SDLSurface(Context context) {
4551
super(context);
4652
getHolder().addCallback(this);
4753

54+
scaleGestureDetector = new ScaleGestureDetector(context, this);
55+
4856
setFocusable(true);
4957
setFocusableInTouchMode(true);
5058
requestFocus();
@@ -214,6 +222,13 @@ private float getNormalizedY(float y)
214222
// Touch events
215223
@Override
216224
public boolean onTouch(View v, MotionEvent event) {
225+
226+
if (scaleGestureDetector.onTouchEvent(event)) {
227+
if (scaleGestureDetector.isInProgress()) {
228+
return true; /* event was consumed as gesture */
229+
}
230+
}
231+
217232
/* Ref: http://developer.android.com/training/gestures/multi.html */
218233
int touchDevId = event.getDeviceId();
219234
final int pointerCount = event.getPointerCount();
@@ -410,4 +425,23 @@ public boolean onCapturedPointerEvent(MotionEvent event)
410425

411426
return false;
412427
}
428+
429+
@Override
430+
public boolean onScale(ScaleGestureDetector detector) {
431+
float scale = detector.getScaleFactor();
432+
SDLActivity.onNativePinchUpdate(scale);
433+
return true;
434+
}
435+
436+
@Override
437+
public boolean onScaleBegin(ScaleGestureDetector detector) {
438+
SDLActivity.onNativePinchStart();
439+
return true;
440+
}
441+
442+
@Override
443+
public void onScaleEnd(ScaleGestureDetector detector) {
444+
SDLActivity.onNativePinchEnd();
445+
}
446+
413447
}

cmake/sdlchecks.cmake

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,23 @@ macro(CheckX11)
411411
if(HAVE_XINPUT2_MULTITOUCH)
412412
set(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH 1)
413413
endif()
414+
415+
# Check for gesture
416+
check_c_source_compiles("
417+
#include <X11/Xlib.h>
418+
#include <X11/Xproto.h>
419+
#include <X11/extensions/XInput2.h>
420+
int event_type = XI_GesturePinchBegin;
421+
XITouchClassInfo *t;
422+
Status XIAllowTouchEvents(Display *a,int b,unsigned int c,Window d,int f) {
423+
return (Status)0;
424+
}
425+
int main(int argc, char **argv) { return 0; }" HAVE_XINPUT2_GESTURE)
426+
if(HAVE_XINPUT2_GESTURE)
427+
set(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_GESTURE 1)
428+
endif()
429+
430+
414431
endif()
415432

416433
# check along with XInput2.h because we use Xfixes with XIBarrierReleasePointer

include/SDL3/SDL_events.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,11 @@ typedef enum SDL_EventType
185185
SDL_EVENT_FINGER_UP,
186186
SDL_EVENT_FINGER_MOTION,
187187

188+
/* Pinch events */
189+
SDL_EVENT_PINCH_BEGIN = 0x710,
190+
SDL_EVENT_PINCH_UPDATE,
191+
SDL_EVENT_PINCH_END,
192+
188193
/* 0x800, 0x801, and 0x802 were the Gesture events from SDL2. Do not reuse these values! sdl2-compat needs them! */
189194

190195
/* Clipboard events */
@@ -667,6 +672,17 @@ typedef struct SDL_TouchFingerEvent
667672
SDL_WindowID windowID; /**< The window underneath the finger, if any */
668673
} SDL_TouchFingerEvent;
669674

675+
/**
676+
* Pinch event structure (event.pinch.*)
677+
*/
678+
typedef struct SDL_PinchFingerEvent
679+
{
680+
SDL_EventType type; /**< ::SDL_EVENT_PINCH_BEGIN or ::SDL_EVENT_PINCH_UPDATE or ::SDL_EVENT_PINCH_END */
681+
Uint32 reserved;
682+
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
683+
float scale; /**< The scale factor provided with SDL_EVENT_PINCH_UPDATE. Scale < 1 is "zoom out". Scale > 1 is "zoom in". */
684+
SDL_WindowID windowID; /**< The window underneath the finger, if any */
685+
} SDL_PinchFingerEvent;
670686

671687
/**
672688
* Pressure-sensitive pen touched or stopped touching surface (event.ptip.*)
@@ -849,6 +865,7 @@ typedef union SDL_Event
849865
SDL_QuitEvent quit; /**< Quit request event data */
850866
SDL_UserEvent user; /**< Custom event data */
851867
SDL_TouchFingerEvent tfinger; /**< Touch finger event data */
868+
SDL_PinchFingerEvent pinch; /**< Pinch event data */
852869
SDL_PenTipEvent ptip; /**< Pen tip touching or leaving drawing surface */
853870
SDL_PenMotionEvent pmotion; /**< Pen change in position, pressure, or angle */
854871
SDL_PenButtonEvent pbutton; /**< Pen button press */

include/build_config/SDL_build_config.h.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@
407407
#cmakedefine SDL_VIDEO_DRIVER_X11_XFIXES @SDL_VIDEO_DRIVER_X11_XFIXES@
408408
#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2 @SDL_VIDEO_DRIVER_X11_XINPUT2@
409409
#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH @SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH@
410+
#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_GESTURE @SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_GESTURE@
410411
#cmakedefine SDL_VIDEO_DRIVER_X11_XRANDR @SDL_VIDEO_DRIVER_X11_XRANDR@
411412
#cmakedefine SDL_VIDEO_DRIVER_X11_XSCRNSAVER @SDL_VIDEO_DRIVER_X11_XSCRNSAVER@
412413
#cmakedefine SDL_VIDEO_DRIVER_X11_XSHAPE @SDL_VIDEO_DRIVER_X11_XSHAPE@

src/core/android/SDL_android.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,16 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeTouch)(
108108
jint touch_device_id_in, jint pointer_finger_id_in,
109109
jint action, jfloat x, jfloat y, jfloat p);
110110

111+
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativePinchStart)(
112+
JNIEnv *env, jclass jcls);
113+
114+
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativePinchUpdate)(
115+
JNIEnv *env, jclass jcls,
116+
jfloat scale);
117+
118+
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativePinchEnd)(
119+
JNIEnv *env, jclass jcls);
120+
111121
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeMouse)(
112122
JNIEnv *env, jclass jcls,
113123
jint button, jint action, jfloat x, jfloat y, jboolean relative);
@@ -196,6 +206,9 @@ static JNINativeMethod SDLActivity_tab[] = {
196206
{ "onNativeSoftReturnKey", "()Z", SDL_JAVA_INTERFACE(onNativeSoftReturnKey) },
197207
{ "onNativeKeyboardFocusLost", "()V", SDL_JAVA_INTERFACE(onNativeKeyboardFocusLost) },
198208
{ "onNativeTouch", "(IIIFFF)V", SDL_JAVA_INTERFACE(onNativeTouch) },
209+
{ "onNativePinchStart", "()V", SDL_JAVA_INTERFACE(onNativePinchStart) },
210+
{ "onNativePinchUpdate", "(F)V", SDL_JAVA_INTERFACE(onNativePinchUpdate) },
211+
{ "onNativePinchEnd", "()V", SDL_JAVA_INTERFACE(onNativePinchEnd) },
199212
{ "onNativeMouse", "(IIFFZ)V", SDL_JAVA_INTERFACE(onNativeMouse) },
200213
{ "onNativeAccel", "(FFF)V", SDL_JAVA_INTERFACE(onNativeAccel) },
201214
{ "onNativeClipboardChanged", "()V", SDL_JAVA_INTERFACE(onNativeClipboardChanged) },
@@ -1279,6 +1292,43 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeTouch)(
12791292
SDL_UnlockMutex(Android_ActivityMutex);
12801293
}
12811294

1295+
/* Pinch */
1296+
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativePinchStart)(
1297+
JNIEnv *env, jclass jcls)
1298+
{
1299+
SDL_LockMutex(Android_ActivityMutex);
1300+
1301+
if (Android_Window) {
1302+
SDL_SendPinch(SDL_EVENT_PINCH_BEGIN, 0, Android_Window, 0);
1303+
}
1304+
1305+
SDL_UnlockMutex(Android_ActivityMutex);
1306+
}
1307+
1308+
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativePinchUpdate)(
1309+
JNIEnv *env, jclass jcls, jfloat scale)
1310+
{
1311+
SDL_LockMutex(Android_ActivityMutex);
1312+
1313+
if (Android_Window) {
1314+
SDL_SendPinch(SDL_EVENT_PINCH_UPDATE, 0, Android_Window, scale);
1315+
}
1316+
1317+
SDL_UnlockMutex(Android_ActivityMutex);
1318+
}
1319+
1320+
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativePinchEnd)(
1321+
JNIEnv *env, jclass jcls)
1322+
{
1323+
SDL_LockMutex(Android_ActivityMutex);
1324+
1325+
if (Android_Window) {
1326+
SDL_SendPinch(SDL_EVENT_PINCH_END, 0, Android_Window, 0);
1327+
}
1328+
1329+
SDL_UnlockMutex(Android_ActivityMutex);
1330+
}
1331+
12821332
/* Mouse */
12831333
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeMouse)(
12841334
JNIEnv *env, jclass jcls,

src/events/SDL_events.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,11 @@ static void SDL_LogEvent(const SDL_Event *event)
214214
char name[64];
215215
char details[128];
216216

217-
/* sensor/mouse/pen/finger motion are spammy, ignore these if they aren't demanded. */
217+
/* sensor/mouse/pen/finger/pinch motion are spammy, ignore these if they aren't demanded. */
218218
if ((SDL_EventLoggingVerbosity < 2) &&
219219
((event->type == SDL_EVENT_MOUSE_MOTION) ||
220220
(event->type == SDL_EVENT_FINGER_MOTION) ||
221+
(event->type == SDL_EVENT_PINCH_UPDATE) ||
221222
(event->type == SDL_EVENT_PEN_MOTION) ||
222223
(event->type == SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION) ||
223224
(event->type == SDL_EVENT_GAMEPAD_SENSOR_UPDATE) ||
@@ -523,6 +524,20 @@ static void SDL_LogEvent(const SDL_Event *event)
523524
break;
524525
#undef PRINT_FINGER_EVENT
525526

527+
#define PRINT_PINCH_EVENT(event) \
528+
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u scale=%f)", \
529+
(uint)event->pinch.timestamp, event->pinch.scale)
530+
SDL_EVENT_CASE(SDL_EVENT_PINCH_BEGIN)
531+
PRINT_PINCH_EVENT(event);
532+
break;
533+
SDL_EVENT_CASE(SDL_EVENT_PINCH_UPDATE)
534+
PRINT_PINCH_EVENT(event);
535+
break;
536+
SDL_EVENT_CASE(SDL_EVENT_PINCH_END)
537+
PRINT_PINCH_EVENT(event);
538+
break;
539+
#undef PRINT_PINCH_EVENT
540+
526541
#define PRINT_PTIP_EVENT(event) \
527542
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u tip=%u state=%s x=%g y=%g)", \
528543
(uint)event->ptip.timestamp, (uint)event->ptip.windowID, \

src/events/SDL_touch.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ static int SDL_DelFinger(SDL_Touch *touch, SDL_FingerID fingerid)
245245
// Move the deleted finger to just past the end of the active fingers array and shift the active fingers by one.
246246
// This ensures that the descriptor for the now-deleted finger is located at `touch->fingers[touch->num_fingers]`
247247
// and is ready for use in SDL_AddFinger.
248-
SDL_Finger *deleted_finger = touch->fingers[index];
248+
SDL_Finger *deleted_finger = touch->fingers[index];
249249
SDL_memmove(&touch->fingers[index], &touch->fingers[index + 1], (touch->num_fingers - index) * sizeof(touch->fingers[index]));
250250
touch->fingers[touch->num_fingers] = deleted_finger;
251251
}
@@ -512,3 +512,19 @@ void SDL_QuitTouch(void)
512512
SDL_free(SDL_touchDevices);
513513
SDL_touchDevices = NULL;
514514
}
515+
516+
int SDL_SendPinch(int event_type, Uint64 timestamp, SDL_Window *window, float scale)
517+
{
518+
/* Post the event, if desired */
519+
int posted = 0;
520+
if (SDL_EventEnabled(event_type)) {
521+
SDL_Event event;
522+
event.type = event_type;
523+
event.common.timestamp = timestamp;
524+
event.pinch.scale = scale;
525+
event.pinch.windowID = window ? SDL_GetWindowID(window) : 0;
526+
posted = (SDL_PushEvent(&event) > 0);
527+
}
528+
return posted;
529+
}
530+

src/events/SDL_touch_c.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,7 @@ extern void SDL_DelTouch(SDL_TouchID id);
5757
/* Shutdown the touch subsystem */
5858
extern void SDL_QuitTouch(void);
5959

60+
/* Send Gesture events */
61+
extern int SDL_SendPinch(int event_type, Uint64 timestamp, SDL_Window *window, float scale);
62+
6063
#endif /* SDL_touch_c_h_ */

src/test/SDL_test_common.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1836,6 +1836,16 @@ static void SDLTest_PrintEvent(const SDL_Event *event)
18361836
event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure);
18371837
break;
18381838

1839+
case SDL_EVENT_PINCH_BEGIN:
1840+
SDL_Log("SDL EVENT: Pinch Begin");
1841+
break;
1842+
case SDL_EVENT_PINCH_UPDATE:
1843+
SDL_Log("SDL EVENT: Pinch Update, scale=%f", event->pinch.scale);
1844+
break;
1845+
case SDL_EVENT_PINCH_END:
1846+
SDL_Log("SDL EVENT: Pinch End");
1847+
break;
1848+
18391849
case SDL_EVENT_RENDER_DEVICE_RESET:
18401850
SDL_Log("SDL EVENT: render device reset");
18411851
break;
@@ -2069,7 +2079,8 @@ int SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const SDL_Event
20692079

20702080
if (state->verbose & VERBOSE_EVENT) {
20712081
if (((event->type != SDL_EVENT_MOUSE_MOTION) &&
2072-
(event->type != SDL_EVENT_FINGER_MOTION)) ||
2082+
(event->type != SDL_EVENT_FINGER_MOTION) &&
2083+
(event->type != SDL_EVENT_PINCH_UPDATE)) ||
20732084
(state->verbose & VERBOSE_MOTION)) {
20742085
SDLTest_PrintEvent(event);
20752086
}

0 commit comments

Comments
 (0)