From 7c93346221073e4f80275c4b2c99b76fce77c4c9 Mon Sep 17 00:00:00 2001 From: pfg Date: Sun, 22 Oct 2023 19:32:12 -0400 Subject: [PATCH 1/9] Add macOS events trackpadZoom and trackpadRotate --- include/GLFW/glfw3.h | 86 ++++++++++++++++++++++++++++++++++++++++++++ src/cocoa_window.m | 16 +++++++++ src/input.c | 46 ++++++++++++++++++++++++ src/internal.h | 4 +++ tests/events.c | 16 +++++++++ 5 files changed, 168 insertions(+) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 79b06288..bebaf8e4 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1871,6 +1871,40 @@ typedef void (* GLFWcursorenterfun)(GLFWwindow* window, int entered); */ typedef void (* GLFWscrollfun)(GLFWwindow* window, double xoffset, double yoffset); +/*! @brief The function pointer type for trackpad zoom callbacks. + * + * This is the function pointer type for trackpad zoom callbacks. A zoom + * callback function has the following signature: + * @code + * void function_name(GLFWwindow* window, double scale) + * @endcode + * + * @param[in] window The window that received the event. + * @param[in] scale The manigification amount + * + * @sa @ref glfwSetTrackpadZoomCallback + * + * @ingroup input + */ +typedef void (* GLFWtrackpadzoomfun)(GLFWwindow* window, double scale); + +/*! @brief The function pointer type for trackpad rotate callbacks. + * + * This is the function pointer type for trackpad rotate callbacks. A rotate + * callback function has the following signature: + * @code + * void function_name(GLFWwindow* window, double angle) + * @endcode + * + * @param[in] window The window that received the event. + * @param[in] angle The rotation amount + * + * @sa @ref glfwSetTrackpadRotateCallback + * + * @ingroup input + */ +typedef void (* GLFWtrackpadrotatefun)(GLFWwindow* window, double angle); + /*! @brief The function pointer type for keyboard key callbacks. * * This is the function pointer type for keyboard key callbacks. A keyboard @@ -5430,6 +5464,58 @@ GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* window, GLFWcu */ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun callback); +/*! @brief Sets the trackpad zoom callback. + * + * This function sets the trackpad zoom of the specified window, which is + * called when a trackpad magnification gesture is used on macOS. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new trackpad zoom callback, or `NULL` to remove the + * currently set callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window, double scale) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWtrackpadzoomfun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @ingroup input + */ +GLFWAPI GLFWtrackpadzoomfun glfwSetTrackpadZoomCallback(GLFWwindow* window, GLFWtrackpadzoomfun callback); + +/*! @brief Sets the trackpad rotate callback. + * + * This function sets the trackpad rotate of the specified window, which is + * called when a trackpad rotation gesture is used on macOS. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new trackpad rotate callback, or `NULL` to remove the + * currently set callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window, double angle) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWtrackpadrotatefun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @ingroup input + */ +GLFWAPI GLFWtrackpadrotatefun glfwSetTrackpadRotateCallback(GLFWwindow* window, GLFWtrackpadrotatefun callback); + /*! @brief Sets the path drop callback. * * This function sets the path drop callback of the specified window, which is diff --git a/src/cocoa_window.m b/src/cocoa_window.m index e69b5fe0..05cb2e51 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -614,6 +614,22 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; _glfwInputScroll(window, deltaX, deltaY); } +- (void)magnifyWithEvent:(NSEvent *)event +{ + double magnification = [event magnification]; + + if (fabs(magnification) > 0.0) + _glfwInputTrackpadZoom(window, magnification); +} + +- (void)rotateWithEvent:(NSEvent *)event +{ + double rotation = [event rotation]; + + if (fabs(rotation) > 0.0) + _glfwInputTrackpadRotate(window, rotation); +} + - (NSDragOperation)draggingEntered:(id )sender { // HACK: We don't know what to say here because we don't know what the diff --git a/src/input.c b/src/input.c index c619eefc..4aa44e3d 100644 --- a/src/input.c +++ b/src/input.c @@ -342,6 +342,30 @@ void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset) window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset); } +// Notifies shared code of a trackpad zoom event +// +void _glfwInputTrackpadZoom(_GLFWwindow* window, double scale) +{ + assert(window != NULL); + assert(scale > -FLT_MAX); + assert(scale < FLT_MAX); + + if (window->callbacks.trackpadZoom) + window->callbacks.trackpadZoom((GLFWwindow*) window, scale); +} + +// Notifies shared code of a trackpad rotate event +// +void _glfwInputTrackpadRotate(_GLFWwindow* window, double angle) +{ + assert(window != NULL); + assert(angle > -FLT_MAX); + assert(angle < FLT_MAX); + + if (window->callbacks.trackpadRotate) + window->callbacks.trackpadRotate((GLFWwindow*) window, angle); +} + // Notifies shared code of a mouse button click event // void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods) @@ -1034,6 +1058,28 @@ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle, return cbfun; } +GLFWAPI GLFWtrackpadzoomfun glfwSetTrackpadZoomCallback(GLFWwindow* handle, + GLFWtrackpadzoomfun cbfun) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFW_SWAP(GLFWtrackpadzoomfun, window->callbacks.trackpadZoom, cbfun); + return cbfun; +} + +GLFWAPI GLFWtrackpadzoomfun glfwSetTrackpadRotateCallback(GLFWwindow* handle, + GLFWtrackpadrotatefun cbfun) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFW_SWAP(GLFWtrackpadrotatefun, window->callbacks.trackpadRotate, cbfun); + return cbfun; +} + GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL); diff --git a/src/internal.h b/src/internal.h index 4f097aa8..7a58cbae 100644 --- a/src/internal.h +++ b/src/internal.h @@ -577,6 +577,8 @@ struct _GLFWwindow GLFWcursorposfun cursorPos; GLFWcursorenterfun cursorEnter; GLFWscrollfun scroll; + GLFWtrackpadzoomfun trackpadZoom; + GLFWtrackpadrotatefun trackpadRotate; GLFWkeyfun key; GLFWcharfun character; GLFWcharmodsfun charmods; @@ -935,6 +937,8 @@ void _glfwInputKey(_GLFWwindow* window, void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool plain); void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset); +void _glfwInputTrackpadZoom(_GLFWwindow* window, double scale); +void _glfwInputTrackpadRotate(_GLFWwindow* window, double angle); void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods); void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos); void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered); diff --git a/tests/events.c b/tests/events.c index ab3b99a7..f3c68949 100644 --- a/tests/events.c +++ b/tests/events.c @@ -397,6 +397,20 @@ static void scroll_callback(GLFWwindow* window, double x, double y) counter++, slot->number, glfwGetTime(), x, y); } +static void trackpad_zoom_callback(GLFWwindow* window, double scale) +{ + Slot* slot = glfwGetWindowUserPointer(window); + printf("%08x to %i at %0.3f: Trackpad Zoom: %0.3f\n", + counter++, slot->number, glfwGetTime(), scale); +} + +static void trackpad_rotate_callback(GLFWwindow* window, double angle) +{ + Slot* slot = glfwGetWindowUserPointer(window); + printf("%08x to %i at %0.3f: Trackpad Rotate: %0.3f\n", + counter++, slot->number, glfwGetTime(), angle); +} + static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { Slot* slot = glfwGetWindowUserPointer(window); @@ -647,6 +661,8 @@ int main(int argc, char** argv) glfwSetCursorPosCallback(slots[i].window, cursor_position_callback); glfwSetCursorEnterCallback(slots[i].window, cursor_enter_callback); glfwSetScrollCallback(slots[i].window, scroll_callback); + glfwSetTrackpadZoomCallback(slots[i].window, trackpad_zoom_callback); + glfwSetTrackpadRotateCallback(slots[i].window, trackpad_rotate_callback); glfwSetKeyCallback(slots[i].window, key_callback); glfwSetCharCallback(slots[i].window, char_callback); glfwSetDropCallback(slots[i].window, drop_callback); From 9f5a4f672fc2f3cea05194a839b678848ca51b85 Mon Sep 17 00:00:00 2001 From: pfg Date: Sun, 22 Oct 2023 19:37:23 -0400 Subject: [PATCH 2/9] Add changelog entry for trackpad zoom/rotate --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 10044faf..d16fb8dd 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,8 @@ information on what to include when reporting a bug. - [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless` - [EGL] Allowed native access on Wayland with `GLFW_CONTEXT_CREATION_API` set to `GLFW_NATIVE_CONTEXT_API` (#2518) + - [Cocoa] Added `glfwSetTrackpadZoomCallback` and `glfwSetTrackpadRotateCallback` + for trackpad zoom and rotate events (#90) ## Contact From 49e74fd593ca27177b46b29f68e65f71fc823e8d Mon Sep 17 00:00:00 2001 From: pfg Date: Sun, 22 Oct 2023 19:45:16 -0400 Subject: [PATCH 3/9] Add news entry for trackpad events --- docs/news.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/news.md b/docs/news.md index 148d0871..c832fa16 100644 --- a/docs/news.md +++ b/docs/news.md @@ -14,6 +14,13 @@ values over 8. For compatibility with older versions, the @ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode needs to be set to make use of this. +### Support for trackpad zoom and rotate on macOS + +Trackpad zoom and rotate events are now supported on macOS using +[glfwSetTrackpadZoomCallback](@ref glfwSetTrackpadZoomCallback) and [glfwSetTrackpadRotateCallback](@ref glfwSetTrackpadRotateCallback). These +events have not yet been implemented and currently will not emit anything on +Windows, X11, and Wayland. + ## Caveats {#caveats} ## Deprecations {#deprecations} From 549865a41a8108b1cb6c2513f5b1e1ab6f58e065 Mon Sep 17 00:00:00 2001 From: pfg Date: Thu, 11 Apr 2024 20:58:14 -0400 Subject: [PATCH 4/9] wayland support, needs review --- docs/news.md | 7 ++--- include/GLFW/glfw3.h | 4 +-- src/CMakeLists.txt | 1 + src/cocoa_window.m | 4 ++- src/wl_init.c | 16 +++++++++++ src/wl_platform.h | 6 ++++ src/wl_window.c | 65 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 96 insertions(+), 7 deletions(-) diff --git a/docs/news.md b/docs/news.md index c832fa16..7a422b14 100644 --- a/docs/news.md +++ b/docs/news.md @@ -14,12 +14,11 @@ values over 8. For compatibility with older versions, the @ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode needs to be set to make use of this. -### Support for trackpad zoom and rotate on macOS +### Support for trackpad zoom and rotate on macOS and Wayland -Trackpad zoom and rotate events are now supported on macOS using +Trackpad zoom and rotate events are now supported on macOS and Wayland using [glfwSetTrackpadZoomCallback](@ref glfwSetTrackpadZoomCallback) and [glfwSetTrackpadRotateCallback](@ref glfwSetTrackpadRotateCallback). These -events have not yet been implemented and currently will not emit anything on -Windows, X11, and Wayland. +events will not yet emit anything on Windows or X11. ## Caveats {#caveats} diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index bebaf8e4..4152b648 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1880,7 +1880,7 @@ typedef void (* GLFWscrollfun)(GLFWwindow* window, double xoffset, double yoffse * @endcode * * @param[in] window The window that received the event. - * @param[in] scale The manigification amount + * @param[in] scale The manigification amount, as a scale factor * * @sa @ref glfwSetTrackpadZoomCallback * @@ -1897,7 +1897,7 @@ typedef void (* GLFWtrackpadzoomfun)(GLFWwindow* window, double scale); * @endcode * * @param[in] window The window that received the event. - * @param[in] angle The rotation amount + * @param[in] angle The rotation amount, in degrees * * @sa @ref glfwSetTrackpadRotateCallback * diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 463b898d..cbcc7b87 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -104,6 +104,7 @@ if (GLFW_BUILD_WAYLAND) generate_wayland_protocol("fractional-scale-v1.xml") generate_wayland_protocol("xdg-activation-v1.xml") generate_wayland_protocol("xdg-decoration-unstable-v1.xml") + generate_wayland_protocol("pointer-gestures-unstable-v1.xml") endif() if (WIN32 AND GLFW_BUILD_SHARED_LIBRARY) diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 05cb2e51..ea84d9ab 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -618,8 +618,10 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; { double magnification = [event magnification]; + // 1.0 is added to convert the magnification value to a scale factor, + // as suggested in apple documentation if (fabs(magnification) > 0.0) - _glfwInputTrackpadZoom(window, magnification); + _glfwInputTrackpadZoom(window, magnification + 1.0); } - (void)rotateWithEvent:(NSEvent *)event diff --git a/src/wl_init.c b/src/wl_init.c index 76054bc6..3c63ad84 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -49,6 +49,7 @@ #include "fractional-scale-v1-client-protocol.h" #include "xdg-activation-v1-client-protocol.h" #include "idle-inhibit-unstable-v1-client-protocol.h" +#include "pointer-gestures-unstable-v1-client-protocol.h" // NOTE: Versions of wayland-scanner prior to 1.17.91 named every global array of // wl_interface pointers 'types', making it impossible to combine several unmodified @@ -91,6 +92,10 @@ #include "idle-inhibit-unstable-v1-client-protocol-code.h" #undef types +#define types _glfw_pointer_gestures_types +#include "wayland-pointer-gestures-unstable-v1-client-protocol-code.h" +#undef types + static void wmBaseHandlePing(void* userData, struct xdg_wm_base* wmBase, uint32_t serial) @@ -207,6 +212,13 @@ static void registryHandleGlobal(void* userData, wl_registry_bind(registry, name, &wp_fractional_scale_manager_v1_interface, 1); + else if (strcmp(interface, "zwp_pointer_gestures_v1") == 0) + { + _glfw.wl.pointerGestures = + wl_registry_bind(registry, name, + &zwp_pointer_gestures_v1_interface, + 1); + _glfwAddPointerGesturesListeners(_glfw.wl.pointerGestures); } } @@ -984,6 +996,10 @@ void _glfwTerminateWayland(void) xdg_activation_v1_destroy(_glfw.wl.activationManager); if (_glfw.wl.fractionalScaleManager) wp_fractional_scale_manager_v1_destroy(_glfw.wl.fractionalScaleManager); + if (_glfw.wl.pinchGesture) + zwp_pointer_gesture_pinch_v1_destroy(_glfw.wl.pinchGesture); + if (_glfw.wl.pointerGestures) + zwp_pointer_gestures_v1_destroy(_glfw.wl.pointerGestures); if (_glfw.wl.registry) wl_registry_destroy(_glfw.wl.registry); if (_glfw.wl.display) diff --git a/src/wl_platform.h b/src/wl_platform.h index f3e8cba2..71da0913 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -117,6 +117,7 @@ struct wl_output; #define zwp_pointer_constraints_v1_interface _glfw_zwp_pointer_constraints_v1_interface #define zwp_relative_pointer_v1_interface _glfw_zwp_relative_pointer_v1_interface #define zwp_relative_pointer_manager_v1_interface _glfw_zwp_relative_pointer_manager_v1_interface +#define zwp_pointer_gestures_v1_interface _glfw_zwp_pointer_gestures_v1_interface #define wp_viewport_interface _glfw_wp_viewport_interface #define wp_viewporter_interface _glfw_wp_viewporter_interface #define xdg_toplevel_interface _glfw_xdg_toplevel_interface @@ -435,6 +436,8 @@ typedef struct _GLFWlibraryWayland struct zwp_idle_inhibit_manager_v1* idleInhibitManager; struct xdg_activation_v1* activationManager; struct wp_fractional_scale_manager_v1* fractionalScaleManager; + struct zwp_pointer_gestures_v1* pointerGestures; + struct zwp_pointer_gesture_pinch_v1* pinchGesture; _GLFWofferWayland* offers; unsigned int offerCount; @@ -466,6 +469,8 @@ typedef struct _GLFWlibraryWayland short int scancodes[GLFW_KEY_LAST + 1]; char keynames[GLFW_KEY_LAST + 1][5]; + double pinchGesturePreviousScale; + struct { void* handle; struct xkb_context* context; @@ -686,4 +691,5 @@ void _glfwUpdateBufferScaleFromOutputsWayland(_GLFWwindow* window); void _glfwAddSeatListenerWayland(struct wl_seat* seat); void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device); +void _glfwAddPointerGesturesListeners(struct zwp_pointer_gestures_v1* pointer_gestures); diff --git a/src/wl_window.c b/src/wl_window.c index 2e842aaa..09493134 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -51,6 +51,7 @@ #include "xdg-activation-v1-client-protocol.h" #include "idle-inhibit-unstable-v1-client-protocol.h" #include "fractional-scale-v1-client-protocol.h" +#include "pointer-gestures-unstable-v1-client-protocol.h" #define GLFW_BORDER_SIZE 4 #define GLFW_CAPTION_HEIGHT 24 @@ -1631,6 +1632,53 @@ static const struct wl_pointer_listener pointerListener = pointerHandleAxis, }; +static void pointerGesturesHandlePinchBegin(void *userData, + struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, + uint32_t serial, + uint32_t time, + struct wl_surface *surface, + uint32_t fingers) +{ + _glfw.wl.pinchGesturePreviousScale = 1.0; +} + +static void pointerGesturesHandlePinchMotion(void *userData, + 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) +{ + _GLFWwindow* window = _glfw.wl.pointerFocus; + + double zoom_value = wl_fixed_to_double(scale); + double prev_zoom_value = _glfw.wl.pinchGesturePreviousScale; + double zoom_delta = zoom_value / prev_zoom_value; + _glfw.wl.pinchGesturePreviousScale = zoom_value; + + double rotation_value = wl_fixed_to_double(rotation); + + _glfwInputTrackpadZoom(window, zoom_delta); + _glfwInputTrackpadRotate(window, rotation_value); +} + +static void pointerGesturesHandlePinchEnd(void *userData, + struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, + uint32_t serial, + uint32_t time, + int32_t cancelled) +{ + _glfw.wl.pinchGesturePreviousScale = 1.0; +} + +static const struct zwp_pointer_gesture_pinch_v1_listener pinchGestureListener = +{ + pointerGesturesHandlePinchBegin, + pointerGesturesHandlePinchMotion, + pointerGesturesHandlePinchEnd, +}; + static void keyboardHandleKeymap(void* userData, struct wl_keyboard* keyboard, uint32_t format, @@ -1885,6 +1933,8 @@ static void seatHandleCapabilities(void* userData, { _glfw.wl.pointer = wl_seat_get_pointer(seat); wl_pointer_add_listener(_glfw.wl.pointer, &pointerListener, NULL); + + _glfwAddPointerGesturesListeners(_glfw.wl.pointerGestures); } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && _glfw.wl.pointer) { @@ -2120,6 +2170,21 @@ void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device) wl_data_device_add_listener(device, &dataDeviceListener, NULL); } +void _glfwAddPointerGesturesListeners(struct zwp_pointer_gestures_v1* pointer_gestures) +{ + if (_glfw.wl.pinchGesture) return; + if (!_glfw.wl.pointer) return; + + _glfw.wl.pinchGesture = + zwp_pointer_gestures_v1_get_pinch_gesture( + pointer_gestures, + _glfw.wl.pointer); + zwp_pointer_gesture_pinch_v1_add_listener(_glfw.wl.pinchGesture, + &pinchGestureListener, + NULL); + // zwp_pointer_gestures_v1 +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// From ecf1351ef09730cb4d571fb6c4e0fea5b088b78a Mon Sep 17 00:00:00 2001 From: pfg Date: Tue, 16 Apr 2024 14:41:35 -0400 Subject: [PATCH 5/9] Add protocol usage note --- docs/compat.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/compat.md b/docs/compat.md index 5072d5c1..e85d723e 100644 --- a/docs/compat.md +++ b/docs/compat.md @@ -158,6 +158,12 @@ less than the actual scale. [fractional-scale-v1]: https://wayland.app/protocols/fractional-scale-v1 +GLFW uses the [pointer-gestures-unstable-v1][] protocol to handle trackpad +pinch and rotate gestures. If the running compositor does not support this +protocol, trackpad pinch and rotate gestures will not be emitted. + +[pointer-gestures-unstable-v1]: https://wayland.app/protocols/pointer-gestures-unstable-v1 + ## GLX extensions {#compat_glx} From 4207999bb3600a468ce41a8b335e8125a4037851 Mon Sep 17 00:00:00 2001 From: pfg Date: Tue, 16 Apr 2024 14:45:04 -0400 Subject: [PATCH 6/9] Fix build after rebase --- deps/wayland/pointer-gestures-unstable-v1.xml | 253 ++++++++++++++++++ src/wl_init.c | 1 + 2 files changed, 254 insertions(+) create mode 100644 deps/wayland/pointer-gestures-unstable-v1.xml diff --git a/deps/wayland/pointer-gestures-unstable-v1.xml b/deps/wayland/pointer-gestures-unstable-v1.xml new file mode 100644 index 00000000..f92a1160 --- /dev/null +++ b/deps/wayland/pointer-gestures-unstable-v1.xml @@ -0,0 +1,253 @@ + + + + + + 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. + + + + + Create a swipe gesture object. See the + wl_pointer_gesture_swipe interface for details. + + + + + + + + Create a pinch gesture object. See the + wl_pointer_gesture_pinch interface for details. + + + + + + + + + + Destroy the pointer gesture object. Swipe, pinch and hold objects + created via this gesture object remain valid. + + + + + + + + Create a hold gesture object. See the + wl_pointer_gesture_hold interface for details. + + + + + + + + + + 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. + + + + + + + + + This event is sent when a multi-finger swipe gesture is detected + on the device. + + + + + + + + + + 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. + + + + + + + + + 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. + + + + + + + + + + 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. + + + + + + + + + This event is sent when a multi-finger pinch gesture is detected + on the device. + + + + + + + + + + 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. + + + + + + + + + + + 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. + + + + + + + + + + + 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. + + + + + + + + + This event is sent when a hold gesture is detected on the device. + + + + + + + + + + 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. + + + + + + + + diff --git a/src/wl_init.c b/src/wl_init.c index 3c63ad84..167716af 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -212,6 +212,7 @@ static void registryHandleGlobal(void* userData, wl_registry_bind(registry, name, &wp_fractional_scale_manager_v1_interface, 1); + } else if (strcmp(interface, "zwp_pointer_gestures_v1") == 0) { _glfw.wl.pointerGestures = From 841cf79c5f76414b36fd5dfc1843d594e6e56700 Mon Sep 17 00:00:00 2001 From: pfg Date: Thu, 19 Sep 2024 17:30:23 -0500 Subject: [PATCH 7/9] Fix incorrect header file name --- src/wl_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wl_init.c b/src/wl_init.c index 167716af..e9a2ffe6 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -93,7 +93,7 @@ #undef types #define types _glfw_pointer_gestures_types -#include "wayland-pointer-gestures-unstable-v1-client-protocol-code.h" +#include "pointer-gestures-unstable-v1-client-protocol-code.h" #undef types static void wmBaseHandlePing(void* userData, From 6e19d07de886d179f814c90093c08bb607604b0f Mon Sep 17 00:00:00 2001 From: pfg Date: Thu, 19 Sep 2024 18:03:05 -0500 Subject: [PATCH 8/9] Add guide documentation & fixes --- README.md | 2 +- docs/input.md | 36 ++++++++++++++++++++++++++++++++++++ include/GLFW/glfw3.h | 3 ++- src/input.c | 2 +- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d16fb8dd..a32c395d 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ information on what to include when reporting a bug. - [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless` - [EGL] Allowed native access on Wayland with `GLFW_CONTEXT_CREATION_API` set to `GLFW_NATIVE_CONTEXT_API` (#2518) - - [Cocoa] Added `glfwSetTrackpadZoomCallback` and `glfwSetTrackpadRotateCallback` + - [Cocoa & Wayland] Added `glfwSetTrackpadZoomCallback` and `glfwSetTrackpadRotateCallback` for trackpad zoom and rotate events (#90) diff --git a/docs/input.md b/docs/input.md index 3ef1aebe..2bfa9c7d 100644 --- a/docs/input.md +++ b/docs/input.md @@ -581,6 +581,42 @@ void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) A normal mouse wheel, being vertical, provides offsets along the Y-axis. +### Trackpad zoom and rotate {#input_mouse_trackpad_gestures} + +Trackpad events are currently only available on macOS and Wayland (Linux). + +If you wish to be notified when a zoom gesture is performed on a trackpad, +set the trackpadZoom callback. + +```c +glfwSetTrackpadZoomCallback(window, trackpad_zoom_callback); +``` + +The callback function receives the scale of the zoom, which is a ratio that +should be multiplied by the current zoom level to get the new zoom level. + +```c +static void trackpad_zoom_callback(GLFWwindow* window, double scale) +{ + my_app->zoom_level *= scale; +} +``` + +For trackpad rotate gestures, set the trackpadRotateCallback. + +```c +glfwSetTrackpadRotateCallback(window, trackpad_rotate_callback); +``` + +The callback function recieves the angle, in degrees, to rotate by. + +```c +static void trackpad_rotate_callback(GLFWwindow* window, double angle) +{ + my_app->rotation_angle_degrees += angle; +} +``` + ## Joystick input {#joystick} diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 4152b648..48579930 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1880,7 +1880,8 @@ typedef void (* GLFWscrollfun)(GLFWwindow* window, double xoffset, double yoffse * @endcode * * @param[in] window The window that received the event. - * @param[in] scale The manigification amount, as a scale factor + * @param[in] scale The manigification amount, to be multiplied by the current + * scale factor to get the new scale factor. * * @sa @ref glfwSetTrackpadZoomCallback * diff --git a/src/input.c b/src/input.c index 4aa44e3d..17c66b64 100644 --- a/src/input.c +++ b/src/input.c @@ -1069,7 +1069,7 @@ GLFWAPI GLFWtrackpadzoomfun glfwSetTrackpadZoomCallback(GLFWwindow* handle, return cbfun; } -GLFWAPI GLFWtrackpadzoomfun glfwSetTrackpadRotateCallback(GLFWwindow* handle, +GLFWAPI GLFWtrackpadrotatefun glfwSetTrackpadRotateCallback(GLFWwindow* handle, GLFWtrackpadrotatefun cbfun) { _GLFWwindow* window = (_GLFWwindow*) handle; From 17d9c90d3f3ab2b6a6e07408ee0fbe255e73c619 Mon Sep 17 00:00:00 2001 From: pfg Date: Thu, 19 Sep 2024 18:07:37 -0500 Subject: [PATCH 9/9] Finish checklist --- CONTRIBUTORS.md | 1 + include/GLFW/glfw3.h | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 1371aedb..3e1d1bc0 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -294,6 +294,7 @@ video tutorials. - Jonas Ådahl - Lasse Öörni - Leonard König + - pfgithub - All the unmentioned and anonymous contributors in the GLFW community, for bug reports, patches, feedback, testing and encouragement diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 48579930..20d548e2 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -5487,6 +5487,10 @@ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun ca * * @thread_safety This function must only be called from the main thread. * + * @sa @ref input_mouse_trackpad_gestures + * + * @since Added in version 3.5. + * * @ingroup input */ GLFWAPI GLFWtrackpadzoomfun glfwSetTrackpadZoomCallback(GLFWwindow* window, GLFWtrackpadzoomfun callback); @@ -5513,6 +5517,10 @@ GLFWAPI GLFWtrackpadzoomfun glfwSetTrackpadZoomCallback(GLFWwindow* window, GLFW * * @thread_safety This function must only be called from the main thread. * + * @sa @ref input_mouse_trackpad_gestures + * + * @since Added in version 3.5. + * * @ingroup input */ GLFWAPI GLFWtrackpadrotatefun glfwSetTrackpadRotateCallback(GLFWwindow* window, GLFWtrackpadrotatefun callback);