Compare commits

...

15 Commits

Author SHA1 Message Date
pfg 17d9c90d3f Finish checklist 2024-09-19 18:07:37 -05:00
pfg 6e19d07de8 Add guide documentation & fixes 2024-09-19 18:03:05 -05:00
pfg 841cf79c5f Fix incorrect header file name 2024-09-19 17:32:15 -05:00
pfg 4207999bb3 Fix build after rebase 2024-09-19 17:32:15 -05:00
pfg ecf1351ef0 Add protocol usage note 2024-09-19 17:32:15 -05:00
pfg 549865a41a wayland support, needs review 2024-09-19 17:32:15 -05:00
pfg 49e74fd593 Add news entry for trackpad events 2024-09-19 17:32:15 -05:00
pfg 9f5a4f672f Add changelog entry for trackpad zoom/rotate 2024-09-19 17:32:15 -05:00
pfg 7c93346221 Add macOS events trackpadZoom and trackpadRotate 2024-09-19 17:32:15 -05:00
Camilla Löwy b35641f4a3 Wayland: Cleanup 2024-04-12 18:27:53 +02:00
Camilla Löwy 64906f8e64 Wayland: Cleanup 2024-04-12 18:25:06 +02:00
Camilla Löwy 51b6434ac4 Wayland: Fix possible segfault on drag enter
Found with Clang static analysis.
2024-04-11 19:12:17 +02:00
Camilla Löwy dfebad786d Update macOS OpenGL compatibility notes 2024-04-07 20:56:18 +02:00
Camilla Löwy 97892c6037 Cocoa: Add QuartzCore as a link-time dependency 2024-04-07 20:55:30 +02:00
Camilla Löwy 8b574030a8 Cocoa: Remove support for OS X 10.10 Yosemite
Fixes #2506
2024-04-07 20:43:48 +02:00
19 changed files with 642 additions and 78 deletions

View File

@ -54,7 +54,7 @@ jobs:
timeout-minutes: 4
env:
CFLAGS: -Werror
MACOSX_DEPLOYMENT_TARGET: 10.8
MACOSX_DEPLOYMENT_TARGET: 10.11
CMAKE_OSX_ARCHITECTURES: x86_64;arm64
steps:
- uses: actions/checkout@v4

View File

@ -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

View File

@ -79,7 +79,7 @@ more information.
## System requirements
GLFW supports Windows XP and later and macOS 10.8 and later. Linux and other
GLFW supports Windows XP and later and macOS 10.11 and later. Linux and other
Unix-like systems running the X Window System are supported even without
a desktop environment or modern extensions, although some features require
a running window or clipboard manager. The OSMesa backend requires Mesa 6.3.
@ -123,12 +123,17 @@ information on what to include when reporting a bug.
- Added `GLFW_UNLIMITED_MOUSE_BUTTONS` input mode that allows mouse buttons beyond
the limit of the mouse button tokens to be reported (#2423)
- [Cocoa] Added `QuartzCore` framework as link-time dependency
- [Cocoa] Removed support for OS X 10.10 Yosemite and earlier (#2506)
- [Wayland] Bugfix: The fractional scaling related objects were not destroyed
- [Wayland] Bugfix: `glfwInit` would segfault on compositor with no seat (#2517)
- [Wayland] Bugfix: A drag entering a non-GLFW surface could cause a segfault
- [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface`
- [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 & Wayland] Added `glfwSetTrackpadZoomCallback` and `glfwSetTrackpadRotateCallback`
for trackpad zoom and rotate events (#90)
## Contact

View 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>

View File

@ -390,8 +390,8 @@ If you are using the dynamic library version of GLFW, add it to the project
dependencies.
If you are using the static library version of GLFW, add it and the Cocoa,
OpenGL and IOKit frameworks to the project as dependencies. They can all be
found in `/System/Library/Frameworks`.
OpenGL, IOKit and QuartzCore frameworks to the project as dependencies. They
can all be found in `/System/Library/Frameworks`.
### With command-line or makefile on macOS {#build_link_osx}
@ -405,7 +405,7 @@ command-line yourself using the `-l` and `-framework` switches.
If you are using the dynamic GLFW library, which is named `libglfw.3.dylib`, do:
```sh
cc -o myprog myprog.c -lglfw -framework Cocoa -framework OpenGL -framework IOKit
cc -o myprog myprog.c -lglfw -framework Cocoa -framework OpenGL -framework IOKit -framework QuartzCore
```
If you are using the static library, named `libglfw3.a`, substitute `-lglfw3`

View File

@ -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}
@ -242,24 +248,27 @@ extensions are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect.
## OpenGL on macOS {#compat_osx}
Support for OpenGL 3.2 and above was introduced with OS X 10.7 and even then
only forward-compatible, core profile contexts are supported. Support for
OpenGL 4.1 was introduced with OS X 10.9, also limited to forward-compatible,
core profile contexts. There is also still no mechanism for requesting debug
contexts or no-error contexts. Versions of Mac OS X earlier than 10.7 support
at most OpenGL version 2.1.
macOS (as of version 14) still provides OpenGL but it has been deprecated by
Apple. While the API is still available, it is poorly maintained and frequently
develops new issues. On modern systems, OpenGL is implemented on top of Metal
and is not fully thread-safe.
Because of this, on OS X 10.7 and later, the `GLFW_CONTEXT_VERSION_MAJOR` and
`GLFW_CONTEXT_VERSION_MINOR` hints will cause @ref glfwCreateWindow to fail if
given version 3.0 or 3.1. The `GLFW_OPENGL_PROFILE` hint must be set to
`GLFW_OPENGL_CORE_PROFILE` when creating OpenGL 3.2 and later contexts. The
`GLFW_CONTEXT_DEBUG` and `GLFW_CONTEXT_NO_ERROR` hints are ignored.
macOS does not support OpenGL stereo rendering. If the `GLFW_STEREO` hint is
set to true, OpenGL context creation will always fail.
Also, on Mac OS X 10.6 and below, the `GLFW_CONTEXT_VERSION_MAJOR` and
`GLFW_CONTEXT_VERSION_MINOR` hints will fail if given a version above 2.1,
setting the `GLFW_OPENGL_PROFILE` or `GLFW_OPENGL_FORWARD_COMPAT` hints to
a non-default value will cause @ref glfwCreateWindow to fail and the
`GLFW_CONTEXT_DEBUG` hint is ignored.
macOS only supports OpenGL core profile contexts that are forward-compatible,
but the `GLFW_OPENGL_FORWARD_COMPAT` hint is ignored since GLFW 3.4. Even if
this hint is set to false (the default), a forward-compatible context will be
returned if available.
macOS does not support OpenGL debug contexts, no-error contexts or robustness.
The `GLFW_CONTEXT_DEBUG`, `GLFW_CONTEXT_NO_ERROR` and `GLFW_CONTEXT_ROBUSTNESS`
hints will be ignored and a context without these features will be returned.
macOS does not flush OpenGL contexts when they are made non-current. The
`GLFW_CONTEXT_RELEASE_BEHAVIOR` hint is ignored and the release behavior will
always be the equivalent of `GLFW_RELEASE_BEHAVIOR_NONE`. If you need a context
to be flushed, call `glFlush` before making it non-current.
## Vulkan loader and API {#compat_vulkan}

View File

@ -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}

View File

@ -14,6 +14,12 @@ 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 and Wayland
Trackpad zoom and rotate events are now supported on macOS and Wayland using
[glfwSetTrackpadZoomCallback](@ref glfwSetTrackpadZoomCallback) and [glfwSetTrackpadRotateCallback](@ref glfwSetTrackpadRotateCallback). These
events will not yet emit anything on Windows or X11.
## Caveats {#caveats}
## Deprecations {#deprecations}

View File

@ -1871,6 +1871,41 @@ 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, to be multiplied by the current
* scale factor to get the new scale factor.
*
* @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, in degrees
*
* @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
@ -3183,8 +3218,8 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
*
* [bundle-guide]: https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/
*
* @remark @macos On OS X 10.10 and later the window frame will not be rendered
* at full resolution on Retina displays unless the
* @remark @macos The window frame will not be rendered at full resolution on
* Retina displays unless the
* [GLFW_SCALE_FRAMEBUFFER](@ref GLFW_SCALE_FRAMEBUFFER_hint)
* hint is `GLFW_TRUE` and the `NSHighResolutionCapable` key is enabled in the
* application bundle's `Info.plist`. For more information, see
@ -5430,6 +5465,66 @@ 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.
*
* @sa @ref input_mouse_trackpad_gestures
*
* @since Added in version 3.5.
*
* @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.
*
* @sa @ref input_mouse_trackpad_gestures
*
* @since Added in version 3.5.
*
* @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

View File

@ -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)
@ -151,10 +152,11 @@ endif()
if (GLFW_BUILD_COCOA)
target_link_libraries(glfw PRIVATE "-framework Cocoa"
"-framework IOKit"
"-framework CoreFoundation")
"-framework CoreFoundation"
"-framework QuartzCore")
set(glfw_PKG_DEPS "")
set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation")
set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation -framework QuartzCore")
endif()
if (GLFW_BUILD_WAYLAND)

View File

@ -137,7 +137,7 @@ static GLFWbool modeIsGood(CGDisplayModeRef mode)
if (flags & kDisplayModeStretchedFlag)
return GLFW_FALSE;
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
#if MAC_OS_X_VERSION_MAX_ALLOWED == 101100
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) &&
CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
@ -164,7 +164,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
if (result.refreshRate == 0)
result.refreshRate = (int) round(fallbackRefreshRate);
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
#if MAC_OS_X_VERSION_MAX_ALLOWED == 101100
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0)
{
@ -180,7 +180,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
result.blueBits = 8;
}
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
#if MAC_OS_X_VERSION_MAX_ALLOWED == 101100
CFRelease(format);
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
return result;

View File

@ -28,6 +28,8 @@
#if defined(_GLFW_COCOA)
#import <QuartzCore/CAMetalLayer.h>
#include <float.h>
#include <string.h>
#include <assert.h>
@ -310,7 +312,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)windowDidChangeOcclusionState:(NSNotification* )notification
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
if ([window->ns.object respondsToSelector:@selector(occlusionState)])
{
if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible)
@ -318,7 +319,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
else
window->ns.occluded = GLFW_TRUE;
}
#endif
}
@end
@ -614,6 +614,24 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
_glfwInputScroll(window, deltaX, deltaY);
}
- (void)magnifyWithEvent:(NSEvent *)event
{
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 + 1.0);
}
- (void)rotateWithEvent:(NSEvent *)event
{
double rotation = [event rotation];
if (fabs(rotation) > 0.0)
_glfwInputTrackpadRotate(window, rotation);
}
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
// HACK: We don't know what to say here because we don't know what the
@ -1950,19 +1968,8 @@ VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance,
{
@autoreleasepool {
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
// HACK: Dynamically load Core Animation to avoid adding an extra
// dependency for the majority who don't use MoltenVK
NSBundle* bundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/QuartzCore.framework"];
if (!bundle)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Cocoa: Failed to find QuartzCore.framework");
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
// NOTE: Create the layer here as makeBackingLayer should not return nil
window->ns.layer = [[bundle classNamed:@"CAMetalLayer"] layer];
window->ns.layer = [CAMetalLayer layer];
if (!window->ns.layer)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
@ -2027,9 +2034,6 @@ VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance,
}
return err;
#else
return VK_ERROR_EXTENSION_NOT_PRESENT;
#endif
} // autoreleasepool
}

View File

@ -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 GLFWtrackpadrotatefun 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);

View File

@ -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);

View File

@ -183,16 +183,16 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
return GLFW_FALSE;
}
// Context robustness modes (GL_KHR_robustness) are not yet supported by
// Context robustness modes (GL_KHR_robustness) are not supported by
// macOS but are not a hard constraint, so ignore and continue
// Context release behaviors (GL_KHR_context_flush_control) are not yet
// Context release behaviors (GL_KHR_context_flush_control) are not
// supported by macOS but are not a hard constraint, so ignore and continue
// Debug contexts (GL_KHR_debug) are not yet supported by macOS but are not
// Debug contexts (GL_KHR_debug) are not supported by macOS but are not
// a hard constraint, so ignore and continue
// No-error contexts (GL_KHR_no_error) are not yet supported by macOS but
// No-error contexts (GL_KHR_no_error) are not supported by macOS but
// are not a hard constraint, so ignore and continue
#define ADD_ATTRIB(a) \
@ -218,14 +218,11 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
ADD_ATTRIB(kCGLPFASupportsAutomaticGraphicsSwitching);
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
if (ctxconfig->major >= 4)
{
SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
}
else
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
if (ctxconfig->major >= 3)
else if (ctxconfig->major >= 3)
{
SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
}

View File

@ -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 "pointer-gestures-unstable-v1-client-protocol-code.h"
#undef types
static void wmBaseHandlePing(void* userData,
struct xdg_wm_base* wmBase,
uint32_t serial)
@ -208,6 +213,14 @@ static void registryHandleGlobal(void* userData,
&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);
}
}
static void registryHandleGlobalRemove(void* userData,
@ -984,6 +997,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)

View File

@ -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);

View File

@ -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)
{
@ -1974,41 +2024,41 @@ static void dataDeviceHandleEnter(void* userData,
_glfw.wl.dragFocus = NULL;
}
for (unsigned int i = 0; i < _glfw.wl.offerCount; i++)
unsigned int i;
for (i = 0; i < _glfw.wl.offerCount; i++)
{
if (_glfw.wl.offers[i].offer == offer)
{
_GLFWwindow* window = NULL;
if (surface)
{
if (wl_proxy_get_tag((struct wl_proxy*) surface) == &_glfw.wl.tag)
window = wl_surface_get_user_data(surface);
break;
}
if (surface == window->wl.surface && _glfw.wl.offers[i].text_uri_list)
if (i == _glfw.wl.offerCount)
return;
if (surface && wl_proxy_get_tag((struct wl_proxy*) surface) == &_glfw.wl.tag)
{
_GLFWwindow* window = wl_surface_get_user_data(surface);
if (window->wl.surface == surface)
{
if (_glfw.wl.offers[i].text_uri_list)
{
_glfw.wl.dragOffer = offer;
_glfw.wl.dragFocus = window;
_glfw.wl.dragSerial = serial;
}
_glfw.wl.offers[i] = _glfw.wl.offers[_glfw.wl.offerCount - 1];
_glfw.wl.offerCount--;
break;
}
}
if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
return;
if (_glfw.wl.dragOffer)
wl_data_offer_accept(offer, serial, "text/uri-list");
else
}
}
}
if (!_glfw.wl.dragOffer)
{
wl_data_offer_accept(offer, serial, NULL);
wl_data_offer_destroy(offer);
}
_glfw.wl.offers[i] = _glfw.wl.offers[_glfw.wl.offerCount - 1];
_glfw.wl.offerCount--;
}
static void dataDeviceHandleLeave(void* userData,
@ -2042,6 +2092,7 @@ static void dataDeviceHandleDrop(void* userData,
int count;
char** paths = _glfwParseUriList(string, &count);
if (paths)
{
_glfwInputDrop(_glfw.wl.dragFocus, count, (const char**) paths);
for (int i = 0; i < count; i++)
@ -2051,6 +2102,7 @@ static void dataDeviceHandleDrop(void* userData,
}
_glfw_free(string);
}
}
static void dataDeviceHandleSelection(void* userData,
@ -2118,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 //////

View File

@ -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);