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
- Felipe Ferreira
- Michael Fogleman
- forworldm
- Jason Francis
- Gerald Franz
- Mário Freitas
@ -78,6 +79,7 @@ video tutorials.
- Kovid Goyal
- Kevin Grandemange
- Eloi Marín Gratacós
- Grzesiek11
- Stefan Gustavson
- Andrew Gutekanst
- Stephen Gutekanst
@ -102,6 +104,7 @@ video tutorials.
- Andreas O. Jansen
- Erik S. V. Jansson
- jjYBdx4IL
- Peter Johnson
- Toni Jovanoski
- Arseny Kapoulkine
- Cem Karan
@ -214,6 +217,7 @@ video tutorials.
- Matt Sealey
- Steve Sexton
- Arkady Shapkin
- Mingjie Shen
- Ali Sherief
- Yoshiki Shibukawa
- Dmitri Shuralyov
@ -251,6 +255,7 @@ video tutorials.
- Jari Vetoniemi
- Ricardo Vieira
- Nicholas Vitovitch
- Vladimír Vondruš
- Simon Voordouw
- Corentin Wallez
- 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: `glfwSetGammaRamp` could emit `GLFW_INVALID_VALUE` before initialization
- 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
to the window menu
- [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: 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: 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 locating the Vulkan loader at runtime in an application bundle
- [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)
- [Cocoa] Bugfix: The Vulkan loader was not loaded from the `Frameworks` bundle
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: Key names were not updated when the keyboard layout changed
(#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
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
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
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
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
@ -142,16 +146,16 @@ keys.
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
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
platform with @ref glfwGetKeyScancode.
You can query the scancode for any [key token](@ref keys) supported on the
current platform with @ref glfwGetKeyScancode.
@code
const int scancode = glfwGetKeyScancode(GLFW_KEY_X);
set_key_mapping(scancode, swap_weapons);
@endcode
The last reported state for every [named key](@ref keys) is also saved in
per-window state arrays that can be polled with @ref glfwGetKey.
The last reported state for every physical key with a [key token](@ref keys) is
also saved in per-window state arrays that can be polled with @ref glfwGetKey.
@code
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`.
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
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.
The `GLFW_KEY_LAST` constant holds the highest value of any
[named key](@ref keys).
[key token](@ref keys).
@subsection input_char Text input
GLFW supports text input in the form of a stream of
[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
layouts and modifier keys and supports composing characters using
operating system text input system. Unlike key input, text input is affected by
keyboard layouts and modifier keys and supports composing characters using
[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.
@ -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`.
Mouse button states for [named buttons](@ref buttons) are also saved in
per-window state arrays that can be polled with @ref glfwGetMouseButton.
The last reported state for every [supported mouse button](@ref buttons) is also
saved in per-window state arrays that can be polled with @ref
glfwGetMouseButton.
@code
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`.
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

View File

@ -277,6 +277,7 @@ then GLFW will fail to initialize.
- @ref GLFW_POSITION_X
- @ref GLFW_POSITION_Y
- @ref GLFW_ANY_POSITION
- @ref GLFW_WAYLAND_APP_ID
- @ref GLFW_WAYLAND_LIBDECOR
- @ref GLFW_WAYLAND_PREFER_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_LEFT_UP (GLFW_HAT_LEFT | GLFW_HAT_UP)
#define GLFW_HAT_LEFT_DOWN (GLFW_HAT_LEFT | GLFW_HAT_DOWN)
/*! @ingroup input
*/
#define GLFW_KEY_UNKNOWN -1
/*! @} */
/*! @defgroup keys Keyboard keys
* @brief Keyboard key IDs.
/*! @defgroup keys Keyboard key tokens
* @brief Keyboard key tokens.
*
* 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 */
#define GLFW_KEY_SPACE 32
#define GLFW_KEY_APOSTROPHE 39 /* ' */
@ -4872,8 +4874,8 @@ GLFWAPI int glfwRawMouseMotionSupported(void);
* @param[in] scancode The scancode of the key to query.
* @return The UTF-8 encoded, layout-specific name of the key, or `NULL`.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_INVALID_VALUE, @ref GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
*
* @remark The contents of the returned string may change when a keyboard
* 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.
*
* If the key is `GLFW_KEY_UNKNOWN` or does not exist on the keyboard this
* method will return `-1`.
* If the specified [key token](@ref keys) corresponds to a physical key not
* 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).
* @return The platform-specific scancode for the key, or `-1` if an
* [error](@ref error_handling) occurred.
* @param[in] key Any [key token](@ref keys).
* @return The platform-specific scancode for the key, or `-1` if the key is
* not supported on the current platform or an [error](@ref error_handling)
* occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_INVALID_ENUM.
*
* @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.
*
* 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 by the fact that the synthetic ones are generated after the focus
* loss event has been processed, i.e. after the
* events for all pressed keys with associated key tokens. You can tell these
* events from user-generated events by the fact that the synthetic ones are
* generated after the focus loss event has been processed, i.e. after the
* [window focus callback](@ref glfwSetWindowFocusCallback) has been called.
*
* 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.
*
* 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
* a single thread at a time and each thread can have only a single current
* context at a time.
* current on the calling thread. It can also detach the current context from
* the calling thread without making a new one current by passing in `NULL`.
*
* When moving a context between threads, you must make it non-current on the
* old thread before making it current on the new one.
* A context must only be made current on a single thread at a time and each
* 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.
* 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
* 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
* 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
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
if ([window->ns.object respondsToSelector:@selector(occlusionState)])
{
if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible)
window->ns.occluded = GLFW_FALSE;
else
window->ns.occluded = GLFW_TRUE;
}
#endif
}
@end

View File

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

View File

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

View File

@ -192,6 +192,7 @@ static void swapBuffersGLX(_GLFWwindow* window)
static void swapIntervalGLX(int interval)
{
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
assert(window != NULL);
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 < js->hatCount);
// Valid hat values only use the least significant nibble and have at most two bits
// set, which can be considered adjacent plus an arbitrary rotation within the nibble
// Valid hat values only use the least significant nibble
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;
@ -701,6 +702,12 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode)
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 &&
(key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) &&
(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)
{
_glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
return GLFW_RELEASE;
return -1;
}
return _glfw.platform.getKeyScancode(key);

View File

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

View File

@ -332,6 +332,7 @@ static void swapBuffersWGL(_GLFWwindow* window)
static void swapIntervalWGL(int interval)
{
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
assert(window != NULL);
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)
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);
}

View File

@ -40,6 +40,7 @@
#include <sys/timerfd.h>
#include <unistd.h>
#include <time.h>
#include <assert.h>
#include "wayland-client-protocol.h"
#include "wayland-xdg-shell-client-protocol.h"
@ -216,6 +217,22 @@ static const struct libdecor_interface libdecorInterface =
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
//
static void createKeyTables(void)
@ -780,10 +797,17 @@ int _glfwInitWayland(void)
if (_glfw.wl.libdecor.handle)
{
_glfw.wl.libdecor.context = libdecor_new(_glfw.wl.display, &libdecorInterface);
// Allow libdecor to receive its globals before proceeding
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
@ -827,6 +851,8 @@ void _glfwTerminateWayland(void)
_glfwTerminateEGL();
_glfwTerminateOSMesa();
if (_glfw.wl.libdecor.callback)
wl_callback_destroy(_glfw.wl.libdecor.callback);
if (_glfw.wl.libdecor.context)
libdecor_unref(_glfw.wl.libdecor.context);

View File

@ -550,6 +550,8 @@ typedef struct _GLFWlibraryWayland
struct {
void* handle;
struct libdecor* context;
struct wl_callback* callback;
GLFWbool ready;
PFN_libdecor_new libdecor_new_;
PFN_libdecor_unref libdecor_unref_;
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)
{
// 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.surface,
&libdecorFrameInterface,
@ -746,6 +750,11 @@ static GLFWbool createLibdecorFrame(_GLFWwindow* window)
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))
libdecor_frame_set_app_id(window->wl.libdecor.frame, window->wl.appId);
@ -776,12 +785,6 @@ static GLFWbool createLibdecorFrame(_GLFWwindow* window)
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,
window->monitor->wl.output);
setIdleInhibitor(window, GLFW_TRUE);
@ -1115,7 +1118,10 @@ static void handleEvents(double* timeout)
while (!event)
{
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
// from the Wayland session; try to handle that the best we can.
@ -1173,14 +1179,14 @@ static void handleEvents(double* timeout)
uint64_t repeats;
if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8)
{
incrementCursorImage(_glfw.wl.pointerFocus);
event = GLFW_TRUE;
}
}
if (fds[3].revents & POLLIN)
libdecor_dispatch(_glfw.wl.libdecor.context, 0);
{
if (libdecor_dispatch(_glfw.wl.libdecor.context, 0) > 0)
event = GLFW_TRUE;
}
}
}