Merge branch 'glfw:master' into master

This commit is contained in:
Richard Knight 2022-02-17 13:29:50 +00:00 committed by GitHub
commit 48dc1e08d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 421 additions and 288 deletions

View File

@ -58,16 +58,20 @@ video tutorials.
- Ahmad Fatoum - Ahmad Fatoum
- Felipe Ferreira - Felipe Ferreira
- Michael Fogleman - Michael Fogleman
- Jason Francis
- Gerald Franz - Gerald Franz
- Mário Freitas - Mário Freitas
- GeO4d - GeO4d
- Marcus Geelnard - Marcus Geelnard
- ghuser404
- Charles Giessen - Charles Giessen
- Ryan C. Gordon - Ryan C. Gordon
- Stephen Gowen - Stephen Gowen
- Kovid Goyal - Kovid Goyal
- Eloi Marín Gratacós - Eloi Marín Gratacós
- Stefan Gustavson - Stefan Gustavson
- Andrew Gutekanst
- Stephen Gutekanst
- Jonathan Hale - Jonathan Hale
- hdf89shfdfs - hdf89shfdfs
- Sylvain Hellegouarch - Sylvain Hellegouarch
@ -77,6 +81,7 @@ video tutorials.
- Paul Holden - Paul Holden
- Warren Hu - Warren Hu
- Charles Huber - Charles Huber
- InKryption
- IntellectualKitty - IntellectualKitty
- Aaron Jacobs - Aaron Jacobs
- Erik S. V. Jansson - Erik S. V. Jansson
@ -178,6 +183,7 @@ video tutorials.
- Ali Sherief - Ali Sherief
- Yoshiki Shibukawa - Yoshiki Shibukawa
- Dmitri Shuralyov - Dmitri Shuralyov
- Daniel Sieger
- Daniel Skorupski - Daniel Skorupski
- Anthony Smith - Anthony Smith
- Bradley Smith - Bradley Smith

View File

@ -202,6 +202,9 @@ information on what to include when reporting a bug.
later (#1783,#1796) later (#1783,#1796)
- [Win32] Bugfix: Compilation with LLVM for Windows failed (#1807,#1824,#1874) - [Win32] Bugfix: Compilation with LLVM for Windows failed (#1807,#1824,#1874)
- [Win32] Bugfix: The foreground lock timeout was overridden, ignoring the user - [Win32] Bugfix: The foreground lock timeout was overridden, ignoring the user
- [Win32] Bugfix: Content scale queries could fail silently (#1615)
- [Win32] Bugfix: Content scales could have garbage values if monitor was recently
disconnected (#1615)
- [Cocoa] Added support for `VK_EXT_metal_surface` (#1619) - [Cocoa] Added support for `VK_EXT_metal_surface` (#1619)
- [Cocoa] Added locating the Vulkan loader at runtime in an application bundle - [Cocoa] Added locating the Vulkan loader at runtime in an application bundle
- [Cocoa] Moved main menu creation to GLFW initialization time (#1649) - [Cocoa] Moved main menu creation to GLFW initialization time (#1649)
@ -231,6 +234,7 @@ information on what to include when reporting a bug.
- [Cocoa] Bugfix: Moving the cursor programmatically would freeze it for - [Cocoa] Bugfix: Moving the cursor programmatically would freeze it for
a fraction of a second (#1962) a fraction of a second (#1962)
- [Cocoa] Bugfix: `kIOMasterPortDefault` was deprecated in macOS 12.0 (#1980) - [Cocoa] Bugfix: `kIOMasterPortDefault` was deprecated in macOS 12.0 (#1980)
- [Cocoa] Bugfix: `kUTTypeURL` was deprecated in macOS 12.0 (#2003)
- [X11] Bugfix: The CMake files did not check for the XInput headers (#1480) - [X11] Bugfix: The CMake files did not check for the XInput headers (#1480)
- [X11] Bugfix: Key names were not updated when the keyboard layout changed - [X11] Bugfix: Key names were not updated when the keyboard layout changed
(#1462,#1528) (#1462,#1528)
@ -259,7 +263,11 @@ information on what to include when reporting a bug.
- [X11] Bugfix: Some window attributes were not applied on leaving fullscreen - [X11] Bugfix: Some window attributes were not applied on leaving fullscreen
(#1863) (#1863)
- [X11] Bugfix: Changing `GLFW_FLOATING` could leak memory - [X11] Bugfix: Changing `GLFW_FLOATING` could leak memory
- [X11] Bugfix: Icon pixel format conversion worked only by accident, relying on
undefined behavior (#1986)
- [X11] Bugfix: Dynamic loading on OpenBSD failed due to soname differences
- [Wayland] Added dynamic loading of all Wayland libraries - [Wayland] Added dynamic loading of all Wayland libraries
- [Wayland] Added support for key names via xkbcommon
- [Wayland] Removed support for `wl_shell` (#1443) - [Wayland] Removed support for `wl_shell` (#1443)
- [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432) - [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432)
- [Wayland] Bugfix: `CLOCK_MONOTONIC` was not correctly enabled - [Wayland] Bugfix: `CLOCK_MONOTONIC` was not correctly enabled
@ -273,6 +281,15 @@ information on what to include when reporting a bug.
- [Wayland] Bugfix: Some keys were not repeating in Wayland (#1908) - [Wayland] Bugfix: Some keys were not repeating in Wayland (#1908)
- [Wayland] Bugfix: Non-arrow cursors are offset from the hotspot (#1706,#1899) - [Wayland] Bugfix: Non-arrow cursors are offset from the hotspot (#1706,#1899)
- [Wayland] Bugfix: The `O_CLOEXEC` flag was not defined on FreeBSD - [Wayland] Bugfix: The `O_CLOEXEC` flag was not defined on FreeBSD
- [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
- [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Removed use of deprecated function `gettimeofday`
- [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled
- [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072) - [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072)

View File

@ -2167,15 +2167,6 @@ EXTERNAL_PAGES = YES
# Configuration options related to the dot tool # Configuration options related to the dot tool
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
# disabled, but it is recommended to install and use dot, since it yields more
# powerful graphs.
# The default value is: YES.
CLASS_DIAGRAMS = YES
# You can include diagrams made with dia in doxygen documentation. Doxygen will # You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The # then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides. # DIA_PATH tag allows you to specify the directory where the dia binary resides.

View File

@ -104,9 +104,8 @@ integration by libwayland-egl, and keyboard handling by
from wayland-protocols to provide additional features if the compositor from wayland-protocols to provide additional features if the compositor
supports them. supports them.
GLFW uses xkbcommon 0.5.0 to provide compose key support. When it has been GLFW uses xkbcommon 0.5.0 to provide key and text input support. Earlier
built against an older xkbcommon, the compose key will be disabled even if it versions are not supported.
has been configured in the compositor.
GLFW uses the [xdg-shell GLFW uses the [xdg-shell
protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/xdg-shell/xdg-shell.xml) protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/xdg-shell/xdg-shell.xml)

View File

@ -2,7 +2,7 @@
// This is an example program for the GLFW library // This is an example program for the GLFW library
// //
// The program uses a "split window" view, rendering four views of the // The program uses a "split window" view, rendering four views of the
// same scene in one window (e.g. uesful for 3D modelling software). This // same scene in one window (e.g. useful for 3D modelling software). This
// demo uses scissors to separate the four different rendering areas from // demo uses scissors to separate the four different rendering areas from
// each other. // each other.
// //

View File

@ -1028,7 +1028,7 @@ extern "C" {
* and [attribute](@ref GLFW_CONTEXT_VERSION_MINOR_attrib). * and [attribute](@ref GLFW_CONTEXT_VERSION_MINOR_attrib).
*/ */
#define GLFW_CONTEXT_VERSION_MINOR 0x00022003 #define GLFW_CONTEXT_VERSION_MINOR 0x00022003
/*! @brief Context client API revision number hint and attribute. /*! @brief Context client API revision number attribute.
* *
* Context client API revision number * Context client API revision number
* [attribute](@ref GLFW_CONTEXT_REVISION_attrib). * [attribute](@ref GLFW_CONTEXT_REVISION_attrib).
@ -3764,6 +3764,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
@ -5703,6 +5708,8 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string);
* joystick is not present, does not have a mapping or an * joystick is not present, does not have a mapping or an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref GLFW_INVALID_ENUM.
*
* @pointer_lifetime The returned string is allocated and freed by GLFW. You * @pointer_lifetime The returned string is allocated and freed by GLFW. You
* should not free it yourself. It is valid until the specified joystick is * should not free it yourself. It is valid until the specified joystick is
* disconnected, the gamepad mappings are updated or the library is terminated. * disconnected, the gamepad mappings are updated or the library is terminated.
@ -5792,8 +5799,8 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
* @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL`
* if an [error](@ref error_handling) occurred. * if an [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR. * GLFW_FORMAT_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
* *
* @pointer_lifetime The returned string is allocated and freed by GLFW. You * @pointer_lifetime The returned string is allocated and freed by GLFW. You
* should not free it yourself. It is valid until the next call to @ref * should not free it yourself. It is valid until the next call to @ref
@ -6187,9 +6194,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.
@ -6328,17 +6332,20 @@ 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.
* *
* @remark @x11 GLFW by default attempts to use the `VK_KHR_xcb_surface` * @remark @x11 By default GLFW prefers the `VK_KHR_xcb_surface` extension,
* extension, if available. You can make it prefer the `VK_KHR_xlib_surface` * with the `VK_KHR_xlib_surface` extension as a fallback. You can make
* extension by setting the * `VK_KHR_xlib_surface` the preferred extension by setting the
* [GLFW_X11_XCB_VULKAN_SURFACE](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint) init * [GLFW_X11_XCB_VULKAN_SURFACE](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint) init
* hint. * hint. The name of the selected extension, if any, is included in the array
* returned by @ref glfwGetRequiredInstanceExtensions.
* *
* @thread_safety This function may be called from any thread. For * @thread_safety This function may be called from any thread. For
* synchronization details of Vulkan objects, see the Vulkan specification. * synchronization details of Vulkan objects, see the Vulkan specification.

View File

@ -65,10 +65,6 @@ endif()
if (GLFW_BUILD_WAYLAND) if (GLFW_BUILD_WAYLAND)
include(CheckIncludeFiles) include(CheckIncludeFiles)
include(CheckFunctionExists) include(CheckFunctionExists)
check_include_files(xkbcommon/xkbcommon-compose.h HAVE_XKBCOMMON_COMPOSE_H)
if (HAVE_XKBCOMMON_COMPOSE_H)
target_compile_definitions(glfw PRIVATE HAVE_XKBCOMMON_COMPOSE_H)
endif()
check_function_exists(memfd_create HAVE_MEMFD_CREATE) check_function_exists(memfd_create HAVE_MEMFD_CREATE)
if (HAVE_MEMFD_CREATE) if (HAVE_MEMFD_CREATE)
target_compile_definitions(glfw PRIVATE HAVE_MEMFD_CREATE) target_compile_definitions(glfw PRIVATE HAVE_MEMFD_CREATE)
@ -173,7 +169,7 @@ if (GLFW_BUILD_WAYLAND)
wayland-client>=0.2.7 wayland-client>=0.2.7
wayland-cursor>=0.2.7 wayland-cursor>=0.2.7
wayland-egl>=0.2.7 wayland-egl>=0.2.7
xkbcommon) xkbcommon>=0.5.0)
target_include_directories(glfw PRIVATE ${Wayland_INCLUDE_DIRS}) target_include_directories(glfw PRIVATE ${Wayland_INCLUDE_DIRS})
@ -194,31 +190,37 @@ if (GLFW_BUILD_X11)
if (NOT X11_Xrandr_INCLUDE_PATH) if (NOT X11_Xrandr_INCLUDE_PATH)
message(FATAL_ERROR "RandR headers not found; install libxrandr development package") message(FATAL_ERROR "RandR headers not found; install libxrandr development package")
endif() endif()
target_include_directories(glfw PRIVATE "${X11_Xrandr_INCLUDE_PATH}")
# Check for Xinerama (legacy multi-monitor support) # Check for Xinerama (legacy multi-monitor support)
if (NOT X11_Xinerama_INCLUDE_PATH) if (NOT X11_Xinerama_INCLUDE_PATH)
message(FATAL_ERROR "Xinerama headers not found; install libxinerama development package") message(FATAL_ERROR "Xinerama headers not found; install libxinerama development package")
endif() endif()
target_include_directories(glfw PRIVATE "${X11_Xinerama_INCLUDE_PATH}")
# Check for Xkb (X keyboard extension) # Check for Xkb (X keyboard extension)
if (NOT X11_Xkb_INCLUDE_PATH) if (NOT X11_Xkb_INCLUDE_PATH)
message(FATAL_ERROR "XKB headers not found; install X11 development package") message(FATAL_ERROR "XKB headers not found; install X11 development package")
endif() endif()
target_include_directories(glfw PRIVATE "${X11_Xkb_INCLUDE_PATH}")
# Check for Xcursor (cursor creation from RGBA images) # Check for Xcursor (cursor creation from RGBA images)
if (NOT X11_Xcursor_INCLUDE_PATH) if (NOT X11_Xcursor_INCLUDE_PATH)
message(FATAL_ERROR "Xcursor headers not found; install libxcursor development package") message(FATAL_ERROR "Xcursor headers not found; install libxcursor development package")
endif() endif()
target_include_directories(glfw PRIVATE "${X11_Xcursor_INCLUDE_PATH}")
# Check for XInput (modern HID input) # Check for XInput (modern HID input)
if (NOT X11_Xi_INCLUDE_PATH) if (NOT X11_Xi_INCLUDE_PATH)
message(FATAL_ERROR "XInput headers not found; install libxi development package") message(FATAL_ERROR "XInput headers not found; install libxi development package")
endif() endif()
target_include_directories(glfw PRIVATE "${X11_Xi_INCLUDE_PATH}")
# Check for X Shape (custom window input shape) # Check for X Shape (custom window input shape)
if (NOT X11_Xshape_INCLUDE_PATH) if (NOT X11_Xshape_INCLUDE_PATH)
message(FATAL_ERROR "X Shape headers not found; install libxext development package") message(FATAL_ERROR "X Shape headers not found; install libxext development package")
endif() endif()
target_include_directories(glfw PRIVATE "${X11_Xshape_INCLUDE_PATH}")
endif() endif()
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)

View File

@ -42,16 +42,15 @@ 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 < 101400 #if MAC_OS_X_VERSION_MAX_ALLOWED < 101400
#define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval #define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval
#define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity #define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
#endif #endif
// NOTE: Many Cocoa enum values have been renamed and we need to build across
// SDK versions where one is unavailable or the other deprecated
// We use the newer names in code and these macros to handle compatibility
#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
@ -70,6 +69,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;

View File

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

View File

@ -231,6 +231,15 @@ static void swapBuffersEGL(_GLFWwindow* window)
return; return;
} }
#if defined(_GLFW_WAYLAND)
if (_glfw.platform.platformID == GLFW_PLATFORM_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);
} }
@ -316,6 +325,8 @@ GLFWbool _glfwInitEGL(void)
"libEGL.dylib", "libEGL.dylib",
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
"libEGL-1.so", "libEGL-1.so",
#elif defined(__OpenBSD__)
"libEGL.so",
#else #else
"libEGL.so.1", "libEGL.so.1",
#endif #endif
@ -472,6 +483,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;
} }
@ -646,6 +659,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);
native = _glfw.platform.getEGLNativeWindow(window); native = _glfw.platform.getEGLNativeWindow(window);
@ -686,6 +702,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__)
"libGLESv1_CM.so",
#else #else
"libGLESv1_CM.so.1", "libGLESv1_CM.so.1",
"libGLES_CM.so.1", "libGLES_CM.so.1",
@ -703,6 +721,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
"libGLESv2.dylib", "libGLESv2.dylib",
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
"libGLESv2-2.so", "libGLESv2-2.so",
#elif defined(__OpenBSD__)
"libGLESv2.so",
#else #else
"libGLESv2.so.2", "libGLESv2.so.2",
#endif #endif
@ -714,6 +734,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__)
"libGL.so",
#else #else
"libGL.so.1", "libGL.so.1",
#endif #endif

View File

@ -259,6 +259,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__)
"libGL.so",
#else #else
"libGL.so.1", "libGL.so.1",
"libGL.so", "libGL.so",

View File

@ -36,16 +36,15 @@
#include <assert.h> #include <assert.h>
// The global variables below comprise all mutable global data in GLFW // NOTE: The global variables below comprise all mutable global data in GLFW
// // Any other mutable global variable is a bug
// Any other global variable is a bug
// Global state shared between compilation units of GLFW // This contains all mutable state shared between compilation units of GLFW
// //
_GLFWlibrary _glfw = { GLFW_FALSE }; _GLFWlibrary _glfw = { GLFW_FALSE };
// These are outside of _glfw so they can be used before initialization and // These are outside of _glfw so they can be used before initialization and
// after termination // after termination without special handling when _glfw is cleared to zero
// //
static _GLFWerror _glfwMainThreadError; static _GLFWerror _glfwMainThreadError;
static GLFWerrorfun _glfwErrorCallback; static GLFWerrorfun _glfwErrorCallback;
@ -141,6 +140,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);

View File

@ -295,7 +295,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;

View File

@ -177,6 +177,7 @@ typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint);
#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098 #define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
#define EGL_PLATFORM_X11_EXT 0x31d5 #define EGL_PLATFORM_X11_EXT 0x31d5
#define EGL_PLATFORM_WAYLAND_EXT 0x31d8 #define EGL_PLATFORM_WAYLAND_EXT 0x31d8
#define EGL_PRESENT_OPAQUE_EXT 0x31df
#define EGL_PLATFORM_ANGLE_ANGLE 0x3202 #define EGL_PLATFORM_ANGLE_ANGLE 0x3202
#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203 #define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320d #define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320d
@ -803,6 +804,7 @@ struct _GLFWlibrary
GLFWbool EXT_platform_base; GLFWbool EXT_platform_base;
GLFWbool EXT_platform_x11; GLFWbool EXT_platform_x11;
GLFWbool EXT_platform_wayland; GLFWbool EXT_platform_wayland;
GLFWbool EXT_present_opaque;
GLFWbool ANGLE_platform_angle; GLFWbool ANGLE_platform_angle;
GLFWbool ANGLE_platform_angle_opengl; GLFWbool ANGLE_platform_angle_opengl;
GLFWbool ANGLE_platform_angle_d3d; GLFWbool ANGLE_platform_angle_d3d;
@ -917,7 +919,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);
@ -993,6 +995,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);

View File

@ -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__)
"libOSMesa.so",
#else #else
"libOSMesa.so.8", "libOSMesa.so.8",
"libOSMesa.so.6", "libOSMesa.so.6",

View File

@ -72,6 +72,11 @@ GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform)
// Only allow the Null platform if specifically requested // Only allow the Null platform if specifically requested
if (desiredID == GLFW_PLATFORM_NULL) if (desiredID == GLFW_PLATFORM_NULL)
return _glfwConnectNull(desiredID, platform); return _glfwConnectNull(desiredID, platform);
else if (count == 0)
{
_glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "This binary only supports the Null platform");
return GLFW_FALSE;
}
if (desiredID == GLFW_ANY_PLATFORM) if (desiredID == GLFW_ANY_PLATFORM)
{ {
@ -86,10 +91,7 @@ GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform)
return GLFW_TRUE; return GLFW_TRUE;
} }
if (count)
_glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "Failed to detect any supported platform"); _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "Failed to detect any supported platform");
else
_glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "This binary only supports the Null platform");
} }
else else
{ {

View File

@ -63,6 +63,8 @@ GLFWbool _glfwInitVulkan(int mode)
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib"); _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib");
if (!_glfw.vk.handle) if (!_glfw.vk.handle)
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa(); _glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa();
#elif defined(__OpenBSD__)
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so");
#else #else
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so.1"); _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so.1");
#endif #endif

View File

@ -317,8 +317,19 @@ void _glfwGetHMONITORContentScaleWin32(HMONITOR handle, float* xscale, float* ys
{ {
UINT xdpi, ydpi; UINT xdpi, ydpi;
if (xscale)
*xscale = 0.f;
if (yscale)
*yscale = 0.f;
if (IsWindows8Point1OrGreater()) if (IsWindows8Point1OrGreater())
GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi); {
if (GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi) != S_OK)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to query monitor DPI");
return;
}
}
else else
{ {
const HDC dc = GetDC(NULL); const HDC dc = GetDC(NULL);

View File

@ -649,7 +649,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)
{ {
@ -683,7 +683,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;
} }
@ -1304,9 +1304,13 @@ static int createNativeWindow(_GLFWwindow* window,
{ {
float xscale, yscale; float xscale, yscale;
_glfwGetWindowContentScaleWin32(window, &xscale, &yscale); _glfwGetWindowContentScaleWin32(window, &xscale, &yscale);
if (xscale > 0.f && yscale > 0.f)
{
rect.right = (int) (rect.right * xscale); rect.right = (int) (rect.right * xscale);
rect.bottom = (int) (rect.bottom * yscale); rect.bottom = (int) (rect.bottom * yscale);
} }
}
ClientToScreen(window->win32.handle, (POINT*) &rect.left); ClientToScreen(window->win32.handle, (POINT*) &rect.left);
ClientToScreen(window->win32.handle, (POINT*) &rect.right); ClientToScreen(window->win32.handle, (POINT*) &rect.right);
@ -1645,8 +1649,7 @@ void _glfwGetWindowFrameSizeWin32(_GLFWwindow* window,
*bottom = rect.bottom - height; *bottom = rect.bottom - height;
} }
void _glfwGetWindowContentScaleWin32(_GLFWwindow* window, void _glfwGetWindowContentScaleWin32(_GLFWwindow* window, float* xscale, float* yscale)
float* xscale, float* yscale)
{ {
const HANDLE handle = MonitorFromWindow(window->win32.handle, const HANDLE handle = MonitorFromWindow(window->win32.handle,
MONITOR_DEFAULTTONEAREST); MONITOR_DEFAULTTONEAREST);

View File

@ -207,12 +207,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;
@ -272,9 +272,7 @@ static void pointerHandleButton(void* data,
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP; edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
else else
{
xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial); xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
}
break; break;
case leftDecoration: case leftDecoration:
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
@ -303,6 +301,7 @@ static void pointerHandleButton(void* data,
{ {
xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat, xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat,
serial, edges); serial, edges);
return;
} }
} }
else if (button == BTN_RIGHT) else if (button == BTN_RIGHT)
@ -378,11 +377,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;
@ -431,7 +427,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);
@ -451,7 +446,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);
@ -505,20 +499,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)
@ -538,77 +534,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);
} }
@ -620,9 +604,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)
@ -636,24 +617,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_serialize_mods(_glfw.wl.xkb.state,
XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_DEPRESSED |
XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_DEPRESSED |
XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_LATCHED |
XKB_STATE_LAYOUT_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
@ -970,7 +956,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;
@ -1013,7 +999,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;
@ -1026,9 +1012,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 (int scancode = 0; scancode < 256; scancode++) for (int scancode = 0; scancode < 256; scancode++)
{ {
@ -1287,6 +1274,8 @@ int _glfwInitWayland(void)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index"); _glfwPlatformGetModuleSymbol(_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)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats"); _glfwPlatformGetModuleSymbol(_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)
_glfwPlatformGetModuleSymbol(_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)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_new"); _glfwPlatformGetModuleSymbol(_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)
@ -1297,8 +1286,8 @@ int _glfwInitWayland(void)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_update_mask"); _glfwPlatformGetModuleSymbol(_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)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_serialize_mods"); _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_serialize_mods");
_glfw.wl.xkb.state_key_get_layout = (PFN_xkb_state_key_get_layout)
#ifdef HAVE_XKBCOMMON_COMPOSE_H _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_key_get_layout");
_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)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale"); _glfwPlatformGetModuleSymbol(_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)
@ -1313,7 +1302,6 @@ int _glfwInitWayland(void)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_status"); _glfwPlatformGetModuleSymbol(_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)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym"); _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");
#endif
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display); _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL); wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);
@ -1336,7 +1324,7 @@ int _glfwInitWayland(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.wmBase) if (!_glfw.wl.wmBase)
{ {
@ -1370,7 +1358,7 @@ int _glfwInitWayland(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)
@ -1401,10 +1389,8 @@ void _glfwTerminateWayland(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)

View File

@ -26,9 +26,7 @@
#include <wayland-client-core.h> #include <wayland-client-core.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
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR; typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
@ -163,24 +161,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);
@ -195,7 +196,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
@ -311,6 +311,7 @@ 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;
@ -318,9 +319,7 @@ typedef struct _GLFWlibraryWayland
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;
@ -336,13 +335,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;
@ -350,7 +350,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;
@ -496,4 +495,5 @@ GLFWbool _glfwGetGammaRampWayland(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp); void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
void _glfwAddOutputWayland(uint32_t name, uint32_t version); void _glfwAddOutputWayland(uint32_t name, uint32_t version);
GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode);

View File

@ -432,35 +432,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)
{ {
@ -537,7 +508,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,
@ -645,6 +615,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)
{ {
@ -709,22 +719,19 @@ static void incrementCursorImage(_GLFWwindow* window)
static void handleEvents(int timeout) static void handleEvents(int timeout)
{ {
struct wl_display* display = _glfw.wl.display; struct pollfd fds[] =
struct pollfd fds[] = { {
{ wl_display_get_fd(display), POLLIN }, { 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;
while (wl_display_prepare_read(display) != 0) while (wl_display_prepare_read(_glfw.wl.display) != 0)
wl_display_dispatch_pending(display); wl_display_dispatch_pending(_glfw.wl.display);
// If an error different from EAGAIN happens, we have likely been // If an error other than EAGAIN happens, we have likely been disconnected
// disconnected from the Wayland session, try to handle that the best we // from the Wayland session; try to handle that the best we can.
// can. if (wl_display_flush(_glfw.wl.display) < 0 && errno != EAGAIN)
if (wl_display_flush(display) < 0 && errno != EAGAIN)
{ {
_GLFWwindow* window = _glfw.windowListHead; _GLFWwindow* window = _glfw.windowListHead;
while (window) while (window)
@ -732,7 +739,8 @@ static void handleEvents(int timeout)
_glfwInputWindowCloseRequest(window); _glfwInputWindowCloseRequest(window);
window = window->next; window = window->next;
} }
wl_display_cancel_read(display);
wl_display_cancel_read(_glfw.wl.display);
return; return;
} }
@ -740,46 +748,41 @@ static void handleEvents(int timeout)
{ {
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); wl_display_dispatch_pending(_glfw.wl.display);
} }
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 (uint64_t 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);
} }
} }
} }
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;
if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8)
incrementCursorImage(_glfw.wl.pointerFocus); incrementCursorImage(_glfw.wl.pointerFocus);
} }
} }
else else
{ wl_display_cancel_read(_glfw.wl.display);
wl_display_cancel_read(display);
}
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -791,9 +794,7 @@ int _glfwCreateWindowWayland(_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)
@ -815,29 +816,6 @@ int _glfwCreateWindowWayland(_GLFWwindow* window,
} }
} }
if (wndconfig->title)
window->wl.title = _glfw_strdup(wndconfig->title);
if (wndconfig->visible)
{
if (!createXdgSurface(window))
return GLFW_FALSE;
window->wl.visible = GLFW_TRUE;
}
else
{
window->wl.xdg.surface = NULL;
window->wl.xdg.toplevel = NULL;
window->wl.visible = GLFW_FALSE;
}
window->wl.currentCursor = NULL;
window->wl.monitors = _glfw_calloc(1, sizeof(_GLFWmonitor*));
window->wl.monitorsCount = 0;
window->wl.monitorsSize = 1;
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -1024,21 +1002,24 @@ void _glfwShowWindowWayland(_GLFWwindow* window)
{ {
if (!window->wl.visible) if (!window->wl.visible)
{ {
// NOTE: The XDG surface and role are created here so command-line applications
// with off-screen windows do not appear in for example the Unity dock
if (!window->wl.xdg.toplevel)
createXdgSurface(window); createXdgSurface(window);
window->wl.visible = GLFW_TRUE; window->wl.visible = GLFW_TRUE;
_glfwInputWindowDamage(window);
} }
} }
void _glfwHideWindowWayland(_GLFWwindow* window) void _glfwHideWindowWayland(_GLFWwindow* window)
{ {
if (window->wl.xdg.toplevel) if (window->wl.visible)
{ {
xdg_toplevel_destroy(window->wl.xdg.toplevel);
xdg_surface_destroy(window->wl.xdg.surface);
window->wl.xdg.toplevel = NULL;
window->wl.xdg.surface = NULL;
}
window->wl.visible = GLFW_FALSE; window->wl.visible = GLFW_FALSE;
wl_surface_attach(window->wl.surface, NULL, 0, 0);
wl_surface_commit(window->wl.surface);
}
} }
void _glfwRequestWindowAttentionWayland(_GLFWwindow* window) void _glfwRequestWindowAttentionWayland(_GLFWwindow* window)
@ -1214,12 +1195,59 @@ void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode)
const char* _glfwGetScancodeNameWayland(int scancode) const char* _glfwGetScancodeNameWayland(int scancode)
{ {
// TODO if (scancode < 0 || scancode > 255 ||
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, _glfw.wl.keycodes[scancode] == GLFW_KEY_UNKNOWN)
"Wayland: Key names not yet implemented"); {
_glfwInputError(GLFW_INVALID_VALUE,
"Wayland: Invalid scancode %i",
scancode);
return NULL; 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 _glfwGetKeyScancodeWayland(int key) int _glfwGetKeyScancodeWayland(int key)
{ {
return _glfw.wl.scancodes[key]; return _glfw.wl.scancodes[key];

View File

@ -601,7 +601,11 @@ static void detectEWMH(void)
// //
static GLFWbool initExtensions(void) static GLFWbool initExtensions(void)
{ {
#if defined(__OpenBSD__)
_glfw.x11.vidmode.handle = _glfwPlatformLoadModule("libXxf86vm.so");
#else
_glfw.x11.vidmode.handle = _glfwPlatformLoadModule("libXxf86vm.so.1"); _glfw.x11.vidmode.handle = _glfwPlatformLoadModule("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)
@ -621,6 +625,8 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__) #if defined(__CYGWIN__)
_glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi-6.so"); _glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi-6.so");
#elif defined(__OpenBSD__)
_glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi.so");
#else #else
_glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi.so.6"); _glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi.so.6");
#endif #endif
@ -651,6 +657,8 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__) #if defined(__CYGWIN__)
_glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr-2.so"); _glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr-2.so");
#elif defined(__OpenBSD__)
_glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr.so");
#else #else
_glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr.so.2"); _glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr.so.2");
#endif #endif
@ -743,6 +751,8 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__) #if defined(__CYGWIN__)
_glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor-1.so"); _glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor-1.so");
#elif defined(__OpenBSD__)
_glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor.so");
#else #else
_glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor.so.1"); _glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor.so.1");
#endif #endif
@ -764,6 +774,8 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__) #if defined(__CYGWIN__)
_glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama-1.so"); _glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama-1.so");
#elif defined(__OpenBSD__)
_glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama.so");
#else #else
_glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama.so.1"); _glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama.so.1");
#endif #endif
@ -817,6 +829,8 @@ static GLFWbool initExtensions(void)
{ {
#if defined(__CYGWIN__) #if defined(__CYGWIN__)
_glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb-1.so"); _glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb-1.so");
#elif defined(__OpenBSD__)
_glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb.so");
#else #else
_glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb.so.1"); _glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb.so.1");
#endif #endif
@ -830,6 +844,8 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__) #if defined(__CYGWIN__)
_glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender-1.so"); _glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender-1.so");
#elif defined(__OpenBSD__)
_glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender.so");
#else #else
_glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender.so.1"); _glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender.so.1");
#endif #endif
@ -857,6 +873,8 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__) #if defined(__CYGWIN__)
_glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext-6.so"); _glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext-6.so");
#elif defined(__OpenBSD__)
_glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext.so");
#else #else
_glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext.so.6"); _glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext.so.6");
#endif #endif
@ -1203,6 +1221,8 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform)
#if defined(__CYGWIN__) #if defined(__CYGWIN__)
void* module = _glfwPlatformLoadModule("libX11-6.so"); void* module = _glfwPlatformLoadModule("libX11-6.so");
#elif defined(__OpenBSD__)
void* module = _glfwPlatformLoadModule("libX11.so");
#else #else
void* module = _glfwPlatformLoadModule("libX11.so.6"); void* module = _glfwPlatformLoadModule("libX11.so.6");
#endif #endif

View File

@ -429,44 +429,13 @@ 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)
// //
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
@ -474,13 +443,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];
} }
// Convert the specified Latin-1 string to UTF-8 // Convert the specified Latin-1 string to UTF-8
@ -497,7 +466,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;
} }
@ -1317,9 +1286,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;
@ -2105,8 +2074,8 @@ void _glfwSetWindowIconX11(_GLFWwindow* window, int count, const GLFWimage* imag
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
longCount += 2 + images[i].width * images[i].height; longCount += 2 + images[i].width * images[i].height;
long* icon = _glfw_calloc(longCount, sizeof(long)); unsigned long* icon = _glfw_calloc(longCount, sizeof(unsigned long));
long* target = icon; unsigned long* target = icon;
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
@ -2115,13 +2084,19 @@ void _glfwSetWindowIconX11(_GLFWwindow* window, int count, const GLFWimage* imag
for (int j = 0; j < images[i].width * images[i].height; j++) for (int j = 0; j < images[i].width * images[i].height; j++)
{ {
*target++ = (images[i].pixels[j * 4 + 0] << 16) | *target++ = (((unsigned long) images[i].pixels[j * 4 + 0]) << 16) |
(images[i].pixels[j * 4 + 1] << 8) | (((unsigned long) images[i].pixels[j * 4 + 1]) << 8) |
(images[i].pixels[j * 4 + 2] << 0) | (((unsigned long) images[i].pixels[j * 4 + 2]) << 0) |
(images[i].pixels[j * 4 + 3] << 24); (((unsigned long) images[i].pixels[j * 4 + 3]) << 24);
} }
} }
// NOTE: XChangeProperty expects 32-bit values like the image data above to be
// placed in the 32 least significant bits of individual longs. This is
// true even if long is 64-bit and a WM protocol calls for "packed" data.
// This is because of a historical mistake that then became part of the Xlib
// ABI. Xlib will pack these values into a regular array of 32-bit values
// before sending it over the wire.
XChangeProperty(_glfw.x11.display, window->x11.handle, XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_ICON, _glfw.x11.NET_WM_ICON,
XA_CARDINAL, 32, XA_CARDINAL, 32,
@ -2893,11 +2868,11 @@ const char* _glfwGetScancodeNameX11(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;

View File

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

View File

@ -24,5 +24,7 @@
// //
//======================================================================== //========================================================================
long _glfwKeySym2Unicode(unsigned int keysym); #define GLFW_INVALID_CODEPOINT 0xffffffffu
uint32_t _glfwKeySym2Unicode(unsigned int keysym);

View File

@ -113,6 +113,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);

View File

@ -38,7 +38,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)
{ {
@ -181,8 +181,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);

View File

@ -121,7 +121,7 @@ int main(int argc, char** argv)
nk_glfw3_new_frame(); nk_glfw3_new_frame();
if (nk_begin(nk, "main", area, 0)) if (nk_begin(nk, "main", area, 0))
{ {
nk_layout_row_dynamic(nk, 30, 4); nk_layout_row_dynamic(nk, 30, 5);
if (nk_button_label(nk, "Toggle Fullscreen")) if (nk_button_label(nk, "Toggle Fullscreen"))
{ {
@ -149,6 +149,16 @@ int main(int argc, char** argv)
glfwIconifyWindow(window); glfwIconifyWindow(window);
if (nk_button_label(nk, "Restore")) if (nk_button_label(nk, "Restore"))
glfwRestoreWindow(window); glfwRestoreWindow(window);
if (nk_button_label(nk, "Hide (briefly)"))
{
glfwHideWindow(window);
const double time = glfwGetTime() + 3.0;
while (glfwGetTime() < time)
glfwWaitEventsTimeout(1.0);
glfwShowWindow(window);
}
nk_layout_row_dynamic(nk, 30, 1); nk_layout_row_dynamic(nk, 30, 1);