Merge branch 'glfw:master' into application-badge

This commit is contained in:
Jan Schürkamp 2023-12-08 20:54:26 +01:00 committed by GitHub
commit 0d9f1d625e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 153 additions and 64 deletions

View File

@ -66,6 +66,7 @@ video tutorials.
- Nikita Fediuchin - Nikita Fediuchin
- Felipe Ferreira - Felipe Ferreira
- Michael Fogleman - Michael Fogleman
- forworldm
- Jason Francis - Jason Francis
- Gerald Franz - Gerald Franz
- Mário Freitas - Mário Freitas
@ -78,6 +79,7 @@ video tutorials.
- Kovid Goyal - Kovid Goyal
- Kevin Grandemange - Kevin Grandemange
- Eloi Marín Gratacós - Eloi Marín Gratacós
- Grzesiek11
- Stefan Gustavson - Stefan Gustavson
- Andrew Gutekanst - Andrew Gutekanst
- Stephen Gutekanst - Stephen Gutekanst
@ -102,6 +104,7 @@ video tutorials.
- Andreas O. Jansen - Andreas O. Jansen
- Erik S. V. Jansson - Erik S. V. Jansson
- jjYBdx4IL - jjYBdx4IL
- Peter Johnson
- Toni Jovanoski - Toni Jovanoski
- Arseny Kapoulkine - Arseny Kapoulkine
- Cem Karan - Cem Karan
@ -214,6 +217,7 @@ video tutorials.
- Matt Sealey - Matt Sealey
- Steve Sexton - Steve Sexton
- Arkady Shapkin - Arkady Shapkin
- Mingjie Shen
- Ali Sherief - Ali Sherief
- Yoshiki Shibukawa - Yoshiki Shibukawa
- Dmitri Shuralyov - Dmitri Shuralyov
@ -251,6 +255,7 @@ video tutorials.
- Jari Vetoniemi - Jari Vetoniemi
- Ricardo Vieira - Ricardo Vieira
- Nicholas Vitovitch - Nicholas Vitovitch
- Vladimír Vondruš
- Simon Voordouw - Simon Voordouw
- Corentin Wallez - Corentin Wallez
- Torsten Walluhn - Torsten Walluhn

View File

@ -185,7 +185,8 @@ information on what to include when reporting a bug.
- Bugfix: `glfwMakeContextCurrent` would access TLS slot before initialization - Bugfix: `glfwMakeContextCurrent` would access TLS slot before initialization
- Bugfix: `glfwSetGammaRamp` could emit `GLFW_INVALID_VALUE` before initialization - Bugfix: `glfwSetGammaRamp` could emit `GLFW_INVALID_VALUE` before initialization
- Bugfix: `glfwGetJoystickUserPointer` returned `NULL` during disconnection (#2092) - Bugfix: `glfwGetJoystickUserPointer` returned `NULL` during disconnection (#2092)
- [Win32] Fix pkg-config for dynamic library on Windows (#2386, #2420) - Bugfix: `glfwGetKeyScancode` returned `0` on error when initialized instead of `-1`
- Bugfix: Failure to make a newly created context current could cause segfault (#2327)
- [Win32] Added the `GLFW_WIN32_KEYBOARD_MENU` window hint for enabling access - [Win32] Added the `GLFW_WIN32_KEYBOARD_MENU` window hint for enabling access
to the window menu to the window menu
- [Win32] Added a version info resource to the GLFW DLL - [Win32] Added a version info resource to the GLFW DLL
@ -233,6 +234,8 @@ information on what to include when reporting a bug.
- [Win32] Bugfix: The OSMesa library was not unloaded on termination - [Win32] Bugfix: The OSMesa library was not unloaded on termination
- [Win32] Bugfix: Right shift emitted `GLFW_KEY_UNKNOWN` when using a CJK IME (#2050) - [Win32] Bugfix: Right shift emitted `GLFW_KEY_UNKNOWN` when using a CJK IME (#2050)
- [Win32] Bugfix: `glfwWaitEventsTimeout` did not return for some sent messages (#2408) - [Win32] Bugfix: `glfwWaitEventsTimeout` did not return for some sent messages (#2408)
- [Win32] Bugfix: Fix pkg-config for dynamic library on Windows (#2386, #2420)
- [Win32] Bugfix: XInput could reportedly provide invalid DPad bit masks (#2291)
- [Cocoa] Added support for `VK_EXT_metal_surface` (#1619) - [Cocoa] Added support for `VK_EXT_metal_surface` (#1619)
- [Cocoa] Added locating the Vulkan loader at runtime in an application bundle - [Cocoa] Added locating the Vulkan loader at runtime in an application bundle
- [Cocoa] Moved main menu creation to GLFW initialization time (#1649) - [Cocoa] Moved main menu creation to GLFW initialization time (#1649)
@ -273,6 +276,8 @@ information on what to include when reporting a bug.
application (#2110) application (#2110)
- [Cocoa] Bugfix: The Vulkan loader was not loaded from the `Frameworks` bundle - [Cocoa] Bugfix: The Vulkan loader was not loaded from the `Frameworks` bundle
subdirectory (#2113,#2120) subdirectory (#2113,#2120)
- [Cocoa] Bugfix: Compilation failed on OS X 10.8 due to unconditional use of 10.9+
symbols (#2161)
- [X11] Bugfix: The CMake files did not check for the XInput headers (#1480) - [X11] Bugfix: The CMake files did not check for the XInput headers (#1480)
- [X11] Bugfix: Key names were not updated when the keyboard layout changed - [X11] Bugfix: Key names were not updated when the keyboard layout changed
(#1462,#1528) (#1462,#1528)

View File

@ -95,7 +95,7 @@ new size before everything returns back out of the @ref glfwSetWindowSize call.
GLFW divides keyboard input into two categories; key events and character GLFW divides keyboard input into two categories; key events and character
events. Key events relate to actual physical keyboard keys, whereas character events. Key events relate to actual physical keyboard keys, whereas character
events relate to the Unicode code points generated by pressing some of them. events relate to the text that is generated by pressing some of them.
Keys and characters do not map 1:1. A single key press may produce several Keys and characters do not map 1:1. A single key press may produce several
characters, and a single character may require several keys to produce. This characters, and a single character may require several keys to produce. This
@ -127,6 +127,10 @@ The action is one of `GLFW_PRESS`, `GLFW_REPEAT` or `GLFW_RELEASE`. Events with
`GLFW_PRESS` and `GLFW_RELEASE` actions are emitted for every key press. Most `GLFW_PRESS` and `GLFW_RELEASE` actions are emitted for every key press. Most
keys will also emit events with `GLFW_REPEAT` actions while a key is held down. keys will also emit events with `GLFW_REPEAT` actions while a key is held down.
Note that many keyboards have a limit on how many keys being simultaneous held
down that they can detect. This limit is called
[key rollover](https://en.wikipedia.org/wiki/Key_rollover).
Key events with `GLFW_REPEAT` actions are intended for text input. They are Key events with `GLFW_REPEAT` actions are intended for text input. They are
emitted at the rate set in the user's keyboard settings. At most one key is emitted at the rate set in the user's keyboard settings. At most one key is
repeated even if several keys are held down. `GLFW_REPEAT` actions should not repeated even if several keys are held down. `GLFW_REPEAT` actions should not
@ -142,16 +146,16 @@ keys.
The scancode is unique for every key, regardless of whether it has a key token. The scancode is unique for every key, regardless of whether it has a key token.
Scancodes are platform-specific but consistent over time, so keys will have Scancodes are platform-specific but consistent over time, so keys will have
different scancodes depending on the platform but they are safe to save to disk. different scancodes depending on the platform but they are safe to save to disk.
You can query the scancode for any [named key](@ref keys) on the current You can query the scancode for any [key token](@ref keys) supported on the
platform with @ref glfwGetKeyScancode. current platform with @ref glfwGetKeyScancode.
@code @code
const int scancode = glfwGetKeyScancode(GLFW_KEY_X); const int scancode = glfwGetKeyScancode(GLFW_KEY_X);
set_key_mapping(scancode, swap_weapons); set_key_mapping(scancode, swap_weapons);
@endcode @endcode
The last reported state for every [named key](@ref keys) is also saved in The last reported state for every physical key with a [key token](@ref keys) is
per-window state arrays that can be polled with @ref glfwGetKey. also saved in per-window state arrays that can be polled with @ref glfwGetKey.
@code @code
int state = glfwGetKey(window, GLFW_KEY_E); int state = glfwGetKey(window, GLFW_KEY_E);
@ -164,7 +168,8 @@ if (state == GLFW_PRESS)
The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`. The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
This function only returns cached key event state. It does not poll the This function only returns cached key event state. It does not poll the
system for the current physical state of the key. system for the current state of the physical key. It also does not provide any
key repeat information.
@anchor GLFW_STICKY_KEYS @anchor GLFW_STICKY_KEYS
Whenever you poll state, you risk missing the state change you are looking for. Whenever you poll state, you risk missing the state change you are looking for.
@ -195,15 +200,15 @@ Lock was on when the event occurred and the @ref GLFW_MOD_NUM_LOCK bit set if
Num Lock was on. Num Lock was on.
The `GLFW_KEY_LAST` constant holds the highest value of any The `GLFW_KEY_LAST` constant holds the highest value of any
[named key](@ref keys). [key token](@ref keys).
@subsection input_char Text input @subsection input_char Text input
GLFW supports text input in the form of a stream of GLFW supports text input in the form of a stream of
[Unicode code points](https://en.wikipedia.org/wiki/Unicode), as produced by the [Unicode code points](https://en.wikipedia.org/wiki/Unicode), as produced by the
operating system text input system. Unlike key input, text input obeys keyboard operating system text input system. Unlike key input, text input is affected by
layouts and modifier keys and supports composing characters using keyboard layouts and modifier keys and supports composing characters using
[dead keys](https://en.wikipedia.org/wiki/Dead_key). Once received, you can [dead keys](https://en.wikipedia.org/wiki/Dead_key). Once received, you can
encode the code points into UTF-8 or any other encoding you prefer. encode the code points into UTF-8 or any other encoding you prefer.
@ -502,8 +507,9 @@ void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
The action is one of `GLFW_PRESS` or `GLFW_RELEASE`. The action is one of `GLFW_PRESS` or `GLFW_RELEASE`.
Mouse button states for [named buttons](@ref buttons) are also saved in The last reported state for every [supported mouse button](@ref buttons) is also
per-window state arrays that can be polled with @ref glfwGetMouseButton. saved in per-window state arrays that can be polled with @ref
glfwGetMouseButton.
@code @code
int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT); int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
@ -536,7 +542,7 @@ had been processed in the meantime, the state will reset to `GLFW_RELEASE`,
otherwise it will remain `GLFW_PRESS`. otherwise it will remain `GLFW_PRESS`.
The `GLFW_MOUSE_BUTTON_LAST` constant holds the highest value of any The `GLFW_MOUSE_BUTTON_LAST` constant holds the highest value of any
[named button](@ref buttons). [supported mouse button](@ref buttons).
@subsection scrolling Scroll input @subsection scrolling Scroll input

View File

@ -277,6 +277,7 @@ then GLFW will fail to initialize.
- @ref GLFW_POSITION_X - @ref GLFW_POSITION_X
- @ref GLFW_POSITION_Y - @ref GLFW_POSITION_Y
- @ref GLFW_ANY_POSITION - @ref GLFW_ANY_POSITION
- @ref GLFW_WAYLAND_APP_ID
- @ref GLFW_WAYLAND_LIBDECOR - @ref GLFW_WAYLAND_LIBDECOR
- @ref GLFW_WAYLAND_PREFER_LIBDECOR - @ref GLFW_WAYLAND_PREFER_LIBDECOR
- @ref GLFW_WAYLAND_DISABLE_LIBDECOR - @ref GLFW_WAYLAND_DISABLE_LIBDECOR

View File

@ -361,10 +361,15 @@ extern "C" {
#define GLFW_HAT_RIGHT_DOWN (GLFW_HAT_RIGHT | GLFW_HAT_DOWN) #define GLFW_HAT_RIGHT_DOWN (GLFW_HAT_RIGHT | GLFW_HAT_DOWN)
#define GLFW_HAT_LEFT_UP (GLFW_HAT_LEFT | GLFW_HAT_UP) #define GLFW_HAT_LEFT_UP (GLFW_HAT_LEFT | GLFW_HAT_UP)
#define GLFW_HAT_LEFT_DOWN (GLFW_HAT_LEFT | GLFW_HAT_DOWN) #define GLFW_HAT_LEFT_DOWN (GLFW_HAT_LEFT | GLFW_HAT_DOWN)
/*! @ingroup input
*/
#define GLFW_KEY_UNKNOWN -1
/*! @} */ /*! @} */
/*! @defgroup keys Keyboard keys /*! @defgroup keys Keyboard key tokens
* @brief Keyboard key IDs. * @brief Keyboard key tokens.
* *
* See [key input](@ref input_key) for how these are used. * See [key input](@ref input_key) for how these are used.
* *
@ -387,9 +392,6 @@ extern "C" {
* @{ * @{
*/ */
/* The unknown key */
#define GLFW_KEY_UNKNOWN -1
/* Printable keys */ /* Printable keys */
#define GLFW_KEY_SPACE 32 #define GLFW_KEY_SPACE 32
#define GLFW_KEY_APOSTROPHE 39 /* ' */ #define GLFW_KEY_APOSTROPHE 39 /* ' */
@ -4872,8 +4874,8 @@ GLFWAPI int glfwRawMouseMotionSupported(void);
* @param[in] scancode The scancode of the key to query. * @param[in] scancode The scancode of the key to query.
* @return The UTF-8 encoded, layout-specific name of the key, or `NULL`. * @return The UTF-8 encoded, layout-specific name of the key, or `NULL`.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR. * GLFW_INVALID_VALUE, @ref GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
* *
* @remark The contents of the returned string may change when a keyboard * @remark The contents of the returned string may change when a keyboard
* layout change event is received. * layout change event is received.
@ -4895,15 +4897,18 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode);
* *
* This function returns the platform-specific scancode of the specified key. * This function returns the platform-specific scancode of the specified key.
* *
* If the key is `GLFW_KEY_UNKNOWN` or does not exist on the keyboard this * If the specified [key token](@ref keys) corresponds to a physical key not
* method will return `-1`. * supported on the current platform then this method will return `-1`.
* Calling this function with anything other than a key token will return `-1`
* and generate a @ref GLFW_INVALID_ENUM error.
* *
* @param[in] key Any [named key](@ref keys). * @param[in] key Any [key token](@ref keys).
* @return The platform-specific scancode for the key, or `-1` if an * @return The platform-specific scancode for the key, or `-1` if the key is
* [error](@ref error_handling) occurred. * not supported on the current platform or an [error](@ref error_handling)
* occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * GLFW_INVALID_ENUM.
* *
* @thread_safety This function may be called from any thread. * @thread_safety This function may be called from any thread.
* *
@ -5212,9 +5217,9 @@ GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor);
* [character callback](@ref glfwSetCharCallback) instead. * [character callback](@ref glfwSetCharCallback) instead.
* *
* When a window loses input focus, it will generate synthetic key release * When a window loses input focus, it will generate synthetic key release
* events for all pressed keys. You can tell these events from user-generated * events for all pressed keys with associated key tokens. You can tell these
* events by the fact that the synthetic ones are generated after the focus * events from user-generated events by the fact that the synthetic ones are
* loss event has been processed, i.e. after the * generated after the focus loss event has been processed, i.e. after the
* [window focus callback](@ref glfwSetWindowFocusCallback) has been called. * [window focus callback](@ref glfwSetWindowFocusCallback) has been called.
* *
* The scancode of a key is specific to that platform or sometimes even to that * The scancode of a key is specific to that platform or sometimes even to that
@ -6113,12 +6118,15 @@ GLFWAPI uint64_t glfwGetTimerFrequency(void);
* thread. * thread.
* *
* This function makes the OpenGL or OpenGL ES context of the specified window * This function makes the OpenGL or OpenGL ES context of the specified window
* current on the calling thread. A context must only be made current on * current on the calling thread. It can also detach the current context from
* a single thread at a time and each thread can have only a single current * the calling thread without making a new one current by passing in `NULL`.
* context at a time.
* *
* When moving a context between threads, you must make it non-current on the * A context must only be made current on a single thread at a time and each
* old thread before making it current on the new one. * thread can have only a single current context at a time. Making a context
* current detaches any previously current context on the calling thread.
*
* When moving a context between threads, you must detach it (make it
* non-current) on the old thread before making it current on the new one.
* *
* By default, making a context non-current implicitly forces a pipeline flush. * By default, making a context non-current implicitly forces a pipeline flush.
* On machines that support `GL_KHR_context_flush_control`, you can control * On machines that support `GL_KHR_context_flush_control`, you can control
@ -6133,6 +6141,10 @@ GLFWAPI uint64_t glfwGetTimerFrequency(void);
* @param[in] window The window whose context to make current, or `NULL` to * @param[in] window The window whose context to make current, or `NULL` to
* detach the current context. * detach the current context.
* *
* @remarks If the previously current context was created via a different
* context creation API than the one passed to this function, GLFW will still
* detach the previous one from its API before making the new one current.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.
* *

View File

@ -388,10 +388,15 @@ static void setDockProgressIndicator(int progressState, double value)
- (void)windowDidChangeOcclusionState:(NSNotification* )notification - (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) if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible)
window->ns.occluded = GLFW_FALSE; window->ns.occluded = GLFW_FALSE;
else else
window->ns.occluded = GLFW_TRUE; window->ns.occluded = GLFW_TRUE;
}
#endif
} }
@end @end

View File

@ -363,6 +363,8 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
previous = _glfwPlatformGetTls(&_glfw.contextSlot); previous = _glfwPlatformGetTls(&_glfw.contextSlot);
glfwMakeContextCurrent((GLFWwindow*) window); glfwMakeContextCurrent((GLFWwindow*) window);
if (_glfwPlatformGetTls(&_glfw.contextSlot) != window)
return GLFW_FALSE;
window->context.GetIntegerv = (PFNGLGETINTEGERVPROC) window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
window->context.getProcAddress("glGetIntegerv"); window->context.getProcAddress("glGetIntegerv");

View File

@ -311,6 +311,7 @@ static int extensionSupportedEGL(const char* extension)
static GLFWglproc getProcAddressEGL(const char* procname) static GLFWglproc getProcAddressEGL(const char* procname)
{ {
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
assert(window != NULL);
if (window->context.egl.client) if (window->context.egl.client)
{ {
@ -703,8 +704,11 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
if (!fbconfig->doublebuffer) if (!fbconfig->doublebuffer)
SET_ATTRIB(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER); SET_ATTRIB(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
if (_glfw.platform.platformID == GLFW_PLATFORM_WAYLAND)
{
if (_glfw.egl.EXT_present_opaque) if (_glfw.egl.EXT_present_opaque)
SET_ATTRIB(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent); SET_ATTRIB(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent);
}
SET_ATTRIB(EGL_NONE, EGL_NONE); SET_ATTRIB(EGL_NONE, EGL_NONE);

View File

@ -192,6 +192,7 @@ static void swapBuffersGLX(_GLFWwindow* window)
static void swapIntervalGLX(int interval) static void swapIntervalGLX(int interval)
{ {
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
assert(window != NULL);
if (_glfw.glx.EXT_swap_control) if (_glfw.glx.EXT_swap_control)
{ {

View File

@ -462,10 +462,11 @@ void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
assert(hat >= 0); assert(hat >= 0);
assert(hat < js->hatCount); assert(hat < js->hatCount);
// Valid hat values only use the least significant nibble and have at most two bits // Valid hat values only use the least significant nibble
// set, which can be considered adjacent plus an arbitrary rotation within the nibble
assert((value & 0xf0) == 0); assert((value & 0xf0) == 0);
assert((value & ((value << 2) | (value >> 2))) == 0); // Valid hat values do not have both bits of an axis set
assert((value & GLFW_HAT_LEFT) == 0 || (value & GLFW_HAT_RIGHT) == 0);
assert((value & GLFW_HAT_UP) == 0 || (value & GLFW_HAT_DOWN) == 0);
base = js->buttonCount + hat * 4; base = js->buttonCount + hat * 4;
@ -701,6 +702,12 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode)
if (key != GLFW_KEY_UNKNOWN) if (key != GLFW_KEY_UNKNOWN)
{ {
if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
{
_glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
return NULL;
}
if (key != GLFW_KEY_KP_EQUAL && if (key != GLFW_KEY_KP_EQUAL &&
(key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) && (key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) &&
(key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_WORLD_2)) (key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_WORLD_2))
@ -721,7 +728,7 @@ GLFWAPI int glfwGetKeyScancode(int key)
if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST) if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
{ {
_glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key); _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
return GLFW_RELEASE; return -1;
} }
return _glfw.platform.getKeyScancode(key); return _glfw.platform.getKeyScancode(key);

View File

@ -83,11 +83,10 @@ static void swapIntervalNSGL(int interval)
@autoreleasepool { @autoreleasepool {
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (window) assert(window != NULL);
{
[window->context.nsgl.object setValues:&interval [window->context.nsgl.object setValues:&interval
forParameter:NSOpenGLContextParameterSwapInterval]; forParameter:NSOpenGLContextParameterSwapInterval];
}
} // autoreleasepool } // autoreleasepool
} }

View File

@ -332,6 +332,7 @@ static void swapBuffersWGL(_GLFWwindow* window)
static void swapIntervalWGL(int interval) static void swapIntervalWGL(int interval)
{ {
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
assert(window != NULL);
window->context.wgl.interval = interval; window->context.wgl.interval = interval;

View File

@ -736,6 +736,13 @@ GLFWbool _glfwPollJoystickWin32(_GLFWjoystick* js, int mode)
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
dpad |= GLFW_HAT_LEFT; dpad |= GLFW_HAT_LEFT;
// Treat invalid combinations as neither being pressed
// while preserving what data can be preserved
if ((dpad & GLFW_HAT_RIGHT) && (dpad & GLFW_HAT_LEFT))
dpad &= ~(GLFW_HAT_RIGHT | GLFW_HAT_LEFT);
if ((dpad & GLFW_HAT_UP) && (dpad & GLFW_HAT_DOWN))
dpad &= ~(GLFW_HAT_UP | GLFW_HAT_DOWN);
_glfwInputJoystickHat(js, 0, dpad); _glfwInputJoystickHat(js, 0, dpad);
} }

View File

@ -40,6 +40,7 @@
#include <sys/timerfd.h> #include <sys/timerfd.h>
#include <unistd.h> #include <unistd.h>
#include <time.h> #include <time.h>
#include <assert.h>
#include "wayland-client-protocol.h" #include "wayland-client-protocol.h"
#include "wayland-xdg-shell-client-protocol.h" #include "wayland-xdg-shell-client-protocol.h"
@ -216,6 +217,22 @@ static const struct libdecor_interface libdecorInterface =
libdecorHandleError libdecorHandleError
}; };
static void libdecorReadyCallback(void* userData,
struct wl_callback* callback,
uint32_t time)
{
_glfw.wl.libdecor.ready = GLFW_TRUE;
assert(_glfw.wl.libdecor.callback == callback);
wl_callback_destroy(_glfw.wl.libdecor.callback);
_glfw.wl.libdecor.callback = NULL;
}
static const struct wl_callback_listener libdecorReadyListener =
{
libdecorReadyCallback
};
// Create key code translation tables // Create key code translation tables
// //
static void createKeyTables(void) static void createKeyTables(void)
@ -780,10 +797,17 @@ int _glfwInitWayland(void)
if (_glfw.wl.libdecor.handle) if (_glfw.wl.libdecor.handle)
{ {
_glfw.wl.libdecor.context = libdecor_new(_glfw.wl.display, &libdecorInterface); _glfw.wl.libdecor.context = libdecor_new(_glfw.wl.display, &libdecorInterface);
// Allow libdecor to receive its globals before proceeding
if (_glfw.wl.libdecor.context) if (_glfw.wl.libdecor.context)
libdecor_dispatch(_glfw.wl.libdecor.context, 1); {
// Perform an initial dispatch and flush to get the init started
libdecor_dispatch(_glfw.wl.libdecor.context, 0);
// Create sync point to "know" when libdecor is ready for use
_glfw.wl.libdecor.callback = wl_display_sync(_glfw.wl.display);
wl_callback_add_listener(_glfw.wl.libdecor.callback,
&libdecorReadyListener,
NULL);
}
} }
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION #ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
@ -827,6 +851,8 @@ void _glfwTerminateWayland(void)
_glfwTerminateEGL(); _glfwTerminateEGL();
_glfwTerminateOSMesa(); _glfwTerminateOSMesa();
if (_glfw.wl.libdecor.callback)
wl_callback_destroy(_glfw.wl.libdecor.callback);
if (_glfw.wl.libdecor.context) if (_glfw.wl.libdecor.context)
libdecor_unref(_glfw.wl.libdecor.context); libdecor_unref(_glfw.wl.libdecor.context);

View File

@ -550,6 +550,8 @@ typedef struct _GLFWlibraryWayland
struct { struct {
void* handle; void* handle;
struct libdecor* context; struct libdecor* context;
struct wl_callback* callback;
GLFWbool ready;
PFN_libdecor_new libdecor_new_; PFN_libdecor_new libdecor_new_;
PFN_libdecor_unref libdecor_unref_; PFN_libdecor_unref libdecor_unref_;
PFN_libdecor_get_fd libdecor_get_fd_; PFN_libdecor_get_fd libdecor_get_fd_;

View File

@ -735,6 +735,10 @@ static const struct libdecor_frame_interface libdecorFrameInterface =
static GLFWbool createLibdecorFrame(_GLFWwindow* window) static GLFWbool createLibdecorFrame(_GLFWwindow* window)
{ {
// Allow libdecor to finish initialization of itself and its plugin
while (!_glfw.wl.libdecor.ready)
_glfwWaitEventsWayland();
window->wl.libdecor.frame = libdecor_decorate(_glfw.wl.libdecor.context, window->wl.libdecor.frame = libdecor_decorate(_glfw.wl.libdecor.context,
window->wl.surface, window->wl.surface,
&libdecorFrameInterface, &libdecorFrameInterface,
@ -746,6 +750,11 @@ static GLFWbool createLibdecorFrame(_GLFWwindow* window)
return GLFW_FALSE; return GLFW_FALSE;
} }
struct libdecor_state* frameState =
libdecor_state_new(window->wl.width, window->wl.height);
libdecor_frame_commit(window->wl.libdecor.frame, frameState, NULL);
libdecor_state_free(frameState);
if (strlen(window->wl.appId)) if (strlen(window->wl.appId))
libdecor_frame_set_app_id(window->wl.libdecor.frame, window->wl.appId); libdecor_frame_set_app_id(window->wl.libdecor.frame, window->wl.appId);
@ -776,12 +785,6 @@ static GLFWbool createLibdecorFrame(_GLFWwindow* window)
if (window->monitor) if (window->monitor)
{ {
// HACK: Allow libdecor to finish initialization of itself and its
// plugin so it will create the xdg_toplevel for the frame
// This needs to exist when setting the frame to fullscreen
while (!libdecor_frame_get_xdg_toplevel(window->wl.libdecor.frame))
_glfwWaitEventsWayland();
libdecor_frame_set_fullscreen(window->wl.libdecor.frame, libdecor_frame_set_fullscreen(window->wl.libdecor.frame,
window->monitor->wl.output); window->monitor->wl.output);
setIdleInhibitor(window, GLFW_TRUE); setIdleInhibitor(window, GLFW_TRUE);
@ -1115,7 +1118,10 @@ static void handleEvents(double* timeout)
while (!event) while (!event)
{ {
while (wl_display_prepare_read(_glfw.wl.display) != 0) while (wl_display_prepare_read(_glfw.wl.display) != 0)
wl_display_dispatch_pending(_glfw.wl.display); {
if (wl_display_dispatch_pending(_glfw.wl.display) > 0)
return;
}
// If an error other than EAGAIN happens, we have likely been disconnected // If an error other than EAGAIN happens, we have likely been disconnected
// from the Wayland session; try to handle that the best we can. // from the Wayland session; try to handle that the best we can.
@ -1173,14 +1179,14 @@ static void handleEvents(double* timeout)
uint64_t repeats; uint64_t repeats;
if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8) if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8)
{
incrementCursorImage(_glfw.wl.pointerFocus); incrementCursorImage(_glfw.wl.pointerFocus);
event = GLFW_TRUE;
}
} }
if (fds[3].revents & POLLIN) if (fds[3].revents & POLLIN)
libdecor_dispatch(_glfw.wl.libdecor.context, 0); {
if (libdecor_dispatch(_glfw.wl.libdecor.context, 0) > 0)
event = GLFW_TRUE;
}
} }
} }