mirror of
https://github.com/glfw/glfw.git
synced 2026-09-19 15:25:50 +00:00
Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 45ce5ddd19 | |||
| 395f0a8b63 | |||
| d9fd087bbf | |||
| 5688fb19e6 | |||
| d1269c1b7d | |||
| 541b151cff | |||
| 8d08426725 | |||
| 85a3bf40fb | |||
| d9512b694b | |||
| 35a65361ff | |||
| 6659a80040 | |||
| 1813cc0af5 | |||
| 9cfd4c49b0 | |||
| eac18b9324 | |||
| 499a5a7917 | |||
| b0af476799 | |||
| 9dd3f25d6d | |||
| 7302a8f520 | |||
| 9f73e9afa3 | |||
| 5ccc756c56 | |||
| e219c00d87 | |||
| 7f752c17c6 | |||
| 811e6bb01c | |||
| b4aa5f626f | |||
| ca1a98e7a2 | |||
| 54f2a865e9 | |||
| 09470b68c1 | |||
| 9340324380 | |||
| 7a4813cedd | |||
| d1c0797630 | |||
| b716ff5b97 | |||
| dccec7fcae | |||
| 4bf6bd42fd | |||
| c68ad09c04 | |||
| e155c19f8e | |||
| 6b15731e6c | |||
| 554f5d0492 | |||
| 3901824c0e | |||
| 5066f57371 | |||
| 1f7ce12cbc | |||
| 0eaf9d557f | |||
| 61497796e6 | |||
| 86a1d3b628 | |||
| 9ab14a8cc0 | |||
| f5dab59071 | |||
| 658c931561 | |||
| 0c46a730de | |||
| 1fa4312b29 | |||
| eb6fc17746 | |||
| ed785a2c79 | |||
| fba79aaaec | |||
| ec934edfbf | |||
| 5f0b316c24 | |||
| 5e8186af0a | |||
| 17c5c53910 | |||
| 6afc571ade | |||
| 22eaa04b49 | |||
| 65fc4fa625 | |||
| 8ecb49d143 | |||
| 9240ee5ddf | |||
| 3b806aef27 | |||
| 5470fd6de9 | |||
| 52133a3690 | |||
| 8f3677a0d4 | |||
| f21a9104e4 | |||
| 869e68a015 |
@@ -96,8 +96,8 @@ jobs:
|
|||||||
- name: Build shared library
|
- name: Build shared library
|
||||||
run: cmake --build build-shared --parallel
|
run: cmake --build build-shared --parallel
|
||||||
|
|
||||||
build-windows-win32-vs2019:
|
build-windows-win32-vs2022:
|
||||||
name: Win32 (Windows, VS2019)
|
name: Win32 (Windows, VS2022)
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
env:
|
env:
|
||||||
CFLAGS: /WX
|
CFLAGS: /WX
|
||||||
@@ -105,12 +105,12 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Configure static library
|
- name: Configure static library
|
||||||
run: cmake -S . -B build-static -G "Visual Studio 16 2019"
|
run: cmake -S . -B build-static -G "Visual Studio 17 2022"
|
||||||
- name: Build static library
|
- name: Build static library
|
||||||
run: cmake --build build-static --parallel
|
run: cmake --build build-static --parallel
|
||||||
|
|
||||||
- name: Configure shared library
|
- name: Configure shared library
|
||||||
run: cmake -S . -B build-shared -G "Visual Studio 16 2019" -D BUILD_SHARED_LIBS=ON
|
run: cmake -S . -B build-shared -G "Visual Studio 17 2022" -D BUILD_SHARED_LIBS=ON
|
||||||
- name: Build shared library
|
- name: Build shared library
|
||||||
run: cmake --build build-shared --parallel
|
run: cmake --build build-shared --parallel
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.0...3.20 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.0...3.20 FATAL_ERROR)
|
||||||
|
|
||||||
project(GLFW VERSION 3.3.6 LANGUAGES C)
|
project(GLFW VERSION 3.3.7 LANGUAGES C)
|
||||||
|
|
||||||
set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
|
set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
|
||||||
|
|
||||||
@@ -266,7 +266,6 @@ if (_GLFW_WAYLAND)
|
|||||||
|
|
||||||
include(CheckIncludeFiles)
|
include(CheckIncludeFiles)
|
||||||
include(CheckFunctionExists)
|
include(CheckFunctionExists)
|
||||||
check_include_files(xkbcommon/xkbcommon-compose.h HAVE_XKBCOMMON_COMPOSE_H)
|
|
||||||
check_function_exists(memfd_create HAVE_MEMFD_CREATE)
|
check_function_exists(memfd_create HAVE_MEMFD_CREATE)
|
||||||
|
|
||||||
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ video tutorials.
|
|||||||
- David Carlier
|
- David Carlier
|
||||||
- Arturo Castro
|
- Arturo Castro
|
||||||
- Chi-kwan Chan
|
- Chi-kwan Chan
|
||||||
|
- TheChocolateOre
|
||||||
- Joseph Chua
|
- Joseph Chua
|
||||||
- Ian Clarkson
|
- Ian Clarkson
|
||||||
- Michał Cichoń
|
- Michał Cichoń
|
||||||
@@ -58,6 +59,7 @@ video tutorials.
|
|||||||
- TheExileFox
|
- TheExileFox
|
||||||
- Felipe Ferreira
|
- Felipe Ferreira
|
||||||
- Michael Fogleman
|
- Michael Fogleman
|
||||||
|
- Jason Francis
|
||||||
- Gerald Franz
|
- Gerald Franz
|
||||||
- Mário Freitas
|
- Mário Freitas
|
||||||
- GeO4d
|
- GeO4d
|
||||||
@@ -80,6 +82,7 @@ video tutorials.
|
|||||||
- Paul Holden
|
- Paul Holden
|
||||||
- Warren Hu
|
- Warren Hu
|
||||||
- Charles Huber
|
- Charles Huber
|
||||||
|
- illustris
|
||||||
- InKryption
|
- InKryption
|
||||||
- IntellectualKitty
|
- IntellectualKitty
|
||||||
- Aaron Jacobs
|
- Aaron Jacobs
|
||||||
@@ -178,11 +181,15 @@ video tutorials.
|
|||||||
- Ali Sherief
|
- Ali Sherief
|
||||||
- Yoshiki Shibukawa
|
- Yoshiki Shibukawa
|
||||||
- Dmitri Shuralyov
|
- Dmitri Shuralyov
|
||||||
|
- Joao da Silva
|
||||||
|
- Daniel Sieger
|
||||||
- Daniel Skorupski
|
- Daniel Skorupski
|
||||||
|
- Slemmie
|
||||||
- Bradley Smith
|
- Bradley Smith
|
||||||
- Cliff Smolinsky
|
- Cliff Smolinsky
|
||||||
- Patrick Snape
|
- Patrick Snape
|
||||||
- Erlend Sogge Heggen
|
- Erlend Sogge Heggen
|
||||||
|
- Olivier Sohn
|
||||||
- Julian Squires
|
- Julian Squires
|
||||||
- Johannes Stein
|
- Johannes Stein
|
||||||
- Pontus Stenetorp
|
- Pontus Stenetorp
|
||||||
|
|||||||
@@ -123,14 +123,33 @@ information on what to include when reporting a bug.
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
- Bugfix: Joysticks connected before init did not get gamepad mappings (#1996)
|
- [Win32] Bugfix: A window created maximized and undecorated would cover the whole
|
||||||
- [Win32] Bugfix: Content scale queries could fail silently (#1615)
|
monitor (#1806)
|
||||||
- [Win32] Bugfix: Content scales could have garbage values if monitor was recently
|
- [Win32] Bugfix: The default restored window position was lost when creating a maximized
|
||||||
disconnected (#1615)
|
window
|
||||||
- [Cocoa] Bugfix: A dependency on an external constant caused crashes on macOS
|
- [Win32] Bugfix: `glfwMaximizeWindow` would make a hidden window visible
|
||||||
11 and earlier (#1985,#1994)
|
- [Cocoa] Bugfix: `kUTTypeURL` was deprecated in macOS 12.0 (#2003)
|
||||||
- [X11] Bugfix: Icon pixel format conversion worked only by accident, relying on
|
- [X11] Bugfix: Dynamic loading on OpenBSD failed due to soname differences
|
||||||
undefined behavior (#1986)
|
- [X11] Bugfix: Waiting for events would fail if file descriptor was too large
|
||||||
|
(#2024)
|
||||||
|
- [X11] Bugfix: Joystick events could lead to busy-waiting (#1872)
|
||||||
|
- [X11] Bugfix: `glfwWaitEvents*` did not continue for joystick events
|
||||||
|
- [X11] Bugfix: `glfwPostEmptyEvent` could be ignored due to race condition
|
||||||
|
(#379,#1281,#1285,#2033)
|
||||||
|
- [X11] Bugfix: Dynamic loading on NetBSD failed due to soname differences
|
||||||
|
- [X11] Bugfix: Left shift of int constant relied on undefined behavior (#1951)
|
||||||
|
- [Wayland] Added support for key names via xkbcommon
|
||||||
|
- [Wayland] Bugfix: Key repeat could lead to a race condition (#1710)
|
||||||
|
- [Wayland] Bugfix: Activating a window would emit two input focus events
|
||||||
|
- [Wayland] Bugfix: Disable key repeat mechanism when window loses input focus
|
||||||
|
- [Wayland] Bugfix: Window hiding and showing did not work (#1492,#1731)
|
||||||
|
- [Wayland] Bugfix: A key being repeated was not released when window lost focus
|
||||||
|
- [Wayland] Bugfix: Showing a hidden window did not emit a window refresh event
|
||||||
|
- [Wayland] Bugfix: Full screen window creation did not ignore `GLFW_VISIBLE`
|
||||||
|
- [Wayland] Bugfix: Some keys were reported as wrong key or `GLFW_KEY_UNKNOWN`
|
||||||
|
- [Wayland] Bugfix: Text input did not repeat along with key repeat
|
||||||
|
- [Wayland] Bugfix: `glfwPostEmptyEvent` sometimes had no effect (#1520,#1521)
|
||||||
|
- [GLX] Bugfix: Context creation failed if GLX 1.4 was not exported by GLX library
|
||||||
|
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
|
|||||||
+4
-2
@@ -68,8 +68,10 @@ install the `xorgproto` package.
|
|||||||
pkg install xorgproto
|
pkg install xorgproto
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
On Cygwin the `xorgproto` package in the Devel section of the GUI installer will
|
On Cygwin the `libXcursor-devel`, `libXi-devel`, `libXinerama-devel`,
|
||||||
install the headers and other development related files for all of X11.
|
`libXrandr-devel` and `libXrender-devel` packages in the Libs section of the GUI
|
||||||
|
installer will install all the headers and other development related files GLFW
|
||||||
|
requires for X11.
|
||||||
|
|
||||||
Once you have the required depdendencies, move on to @ref compile_generate.
|
Once you have the required depdendencies, move on to @ref compile_generate.
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -818,7 +818,7 @@ The second value is always the human-readable name of the gamepad.
|
|||||||
All subsequent values are in the form `<field>:<value>` and describe the layout
|
All subsequent values are in the form `<field>:<value>` and describe the layout
|
||||||
of the mapping. These fields may not all be present and may occur in any order.
|
of the mapping. These fields may not all be present and may occur in any order.
|
||||||
|
|
||||||
The button fields are `a`, `b`, `c`, `d`, `back`, `start`, `guide`, `dpup`,
|
The button fields are `a`, `b`, `x`, `y`, `back`, `start`, `guide`, `dpup`,
|
||||||
`dpright`, `dpdown`, `dpleft`, `leftshoulder`, `rightshoulder`, `leftstick` and
|
`dpright`, `dpdown`, `dpleft`, `leftshoulder`, `rightshoulder`, `leftstick` and
|
||||||
`rightstick`.
|
`rightstick`.
|
||||||
|
|
||||||
|
|||||||
@@ -306,6 +306,12 @@ GLFW_TRANSPARENT_FRAMEBUFFER on Windows 7 if DWM transparency is off
|
|||||||
(the Transparency setting under Personalization > Window Color).
|
(the Transparency setting under Personalization > Window Color).
|
||||||
|
|
||||||
|
|
||||||
|
@subsubsection emptyevents_33 Empty events on X11 no longer roundtrip to server
|
||||||
|
|
||||||
|
Starting with GLFW 3.3.7, events posted with @ref glfwPostEmptyEvent now use a separate
|
||||||
|
unnamed pipe instead of sending an X11 client event to the helper window.
|
||||||
|
|
||||||
|
|
||||||
@subsection deprecations_33 Deprecations in version 3.3
|
@subsection deprecations_33 Deprecations in version 3.3
|
||||||
|
|
||||||
@subsubsection charmods_callback_33 Character with modifiers callback
|
@subsubsection charmods_callback_33 Character with modifiers callback
|
||||||
|
|||||||
+10
-6
@@ -299,7 +299,7 @@ extern "C" {
|
|||||||
* release is made that does not contain any API changes.
|
* release is made that does not contain any API changes.
|
||||||
* @ingroup init
|
* @ingroup init
|
||||||
*/
|
*/
|
||||||
#define GLFW_VERSION_REVISION 6
|
#define GLFW_VERSION_REVISION 7
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
||||||
/*! @brief One.
|
/*! @brief One.
|
||||||
@@ -3312,6 +3312,11 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* window);
|
|||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_PLATFORM_ERROR.
|
||||||
*
|
*
|
||||||
|
* @remark @wayland Because Wayland wants every frame of the desktop to be
|
||||||
|
* complete, this function does not immediately make the window visible.
|
||||||
|
* Instead it will become visible the next time the window framebuffer is
|
||||||
|
* updated after this call.
|
||||||
|
*
|
||||||
* @thread_safety This function must only be called from the main thread.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref window_hide
|
* @sa @ref window_hide
|
||||||
@@ -5713,9 +5718,6 @@ GLFWAPI int glfwVulkanSupported(void);
|
|||||||
* returned array, as it is an error to specify an extension more than once in
|
* returned array, as it is an error to specify an extension more than once in
|
||||||
* the `VkInstanceCreateInfo` struct.
|
* the `VkInstanceCreateInfo` struct.
|
||||||
*
|
*
|
||||||
* @remark @macos GLFW currently supports both the `VK_MVK_macos_surface` and
|
|
||||||
* the newer `VK_EXT_metal_surface` extensions.
|
|
||||||
*
|
|
||||||
* @pointer_lifetime The returned array is allocated and freed by GLFW. You
|
* @pointer_lifetime The returned array is allocated and freed by GLFW. You
|
||||||
* should not free it yourself. It is guaranteed to be valid only until the
|
* should not free it yourself. It is guaranteed to be valid only until the
|
||||||
* library is terminated.
|
* library is terminated.
|
||||||
@@ -5854,8 +5856,10 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhys
|
|||||||
* @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should
|
* @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should
|
||||||
* eliminate almost all occurrences of these errors.
|
* eliminate almost all occurrences of these errors.
|
||||||
*
|
*
|
||||||
* @remark @macos This function currently only supports the
|
* @remark @macos GLFW prefers the `VK_EXT_metal_surface` extension, with the
|
||||||
* `VK_MVK_macos_surface` extension from MoltenVK.
|
* `VK_MVK_macos_surface` extension as a fallback. The name of the selected
|
||||||
|
* extension, if any, is included in the array returned by @ref
|
||||||
|
* glfwGetRequiredInstanceExtensions.
|
||||||
*
|
*
|
||||||
* @remark @macos This function creates and sets a `CAMetalLayer` instance for
|
* @remark @macos This function creates and sets a `CAMetalLayer` instance for
|
||||||
* the window content view, which is required for MoltenVK to function.
|
* the window content view, which is required for MoltenVK to function.
|
||||||
|
|||||||
+13
-2
@@ -42,8 +42,10 @@ typedef void* id;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// NOTE: Many Cocoa enum values have been renamed and we need to build across
|
// NOTE: Many Cocoa enum values have been renamed and we need to build across
|
||||||
// SDK versions where one is unavailable or the other deprecated
|
// SDK versions where one is unavailable or deprecated.
|
||||||
// We use the newer names in code and these macros to handle compatibility
|
// We use the newer names in code and replace them with the older names if
|
||||||
|
// the base SDK does not provide the newer names.
|
||||||
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
||||||
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
|
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
|
||||||
#define NSEventMaskAny NSAnyEventMask
|
#define NSEventMaskAny NSAnyEventMask
|
||||||
@@ -62,6 +64,15 @@ typedef void* id;
|
|||||||
#define NSWindowStyleMaskTitled NSTitledWindowMask
|
#define NSWindowStyleMaskTitled NSTitledWindowMask
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// NOTE: Many Cocoa dynamically linked constants have been renamed and we need
|
||||||
|
// to build across SDK versions where one is unavailable or deprecated.
|
||||||
|
// We use the newer names in code and replace them with the older names if
|
||||||
|
// the deployment target is older than the newer names.
|
||||||
|
|
||||||
|
#if MAC_OS_X_VERSION_MIN_REQUIRED < 101300
|
||||||
|
#define NSPasteboardTypeURL NSURLPboardType
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
|
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
|
||||||
typedef VkFlags VkMetalSurfaceCreateFlagsEXT;
|
typedef VkFlags VkMetalSurfaceCreateFlagsEXT;
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -361,9 +361,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
markedText = [[NSMutableAttributedString alloc] init];
|
markedText = [[NSMutableAttributedString alloc] init];
|
||||||
|
|
||||||
[self updateTrackingAreas];
|
[self updateTrackingAreas];
|
||||||
// NOTE: kUTTypeURL corresponds to NSPasteboardTypeURL but is available
|
[self registerForDraggedTypes:@[NSPasteboardTypeURL]];
|
||||||
// on 10.7 without having been deprecated yet
|
|
||||||
[self registerForDraggedTypes:@[(__bridge NSString*) kUTTypeURL]];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
|||||||
@@ -230,6 +230,12 @@ static void swapBuffersEGL(_GLFWwindow* window)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(_GLFW_WAYLAND)
|
||||||
|
// NOTE: Swapping buffers on a hidden window on Wayland makes it visible
|
||||||
|
if (!window->wl.visible)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
|
eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,6 +320,8 @@ GLFWbool _glfwInitEGL(void)
|
|||||||
"libEGL.dylib",
|
"libEGL.dylib",
|
||||||
#elif defined(__CYGWIN__)
|
#elif defined(__CYGWIN__)
|
||||||
"libEGL-1.so",
|
"libEGL-1.so",
|
||||||
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
|
"libEGL.so",
|
||||||
#else
|
#else
|
||||||
"libEGL.so.1",
|
"libEGL.so.1",
|
||||||
#endif
|
#endif
|
||||||
@@ -426,6 +434,8 @@ GLFWbool _glfwInitEGL(void)
|
|||||||
extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
|
extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
|
||||||
_glfw.egl.KHR_context_flush_control =
|
_glfw.egl.KHR_context_flush_control =
|
||||||
extensionSupportedEGL("EGL_KHR_context_flush_control");
|
extensionSupportedEGL("EGL_KHR_context_flush_control");
|
||||||
|
_glfw.egl.EXT_present_opaque =
|
||||||
|
extensionSupportedEGL("EGL_EXT_present_opaque");
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
@@ -599,6 +609,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
if (!fbconfig->doublebuffer)
|
if (!fbconfig->doublebuffer)
|
||||||
setAttrib(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
|
setAttrib(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
|
||||||
|
|
||||||
|
if (_glfw.egl.EXT_present_opaque)
|
||||||
|
setAttrib(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent);
|
||||||
|
|
||||||
setAttrib(EGL_NONE, EGL_NONE);
|
setAttrib(EGL_NONE, EGL_NONE);
|
||||||
|
|
||||||
window->context.egl.surface =
|
window->context.egl.surface =
|
||||||
@@ -630,6 +643,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
"libGLES_CM.dll",
|
"libGLES_CM.dll",
|
||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
"libGLESv1_CM.dylib",
|
"libGLESv1_CM.dylib",
|
||||||
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
|
"libGLESv1_CM.so",
|
||||||
#else
|
#else
|
||||||
"libGLESv1_CM.so.1",
|
"libGLESv1_CM.so.1",
|
||||||
"libGLES_CM.so.1",
|
"libGLES_CM.so.1",
|
||||||
@@ -647,6 +662,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
"libGLESv2.dylib",
|
"libGLESv2.dylib",
|
||||||
#elif defined(__CYGWIN__)
|
#elif defined(__CYGWIN__)
|
||||||
"libGLESv2-2.so",
|
"libGLESv2-2.so",
|
||||||
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
|
"libGLESv2.so",
|
||||||
#else
|
#else
|
||||||
"libGLESv2.so.2",
|
"libGLESv2.so.2",
|
||||||
#endif
|
#endif
|
||||||
@@ -658,6 +675,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
_GLFW_OPENGL_LIBRARY,
|
_GLFW_OPENGL_LIBRARY,
|
||||||
#elif defined(_GLFW_WIN32)
|
#elif defined(_GLFW_WIN32)
|
||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
|
"libGL.so",
|
||||||
#else
|
#else
|
||||||
"libGL.so.1",
|
"libGL.so.1",
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ typedef struct wl_egl_window* EGLNativeWindowType;
|
|||||||
#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
|
#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
|
||||||
#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
|
#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
|
||||||
#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
|
#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
|
||||||
|
#define EGL_PRESENT_OPAQUE_EXT 0x31df
|
||||||
|
|
||||||
typedef int EGLint;
|
typedef int EGLint;
|
||||||
typedef unsigned int EGLBoolean;
|
typedef unsigned int EGLBoolean;
|
||||||
@@ -179,6 +180,7 @@ typedef struct _GLFWlibraryEGL
|
|||||||
GLFWbool KHR_gl_colorspace;
|
GLFWbool KHR_gl_colorspace;
|
||||||
GLFWbool KHR_get_all_proc_addresses;
|
GLFWbool KHR_get_all_proc_addresses;
|
||||||
GLFWbool KHR_context_flush_control;
|
GLFWbool KHR_context_flush_control;
|
||||||
|
GLFWbool EXT_present_opaque;
|
||||||
|
|
||||||
void* handle;
|
void* handle;
|
||||||
|
|
||||||
|
|||||||
@@ -53,8 +53,6 @@
|
|||||||
// Define this to 1 to force use of high-performance GPU on hybrid systems
|
// Define this to 1 to force use of high-performance GPU on hybrid systems
|
||||||
#cmakedefine _GLFW_USE_HYBRID_HPG
|
#cmakedefine _GLFW_USE_HYBRID_HPG
|
||||||
|
|
||||||
// Define this to 1 if xkbcommon supports the compose key
|
|
||||||
#cmakedefine HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
// Define this to 1 if the libc supports memfd_create()
|
// Define this to 1 if the libc supports memfd_create()
|
||||||
#cmakedefine HAVE_MEMFD_CREATE
|
#cmakedefine HAVE_MEMFD_CREATE
|
||||||
|
|
||||||
|
|||||||
+8
-6
@@ -260,6 +260,8 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
_GLFW_GLX_LIBRARY,
|
_GLFW_GLX_LIBRARY,
|
||||||
#elif defined(__CYGWIN__)
|
#elif defined(__CYGWIN__)
|
||||||
"libGL-1.so",
|
"libGL-1.so",
|
||||||
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
|
"libGL.so",
|
||||||
#else
|
#else
|
||||||
"libGL.so.1",
|
"libGL.so.1",
|
||||||
"libGL.so",
|
"libGL.so",
|
||||||
@@ -307,10 +309,6 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
_glfw_dlsym(_glfw.glx.handle, "glXCreateWindow");
|
_glfw_dlsym(_glfw.glx.handle, "glXCreateWindow");
|
||||||
_glfw.glx.DestroyWindow =
|
_glfw.glx.DestroyWindow =
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXDestroyWindow");
|
_glfw_dlsym(_glfw.glx.handle, "glXDestroyWindow");
|
||||||
_glfw.glx.GetProcAddress =
|
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXGetProcAddress");
|
|
||||||
_glfw.glx.GetProcAddressARB =
|
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
|
|
||||||
_glfw.glx.GetVisualFromFBConfig =
|
_glfw.glx.GetVisualFromFBConfig =
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
|
_glfw_dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
|
||||||
|
|
||||||
@@ -326,8 +324,6 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
!_glfw.glx.CreateNewContext ||
|
!_glfw.glx.CreateNewContext ||
|
||||||
!_glfw.glx.CreateWindow ||
|
!_glfw.glx.CreateWindow ||
|
||||||
!_glfw.glx.DestroyWindow ||
|
!_glfw.glx.DestroyWindow ||
|
||||||
!_glfw.glx.GetProcAddress ||
|
|
||||||
!_glfw.glx.GetProcAddressARB ||
|
|
||||||
!_glfw.glx.GetVisualFromFBConfig)
|
!_glfw.glx.GetVisualFromFBConfig)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
@@ -335,6 +331,12 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: Unlike GLX 1.3 entry points these are not required to be present
|
||||||
|
_glfw.glx.GetProcAddress = (PFNGLXGETPROCADDRESSPROC)
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXGetProcAddress");
|
||||||
|
_glfw.glx.GetProcAddressARB = (PFNGLXGETPROCADDRESSPROC)
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
|
||||||
|
|
||||||
if (!glXQueryExtension(_glfw.x11.display,
|
if (!glXQueryExtension(_glfw.x11.display,
|
||||||
&_glfw.glx.errorBase,
|
&_glfw.glx.errorBase,
|
||||||
&_glfw.glx.eventBase))
|
&_glfw.glx.eventBase))
|
||||||
|
|||||||
+31
@@ -111,6 +111,37 @@ static void terminate(void)
|
|||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Encode a Unicode code point to a UTF-8 stream
|
||||||
|
// Based on cutef8 by Jeff Bezanson (Public Domain)
|
||||||
|
//
|
||||||
|
size_t _glfwEncodeUTF8(char* s, uint32_t codepoint)
|
||||||
|
{
|
||||||
|
size_t count = 0;
|
||||||
|
|
||||||
|
if (codepoint < 0x80)
|
||||||
|
s[count++] = (char) codepoint;
|
||||||
|
else if (codepoint < 0x800)
|
||||||
|
{
|
||||||
|
s[count++] = (codepoint >> 6) | 0xc0;
|
||||||
|
s[count++] = (codepoint & 0x3f) | 0x80;
|
||||||
|
}
|
||||||
|
else if (codepoint < 0x10000)
|
||||||
|
{
|
||||||
|
s[count++] = (codepoint >> 12) | 0xe0;
|
||||||
|
s[count++] = ((codepoint >> 6) & 0x3f) | 0x80;
|
||||||
|
s[count++] = (codepoint & 0x3f) | 0x80;
|
||||||
|
}
|
||||||
|
else if (codepoint < 0x110000)
|
||||||
|
{
|
||||||
|
s[count++] = (codepoint >> 18) | 0xf0;
|
||||||
|
s[count++] = ((codepoint >> 12) & 0x3f) | 0x80;
|
||||||
|
s[count++] = ((codepoint >> 6) & 0x3f) | 0x80;
|
||||||
|
s[count++] = (codepoint & 0x3f) | 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
char* _glfw_strdup(const char* source)
|
char* _glfw_strdup(const char* source)
|
||||||
{
|
{
|
||||||
const size_t length = strlen(source);
|
const size_t length = strlen(source);
|
||||||
|
|||||||
+1
-1
@@ -278,7 +278,7 @@ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int m
|
|||||||
// Notifies shared code of a Unicode codepoint input event
|
// Notifies shared code of a Unicode codepoint input event
|
||||||
// The 'plain' parameter determines whether to emit a regular character event
|
// The 'plain' parameter determines whether to emit a regular character event
|
||||||
//
|
//
|
||||||
void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain)
|
void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool plain)
|
||||||
{
|
{
|
||||||
if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
|
if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
|
||||||
return;
|
return;
|
||||||
|
|||||||
+3
-1
@@ -718,7 +718,7 @@ void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
|
|||||||
void _glfwInputKey(_GLFWwindow* window,
|
void _glfwInputKey(_GLFWwindow* window,
|
||||||
int key, int scancode, int action, int mods);
|
int key, int scancode, int action, int mods);
|
||||||
void _glfwInputChar(_GLFWwindow* window,
|
void _glfwInputChar(_GLFWwindow* window,
|
||||||
unsigned int codepoint, int mods, GLFWbool plain);
|
uint32_t codepoint, int mods, GLFWbool plain);
|
||||||
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset);
|
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset);
|
||||||
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
|
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
|
||||||
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
||||||
@@ -774,6 +774,8 @@ GLFWbool _glfwInitVulkan(int mode);
|
|||||||
void _glfwTerminateVulkan(void);
|
void _glfwTerminateVulkan(void);
|
||||||
const char* _glfwGetVulkanResultString(VkResult result);
|
const char* _glfwGetVulkanResultString(VkResult result);
|
||||||
|
|
||||||
|
size_t _glfwEncodeUTF8(char* s, uint32_t codepoint);
|
||||||
|
|
||||||
char* _glfw_strdup(const char* source);
|
char* _glfw_strdup(const char* source);
|
||||||
float _glfw_fminf(float a, float b);
|
float _glfw_fminf(float a, float b);
|
||||||
float _glfw_fmaxf(float a, float b);
|
float _glfw_fmaxf(float a, float b);
|
||||||
|
|||||||
+4
-2
@@ -25,8 +25,10 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
// NOTE: Many Cocoa enum values have been renamed and we need to build across
|
// NOTE: Many Cocoa enum values have been renamed and we need to build across
|
||||||
// SDK versions where one is unavailable or the other deprecated
|
// SDK versions where one is unavailable or deprecated.
|
||||||
// We use the newer names in code and these macros to handle compatibility
|
// We use the newer names in code and replace them with the older names if
|
||||||
|
// the base SDK does not provide the newer names.
|
||||||
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101400
|
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101400
|
||||||
#define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval
|
#define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval
|
||||||
#define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
|
#define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
|
||||||
|
|||||||
@@ -124,6 +124,8 @@ GLFWbool _glfwInitOSMesa(void)
|
|||||||
"libOSMesa.8.dylib",
|
"libOSMesa.8.dylib",
|
||||||
#elif defined(__CYGWIN__)
|
#elif defined(__CYGWIN__)
|
||||||
"libOSMesa-8.so",
|
"libOSMesa-8.so",
|
||||||
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
|
"libOSMesa.so",
|
||||||
#else
|
#else
|
||||||
"libOSMesa.so.8",
|
"libOSMesa.so.8",
|
||||||
"libOSMesa.so.6",
|
"libOSMesa.so.6",
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ GLFWbool _glfwInitVulkan(int mode)
|
|||||||
_glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
|
_glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
|
||||||
if (!_glfw.vk.handle)
|
if (!_glfw.vk.handle)
|
||||||
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS();
|
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS();
|
||||||
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
|
_glfw.vk.handle = _glfw_dlopen("libvulkan.so");
|
||||||
#else
|
#else
|
||||||
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
|
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+5
-2
@@ -92,6 +92,8 @@ static GLFWbool loadLibraries(void)
|
|||||||
GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow");
|
GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow");
|
||||||
_glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)
|
_glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)
|
||||||
GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");
|
GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");
|
||||||
|
_glfw.win32.user32.GetSystemMetricsForDpi_ = (PFN_GetSystemMetricsForDpi)
|
||||||
|
GetProcAddress(_glfw.win32.user32.instance, "GetSystemMetricsForDpi");
|
||||||
|
|
||||||
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
|
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
|
||||||
if (_glfw.win32.dinput8.instance)
|
if (_glfw.win32.dinput8.instance)
|
||||||
@@ -484,7 +486,7 @@ void _glfwUpdateKeyNamesWin32(void)
|
|||||||
vk = vks[key - GLFW_KEY_KP_0];
|
vk = vks[key - GLFW_KEY_KP_0];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK);
|
vk = MapVirtualKeyW(scancode, MAPVK_VSC_TO_VK);
|
||||||
|
|
||||||
length = ToUnicode(vk, scancode, state,
|
length = ToUnicode(vk, scancode, state,
|
||||||
chars, sizeof(chars) / sizeof(WCHAR),
|
chars, sizeof(chars) / sizeof(WCHAR),
|
||||||
@@ -507,7 +509,8 @@ void _glfwUpdateKeyNamesWin32(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replacement for IsWindowsVersionOrGreater as MinGW lacks versionhelpers.h
|
// Replacement for IsWindowsVersionOrGreater, as we cannot rely on the
|
||||||
|
// application having a correct embedded manifest
|
||||||
//
|
//
|
||||||
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp)
|
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -497,7 +497,7 @@ void _glfwInitJoysticksWin32(void)
|
|||||||
{
|
{
|
||||||
if (_glfw.win32.dinput8.instance)
|
if (_glfw.win32.dinput8.instance)
|
||||||
{
|
{
|
||||||
if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
|
if (FAILED(DirectInput8Create(GetModuleHandleW(NULL),
|
||||||
DIRECTINPUT_VERSION,
|
DIRECTINPUT_VERSION,
|
||||||
&IID_IDirectInput8W,
|
&IID_IDirectInput8W,
|
||||||
(void**) &_glfw.win32.dinput8.api,
|
(void**) &_glfw.win32.dinput8.api,
|
||||||
|
|||||||
+1
-1
@@ -382,7 +382,7 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
|
|||||||
int* width, int* height)
|
int* width, int* height)
|
||||||
{
|
{
|
||||||
MONITORINFO mi = { sizeof(mi) };
|
MONITORINFO mi = { sizeof(mi) };
|
||||||
GetMonitorInfo(monitor->win32.handle, &mi);
|
GetMonitorInfoW(monitor->win32.handle, &mi);
|
||||||
|
|
||||||
if (xpos)
|
if (xpos)
|
||||||
*xpos = mi.rcWork.left;
|
*xpos = mi.rcWork.left;
|
||||||
|
|||||||
@@ -162,7 +162,9 @@ typedef enum
|
|||||||
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE) -4)
|
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE) -4)
|
||||||
#endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/
|
#endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/
|
||||||
|
|
||||||
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
|
// Replacement for versionhelpers.h macros, as we cannot rely on the
|
||||||
|
// application having a correct embedded manifest
|
||||||
|
//
|
||||||
#define IsWindowsXPOrGreater() \
|
#define IsWindowsXPOrGreater() \
|
||||||
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINXP), \
|
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINXP), \
|
||||||
LOBYTE(_WIN32_WINNT_WINXP), 0)
|
LOBYTE(_WIN32_WINNT_WINXP), 0)
|
||||||
@@ -235,12 +237,14 @@ typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND);
|
|||||||
typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE);
|
typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE);
|
||||||
typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
|
typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
|
||||||
typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
|
typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
|
||||||
|
typedef int (WINAPI * PFN_GetSystemMetricsForDpi)(int,UINT);
|
||||||
#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
|
#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
|
||||||
#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
|
#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
|
||||||
#define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
|
#define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
|
||||||
#define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_
|
#define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_
|
||||||
#define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_
|
#define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_
|
||||||
#define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_
|
#define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_
|
||||||
|
#define GetSystemMetricsForDpi _glfw.win32.user32.GetSystemMetricsForDpi_
|
||||||
|
|
||||||
// dwmapi.dll function pointer typedefs
|
// dwmapi.dll function pointer typedefs
|
||||||
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
||||||
@@ -366,6 +370,7 @@ typedef struct _GLFWlibraryWin32
|
|||||||
PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
|
PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
|
||||||
PFN_GetDpiForWindow GetDpiForWindow_;
|
PFN_GetDpiForWindow GetDpiForWindow_;
|
||||||
PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi_;
|
PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi_;
|
||||||
|
PFN_GetSystemMetricsForDpi GetSystemMetricsForDpi_;
|
||||||
} user32;
|
} user32;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
+97
-21
@@ -435,7 +435,7 @@ static int getKeyMods(void)
|
|||||||
static void fitToMonitor(_GLFWwindow* window)
|
static void fitToMonitor(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
MONITORINFO mi = { sizeof(mi) };
|
MONITORINFO mi = { sizeof(mi) };
|
||||||
GetMonitorInfo(window->monitor->win32.handle, &mi);
|
GetMonitorInfoW(window->monitor->win32.handle, &mi);
|
||||||
SetWindowPos(window->win32.handle, HWND_TOPMOST,
|
SetWindowPos(window->win32.handle, HWND_TOPMOST,
|
||||||
mi.rcMonitor.left,
|
mi.rcMonitor.left,
|
||||||
mi.rcMonitor.top,
|
mi.rcMonitor.top,
|
||||||
@@ -456,8 +456,8 @@ static void acquireMonitor(_GLFWwindow* window)
|
|||||||
// the OpenGL ICD switches to page flipping
|
// the OpenGL ICD switches to page flipping
|
||||||
if (IsWindowsXPOrGreater())
|
if (IsWindowsXPOrGreater())
|
||||||
{
|
{
|
||||||
SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
|
SystemParametersInfoW(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
|
||||||
SystemParametersInfo(SPI_SETMOUSETRAILS, 0, 0, 0);
|
SystemParametersInfoW(SPI_SETMOUSETRAILS, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,13 +482,66 @@ static void releaseMonitor(_GLFWwindow* window)
|
|||||||
|
|
||||||
// HACK: Restore mouse trail length saved in acquireMonitor
|
// HACK: Restore mouse trail length saved in acquireMonitor
|
||||||
if (IsWindowsXPOrGreater())
|
if (IsWindowsXPOrGreater())
|
||||||
SystemParametersInfo(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
|
SystemParametersInfoW(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwInputMonitorWindow(window->monitor, NULL);
|
_glfwInputMonitorWindow(window->monitor, NULL);
|
||||||
_glfwRestoreVideoModeWin32(window->monitor);
|
_glfwRestoreVideoModeWin32(window->monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Manually maximize the window, for when SW_MAXIMIZE cannot be used
|
||||||
|
//
|
||||||
|
static void maximizeWindowManually(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
RECT rect;
|
||||||
|
DWORD style;
|
||||||
|
MONITORINFO mi = { sizeof(mi) };
|
||||||
|
|
||||||
|
GetMonitorInfoW(MonitorFromWindow(window->win32.handle,
|
||||||
|
MONITOR_DEFAULTTONEAREST), &mi);
|
||||||
|
|
||||||
|
rect = mi.rcWork;
|
||||||
|
|
||||||
|
if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
if (rect.right - rect.left > window->maxwidth)
|
||||||
|
rect.right = rect.left + window->maxwidth;
|
||||||
|
if (rect.bottom - rect.top > window->maxheight)
|
||||||
|
rect.bottom = rect.top + window->maxheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
style = GetWindowLongW(window->win32.handle, GWL_STYLE);
|
||||||
|
style |= WS_MAXIMIZE;
|
||||||
|
SetWindowLongW(window->win32.handle, GWL_STYLE, style);
|
||||||
|
|
||||||
|
if (window->decorated)
|
||||||
|
{
|
||||||
|
const DWORD exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
|
||||||
|
|
||||||
|
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
|
||||||
|
{
|
||||||
|
const UINT dpi = GetDpiForWindow(window->win32.handle);
|
||||||
|
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
|
||||||
|
OffsetRect(&rect, 0, GetSystemMetricsForDpi(SM_CYCAPTION, dpi));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
|
||||||
|
OffsetRect(&rect, 0, GetSystemMetrics(SM_CYCAPTION));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rect.bottom > mi.rcWork.bottom)
|
||||||
|
rect.bottom = mi.rcWork.bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWindowPos(window->win32.handle, HWND_TOP,
|
||||||
|
rect.left,
|
||||||
|
rect.top,
|
||||||
|
rect.right - rect.left,
|
||||||
|
rect.bottom - rect.top,
|
||||||
|
SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
// Window callback function (handles window messages)
|
// Window callback function (handles window messages)
|
||||||
//
|
//
|
||||||
static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||||
@@ -646,7 +699,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
window->win32.highSurrogate = (WCHAR) wParam;
|
window->win32.highSurrogate = (WCHAR) wParam;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int codepoint = 0;
|
uint32_t codepoint = 0;
|
||||||
|
|
||||||
if (wParam >= 0xdc00 && wParam <= 0xdfff)
|
if (wParam >= 0xdc00 && wParam <= 0xdfff)
|
||||||
{
|
{
|
||||||
@@ -677,7 +730,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GLFW_TRUE);
|
_glfwInputChar(window, (uint32_t) wParam, getKeyMods(), GLFW_TRUE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1067,7 +1120,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
|
|
||||||
ZeroMemory(&mi, sizeof(mi));
|
ZeroMemory(&mi, sizeof(mi));
|
||||||
mi.cbSize = sizeof(mi);
|
mi.cbSize = sizeof(mi);
|
||||||
GetMonitorInfo(mh, &mi);
|
GetMonitorInfoW(mh, &mi);
|
||||||
|
|
||||||
mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left;
|
mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left;
|
||||||
mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top;
|
mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top;
|
||||||
@@ -1285,18 +1338,22 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||||||
|
|
||||||
window->win32.scaleToMonitor = wndconfig->scaleToMonitor;
|
window->win32.scaleToMonitor = wndconfig->scaleToMonitor;
|
||||||
|
|
||||||
// Adjust window rect to account for DPI scaling of the window frame and
|
|
||||||
// (if enabled) DPI scaling of the content area
|
|
||||||
// This cannot be done until we know what monitor the window was placed on
|
|
||||||
if (!window->monitor)
|
if (!window->monitor)
|
||||||
{
|
{
|
||||||
RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
|
RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
|
||||||
WINDOWPLACEMENT wp = { sizeof(wp) };
|
WINDOWPLACEMENT wp = { sizeof(wp) };
|
||||||
|
const HMONITOR mh = MonitorFromWindow(window->win32.handle,
|
||||||
|
MONITOR_DEFAULTTONEAREST);
|
||||||
|
|
||||||
|
// Adjust window rect to account for DPI scaling of the window frame and
|
||||||
|
// (if enabled) DPI scaling of the content area
|
||||||
|
// This cannot be done until we know what monitor the window was placed on
|
||||||
|
// Only update the restored window rect as the window may be maximized
|
||||||
|
|
||||||
if (wndconfig->scaleToMonitor)
|
if (wndconfig->scaleToMonitor)
|
||||||
{
|
{
|
||||||
float xscale, yscale;
|
float xscale, yscale;
|
||||||
_glfwPlatformGetWindowContentScale(window, &xscale, &yscale);
|
_glfwGetMonitorContentScaleWin32(mh, &xscale, &yscale);
|
||||||
|
|
||||||
if (xscale > 0.f && yscale > 0.f)
|
if (xscale > 0.f && yscale > 0.f)
|
||||||
{
|
{
|
||||||
@@ -1305,9 +1362,6 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientToScreen(window->win32.handle, (POINT*) &rect.left);
|
|
||||||
ClientToScreen(window->win32.handle, (POINT*) &rect.right);
|
|
||||||
|
|
||||||
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
|
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
|
||||||
{
|
{
|
||||||
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
|
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
|
||||||
@@ -1316,11 +1370,30 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||||||
else
|
else
|
||||||
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
|
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
|
||||||
|
|
||||||
// Only update the restored window rect as the window may be maximized
|
|
||||||
GetWindowPlacement(window->win32.handle, &wp);
|
GetWindowPlacement(window->win32.handle, &wp);
|
||||||
|
OffsetRect(&rect,
|
||||||
|
wp.rcNormalPosition.left - rect.left,
|
||||||
|
wp.rcNormalPosition.top - rect.top);
|
||||||
|
|
||||||
wp.rcNormalPosition = rect;
|
wp.rcNormalPosition = rect;
|
||||||
wp.showCmd = SW_HIDE;
|
wp.showCmd = SW_HIDE;
|
||||||
SetWindowPlacement(window->win32.handle, &wp);
|
SetWindowPlacement(window->win32.handle, &wp);
|
||||||
|
|
||||||
|
// Adjust rect of maximized undecorated window, because by default Windows will
|
||||||
|
// make such a window cover the whole monitor instead of its workarea
|
||||||
|
|
||||||
|
if (wndconfig->maximized && !wndconfig->decorated)
|
||||||
|
{
|
||||||
|
MONITORINFO mi = { sizeof(mi) };
|
||||||
|
GetMonitorInfoW(mh, &mi);
|
||||||
|
|
||||||
|
SetWindowPos(window->win32.handle, HWND_TOP,
|
||||||
|
mi.rcWork.left,
|
||||||
|
mi.rcWork.top,
|
||||||
|
mi.rcWork.right - mi.rcWork.left,
|
||||||
|
mi.rcWork.bottom - mi.rcWork.top,
|
||||||
|
SWP_NOACTIVATE | SWP_NOZORDER);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DragAcceptFiles(window->win32.handle, TRUE);
|
DragAcceptFiles(window->win32.handle, TRUE);
|
||||||
@@ -1491,8 +1564,8 @@ void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
|||||||
smallIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICONSM);
|
smallIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICONSM);
|
||||||
}
|
}
|
||||||
|
|
||||||
SendMessage(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon);
|
SendMessageW(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon);
|
||||||
SendMessage(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon);
|
SendMessageW(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon);
|
||||||
|
|
||||||
if (window->win32.bigIcon)
|
if (window->win32.bigIcon)
|
||||||
DestroyIcon(window->win32.bigIcon);
|
DestroyIcon(window->win32.bigIcon);
|
||||||
@@ -1672,7 +1745,10 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
ShowWindow(window->win32.handle, SW_MAXIMIZE);
|
if (IsWindowVisible(window->win32.handle))
|
||||||
|
ShowWindow(window->win32.handle, SW_MAXIMIZE);
|
||||||
|
else
|
||||||
|
maximizeWindowManually(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||||
@@ -1759,7 +1835,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
|||||||
|
|
||||||
acquireMonitor(window);
|
acquireMonitor(window);
|
||||||
|
|
||||||
GetMonitorInfo(window->monitor->win32.handle, &mi);
|
GetMonitorInfoW(window->monitor->win32.handle, &mi);
|
||||||
SetWindowPos(window->win32.handle, HWND_TOPMOST,
|
SetWindowPos(window->win32.handle, HWND_TOPMOST,
|
||||||
mi.rcMonitor.left,
|
mi.rcMonitor.left,
|
||||||
mi.rcMonitor.top,
|
mi.rcMonitor.top,
|
||||||
@@ -2023,7 +2099,7 @@ void _glfwPlatformWaitEventsTimeout(double timeout)
|
|||||||
|
|
||||||
void _glfwPlatformPostEmptyEvent(void)
|
void _glfwPlatformPostEmptyEvent(void)
|
||||||
{
|
{
|
||||||
PostMessage(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0);
|
PostMessageW(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||||
@@ -2267,7 +2343,7 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
|||||||
|
|
||||||
memset(&sci, 0, sizeof(sci));
|
memset(&sci, 0, sizeof(sci));
|
||||||
sci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
sci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
||||||
sci.hinstance = GetModuleHandle(NULL);
|
sci.hinstance = GetModuleHandleW(NULL);
|
||||||
sci.hwnd = window->win32.handle;
|
sci.hwnd = window->win32.handle;
|
||||||
|
|
||||||
err = vkCreateWin32SurfaceKHR(instance, &sci, allocator, surface);
|
err = vkCreateWin32SurfaceKHR(instance, &sci, allocator, surface);
|
||||||
|
|||||||
+63
-76
@@ -193,12 +193,12 @@ static void pointerHandleMotion(void* data,
|
|||||||
return;
|
return;
|
||||||
x = wl_fixed_to_double(sx);
|
x = wl_fixed_to_double(sx);
|
||||||
y = wl_fixed_to_double(sy);
|
y = wl_fixed_to_double(sy);
|
||||||
|
window->wl.cursorPosX = x;
|
||||||
|
window->wl.cursorPosY = y;
|
||||||
|
|
||||||
switch (window->wl.decorations.focus)
|
switch (window->wl.decorations.focus)
|
||||||
{
|
{
|
||||||
case mainWindow:
|
case mainWindow:
|
||||||
window->wl.cursorPosX = x;
|
|
||||||
window->wl.cursorPosY = y;
|
|
||||||
_glfwInputCursorPos(window, x, y);
|
_glfwInputCursorPos(window, x, y);
|
||||||
_glfw.wl.cursorPreviousName = NULL;
|
_glfw.wl.cursorPreviousName = NULL;
|
||||||
return;
|
return;
|
||||||
@@ -298,6 +298,7 @@ static void pointerHandleButton(void* data,
|
|||||||
else
|
else
|
||||||
wl_shell_surface_resize(window->wl.shellSurface, _glfw.wl.seat,
|
wl_shell_surface_resize(window->wl.shellSurface, _glfw.wl.seat,
|
||||||
serial, edges);
|
serial, edges);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (button == BTN_RIGHT)
|
else if (button == BTN_RIGHT)
|
||||||
@@ -373,12 +374,8 @@ static void keyboardHandleKeymap(void* data,
|
|||||||
{
|
{
|
||||||
struct xkb_keymap* keymap;
|
struct xkb_keymap* keymap;
|
||||||
struct xkb_state* state;
|
struct xkb_state* state;
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
struct xkb_compose_table* composeTable;
|
struct xkb_compose_table* composeTable;
|
||||||
struct xkb_compose_state* composeState;
|
struct xkb_compose_state* composeState;
|
||||||
#endif
|
|
||||||
|
|
||||||
char* mapStr;
|
char* mapStr;
|
||||||
const char* locale;
|
const char* locale;
|
||||||
|
|
||||||
@@ -426,7 +423,6 @@ static void keyboardHandleKeymap(void* data,
|
|||||||
if (!locale)
|
if (!locale)
|
||||||
locale = "C";
|
locale = "C";
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
composeTable =
|
composeTable =
|
||||||
xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
|
xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
|
||||||
XKB_COMPOSE_COMPILE_NO_FLAGS);
|
XKB_COMPOSE_COMPILE_NO_FLAGS);
|
||||||
@@ -446,7 +442,6 @@ static void keyboardHandleKeymap(void* data,
|
|||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Failed to create XKB compose table");
|
"Wayland: Failed to create XKB compose table");
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
||||||
xkb_state_unref(_glfw.wl.xkb.state);
|
xkb_state_unref(_glfw.wl.xkb.state);
|
||||||
@@ -500,20 +495,22 @@ static void keyboardHandleLeave(void* data,
|
|||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
struct itimerspec timer = {};
|
||||||
|
timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
|
||||||
|
|
||||||
_glfw.wl.serial = serial;
|
_glfw.wl.serial = serial;
|
||||||
_glfw.wl.keyboardFocus = NULL;
|
_glfw.wl.keyboardFocus = NULL;
|
||||||
_glfwInputWindowFocus(window, GLFW_FALSE);
|
_glfwInputWindowFocus(window, GLFW_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int toGLFWKeyCode(uint32_t key)
|
static int translateKey(uint32_t scancode)
|
||||||
{
|
{
|
||||||
if (key < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
|
if (scancode < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
|
||||||
return _glfw.wl.keycodes[key];
|
return _glfw.wl.keycodes[scancode];
|
||||||
|
|
||||||
return GLFW_KEY_UNKNOWN;
|
return GLFW_KEY_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
|
static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
|
||||||
{
|
{
|
||||||
if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
|
if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
|
||||||
@@ -533,77 +530,65 @@ static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
|
|||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static GLFWbool inputChar(_GLFWwindow* window, uint32_t key)
|
GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode)
|
||||||
{
|
{
|
||||||
uint32_t code, numSyms;
|
const xkb_keysym_t* keysyms;
|
||||||
long cp;
|
const xkb_keycode_t keycode = scancode + 8;
|
||||||
const xkb_keysym_t *syms;
|
|
||||||
xkb_keysym_t sym;
|
|
||||||
|
|
||||||
code = key + 8;
|
if (xkb_state_key_get_syms(_glfw.wl.xkb.state, keycode, &keysyms) == 1)
|
||||||
numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms);
|
|
||||||
|
|
||||||
if (numSyms == 1)
|
|
||||||
{
|
{
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
const xkb_keysym_t keysym = composeSymbol(keysyms[0]);
|
||||||
sym = composeSymbol(syms[0]);
|
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
|
||||||
#else
|
if (codepoint != GLFW_INVALID_CODEPOINT)
|
||||||
sym = syms[0];
|
|
||||||
#endif
|
|
||||||
cp = _glfwKeySym2Unicode(sym);
|
|
||||||
if (cp != -1)
|
|
||||||
{
|
{
|
||||||
const int mods = _glfw.wl.xkb.modifiers;
|
const int mods = _glfw.wl.xkb.modifiers;
|
||||||
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
|
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
|
||||||
_glfwInputChar(window, cp, mods, plain);
|
_glfwInputChar(window, codepoint, mods, plain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, code);
|
return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, keycode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyboardHandleKey(void* data,
|
static void keyboardHandleKey(void* data,
|
||||||
struct wl_keyboard* keyboard,
|
struct wl_keyboard* keyboard,
|
||||||
uint32_t serial,
|
uint32_t serial,
|
||||||
uint32_t time,
|
uint32_t time,
|
||||||
uint32_t key,
|
uint32_t scancode,
|
||||||
uint32_t state)
|
uint32_t state)
|
||||||
{
|
{
|
||||||
int keyCode;
|
|
||||||
int action;
|
|
||||||
_GLFWwindow* window = _glfw.wl.keyboardFocus;
|
_GLFWwindow* window = _glfw.wl.keyboardFocus;
|
||||||
GLFWbool shouldRepeat;
|
|
||||||
struct itimerspec timer = {};
|
|
||||||
|
|
||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
keyCode = toGLFWKeyCode(key);
|
const int key = translateKey(scancode);
|
||||||
action = state == WL_KEYBOARD_KEY_STATE_PRESSED
|
const int action =
|
||||||
? GLFW_PRESS : GLFW_RELEASE;
|
state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
|
||||||
|
|
||||||
_glfw.wl.serial = serial;
|
_glfw.wl.serial = serial;
|
||||||
_glfwInputKey(window, keyCode, key, action,
|
_glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers);
|
||||||
_glfw.wl.xkb.modifiers);
|
|
||||||
|
struct itimerspec timer = {};
|
||||||
|
|
||||||
if (action == GLFW_PRESS)
|
if (action == GLFW_PRESS)
|
||||||
{
|
{
|
||||||
shouldRepeat = inputChar(window, key);
|
const GLFWbool shouldRepeat = _glfwInputTextWayland(window, scancode);
|
||||||
|
|
||||||
if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0)
|
if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0)
|
||||||
{
|
{
|
||||||
_glfw.wl.keyboardLastKey = keyCode;
|
_glfw.wl.keyboardLastKey = key;
|
||||||
_glfw.wl.keyboardLastScancode = key;
|
_glfw.wl.keyboardLastScancode = scancode;
|
||||||
if (_glfw.wl.keyboardRepeatRate > 1)
|
if (_glfw.wl.keyboardRepeatRate > 1)
|
||||||
timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyboardRepeatRate;
|
timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyboardRepeatRate;
|
||||||
else
|
else
|
||||||
timer.it_interval.tv_sec = 1;
|
timer.it_interval.tv_sec = 1;
|
||||||
|
|
||||||
timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000;
|
timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000;
|
||||||
timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000;
|
timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
|
timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -615,9 +600,6 @@ static void keyboardHandleModifiers(void* data,
|
|||||||
uint32_t modsLocked,
|
uint32_t modsLocked,
|
||||||
uint32_t group)
|
uint32_t group)
|
||||||
{
|
{
|
||||||
xkb_mod_mask_t mask;
|
|
||||||
unsigned int modifiers = 0;
|
|
||||||
|
|
||||||
_glfw.wl.serial = serial;
|
_glfw.wl.serial = serial;
|
||||||
|
|
||||||
if (!_glfw.wl.xkb.keymap)
|
if (!_glfw.wl.xkb.keymap)
|
||||||
@@ -631,24 +613,29 @@ static void keyboardHandleModifiers(void* data,
|
|||||||
0,
|
0,
|
||||||
group);
|
group);
|
||||||
|
|
||||||
mask = xkb_state_serialize_mods(_glfw.wl.xkb.state,
|
const xkb_mod_mask_t mask =
|
||||||
XKB_STATE_MODS_DEPRESSED |
|
xkb_state_serialize_mods(_glfw.wl.xkb.state,
|
||||||
XKB_STATE_LAYOUT_DEPRESSED |
|
XKB_STATE_MODS_DEPRESSED |
|
||||||
XKB_STATE_MODS_LATCHED |
|
XKB_STATE_LAYOUT_DEPRESSED |
|
||||||
XKB_STATE_LAYOUT_LATCHED);
|
XKB_STATE_MODS_LATCHED |
|
||||||
|
XKB_STATE_LAYOUT_LATCHED);
|
||||||
|
|
||||||
|
unsigned int mods = 0;
|
||||||
|
|
||||||
if (mask & _glfw.wl.xkb.controlMask)
|
if (mask & _glfw.wl.xkb.controlMask)
|
||||||
modifiers |= GLFW_MOD_CONTROL;
|
mods |= GLFW_MOD_CONTROL;
|
||||||
if (mask & _glfw.wl.xkb.altMask)
|
if (mask & _glfw.wl.xkb.altMask)
|
||||||
modifiers |= GLFW_MOD_ALT;
|
mods |= GLFW_MOD_ALT;
|
||||||
if (mask & _glfw.wl.xkb.shiftMask)
|
if (mask & _glfw.wl.xkb.shiftMask)
|
||||||
modifiers |= GLFW_MOD_SHIFT;
|
mods |= GLFW_MOD_SHIFT;
|
||||||
if (mask & _glfw.wl.xkb.superMask)
|
if (mask & _glfw.wl.xkb.superMask)
|
||||||
modifiers |= GLFW_MOD_SUPER;
|
mods |= GLFW_MOD_SUPER;
|
||||||
if (mask & _glfw.wl.xkb.capsLockMask)
|
if (mask & _glfw.wl.xkb.capsLockMask)
|
||||||
modifiers |= GLFW_MOD_CAPS_LOCK;
|
mods |= GLFW_MOD_CAPS_LOCK;
|
||||||
if (mask & _glfw.wl.xkb.numLockMask)
|
if (mask & _glfw.wl.xkb.numLockMask)
|
||||||
modifiers |= GLFW_MOD_NUM_LOCK;
|
mods |= GLFW_MOD_NUM_LOCK;
|
||||||
_glfw.wl.xkb.modifiers = modifiers;
|
|
||||||
|
_glfw.wl.xkb.modifiers = mods;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
|
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
|
||||||
@@ -973,7 +960,7 @@ static void createKeyTables(void)
|
|||||||
_glfw.wl.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
|
_glfw.wl.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
|
||||||
_glfw.wl.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
|
_glfw.wl.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
|
||||||
_glfw.wl.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
|
_glfw.wl.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
|
||||||
_glfw.wl.keycodes[KEY_MENU] = GLFW_KEY_MENU;
|
_glfw.wl.keycodes[KEY_COMPOSE] = GLFW_KEY_MENU;
|
||||||
_glfw.wl.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
|
_glfw.wl.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
|
||||||
_glfw.wl.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
|
_glfw.wl.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
|
||||||
_glfw.wl.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
|
_glfw.wl.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
|
||||||
@@ -1016,7 +1003,7 @@ static void createKeyTables(void)
|
|||||||
_glfw.wl.keycodes[KEY_F23] = GLFW_KEY_F23;
|
_glfw.wl.keycodes[KEY_F23] = GLFW_KEY_F23;
|
||||||
_glfw.wl.keycodes[KEY_F24] = GLFW_KEY_F24;
|
_glfw.wl.keycodes[KEY_F24] = GLFW_KEY_F24;
|
||||||
_glfw.wl.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
|
_glfw.wl.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
|
||||||
_glfw.wl.keycodes[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
|
_glfw.wl.keycodes[KEY_KPASTERISK] = GLFW_KEY_KP_MULTIPLY;
|
||||||
_glfw.wl.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
|
_glfw.wl.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
|
||||||
_glfw.wl.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
|
_glfw.wl.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
|
||||||
_glfw.wl.keycodes[KEY_KP0] = GLFW_KEY_KP_0;
|
_glfw.wl.keycodes[KEY_KP0] = GLFW_KEY_KP_0;
|
||||||
@@ -1029,9 +1016,10 @@ static void createKeyTables(void)
|
|||||||
_glfw.wl.keycodes[KEY_KP7] = GLFW_KEY_KP_7;
|
_glfw.wl.keycodes[KEY_KP7] = GLFW_KEY_KP_7;
|
||||||
_glfw.wl.keycodes[KEY_KP8] = GLFW_KEY_KP_8;
|
_glfw.wl.keycodes[KEY_KP8] = GLFW_KEY_KP_8;
|
||||||
_glfw.wl.keycodes[KEY_KP9] = GLFW_KEY_KP_9;
|
_glfw.wl.keycodes[KEY_KP9] = GLFW_KEY_KP_9;
|
||||||
_glfw.wl.keycodes[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
|
_glfw.wl.keycodes[KEY_KPDOT] = GLFW_KEY_KP_DECIMAL;
|
||||||
_glfw.wl.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
|
_glfw.wl.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
|
||||||
_glfw.wl.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
|
_glfw.wl.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
|
||||||
|
_glfw.wl.keycodes[KEY_102ND] = GLFW_KEY_WORLD_2;
|
||||||
|
|
||||||
for (scancode = 0; scancode < 256; scancode++)
|
for (scancode = 0; scancode < 256; scancode++)
|
||||||
{
|
{
|
||||||
@@ -1105,6 +1093,8 @@ int _glfwPlatformInit(void)
|
|||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
|
||||||
_glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats)
|
_glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats)
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats");
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats");
|
||||||
|
_glfw.wl.xkb.keymap_key_get_syms_by_level = (PFN_xkb_keymap_key_get_syms_by_level)
|
||||||
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_get_syms_by_level");
|
||||||
_glfw.wl.xkb.state_new = (PFN_xkb_state_new)
|
_glfw.wl.xkb.state_new = (PFN_xkb_state_new)
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new");
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new");
|
||||||
_glfw.wl.xkb.state_unref = (PFN_xkb_state_unref)
|
_glfw.wl.xkb.state_unref = (PFN_xkb_state_unref)
|
||||||
@@ -1115,8 +1105,9 @@ int _glfwPlatformInit(void)
|
|||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask");
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask");
|
||||||
_glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods)
|
_glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods)
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods");
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods");
|
||||||
|
_glfw.wl.xkb.state_key_get_layout = (PFN_xkb_state_key_get_layout)
|
||||||
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_layout");
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
_glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)
|
_glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");
|
||||||
_glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref)
|
_glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref)
|
||||||
@@ -1131,7 +1122,6 @@ int _glfwPlatformInit(void)
|
|||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status");
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status");
|
||||||
_glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)
|
_glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");
|
||||||
#endif
|
|
||||||
|
|
||||||
_glfw.wl.display = wl_display_connect(NULL);
|
_glfw.wl.display = wl_display_connect(NULL);
|
||||||
if (!_glfw.wl.display)
|
if (!_glfw.wl.display)
|
||||||
@@ -1169,7 +1159,7 @@ int _glfwPlatformInit(void)
|
|||||||
|
|
||||||
_glfw.wl.timerfd = -1;
|
_glfw.wl.timerfd = -1;
|
||||||
if (_glfw.wl.seatVersion >= 4)
|
if (_glfw.wl.seatVersion >= 4)
|
||||||
_glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
|
_glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
|
||||||
|
|
||||||
if (_glfw.wl.pointer && _glfw.wl.shm)
|
if (_glfw.wl.pointer && _glfw.wl.shm)
|
||||||
{
|
{
|
||||||
@@ -1196,7 +1186,7 @@ int _glfwPlatformInit(void)
|
|||||||
wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm);
|
wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm);
|
||||||
_glfw.wl.cursorSurface =
|
_glfw.wl.cursorSurface =
|
||||||
wl_compositor_create_surface(_glfw.wl.compositor);
|
wl_compositor_create_surface(_glfw.wl.compositor);
|
||||||
_glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
|
_glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfw.wl.seat && _glfw.wl.dataDeviceManager)
|
if (_glfw.wl.seat && _glfw.wl.dataDeviceManager)
|
||||||
@@ -1205,14 +1195,15 @@ int _glfwPlatformInit(void)
|
|||||||
wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager,
|
wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager,
|
||||||
_glfw.wl.seat);
|
_glfw.wl.seat);
|
||||||
wl_data_device_add_listener(_glfw.wl.dataDevice, &dataDeviceListener, NULL);
|
wl_data_device_add_listener(_glfw.wl.dataDevice, &dataDeviceListener, NULL);
|
||||||
_glfw.wl.clipboardString = malloc(4096);
|
|
||||||
|
_glfw.wl.clipboardSize = 4096;
|
||||||
|
_glfw.wl.clipboardString = calloc(_glfw.wl.clipboardSize, 1);
|
||||||
if (!_glfw.wl.clipboardString)
|
if (!_glfw.wl.clipboardString)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_OUT_OF_MEMORY,
|
||||||
"Wayland: Unable to allocate clipboard memory");
|
"Wayland: Unable to allocate clipboard memory");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
_glfw.wl.clipboardSize = 4096;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
@@ -1230,10 +1221,8 @@ void _glfwPlatformTerminate(void)
|
|||||||
_glfw.wl.egl.handle = NULL;
|
_glfw.wl.egl.handle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
if (_glfw.wl.xkb.composeState)
|
if (_glfw.wl.xkb.composeState)
|
||||||
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
|
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
|
||||||
#endif
|
|
||||||
if (_glfw.wl.xkb.keymap)
|
if (_glfw.wl.xkb.keymap)
|
||||||
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
||||||
if (_glfw.wl.xkb.state)
|
if (_glfw.wl.xkb.state)
|
||||||
@@ -1305,10 +1294,8 @@ void _glfwPlatformTerminate(void)
|
|||||||
if (_glfw.wl.cursorTimerfd >= 0)
|
if (_glfw.wl.cursorTimerfd >= 0)
|
||||||
close(_glfw.wl.cursorTimerfd);
|
close(_glfw.wl.cursorTimerfd);
|
||||||
|
|
||||||
if (_glfw.wl.clipboardString)
|
free(_glfw.wl.clipboardString);
|
||||||
free(_glfw.wl.clipboardString);
|
free(_glfw.wl.clipboardSendString);
|
||||||
if (_glfw.wl.clipboardSendString)
|
|
||||||
free(_glfw.wl.clipboardSendString);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
|
|||||||
+8
-9
@@ -26,9 +26,7 @@
|
|||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
#include <xkbcommon/xkbcommon-compose.h>
|
#include <xkbcommon/xkbcommon-compose.h>
|
||||||
#endif
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
|
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
|
||||||
@@ -112,24 +110,27 @@ typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context
|
|||||||
typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*);
|
typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*);
|
||||||
typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*);
|
typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*);
|
||||||
typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t);
|
typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t);
|
||||||
|
typedef int (* PFN_xkb_keymap_key_get_syms_by_level)(struct xkb_keymap*,xkb_keycode_t,xkb_layout_index_t,xkb_level_index_t,const xkb_keysym_t**);
|
||||||
typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
|
typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
|
||||||
typedef void (* PFN_xkb_state_unref)(struct xkb_state*);
|
typedef void (* PFN_xkb_state_unref)(struct xkb_state*);
|
||||||
typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
|
typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
|
||||||
typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
|
typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
|
||||||
typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component);
|
typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component);
|
||||||
|
typedef xkb_layout_index_t (* PFN_xkb_state_key_get_layout)(struct xkb_state*,xkb_keycode_t);
|
||||||
#define xkb_context_new _glfw.wl.xkb.context_new
|
#define xkb_context_new _glfw.wl.xkb.context_new
|
||||||
#define xkb_context_unref _glfw.wl.xkb.context_unref
|
#define xkb_context_unref _glfw.wl.xkb.context_unref
|
||||||
#define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string
|
#define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string
|
||||||
#define xkb_keymap_unref _glfw.wl.xkb.keymap_unref
|
#define xkb_keymap_unref _glfw.wl.xkb.keymap_unref
|
||||||
#define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index
|
#define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index
|
||||||
#define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats
|
#define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats
|
||||||
|
#define xkb_keymap_key_get_syms_by_level _glfw.wl.xkb.keymap_key_get_syms_by_level
|
||||||
#define xkb_state_new _glfw.wl.xkb.state_new
|
#define xkb_state_new _glfw.wl.xkb.state_new
|
||||||
#define xkb_state_unref _glfw.wl.xkb.state_unref
|
#define xkb_state_unref _glfw.wl.xkb.state_unref
|
||||||
#define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms
|
#define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms
|
||||||
#define xkb_state_update_mask _glfw.wl.xkb.state_update_mask
|
#define xkb_state_update_mask _glfw.wl.xkb.state_update_mask
|
||||||
#define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods
|
#define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods
|
||||||
|
#define xkb_state_key_get_layout _glfw.wl.xkb.state_key_get_layout
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
|
typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
|
||||||
typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
|
typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
|
||||||
typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags);
|
typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags);
|
||||||
@@ -144,7 +145,6 @@ typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_st
|
|||||||
#define xkb_compose_state_feed _glfw.wl.xkb.compose_state_feed
|
#define xkb_compose_state_feed _glfw.wl.xkb.compose_state_feed
|
||||||
#define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status
|
#define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status
|
||||||
#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
|
#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
|
||||||
#endif
|
|
||||||
|
|
||||||
#define _GLFW_DECORATION_WIDTH 4
|
#define _GLFW_DECORATION_WIDTH 4
|
||||||
#define _GLFW_DECORATION_TOP 24
|
#define _GLFW_DECORATION_TOP 24
|
||||||
@@ -262,16 +262,14 @@ typedef struct _GLFWlibraryWayland
|
|||||||
int timerfd;
|
int timerfd;
|
||||||
short int keycodes[256];
|
short int keycodes[256];
|
||||||
short int scancodes[GLFW_KEY_LAST + 1];
|
short int scancodes[GLFW_KEY_LAST + 1];
|
||||||
|
char keynames[GLFW_KEY_LAST + 1][5];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
void* handle;
|
void* handle;
|
||||||
struct xkb_context* context;
|
struct xkb_context* context;
|
||||||
struct xkb_keymap* keymap;
|
struct xkb_keymap* keymap;
|
||||||
struct xkb_state* state;
|
struct xkb_state* state;
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
struct xkb_compose_state* composeState;
|
struct xkb_compose_state* composeState;
|
||||||
#endif
|
|
||||||
|
|
||||||
xkb_mod_mask_t controlMask;
|
xkb_mod_mask_t controlMask;
|
||||||
xkb_mod_mask_t altMask;
|
xkb_mod_mask_t altMask;
|
||||||
@@ -287,13 +285,14 @@ typedef struct _GLFWlibraryWayland
|
|||||||
PFN_xkb_keymap_unref keymap_unref;
|
PFN_xkb_keymap_unref keymap_unref;
|
||||||
PFN_xkb_keymap_mod_get_index keymap_mod_get_index;
|
PFN_xkb_keymap_mod_get_index keymap_mod_get_index;
|
||||||
PFN_xkb_keymap_key_repeats keymap_key_repeats;
|
PFN_xkb_keymap_key_repeats keymap_key_repeats;
|
||||||
|
PFN_xkb_keymap_key_get_syms_by_level keymap_key_get_syms_by_level;
|
||||||
PFN_xkb_state_new state_new;
|
PFN_xkb_state_new state_new;
|
||||||
PFN_xkb_state_unref state_unref;
|
PFN_xkb_state_unref state_unref;
|
||||||
PFN_xkb_state_key_get_syms state_key_get_syms;
|
PFN_xkb_state_key_get_syms state_key_get_syms;
|
||||||
PFN_xkb_state_update_mask state_update_mask;
|
PFN_xkb_state_update_mask state_update_mask;
|
||||||
PFN_xkb_state_serialize_mods state_serialize_mods;
|
PFN_xkb_state_serialize_mods state_serialize_mods;
|
||||||
|
PFN_xkb_state_key_get_layout state_key_get_layout;
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;
|
PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;
|
||||||
PFN_xkb_compose_table_unref compose_table_unref;
|
PFN_xkb_compose_table_unref compose_table_unref;
|
||||||
PFN_xkb_compose_state_new compose_state_new;
|
PFN_xkb_compose_state_new compose_state_new;
|
||||||
@@ -301,7 +300,6 @@ typedef struct _GLFWlibraryWayland
|
|||||||
PFN_xkb_compose_state_feed compose_state_feed;
|
PFN_xkb_compose_state_feed compose_state_feed;
|
||||||
PFN_xkb_compose_state_get_status compose_state_get_status;
|
PFN_xkb_compose_state_get_status compose_state_get_status;
|
||||||
PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;
|
PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;
|
||||||
#endif
|
|
||||||
} xkb;
|
} xkb;
|
||||||
|
|
||||||
_GLFWwindow* pointerFocus;
|
_GLFWwindow* pointerFocus;
|
||||||
@@ -352,4 +350,5 @@ typedef struct _GLFWcursorWayland
|
|||||||
|
|
||||||
|
|
||||||
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
|
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
|
||||||
|
GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode);
|
||||||
|
|
||||||
|
|||||||
+236
-139
@@ -39,7 +39,8 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/timerfd.h>
|
#include <sys/timerfd.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
static void shellSurfaceHandlePing(void* data,
|
static void shellSurfaceHandlePing(void* data,
|
||||||
struct wl_shell_surface* shellSurface,
|
struct wl_shell_surface* shellSurface,
|
||||||
@@ -248,6 +249,53 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait for data to arrive on any of the specified file descriptors
|
||||||
|
//
|
||||||
|
static GLFWbool waitForData(struct pollfd* fds, nfds_t count, double* timeout)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (timeout)
|
||||||
|
{
|
||||||
|
const uint64_t base = _glfwPlatformGetTimerValue();
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__)
|
||||||
|
const time_t seconds = (time_t) *timeout;
|
||||||
|
const long nanoseconds = (long) ((*timeout - seconds) * 1e9);
|
||||||
|
const struct timespec ts = { seconds, nanoseconds };
|
||||||
|
const int result = ppoll(fds, count, &ts, NULL);
|
||||||
|
#elif defined(__NetBSD__)
|
||||||
|
const time_t seconds = (time_t) *timeout;
|
||||||
|
const long nanoseconds = (long) ((*timeout - seconds) * 1e9);
|
||||||
|
const struct timespec ts = { seconds, nanoseconds };
|
||||||
|
const int result = pollts(fds, count, &ts, NULL);
|
||||||
|
#else
|
||||||
|
const int milliseconds = (int) (*timeout * 1e3);
|
||||||
|
const int result = poll(fds, count, milliseconds);
|
||||||
|
#endif
|
||||||
|
const int error = errno; // clock_gettime may overwrite our error
|
||||||
|
|
||||||
|
*timeout -= (_glfwPlatformGetTimerValue() - base) /
|
||||||
|
(double) _glfwPlatformGetTimerFrequency();
|
||||||
|
|
||||||
|
if (result > 0)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
else if (result == -1 && error != EINTR && error != EAGAIN)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
else if (*timeout <= 0.0)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const int result = poll(fds, count, -1);
|
||||||
|
if (result > 0)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
else if (result == -1 && errno != EINTR && errno != EAGAIN)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void createDecoration(_GLFWdecorationWayland* decoration,
|
static void createDecoration(_GLFWdecorationWayland* decoration,
|
||||||
struct wl_surface* parent,
|
struct wl_surface* parent,
|
||||||
struct wl_buffer* buffer, GLFWbool opaque,
|
struct wl_buffer* buffer, GLFWbool opaque,
|
||||||
@@ -404,27 +452,25 @@ static void resizeWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
static void checkScaleChange(_GLFWwindow* window)
|
static void checkScaleChange(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
int scale = 1;
|
|
||||||
int i;
|
|
||||||
int monitorScale;
|
|
||||||
|
|
||||||
// Check if we will be able to set the buffer scale or not.
|
// Check if we will be able to set the buffer scale or not.
|
||||||
if (_glfw.wl.compositorVersion < 3)
|
if (_glfw.wl.compositorVersion < 3)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Get the scale factor from the highest scale monitor.
|
// Get the scale factor from the highest scale monitor.
|
||||||
for (i = 0; i < window->wl.monitorsCount; ++i)
|
int maxScale = 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < window->wl.monitorsCount; i++)
|
||||||
{
|
{
|
||||||
monitorScale = window->wl.monitors[i]->wl.scale;
|
const int scale = window->wl.monitors[i]->wl.scale;
|
||||||
if (scale < monitorScale)
|
if (maxScale < scale)
|
||||||
scale = monitorScale;
|
maxScale = scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only change the framebuffer size if the scale changed.
|
// Only change the framebuffer size if the scale changed.
|
||||||
if (scale != window->wl.scale)
|
if (window->wl.scale != maxScale)
|
||||||
{
|
{
|
||||||
window->wl.scale = scale;
|
window->wl.scale = maxScale;
|
||||||
wl_surface_set_buffer_scale(window->wl.surface, scale);
|
wl_surface_set_buffer_scale(window->wl.surface, maxScale);
|
||||||
resizeWindow(window);
|
resizeWindow(window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -493,35 +539,6 @@ static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLFWbool createSurface(_GLFWwindow* window,
|
|
||||||
const _GLFWwndconfig* wndconfig)
|
|
||||||
{
|
|
||||||
window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor);
|
|
||||||
if (!window->wl.surface)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
wl_surface_add_listener(window->wl.surface,
|
|
||||||
&surfaceListener,
|
|
||||||
window);
|
|
||||||
|
|
||||||
wl_surface_set_user_data(window->wl.surface, window);
|
|
||||||
|
|
||||||
window->wl.native = wl_egl_window_create(window->wl.surface,
|
|
||||||
wndconfig->width,
|
|
||||||
wndconfig->height);
|
|
||||||
if (!window->wl.native)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
window->wl.width = wndconfig->width;
|
|
||||||
window->wl.height = wndconfig->height;
|
|
||||||
window->wl.scale = 1;
|
|
||||||
|
|
||||||
if (!window->wl.transparent)
|
|
||||||
setOpaqueRegion(window);
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor,
|
static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor,
|
||||||
int refreshRate)
|
int refreshRate)
|
||||||
{
|
{
|
||||||
@@ -653,7 +670,6 @@ static void xdgToplevelHandleConfigure(void* data,
|
|||||||
}
|
}
|
||||||
if (fullscreen && activated)
|
if (fullscreen && activated)
|
||||||
window->wl.wasFullscreen = GLFW_TRUE;
|
window->wl.wasFullscreen = GLFW_TRUE;
|
||||||
_glfwInputWindowFocus(window, activated);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xdgToplevelHandleClose(void* data,
|
static void xdgToplevelHandleClose(void* data,
|
||||||
@@ -761,6 +777,46 @@ static GLFWbool createXdgSurface(_GLFWwindow* window)
|
|||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GLFWbool createSurface(_GLFWwindow* window,
|
||||||
|
const _GLFWwndconfig* wndconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig)
|
||||||
|
{
|
||||||
|
window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor);
|
||||||
|
if (!window->wl.surface)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
wl_surface_add_listener(window->wl.surface,
|
||||||
|
&surfaceListener,
|
||||||
|
window);
|
||||||
|
|
||||||
|
wl_surface_set_user_data(window->wl.surface, window);
|
||||||
|
|
||||||
|
window->wl.native = wl_egl_window_create(window->wl.surface,
|
||||||
|
wndconfig->width,
|
||||||
|
wndconfig->height);
|
||||||
|
if (!window->wl.native)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
window->wl.width = wndconfig->width;
|
||||||
|
window->wl.height = wndconfig->height;
|
||||||
|
window->wl.scale = 1;
|
||||||
|
window->wl.title = _glfw_strdup(wndconfig->title);
|
||||||
|
|
||||||
|
window->wl.transparent = fbconfig->transparent;
|
||||||
|
if (!window->wl.transparent)
|
||||||
|
setOpaqueRegion(window);
|
||||||
|
|
||||||
|
if (window->monitor || wndconfig->visible)
|
||||||
|
{
|
||||||
|
if (!createXdgSurface(window))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
window->wl.visible = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void setCursorImage(_GLFWwindow* window,
|
static void setCursorImage(_GLFWwindow* window,
|
||||||
_GLFWcursorWayland* cursorWayland)
|
_GLFWcursorWayland* cursorWayland)
|
||||||
{
|
{
|
||||||
@@ -823,79 +879,103 @@ static void incrementCursorImage(_GLFWwindow* window)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleEvents(int timeout)
|
static GLFWbool flushDisplay(void)
|
||||||
{
|
{
|
||||||
struct wl_display* display = _glfw.wl.display;
|
while (wl_display_flush(_glfw.wl.display) == -1)
|
||||||
struct pollfd fds[] = {
|
{
|
||||||
{ wl_display_get_fd(display), POLLIN },
|
if (errno != EAGAIN)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
struct pollfd fd = { wl_display_get_fd(_glfw.wl.display), POLLOUT };
|
||||||
|
|
||||||
|
while (poll(&fd, 1, -1) == -1)
|
||||||
|
{
|
||||||
|
if (errno != EINTR && errno != EAGAIN)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleEvents(double* timeout)
|
||||||
|
{
|
||||||
|
GLFWbool event = GLFW_FALSE;
|
||||||
|
struct pollfd fds[] =
|
||||||
|
{
|
||||||
|
{ wl_display_get_fd(_glfw.wl.display), POLLIN },
|
||||||
{ _glfw.wl.timerfd, POLLIN },
|
{ _glfw.wl.timerfd, POLLIN },
|
||||||
{ _glfw.wl.cursorTimerfd, POLLIN },
|
{ _glfw.wl.cursorTimerfd, POLLIN },
|
||||||
};
|
};
|
||||||
ssize_t read_ret;
|
|
||||||
uint64_t repeats, i;
|
|
||||||
|
|
||||||
while (wl_display_prepare_read(display) != 0)
|
while (!event)
|
||||||
wl_display_dispatch_pending(display);
|
|
||||||
|
|
||||||
// If an error different from EAGAIN happens, we have likely been
|
|
||||||
// disconnected from the Wayland session, try to handle that the best we
|
|
||||||
// can.
|
|
||||||
if (wl_display_flush(display) < 0 && errno != EAGAIN)
|
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfw.windowListHead;
|
while (wl_display_prepare_read(_glfw.wl.display) != 0)
|
||||||
while (window)
|
wl_display_dispatch_pending(_glfw.wl.display);
|
||||||
|
|
||||||
|
// If an error other than EAGAIN happens, we have likely been disconnected
|
||||||
|
// from the Wayland session; try to handle that the best we can.
|
||||||
|
if (!flushDisplay())
|
||||||
{
|
{
|
||||||
_glfwInputWindowCloseRequest(window);
|
wl_display_cancel_read(_glfw.wl.display);
|
||||||
window = window->next;
|
|
||||||
}
|
_GLFWwindow* window = _glfw.windowListHead;
|
||||||
wl_display_cancel_read(display);
|
while (window)
|
||||||
return;
|
{
|
||||||
}
|
_glfwInputWindowCloseRequest(window);
|
||||||
|
window = window->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!waitForData(fds, 3, timeout))
|
||||||
|
{
|
||||||
|
wl_display_cancel_read(_glfw.wl.display);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (poll(fds, 3, timeout) > 0)
|
|
||||||
{
|
|
||||||
if (fds[0].revents & POLLIN)
|
if (fds[0].revents & POLLIN)
|
||||||
{
|
{
|
||||||
wl_display_read_events(display);
|
wl_display_read_events(_glfw.wl.display);
|
||||||
wl_display_dispatch_pending(display);
|
if (wl_display_dispatch_pending(_glfw.wl.display) > 0)
|
||||||
|
event = GLFW_TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
wl_display_cancel_read(_glfw.wl.display);
|
||||||
wl_display_cancel_read(display);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fds[1].revents & POLLIN)
|
if (fds[1].revents & POLLIN)
|
||||||
{
|
{
|
||||||
read_ret = read(_glfw.wl.timerfd, &repeats, sizeof(repeats));
|
uint64_t repeats;
|
||||||
if (read_ret != 8)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_glfw.wl.keyboardFocus)
|
if (read(_glfw.wl.timerfd, &repeats, sizeof(repeats)) == 8)
|
||||||
{
|
{
|
||||||
for (i = 0; i < repeats; ++i)
|
for (uint64_t i = 0; i < repeats; i++)
|
||||||
{
|
{
|
||||||
_glfwInputKey(_glfw.wl.keyboardFocus,
|
_glfwInputKey(_glfw.wl.keyboardFocus,
|
||||||
_glfw.wl.keyboardLastKey,
|
_glfw.wl.keyboardLastKey,
|
||||||
_glfw.wl.keyboardLastScancode,
|
_glfw.wl.keyboardLastScancode,
|
||||||
GLFW_REPEAT,
|
GLFW_PRESS,
|
||||||
_glfw.wl.xkb.modifiers);
|
_glfw.wl.xkb.modifiers);
|
||||||
|
_glfwInputTextWayland(_glfw.wl.keyboardFocus,
|
||||||
|
_glfw.wl.keyboardLastScancode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event = GLFW_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fds[2].revents & POLLIN)
|
if (fds[2].revents & POLLIN)
|
||||||
{
|
{
|
||||||
read_ret = read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats));
|
uint64_t repeats;
|
||||||
if (read_ret != 8)
|
|
||||||
return;
|
|
||||||
|
|
||||||
incrementCursorImage(_glfw.wl.pointerFocus);
|
if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8)
|
||||||
|
{
|
||||||
|
incrementCursorImage(_glfw.wl.pointerFocus);
|
||||||
|
event = GLFW_TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
wl_display_cancel_read(display);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translates a GLFW standard cursor to a theme cursor name
|
// Translates a GLFW standard cursor to a theme cursor name
|
||||||
@@ -929,9 +1009,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig)
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
window->wl.transparent = fbconfig->transparent;
|
if (!createSurface(window, wndconfig, fbconfig))
|
||||||
|
|
||||||
if (!createSurface(window, wndconfig))
|
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
if (ctxconfig->client != GLFW_NO_API)
|
if (ctxconfig->client != GLFW_NO_API)
|
||||||
@@ -953,38 +1031,6 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wndconfig->title)
|
|
||||||
window->wl.title = _glfw_strdup(wndconfig->title);
|
|
||||||
|
|
||||||
if (wndconfig->visible)
|
|
||||||
{
|
|
||||||
if (_glfw.wl.wmBase)
|
|
||||||
{
|
|
||||||
if (!createXdgSurface(window))
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!createShellSurface(window))
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
window->wl.visible = GLFW_TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
window->wl.xdg.surface = NULL;
|
|
||||||
window->wl.xdg.toplevel = NULL;
|
|
||||||
window->wl.shellSurface = NULL;
|
|
||||||
window->wl.visible = GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
window->wl.currentCursor = NULL;
|
|
||||||
|
|
||||||
window->wl.monitors = calloc(1, sizeof(_GLFWmonitor*));
|
|
||||||
window->wl.monitorsCount = 0;
|
|
||||||
window->wl.monitorsSize = 1;
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1202,29 +1248,29 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
|
|||||||
{
|
{
|
||||||
if (!window->wl.visible)
|
if (!window->wl.visible)
|
||||||
{
|
{
|
||||||
|
// NOTE: The XDG/shell surface is created here so command-line applications
|
||||||
|
// with off-screen windows do not appear in for example the Unity dock
|
||||||
if (_glfw.wl.wmBase)
|
if (_glfw.wl.wmBase)
|
||||||
createXdgSurface(window);
|
{
|
||||||
|
if (!window->wl.xdg.toplevel)
|
||||||
|
createXdgSurface(window);
|
||||||
|
}
|
||||||
else if (!window->wl.shellSurface)
|
else if (!window->wl.shellSurface)
|
||||||
createShellSurface(window);
|
createShellSurface(window);
|
||||||
|
|
||||||
window->wl.visible = GLFW_TRUE;
|
window->wl.visible = GLFW_TRUE;
|
||||||
|
_glfwInputWindowDamage(window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window->wl.xdg.toplevel)
|
if (window->wl.visible)
|
||||||
{
|
{
|
||||||
xdg_toplevel_destroy(window->wl.xdg.toplevel);
|
window->wl.visible = GLFW_FALSE;
|
||||||
xdg_surface_destroy(window->wl.xdg.surface);
|
wl_surface_attach(window->wl.surface, NULL, 0, 0);
|
||||||
window->wl.xdg.toplevel = NULL;
|
wl_surface_commit(window->wl.surface);
|
||||||
window->wl.xdg.surface = NULL;
|
|
||||||
}
|
}
|
||||||
else if (window->wl.shellSurface)
|
|
||||||
{
|
|
||||||
wl_shell_surface_destroy(window->wl.shellSurface);
|
|
||||||
window->wl.shellSurface = NULL;
|
|
||||||
}
|
|
||||||
window->wl.visible = GLFW_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||||
@@ -1341,22 +1387,24 @@ GLFWbool _glfwPlatformRawMouseMotionSupported(void)
|
|||||||
|
|
||||||
void _glfwPlatformPollEvents(void)
|
void _glfwPlatformPollEvents(void)
|
||||||
{
|
{
|
||||||
handleEvents(0);
|
double timeout = 0.0;
|
||||||
|
handleEvents(&timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformWaitEvents(void)
|
void _glfwPlatformWaitEvents(void)
|
||||||
{
|
{
|
||||||
handleEvents(-1);
|
handleEvents(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformWaitEventsTimeout(double timeout)
|
void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||||
{
|
{
|
||||||
handleEvents((int) (timeout * 1e3));
|
handleEvents(&timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformPostEmptyEvent(void)
|
void _glfwPlatformPostEmptyEvent(void)
|
||||||
{
|
{
|
||||||
wl_display_sync(_glfw.wl.display);
|
wl_display_sync(_glfw.wl.display);
|
||||||
|
flushDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||||
@@ -1387,8 +1435,57 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
|||||||
|
|
||||||
const char* _glfwPlatformGetScancodeName(int scancode)
|
const char* _glfwPlatformGetScancodeName(int scancode)
|
||||||
{
|
{
|
||||||
// TODO
|
if (scancode < 0 || scancode > 255 ||
|
||||||
return NULL;
|
_glfw.wl.keycodes[scancode] == GLFW_KEY_UNKNOWN)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"Wayland: Invalid scancode %i",
|
||||||
|
scancode);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int key = _glfw.wl.keycodes[scancode];
|
||||||
|
const xkb_keycode_t keycode = scancode + 8;
|
||||||
|
const xkb_layout_index_t layout =
|
||||||
|
xkb_state_key_get_layout(_glfw.wl.xkb.state, keycode);
|
||||||
|
if (layout == XKB_LAYOUT_INVALID)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland: Failed to retrieve layout for key name");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const xkb_keysym_t* keysyms = NULL;
|
||||||
|
xkb_keymap_key_get_syms_by_level(_glfw.wl.xkb.keymap,
|
||||||
|
keycode,
|
||||||
|
layout,
|
||||||
|
0,
|
||||||
|
&keysyms);
|
||||||
|
if (keysyms == NULL)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland: Failed to retrieve keysym for key name");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t codepoint = _glfwKeySym2Unicode(keysyms[0]);
|
||||||
|
if (codepoint == GLFW_INVALID_CODEPOINT)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland: Failed to retrieve codepoint for key name");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t count = _glfwEncodeUTF8(_glfw.wl.keynames[key], codepoint);
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland: Failed to encode codepoint for key name");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.wl.keynames[key][count] = '\0';
|
||||||
|
return _glfw.wl.keynames[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformGetKeyScancode(int key)
|
int _glfwPlatformGetKeyScancode(int key)
|
||||||
@@ -1744,7 +1841,7 @@ static GLFWbool growClipboardString(void)
|
|||||||
clipboard = realloc(clipboard, _glfw.wl.clipboardSize * 2);
|
clipboard = realloc(clipboard, _glfw.wl.clipboardSize * 2);
|
||||||
if (!clipboard)
|
if (!clipboard)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_OUT_OF_MEMORY,
|
||||||
"Wayland: Impossible to grow clipboard string");
|
"Wayland: Impossible to grow clipboard string");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
@@ -1779,9 +1876,9 @@ const char* _glfwPlatformGetClipboardString(void)
|
|||||||
close(fds[1]);
|
close(fds[1]);
|
||||||
|
|
||||||
// XXX: this is a huge hack, this function shouldn’t be synchronous!
|
// XXX: this is a huge hack, this function shouldn’t be synchronous!
|
||||||
handleEvents(-1);
|
handleEvents(NULL);
|
||||||
|
|
||||||
while (1)
|
for (;;)
|
||||||
{
|
{
|
||||||
// Grow the clipboard if we need to paste something bigger, there is no
|
// Grow the clipboard if we need to paste something bigger, there is no
|
||||||
// shrink operation yet.
|
// shrink operation yet.
|
||||||
|
|||||||
@@ -36,6 +36,9 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
// Translate the X11 KeySyms for a key to a GLFW key code
|
// Translate the X11 KeySyms for a key to a GLFW key code
|
||||||
@@ -568,7 +571,11 @@ static void detectEWMH(void)
|
|||||||
//
|
//
|
||||||
static GLFWbool initExtensions(void)
|
static GLFWbool initExtensions(void)
|
||||||
{
|
{
|
||||||
|
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
|
_glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so");
|
||||||
|
#else
|
||||||
_glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1");
|
_glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1");
|
||||||
|
#endif
|
||||||
if (_glfw.x11.vidmode.handle)
|
if (_glfw.x11.vidmode.handle)
|
||||||
{
|
{
|
||||||
_glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension)
|
_glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension)
|
||||||
@@ -588,6 +595,8 @@ static GLFWbool initExtensions(void)
|
|||||||
|
|
||||||
#if defined(__CYGWIN__)
|
#if defined(__CYGWIN__)
|
||||||
_glfw.x11.xi.handle = _glfw_dlopen("libXi-6.so");
|
_glfw.x11.xi.handle = _glfw_dlopen("libXi-6.so");
|
||||||
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
|
_glfw.x11.xi.handle = _glfw_dlopen("libXi.so");
|
||||||
#else
|
#else
|
||||||
_glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6");
|
_glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6");
|
||||||
#endif
|
#endif
|
||||||
@@ -618,6 +627,8 @@ static GLFWbool initExtensions(void)
|
|||||||
|
|
||||||
#if defined(__CYGWIN__)
|
#if defined(__CYGWIN__)
|
||||||
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr-2.so");
|
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr-2.so");
|
||||||
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
|
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so");
|
||||||
#else
|
#else
|
||||||
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2");
|
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2");
|
||||||
#endif
|
#endif
|
||||||
@@ -710,6 +721,8 @@ static GLFWbool initExtensions(void)
|
|||||||
|
|
||||||
#if defined(__CYGWIN__)
|
#if defined(__CYGWIN__)
|
||||||
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor-1.so");
|
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor-1.so");
|
||||||
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
|
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so");
|
||||||
#else
|
#else
|
||||||
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1");
|
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1");
|
||||||
#endif
|
#endif
|
||||||
@@ -725,6 +738,8 @@ static GLFWbool initExtensions(void)
|
|||||||
|
|
||||||
#if defined(__CYGWIN__)
|
#if defined(__CYGWIN__)
|
||||||
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama-1.so");
|
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama-1.so");
|
||||||
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
|
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so");
|
||||||
#else
|
#else
|
||||||
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1");
|
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1");
|
||||||
#endif
|
#endif
|
||||||
@@ -776,6 +791,8 @@ static GLFWbool initExtensions(void)
|
|||||||
|
|
||||||
#if defined(__CYGWIN__)
|
#if defined(__CYGWIN__)
|
||||||
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb-1.so");
|
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb-1.so");
|
||||||
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
|
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so");
|
||||||
#else
|
#else
|
||||||
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1");
|
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1");
|
||||||
#endif
|
#endif
|
||||||
@@ -787,6 +804,8 @@ static GLFWbool initExtensions(void)
|
|||||||
|
|
||||||
#if defined(__CYGWIN__)
|
#if defined(__CYGWIN__)
|
||||||
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender-1.so");
|
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender-1.so");
|
||||||
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
|
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so");
|
||||||
#else
|
#else
|
||||||
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1");
|
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1");
|
||||||
#endif
|
#endif
|
||||||
@@ -952,6 +971,37 @@ static Window createHelperWindow(void)
|
|||||||
CWEventMask, &wa);
|
CWEventMask, &wa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the pipe for empty events without assumuing the OS has pipe2(2)
|
||||||
|
//
|
||||||
|
static GLFWbool createEmptyEventPipe(void)
|
||||||
|
{
|
||||||
|
if (pipe(_glfw.x11.emptyEventPipe) != 0)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"X11: Failed to create empty event pipe: %s",
|
||||||
|
strerror(errno));
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
const int sf = fcntl(_glfw.x11.emptyEventPipe[i], F_GETFL, 0);
|
||||||
|
const int df = fcntl(_glfw.x11.emptyEventPipe[i], F_GETFD, 0);
|
||||||
|
|
||||||
|
if (sf == -1 || df == -1 ||
|
||||||
|
fcntl(_glfw.x11.emptyEventPipe[i], F_SETFL, sf | O_NONBLOCK) == -1 ||
|
||||||
|
fcntl(_glfw.x11.emptyEventPipe[i], F_SETFD, df | FD_CLOEXEC) == -1)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"X11: Failed to set flags for empty event pipe: %s",
|
||||||
|
strerror(errno));
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
// X error handler
|
// X error handler
|
||||||
//
|
//
|
||||||
static int errorHandler(Display *display, XErrorEvent* event)
|
static int errorHandler(Display *display, XErrorEvent* event)
|
||||||
@@ -1073,6 +1123,9 @@ int _glfwPlatformInit(void)
|
|||||||
|
|
||||||
getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY);
|
getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY);
|
||||||
|
|
||||||
|
if (!createEmptyEventPipe())
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
if (!initExtensions())
|
if (!initExtensions())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
@@ -1190,6 +1243,12 @@ void _glfwPlatformTerminate(void)
|
|||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
_glfwTerminateJoysticksLinux();
|
_glfwTerminateJoysticksLinux();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (_glfw.x11.emptyEventPipe[0] || _glfw.x11.emptyEventPipe[1])
|
||||||
|
{
|
||||||
|
close(_glfw.x11.emptyEventPipe[0]);
|
||||||
|
close(_glfw.x11.emptyEventPipe[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
|
|||||||
@@ -238,6 +238,7 @@ typedef struct _GLFWlibraryX11
|
|||||||
double restoreCursorPosX, restoreCursorPosY;
|
double restoreCursorPosX, restoreCursorPosY;
|
||||||
// The window whose disabled cursor mode is active
|
// The window whose disabled cursor mode is active
|
||||||
_GLFWwindow* disabledCursorWindow;
|
_GLFWwindow* disabledCursorWindow;
|
||||||
|
int emptyEventPipe[2];
|
||||||
|
|
||||||
// Window manager atoms
|
// Window manager atoms
|
||||||
Atom NET_SUPPORTED;
|
Atom NET_SUPPORTED;
|
||||||
|
|||||||
+132
-96
@@ -27,12 +27,16 @@
|
|||||||
// It is fine to use C99 in this file because it will not be built with VS
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#include <X11/cursorfont.h>
|
#include <X11/cursorfont.h>
|
||||||
#include <X11/Xmd.h>
|
#include <X11/Xmd.h>
|
||||||
|
|
||||||
#include <sys/select.h>
|
#include <poll.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -56,50 +60,126 @@
|
|||||||
|
|
||||||
#define _GLFW_XDND_VERSION 5
|
#define _GLFW_XDND_VERSION 5
|
||||||
|
|
||||||
|
// Wait for data to arrive on any of the specified file descriptors
|
||||||
// Wait for data to arrive using select
|
|
||||||
// This avoids blocking other threads via the per-display Xlib lock that also
|
|
||||||
// covers GLX functions
|
|
||||||
//
|
//
|
||||||
static GLFWbool waitForEvent(double* timeout)
|
static GLFWbool waitForData(struct pollfd* fds, nfds_t count, double* timeout)
|
||||||
{
|
{
|
||||||
fd_set fds;
|
|
||||||
const int fd = ConnectionNumber(_glfw.x11.display);
|
|
||||||
int count = fd + 1;
|
|
||||||
|
|
||||||
#if defined(__linux__)
|
|
||||||
if (_glfw.linjs.inotify > fd)
|
|
||||||
count = _glfw.linjs.inotify + 1;
|
|
||||||
#endif
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
FD_ZERO(&fds);
|
|
||||||
FD_SET(fd, &fds);
|
|
||||||
#if defined(__linux__)
|
|
||||||
if (_glfw.linjs.inotify > 0)
|
|
||||||
FD_SET(_glfw.linjs.inotify, &fds);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (timeout)
|
if (timeout)
|
||||||
{
|
{
|
||||||
const long seconds = (long) *timeout;
|
|
||||||
const long microseconds = (long) ((*timeout - seconds) * 1e6);
|
|
||||||
struct timeval tv = { seconds, microseconds };
|
|
||||||
const uint64_t base = _glfwPlatformGetTimerValue();
|
const uint64_t base = _glfwPlatformGetTimerValue();
|
||||||
|
|
||||||
const int result = select(count, &fds, NULL, NULL, &tv);
|
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__)
|
||||||
const int error = errno;
|
const time_t seconds = (time_t) *timeout;
|
||||||
|
const long nanoseconds = (long) ((*timeout - seconds) * 1e9);
|
||||||
|
const struct timespec ts = { seconds, nanoseconds };
|
||||||
|
const int result = ppoll(fds, count, &ts, NULL);
|
||||||
|
#elif defined(__NetBSD__)
|
||||||
|
const time_t seconds = (time_t) *timeout;
|
||||||
|
const long nanoseconds = (long) ((*timeout - seconds) * 1e9);
|
||||||
|
const struct timespec ts = { seconds, nanoseconds };
|
||||||
|
const int result = pollts(fds, count, &ts, NULL);
|
||||||
|
#else
|
||||||
|
const int milliseconds = (int) (*timeout * 1e3);
|
||||||
|
const int result = poll(fds, count, milliseconds);
|
||||||
|
#endif
|
||||||
|
const int error = errno; // clock_gettime may overwrite our error
|
||||||
|
|
||||||
*timeout -= (_glfwPlatformGetTimerValue() - base) /
|
*timeout -= (_glfwPlatformGetTimerValue() - base) /
|
||||||
(double) _glfwPlatformGetTimerFrequency();
|
(double) _glfwPlatformGetTimerFrequency();
|
||||||
|
|
||||||
if (result > 0)
|
if (result > 0)
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
if ((result == -1 && error == EINTR) || *timeout <= 0.0)
|
else if (result == -1 && error != EINTR && error != EAGAIN)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
else if (*timeout <= 0.0)
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
else if (select(count, &fds, NULL, NULL, NULL) != -1 || errno != EINTR)
|
else
|
||||||
return GLFW_TRUE;
|
{
|
||||||
|
const int result = poll(fds, count, -1);
|
||||||
|
if (result > 0)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
else if (result == -1 && errno != EINTR && errno != EAGAIN)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for event data to arrive on the X11 display socket
|
||||||
|
// This avoids blocking other threads via the per-display Xlib lock that also
|
||||||
|
// covers GLX functions
|
||||||
|
//
|
||||||
|
static GLFWbool waitForX11Event(double* timeout)
|
||||||
|
{
|
||||||
|
struct pollfd fd = { ConnectionNumber(_glfw.x11.display), POLLIN };
|
||||||
|
|
||||||
|
while (!XPending(_glfw.x11.display))
|
||||||
|
{
|
||||||
|
if (!waitForData(&fd, 1, timeout))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for event data to arrive on any event file descriptor
|
||||||
|
// This avoids blocking other threads via the per-display Xlib lock that also
|
||||||
|
// covers GLX functions
|
||||||
|
//
|
||||||
|
static GLFWbool waitForAnyEvent(double* timeout)
|
||||||
|
{
|
||||||
|
nfds_t count = 2;
|
||||||
|
struct pollfd fds[3] =
|
||||||
|
{
|
||||||
|
{ ConnectionNumber(_glfw.x11.display), POLLIN },
|
||||||
|
{ _glfw.x11.emptyEventPipe[0], POLLIN }
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
if (_glfw.linjs.inotify > 0)
|
||||||
|
fds[count++] = (struct pollfd) { _glfw.linjs.inotify, POLLIN };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (!XPending(_glfw.x11.display))
|
||||||
|
{
|
||||||
|
if (!waitForData(fds, count, timeout))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
for (int i = 1; i < count; i++)
|
||||||
|
{
|
||||||
|
if (fds[i].revents & POLLIN)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes a byte to the empty event pipe
|
||||||
|
//
|
||||||
|
static void writeEmptyEvent(void)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
const char byte = 0;
|
||||||
|
const int result = write(_glfw.x11.emptyEventPipe[1], &byte, 1);
|
||||||
|
if (result == 1 || (result == -1 && errno != EINTR))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drains available data from the empty event pipe
|
||||||
|
//
|
||||||
|
static void drainEmptyEvents(void)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
char dummy[64];
|
||||||
|
const int result = read(_glfw.x11.emptyEventPipe[0], dummy, sizeof(dummy));
|
||||||
|
if (result == -1 && errno != EINTR)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +196,7 @@ static GLFWbool waitForVisibilityNotify(_GLFWwindow* window)
|
|||||||
VisibilityNotify,
|
VisibilityNotify,
|
||||||
&dummy))
|
&dummy))
|
||||||
{
|
{
|
||||||
if (!waitForEvent(&timeout))
|
if (!waitForX11Event(&timeout))
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,45 +509,14 @@ static char** parseUriList(char* text, int* count)
|
|||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode a Unicode code point to a UTF-8 stream
|
|
||||||
// Based on cutef8 by Jeff Bezanson (Public Domain)
|
|
||||||
//
|
|
||||||
static size_t encodeUTF8(char* s, unsigned int ch)
|
|
||||||
{
|
|
||||||
size_t count = 0;
|
|
||||||
|
|
||||||
if (ch < 0x80)
|
|
||||||
s[count++] = (char) ch;
|
|
||||||
else if (ch < 0x800)
|
|
||||||
{
|
|
||||||
s[count++] = (ch >> 6) | 0xc0;
|
|
||||||
s[count++] = (ch & 0x3f) | 0x80;
|
|
||||||
}
|
|
||||||
else if (ch < 0x10000)
|
|
||||||
{
|
|
||||||
s[count++] = (ch >> 12) | 0xe0;
|
|
||||||
s[count++] = ((ch >> 6) & 0x3f) | 0x80;
|
|
||||||
s[count++] = (ch & 0x3f) | 0x80;
|
|
||||||
}
|
|
||||||
else if (ch < 0x110000)
|
|
||||||
{
|
|
||||||
s[count++] = (ch >> 18) | 0xf0;
|
|
||||||
s[count++] = ((ch >> 12) & 0x3f) | 0x80;
|
|
||||||
s[count++] = ((ch >> 6) & 0x3f) | 0x80;
|
|
||||||
s[count++] = (ch & 0x3f) | 0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a Unicode code point from a UTF-8 stream
|
// Decode a Unicode code point from a UTF-8 stream
|
||||||
// Based on cutef8 by Jeff Bezanson (Public Domain)
|
// Based on cutef8 by Jeff Bezanson (Public Domain)
|
||||||
//
|
//
|
||||||
#if defined(X_HAVE_UTF8_STRING)
|
#if defined(X_HAVE_UTF8_STRING)
|
||||||
static unsigned int decodeUTF8(const char** s)
|
static uint32_t decodeUTF8(const char** s)
|
||||||
{
|
{
|
||||||
unsigned int ch = 0, count = 0;
|
uint32_t codepoint = 0, count = 0;
|
||||||
static const unsigned int offsets[] =
|
static const uint32_t offsets[] =
|
||||||
{
|
{
|
||||||
0x00000000u, 0x00003080u, 0x000e2080u,
|
0x00000000u, 0x00003080u, 0x000e2080u,
|
||||||
0x03c82080u, 0xfa082080u, 0x82082080u
|
0x03c82080u, 0xfa082080u, 0x82082080u
|
||||||
@@ -475,13 +524,13 @@ static unsigned int decodeUTF8(const char** s)
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
ch = (ch << 6) + (unsigned char) **s;
|
codepoint = (codepoint << 6) + (unsigned char) **s;
|
||||||
(*s)++;
|
(*s)++;
|
||||||
count++;
|
count++;
|
||||||
} while ((**s & 0xc0) == 0x80);
|
} while ((**s & 0xc0) == 0x80);
|
||||||
|
|
||||||
assert(count <= 6);
|
assert(count <= 6);
|
||||||
return ch - offsets[count - 1];
|
return codepoint - offsets[count - 1];
|
||||||
}
|
}
|
||||||
#endif /*X_HAVE_UTF8_STRING*/
|
#endif /*X_HAVE_UTF8_STRING*/
|
||||||
|
|
||||||
@@ -499,7 +548,7 @@ static char* convertLatin1toUTF8(const char* source)
|
|||||||
char* tp = target;
|
char* tp = target;
|
||||||
|
|
||||||
for (sp = source; *sp; sp++)
|
for (sp = source; *sp; sp++)
|
||||||
tp += encodeUTF8(tp, *sp);
|
tp += _glfwEncodeUTF8(tp, *sp);
|
||||||
|
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
@@ -1002,7 +1051,7 @@ static const char* getSelectionString(Atom selection)
|
|||||||
SelectionNotify,
|
SelectionNotify,
|
||||||
¬ification))
|
¬ification))
|
||||||
{
|
{
|
||||||
waitForEvent(NULL);
|
waitForX11Event(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notification.xselection.property == None)
|
if (notification.xselection.property == None)
|
||||||
@@ -1038,7 +1087,7 @@ static const char* getSelectionString(Atom selection)
|
|||||||
isSelPropNewValueNotify,
|
isSelPropNewValueNotify,
|
||||||
(XPointer) ¬ification))
|
(XPointer) ¬ification))
|
||||||
{
|
{
|
||||||
waitForEvent(NULL);
|
waitForX11Event(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
XFree(data);
|
XFree(data);
|
||||||
@@ -1283,7 +1332,7 @@ static void processEvent(XEvent *event)
|
|||||||
// (the server never sends a timestamp of zero)
|
// (the server never sends a timestamp of zero)
|
||||||
// NOTE: Timestamp difference is compared to handle wrap-around
|
// NOTE: Timestamp difference is compared to handle wrap-around
|
||||||
Time diff = event->xkey.time - window->x11.keyPressTimes[keycode];
|
Time diff = event->xkey.time - window->x11.keyPressTimes[keycode];
|
||||||
if (diff == event->xkey.time || (diff > 0 && diff < (1 << 31)))
|
if (diff == event->xkey.time || (diff > 0 && diff < ((Time)1 << 31)))
|
||||||
{
|
{
|
||||||
if (keycode)
|
if (keycode)
|
||||||
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
|
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
|
||||||
@@ -1359,9 +1408,9 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
|
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
|
||||||
|
|
||||||
const long character = _glfwKeySym2Unicode(keysym);
|
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
|
||||||
if (character != -1)
|
if (codepoint != GLFW_INVALID_CODEPOINT)
|
||||||
_glfwInputChar(window, character, mods, plain);
|
_glfwInputChar(window, codepoint, mods, plain);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -1969,7 +2018,7 @@ void _glfwPushSelectionToManagerX11(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForEvent(NULL);
|
waitForX11Event(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2287,7 +2336,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
|||||||
isFrameExtentsEvent,
|
isFrameExtentsEvent,
|
||||||
(XPointer) window))
|
(XPointer) window))
|
||||||
{
|
{
|
||||||
if (!waitForEvent(&timeout))
|
if (!waitForX11Event(&timeout))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue");
|
"X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue");
|
||||||
@@ -2779,7 +2828,7 @@ GLFWbool _glfwPlatformRawMouseMotionSupported(void)
|
|||||||
|
|
||||||
void _glfwPlatformPollEvents(void)
|
void _glfwPlatformPollEvents(void)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window;
|
drainEmptyEvents();
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
_glfwDetectJoystickConnectionLinux();
|
_glfwDetectJoystickConnectionLinux();
|
||||||
@@ -2793,7 +2842,7 @@ void _glfwPlatformPollEvents(void)
|
|||||||
processEvent(&event);
|
processEvent(&event);
|
||||||
}
|
}
|
||||||
|
|
||||||
window = _glfw.x11.disabledCursorWindow;
|
_GLFWwindow* window = _glfw.x11.disabledCursorWindow;
|
||||||
if (window)
|
if (window)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
@@ -2813,32 +2862,19 @@ void _glfwPlatformPollEvents(void)
|
|||||||
|
|
||||||
void _glfwPlatformWaitEvents(void)
|
void _glfwPlatformWaitEvents(void)
|
||||||
{
|
{
|
||||||
while (!XPending(_glfw.x11.display))
|
waitForAnyEvent(NULL);
|
||||||
waitForEvent(NULL);
|
|
||||||
|
|
||||||
_glfwPlatformPollEvents();
|
_glfwPlatformPollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformWaitEventsTimeout(double timeout)
|
void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||||
{
|
{
|
||||||
while (!XPending(_glfw.x11.display))
|
waitForAnyEvent(&timeout);
|
||||||
{
|
|
||||||
if (!waitForEvent(&timeout))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwPlatformPollEvents();
|
_glfwPlatformPollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformPostEmptyEvent(void)
|
void _glfwPlatformPostEmptyEvent(void)
|
||||||
{
|
{
|
||||||
XEvent event = { ClientMessage };
|
writeEmptyEvent();
|
||||||
event.xclient.window = _glfw.x11.helperWindowHandle;
|
|
||||||
event.xclient.format = 32; // Data is 32-bit longs
|
|
||||||
event.xclient.message_type = _glfw.x11.NULL_;
|
|
||||||
|
|
||||||
XSendEvent(_glfw.x11.display, _glfw.x11.helperWindowHandle, False, 0, &event);
|
|
||||||
XFlush(_glfw.x11.display);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||||
@@ -2902,11 +2938,11 @@ const char* _glfwPlatformGetScancodeName(int scancode)
|
|||||||
if (keysym == NoSymbol)
|
if (keysym == NoSymbol)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
const long ch = _glfwKeySym2Unicode(keysym);
|
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
|
||||||
if (ch == -1)
|
if (codepoint == GLFW_INVALID_CODEPOINT)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
const size_t count = encodeUTF8(_glfw.x11.keynames[key], (unsigned int) ch);
|
const size_t count = _glfwEncodeUTF8(_glfw.x11.keynames[key], codepoint);
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -907,7 +907,7 @@ static const struct codepair {
|
|||||||
|
|
||||||
// Convert XKB KeySym to Unicode
|
// Convert XKB KeySym to Unicode
|
||||||
//
|
//
|
||||||
long _glfwKeySym2Unicode(unsigned int keysym)
|
uint32_t _glfwKeySym2Unicode(unsigned int keysym)
|
||||||
{
|
{
|
||||||
int min = 0;
|
int min = 0;
|
||||||
int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
|
int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
|
||||||
@@ -937,6 +937,6 @@ long _glfwKeySym2Unicode(unsigned int keysym)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// No matching Unicode value found
|
// No matching Unicode value found
|
||||||
return -1;
|
return GLFW_INVALID_CODEPOINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -24,5 +24,7 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
long _glfwKeySym2Unicode(unsigned int keysym);
|
#define GLFW_INVALID_CODEPOINT 0xffffffffu
|
||||||
|
|
||||||
|
uint32_t _glfwKeySym2Unicode(unsigned int keysym);
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,12 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
{
|
{
|
||||||
const GLFWgammaramp* ramp = glfwGetGammaRamp(monitor);
|
const GLFWgammaramp* ramp = glfwGetGammaRamp(monitor);
|
||||||
|
if (!ramp)
|
||||||
|
{
|
||||||
|
glfwTerminate();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
const size_t array_size = ramp->size * sizeof(short);
|
const size_t array_size = ramp->size * sizeof(short);
|
||||||
orig_ramp.size = ramp->size;
|
orig_ramp.size = ramp->size;
|
||||||
orig_ramp.red = malloc(array_size);
|
orig_ramp.red = malloc(array_size);
|
||||||
|
|||||||
+3
-3
@@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
#include "getopt.h"
|
#include "getopt.h"
|
||||||
|
|
||||||
static int windowed_xpos, windowed_ypos, windowed_width, windowed_height;
|
static int windowed_xpos, windowed_ypos, windowed_width = 640, windowed_height = 480;
|
||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
@@ -180,8 +180,8 @@ static GLFWwindow* create_window(GLFWmonitor* monitor)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
width = 640;
|
width = windowed_width;
|
||||||
height = 480;
|
height = windowed_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
window = glfwCreateWindow(width, height, "Iconify", monitor, NULL);
|
window = glfwCreateWindow(width, height, "Iconify", monitor, NULL);
|
||||||
|
|||||||
Reference in New Issue
Block a user