mirror of
https://github.com/glfw/glfw.git
synced 2025-06-08 16:54:57 +00:00
Merge branch 'glfw:master' into master
This commit is contained in:
commit
48dc1e08d1
@ -58,16 +58,20 @@ video tutorials.
|
||||
- Ahmad Fatoum
|
||||
- Felipe Ferreira
|
||||
- Michael Fogleman
|
||||
- Jason Francis
|
||||
- Gerald Franz
|
||||
- Mário Freitas
|
||||
- GeO4d
|
||||
- Marcus Geelnard
|
||||
- ghuser404
|
||||
- Charles Giessen
|
||||
- Ryan C. Gordon
|
||||
- Stephen Gowen
|
||||
- Kovid Goyal
|
||||
- Eloi Marín Gratacós
|
||||
- Stefan Gustavson
|
||||
- Andrew Gutekanst
|
||||
- Stephen Gutekanst
|
||||
- Jonathan Hale
|
||||
- hdf89shfdfs
|
||||
- Sylvain Hellegouarch
|
||||
@ -77,6 +81,7 @@ video tutorials.
|
||||
- Paul Holden
|
||||
- Warren Hu
|
||||
- Charles Huber
|
||||
- InKryption
|
||||
- IntellectualKitty
|
||||
- Aaron Jacobs
|
||||
- Erik S. V. Jansson
|
||||
@ -178,6 +183,7 @@ video tutorials.
|
||||
- Ali Sherief
|
||||
- Yoshiki Shibukawa
|
||||
- Dmitri Shuralyov
|
||||
- Daniel Sieger
|
||||
- Daniel Skorupski
|
||||
- Anthony Smith
|
||||
- Bradley Smith
|
||||
|
17
README.md
17
README.md
@ -202,6 +202,9 @@ information on what to include when reporting a bug.
|
||||
later (#1783,#1796)
|
||||
- [Win32] Bugfix: Compilation with LLVM for Windows failed (#1807,#1824,#1874)
|
||||
- [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 locating the Vulkan loader at runtime in an application bundle
|
||||
- [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
|
||||
a fraction of a second (#1962)
|
||||
- [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: Key names were not updated when the keyboard layout changed
|
||||
(#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
|
||||
(#1863)
|
||||
- [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 support for key names via xkbcommon
|
||||
- [Wayland] Removed support for `wl_shell` (#1443)
|
||||
- [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432)
|
||||
- [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: Non-arrow cursors are offset from the hotspot (#1706,#1899)
|
||||
- [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] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled
|
||||
- [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072)
|
||||
|
@ -2167,15 +2167,6 @@ EXTERNAL_PAGES = YES
|
||||
# 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
|
||||
# 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.
|
||||
|
@ -104,9 +104,8 @@ integration by libwayland-egl, and keyboard handling by
|
||||
from wayland-protocols to provide additional features if the compositor
|
||||
supports them.
|
||||
|
||||
GLFW uses xkbcommon 0.5.0 to provide compose key support. When it has been
|
||||
built against an older xkbcommon, the compose key will be disabled even if it
|
||||
has been configured in the compositor.
|
||||
GLFW uses xkbcommon 0.5.0 to provide key and text input support. Earlier
|
||||
versions are not supported.
|
||||
|
||||
GLFW uses the [xdg-shell
|
||||
protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/xdg-shell/xdg-shell.xml)
|
||||
|
@ -2,7 +2,7 @@
|
||||
// This is an example program for the GLFW library
|
||||
//
|
||||
// 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
|
||||
// each other.
|
||||
//
|
||||
|
@ -1028,7 +1028,7 @@ extern "C" {
|
||||
* and [attribute](@ref GLFW_CONTEXT_VERSION_MINOR_attrib).
|
||||
*/
|
||||
#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
|
||||
* [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
|
||||
* 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.
|
||||
*
|
||||
* @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
|
||||
* [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
|
||||
* should not free it yourself. It is valid until the specified joystick is
|
||||
* 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`
|
||||
* if an [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_FORMAT_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @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
|
||||
@ -6187,9 +6194,6 @@ GLFWAPI int glfwVulkanSupported(void);
|
||||
* returned array, as it is an error to specify an extension more than once in
|
||||
* 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
|
||||
* should not free it yourself. It is guaranteed to be valid only until the
|
||||
* library is terminated.
|
||||
@ -6328,17 +6332,20 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhys
|
||||
* @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should
|
||||
* eliminate almost all occurrences of these errors.
|
||||
*
|
||||
* @remark @macos This function currently only supports the
|
||||
* `VK_MVK_macos_surface` extension from MoltenVK.
|
||||
* @remark @macos GLFW prefers the `VK_EXT_metal_surface` extension, with the
|
||||
* `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
|
||||
* the window content view, which is required for MoltenVK to function.
|
||||
*
|
||||
* @remark @x11 GLFW by default attempts to use the `VK_KHR_xcb_surface`
|
||||
* extension, if available. You can make it prefer the `VK_KHR_xlib_surface`
|
||||
* extension by setting the
|
||||
* @remark @x11 By default GLFW prefers the `VK_KHR_xcb_surface` extension,
|
||||
* with the `VK_KHR_xlib_surface` extension as a fallback. You can make
|
||||
* `VK_KHR_xlib_surface` the preferred extension by setting the
|
||||
* [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
|
||||
* synchronization details of Vulkan objects, see the Vulkan specification.
|
||||
|
@ -65,10 +65,6 @@ endif()
|
||||
if (GLFW_BUILD_WAYLAND)
|
||||
include(CheckIncludeFiles)
|
||||
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)
|
||||
if (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-cursor>=0.2.7
|
||||
wayland-egl>=0.2.7
|
||||
xkbcommon)
|
||||
xkbcommon>=0.5.0)
|
||||
|
||||
target_include_directories(glfw PRIVATE ${Wayland_INCLUDE_DIRS})
|
||||
|
||||
@ -194,31 +190,37 @@ if (GLFW_BUILD_X11)
|
||||
if (NOT X11_Xrandr_INCLUDE_PATH)
|
||||
message(FATAL_ERROR "RandR headers not found; install libxrandr development package")
|
||||
endif()
|
||||
target_include_directories(glfw PRIVATE "${X11_Xrandr_INCLUDE_PATH}")
|
||||
|
||||
# Check for Xinerama (legacy multi-monitor support)
|
||||
if (NOT X11_Xinerama_INCLUDE_PATH)
|
||||
message(FATAL_ERROR "Xinerama headers not found; install libxinerama development package")
|
||||
endif()
|
||||
target_include_directories(glfw PRIVATE "${X11_Xinerama_INCLUDE_PATH}")
|
||||
|
||||
# Check for Xkb (X keyboard extension)
|
||||
if (NOT X11_Xkb_INCLUDE_PATH)
|
||||
message(FATAL_ERROR "XKB headers not found; install X11 development package")
|
||||
endif()
|
||||
target_include_directories(glfw PRIVATE "${X11_Xkb_INCLUDE_PATH}")
|
||||
|
||||
# Check for Xcursor (cursor creation from RGBA images)
|
||||
if (NOT X11_Xcursor_INCLUDE_PATH)
|
||||
message(FATAL_ERROR "Xcursor headers not found; install libxcursor development package")
|
||||
endif()
|
||||
target_include_directories(glfw PRIVATE "${X11_Xcursor_INCLUDE_PATH}")
|
||||
|
||||
# Check for XInput (modern HID input)
|
||||
if (NOT X11_Xi_INCLUDE_PATH)
|
||||
message(FATAL_ERROR "XInput headers not found; install libxi development package")
|
||||
endif()
|
||||
target_include_directories(glfw PRIVATE "${X11_Xi_INCLUDE_PATH}")
|
||||
|
||||
# Check for X Shape (custom window input shape)
|
||||
if (NOT X11_Xshape_INCLUDE_PATH)
|
||||
message(FATAL_ERROR "X Shape headers not found; install libxext development package")
|
||||
endif()
|
||||
target_include_directories(glfw PRIVATE "${X11_Xshape_INCLUDE_PATH}")
|
||||
endif()
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
|
@ -42,16 +42,15 @@ typedef void* id;
|
||||
#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
|
||||
// SDK versions where one is unavailable or deprecated.
|
||||
// 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
|
||||
#define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval
|
||||
#define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
|
||||
#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
|
||||
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
|
||||
#define NSEventMaskAny NSAnyEventMask
|
||||
@ -70,6 +69,15 @@ typedef void* id;
|
||||
#define NSWindowStyleMaskTitled NSTitledWindowMask
|
||||
#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 VkMetalSurfaceCreateFlagsEXT;
|
||||
|
||||
|
@ -361,9 +361,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
markedText = [[NSMutableAttributedString alloc] init];
|
||||
|
||||
[self updateTrackingAreas];
|
||||
// NOTE: kUTTypeURL corresponds to NSPasteboardTypeURL but is available
|
||||
// on 10.7 without having been deprecated yet
|
||||
[self registerForDraggedTypes:@[(__bridge NSString*) kUTTypeURL]];
|
||||
[self registerForDraggedTypes:@[NSPasteboardTypeURL]];
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -231,6 +231,15 @@ static void swapBuffersEGL(_GLFWwindow* window)
|
||||
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);
|
||||
}
|
||||
|
||||
@ -316,6 +325,8 @@ GLFWbool _glfwInitEGL(void)
|
||||
"libEGL.dylib",
|
||||
#elif defined(__CYGWIN__)
|
||||
"libEGL-1.so",
|
||||
#elif defined(__OpenBSD__)
|
||||
"libEGL.so",
|
||||
#else
|
||||
"libEGL.so.1",
|
||||
#endif
|
||||
@ -472,6 +483,8 @@ GLFWbool _glfwInitEGL(void)
|
||||
extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
|
||||
_glfw.egl.KHR_context_flush_control =
|
||||
extensionSupportedEGL("EGL_KHR_context_flush_control");
|
||||
_glfw.egl.EXT_present_opaque =
|
||||
extensionSupportedEGL("EGL_EXT_present_opaque");
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
@ -646,6 +659,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
if (!fbconfig->doublebuffer)
|
||||
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);
|
||||
|
||||
native = _glfw.platform.getEGLNativeWindow(window);
|
||||
@ -686,6 +702,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
"libGLES_CM.dll",
|
||||
#elif defined(_GLFW_COCOA)
|
||||
"libGLESv1_CM.dylib",
|
||||
#elif defined(__OpenBSD__)
|
||||
"libGLESv1_CM.so",
|
||||
#else
|
||||
"libGLESv1_CM.so.1",
|
||||
"libGLES_CM.so.1",
|
||||
@ -703,6 +721,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
"libGLESv2.dylib",
|
||||
#elif defined(__CYGWIN__)
|
||||
"libGLESv2-2.so",
|
||||
#elif defined(__OpenBSD__)
|
||||
"libGLESv2.so",
|
||||
#else
|
||||
"libGLESv2.so.2",
|
||||
#endif
|
||||
@ -714,6 +734,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
_GLFW_OPENGL_LIBRARY,
|
||||
#elif defined(_GLFW_WIN32)
|
||||
#elif defined(_GLFW_COCOA)
|
||||
#elif defined(__OpenBSD__)
|
||||
"libGL.so",
|
||||
#else
|
||||
"libGL.so.1",
|
||||
#endif
|
||||
|
@ -259,6 +259,8 @@ GLFWbool _glfwInitGLX(void)
|
||||
_GLFW_GLX_LIBRARY,
|
||||
#elif defined(__CYGWIN__)
|
||||
"libGL-1.so",
|
||||
#elif defined(__OpenBSD__)
|
||||
"libGL.so",
|
||||
#else
|
||||
"libGL.so.1",
|
||||
"libGL.so",
|
||||
|
40
src/init.c
40
src/init.c
@ -36,16 +36,15 @@
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
// The global variables below comprise all mutable global data in GLFW
|
||||
//
|
||||
// Any other global variable is a bug
|
||||
// NOTE: The global variables below comprise all mutable global data in GLFW
|
||||
// Any other mutable 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 };
|
||||
|
||||
// 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 GLFWerrorfun _glfwErrorCallback;
|
||||
@ -141,6 +140,37 @@ static void terminate(void)
|
||||
////// 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)
|
||||
{
|
||||
const size_t length = strlen(source);
|
||||
|
@ -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
|
||||
// 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))
|
||||
return;
|
||||
|
@ -177,6 +177,7 @@ typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint);
|
||||
#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
|
||||
#define EGL_PLATFORM_X11_EXT 0x31d5
|
||||
#define EGL_PLATFORM_WAYLAND_EXT 0x31d8
|
||||
#define EGL_PRESENT_OPAQUE_EXT 0x31df
|
||||
#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
|
||||
#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
|
||||
#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320d
|
||||
@ -803,6 +804,7 @@ struct _GLFWlibrary
|
||||
GLFWbool EXT_platform_base;
|
||||
GLFWbool EXT_platform_x11;
|
||||
GLFWbool EXT_platform_wayland;
|
||||
GLFWbool EXT_present_opaque;
|
||||
GLFWbool ANGLE_platform_angle;
|
||||
GLFWbool ANGLE_platform_angle_opengl;
|
||||
GLFWbool ANGLE_platform_angle_d3d;
|
||||
@ -917,7 +919,7 @@ void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
|
||||
void _glfwInputKey(_GLFWwindow* window,
|
||||
int key, int scancode, int action, int mods);
|
||||
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 _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
|
||||
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
||||
@ -993,6 +995,8 @@ GLFWbool _glfwInitVulkan(int mode);
|
||||
void _glfwTerminateVulkan(void);
|
||||
const char* _glfwGetVulkanResultString(VkResult result);
|
||||
|
||||
size_t _glfwEncodeUTF8(char* s, uint32_t codepoint);
|
||||
|
||||
char* _glfw_strdup(const char* source);
|
||||
float _glfw_fminf(float a, float b);
|
||||
float _glfw_fmaxf(float a, float b);
|
||||
|
@ -124,6 +124,8 @@ GLFWbool _glfwInitOSMesa(void)
|
||||
"libOSMesa.8.dylib",
|
||||
#elif defined(__CYGWIN__)
|
||||
"libOSMesa-8.so",
|
||||
#elif defined(__OpenBSD__)
|
||||
"libOSMesa.so",
|
||||
#else
|
||||
"libOSMesa.so.8",
|
||||
"libOSMesa.so.6",
|
||||
|
@ -72,6 +72,11 @@ GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform)
|
||||
// Only allow the Null platform if specifically requested
|
||||
if (desiredID == GLFW_PLATFORM_NULL)
|
||||
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)
|
||||
{
|
||||
@ -86,10 +91,7 @@ GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform)
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
if (count)
|
||||
_glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "Failed to detect any supported platform");
|
||||
else
|
||||
_glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "This binary only supports the Null platform");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -63,6 +63,8 @@ GLFWbool _glfwInitVulkan(int mode)
|
||||
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib");
|
||||
if (!_glfw.vk.handle)
|
||||
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa();
|
||||
#elif defined(__OpenBSD__)
|
||||
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so");
|
||||
#else
|
||||
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so.1");
|
||||
#endif
|
||||
|
@ -317,8 +317,19 @@ void _glfwGetHMONITORContentScaleWin32(HMONITOR handle, float* xscale, float* ys
|
||||
{
|
||||
UINT xdpi, ydpi;
|
||||
|
||||
if (xscale)
|
||||
*xscale = 0.f;
|
||||
if (yscale)
|
||||
*yscale = 0.f;
|
||||
|
||||
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
|
||||
{
|
||||
const HDC dc = GetDC(NULL);
|
||||
|
@ -649,7 +649,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
window->win32.highSurrogate = (WCHAR) wParam;
|
||||
else
|
||||
{
|
||||
unsigned int codepoint = 0;
|
||||
uint32_t codepoint = 0;
|
||||
|
||||
if (wParam >= 0xdc00 && wParam <= 0xdfff)
|
||||
{
|
||||
@ -683,7 +683,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GLFW_TRUE);
|
||||
_glfwInputChar(window, (uint32_t) wParam, getKeyMods(), GLFW_TRUE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1304,9 +1304,13 @@ static int createNativeWindow(_GLFWwindow* window,
|
||||
{
|
||||
float xscale, yscale;
|
||||
_glfwGetWindowContentScaleWin32(window, &xscale, &yscale);
|
||||
|
||||
if (xscale > 0.f && yscale > 0.f)
|
||||
{
|
||||
rect.right = (int) (rect.right * xscale);
|
||||
rect.bottom = (int) (rect.bottom * yscale);
|
||||
}
|
||||
}
|
||||
|
||||
ClientToScreen(window->win32.handle, (POINT*) &rect.left);
|
||||
ClientToScreen(window->win32.handle, (POINT*) &rect.right);
|
||||
@ -1645,8 +1649,7 @@ void _glfwGetWindowFrameSizeWin32(_GLFWwindow* window,
|
||||
*bottom = rect.bottom - height;
|
||||
}
|
||||
|
||||
void _glfwGetWindowContentScaleWin32(_GLFWwindow* window,
|
||||
float* xscale, float* yscale)
|
||||
void _glfwGetWindowContentScaleWin32(_GLFWwindow* window, float* xscale, float* yscale)
|
||||
{
|
||||
const HANDLE handle = MonitorFromWindow(window->win32.handle,
|
||||
MONITOR_DEFAULTTONEAREST);
|
||||
|
120
src/wl_init.c
120
src/wl_init.c
@ -207,12 +207,12 @@ static void pointerHandleMotion(void* data,
|
||||
return;
|
||||
x = wl_fixed_to_double(sx);
|
||||
y = wl_fixed_to_double(sy);
|
||||
window->wl.cursorPosX = x;
|
||||
window->wl.cursorPosY = y;
|
||||
|
||||
switch (window->wl.decorations.focus)
|
||||
{
|
||||
case mainWindow:
|
||||
window->wl.cursorPosX = x;
|
||||
window->wl.cursorPosY = y;
|
||||
_glfwInputCursorPos(window, x, y);
|
||||
_glfw.wl.cursorPreviousName = NULL;
|
||||
return;
|
||||
@ -272,9 +272,7 @@ static void pointerHandleButton(void* data,
|
||||
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
||||
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
|
||||
else
|
||||
{
|
||||
xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
|
||||
}
|
||||
break;
|
||||
case leftDecoration:
|
||||
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,
|
||||
serial, edges);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (button == BTN_RIGHT)
|
||||
@ -378,11 +377,8 @@ static void keyboardHandleKeymap(void* data,
|
||||
{
|
||||
struct xkb_keymap* keymap;
|
||||
struct xkb_state* state;
|
||||
|
||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||
struct xkb_compose_table* composeTable;
|
||||
struct xkb_compose_state* composeState;
|
||||
#endif
|
||||
|
||||
char* mapStr;
|
||||
const char* locale;
|
||||
@ -431,7 +427,6 @@ static void keyboardHandleKeymap(void* data,
|
||||
if (!locale)
|
||||
locale = "C";
|
||||
|
||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||
composeTable =
|
||||
xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
|
||||
XKB_COMPOSE_COMPILE_NO_FLAGS);
|
||||
@ -451,7 +446,6 @@ static void keyboardHandleKeymap(void* data,
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Failed to create XKB compose table");
|
||||
}
|
||||
#endif
|
||||
|
||||
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
||||
xkb_state_unref(_glfw.wl.xkb.state);
|
||||
@ -505,20 +499,22 @@ static void keyboardHandleLeave(void* data,
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
struct itimerspec timer = {};
|
||||
timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
|
||||
|
||||
_glfw.wl.serial = serial;
|
||||
_glfw.wl.keyboardFocus = NULL;
|
||||
_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]))
|
||||
return _glfw.wl.keycodes[key];
|
||||
if (scancode < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
|
||||
return _glfw.wl.keycodes[scancode];
|
||||
|
||||
return GLFW_KEY_UNKNOWN;
|
||||
}
|
||||
|
||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||
static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
|
||||
{
|
||||
if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
|
||||
@ -538,77 +534,65 @@ static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
|
||||
return sym;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static GLFWbool inputChar(_GLFWwindow* window, uint32_t key)
|
||||
GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode)
|
||||
{
|
||||
uint32_t code, numSyms;
|
||||
long cp;
|
||||
const xkb_keysym_t *syms;
|
||||
xkb_keysym_t sym;
|
||||
const xkb_keysym_t* keysyms;
|
||||
const xkb_keycode_t keycode = scancode + 8;
|
||||
|
||||
code = key + 8;
|
||||
numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms);
|
||||
|
||||
if (numSyms == 1)
|
||||
if (xkb_state_key_get_syms(_glfw.wl.xkb.state, keycode, &keysyms) == 1)
|
||||
{
|
||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||
sym = composeSymbol(syms[0]);
|
||||
#else
|
||||
sym = syms[0];
|
||||
#endif
|
||||
cp = _glfwKeySym2Unicode(sym);
|
||||
if (cp != -1)
|
||||
const xkb_keysym_t keysym = composeSymbol(keysyms[0]);
|
||||
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
|
||||
if (codepoint != GLFW_INVALID_CODEPOINT)
|
||||
{
|
||||
const int mods = _glfw.wl.xkb.modifiers;
|
||||
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,
|
||||
struct wl_keyboard* keyboard,
|
||||
uint32_t serial,
|
||||
uint32_t time,
|
||||
uint32_t key,
|
||||
uint32_t scancode,
|
||||
uint32_t state)
|
||||
{
|
||||
int keyCode;
|
||||
int action;
|
||||
_GLFWwindow* window = _glfw.wl.keyboardFocus;
|
||||
GLFWbool shouldRepeat;
|
||||
struct itimerspec timer = {};
|
||||
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
keyCode = toGLFWKeyCode(key);
|
||||
action = state == WL_KEYBOARD_KEY_STATE_PRESSED
|
||||
? GLFW_PRESS : GLFW_RELEASE;
|
||||
const int key = translateKey(scancode);
|
||||
const int action =
|
||||
state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
|
||||
|
||||
_glfw.wl.serial = serial;
|
||||
_glfwInputKey(window, keyCode, key, action,
|
||||
_glfw.wl.xkb.modifiers);
|
||||
_glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers);
|
||||
|
||||
struct itimerspec timer = {};
|
||||
|
||||
if (action == GLFW_PRESS)
|
||||
{
|
||||
shouldRepeat = inputChar(window, key);
|
||||
const GLFWbool shouldRepeat = _glfwInputTextWayland(window, scancode);
|
||||
|
||||
if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0)
|
||||
{
|
||||
_glfw.wl.keyboardLastKey = keyCode;
|
||||
_glfw.wl.keyboardLastScancode = key;
|
||||
_glfw.wl.keyboardLastKey = key;
|
||||
_glfw.wl.keyboardLastScancode = scancode;
|
||||
if (_glfw.wl.keyboardRepeatRate > 1)
|
||||
timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyboardRepeatRate;
|
||||
else
|
||||
timer.it_interval.tv_sec = 1;
|
||||
|
||||
timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000;
|
||||
timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
|
||||
}
|
||||
|
||||
@ -620,9 +604,6 @@ static void keyboardHandleModifiers(void* data,
|
||||
uint32_t modsLocked,
|
||||
uint32_t group)
|
||||
{
|
||||
xkb_mod_mask_t mask;
|
||||
unsigned int modifiers = 0;
|
||||
|
||||
_glfw.wl.serial = serial;
|
||||
|
||||
if (!_glfw.wl.xkb.keymap)
|
||||
@ -636,24 +617,29 @@ static void keyboardHandleModifiers(void* data,
|
||||
0,
|
||||
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_LAYOUT_DEPRESSED |
|
||||
XKB_STATE_MODS_LATCHED |
|
||||
XKB_STATE_LAYOUT_LATCHED);
|
||||
|
||||
unsigned int mods = 0;
|
||||
|
||||
if (mask & _glfw.wl.xkb.controlMask)
|
||||
modifiers |= GLFW_MOD_CONTROL;
|
||||
mods |= GLFW_MOD_CONTROL;
|
||||
if (mask & _glfw.wl.xkb.altMask)
|
||||
modifiers |= GLFW_MOD_ALT;
|
||||
mods |= GLFW_MOD_ALT;
|
||||
if (mask & _glfw.wl.xkb.shiftMask)
|
||||
modifiers |= GLFW_MOD_SHIFT;
|
||||
mods |= GLFW_MOD_SHIFT;
|
||||
if (mask & _glfw.wl.xkb.superMask)
|
||||
modifiers |= GLFW_MOD_SUPER;
|
||||
mods |= GLFW_MOD_SUPER;
|
||||
if (mask & _glfw.wl.xkb.capsLockMask)
|
||||
modifiers |= GLFW_MOD_CAPS_LOCK;
|
||||
mods |= GLFW_MOD_CAPS_LOCK;
|
||||
if (mask & _glfw.wl.xkb.numLockMask)
|
||||
modifiers |= GLFW_MOD_NUM_LOCK;
|
||||
_glfw.wl.xkb.modifiers = modifiers;
|
||||
mods |= GLFW_MOD_NUM_LOCK;
|
||||
|
||||
_glfw.wl.xkb.modifiers = mods;
|
||||
}
|
||||
|
||||
#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_LEFTMETA] = GLFW_KEY_LEFT_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_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
|
||||
_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_F24] = GLFW_KEY_F24;
|
||||
_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_KPPLUS] = GLFW_KEY_KP_ADD;
|
||||
_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_KP8] = GLFW_KEY_KP_8;
|
||||
_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_KPENTER] = GLFW_KEY_KP_ENTER;
|
||||
_glfw.wl.keycodes[KEY_102ND] = GLFW_KEY_WORLD_2;
|
||||
|
||||
for (int scancode = 0; scancode < 256; scancode++)
|
||||
{
|
||||
@ -1287,6 +1274,8 @@ int _glfwInitWayland(void)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
|
||||
_glfw.wl.xkb.keymap_key_repeats = (PFN_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)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_new");
|
||||
_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");
|
||||
_glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_serialize_mods");
|
||||
|
||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||
_glfw.wl.xkb.state_key_get_layout = (PFN_xkb_state_key_get_layout)
|
||||
_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)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");
|
||||
_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");
|
||||
_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");
|
||||
#endif
|
||||
|
||||
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
||||
wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
|
||||
@ -1336,7 +1324,7 @@ int _glfwInitWayland(void)
|
||||
|
||||
_glfw.wl.timerfd = -1;
|
||||
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)
|
||||
{
|
||||
@ -1370,7 +1358,7 @@ int _glfwInitWayland(void)
|
||||
wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm);
|
||||
_glfw.wl.cursorSurface =
|
||||
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)
|
||||
@ -1401,10 +1389,8 @@ void _glfwTerminateWayland(void)
|
||||
_glfw.wl.egl.handle = NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||
if (_glfw.wl.xkb.composeState)
|
||||
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
|
||||
#endif
|
||||
if (_glfw.wl.xkb.keymap)
|
||||
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
||||
if (_glfw.wl.xkb.state)
|
||||
|
@ -26,9 +26,7 @@
|
||||
|
||||
#include <wayland-client-core.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||
#include <xkbcommon/xkbcommon-compose.h>
|
||||
#endif
|
||||
|
||||
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 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_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 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 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_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_unref _glfw.wl.xkb.context_unref
|
||||
#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_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_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_unref _glfw.wl.xkb.state_unref
|
||||
#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_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 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);
|
||||
@ -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_get_status _glfw.wl.xkb.compose_state_get_status
|
||||
#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
|
||||
#endif
|
||||
|
||||
#define _GLFW_DECORATION_WIDTH 4
|
||||
#define _GLFW_DECORATION_TOP 24
|
||||
@ -311,6 +311,7 @@ typedef struct _GLFWlibraryWayland
|
||||
int timerfd;
|
||||
short int keycodes[256];
|
||||
short int scancodes[GLFW_KEY_LAST + 1];
|
||||
char keynames[GLFW_KEY_LAST + 1][5];
|
||||
|
||||
struct {
|
||||
void* handle;
|
||||
@ -318,9 +319,7 @@ typedef struct _GLFWlibraryWayland
|
||||
struct xkb_keymap* keymap;
|
||||
struct xkb_state* state;
|
||||
|
||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||
struct xkb_compose_state* composeState;
|
||||
#endif
|
||||
|
||||
xkb_mod_mask_t controlMask;
|
||||
xkb_mod_mask_t altMask;
|
||||
@ -336,13 +335,14 @@ typedef struct _GLFWlibraryWayland
|
||||
PFN_xkb_keymap_unref keymap_unref;
|
||||
PFN_xkb_keymap_mod_get_index keymap_mod_get_index;
|
||||
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_unref state_unref;
|
||||
PFN_xkb_state_key_get_syms state_key_get_syms;
|
||||
PFN_xkb_state_update_mask state_update_mask;
|
||||
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_unref compose_table_unref;
|
||||
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_get_status compose_state_get_status;
|
||||
PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;
|
||||
#endif
|
||||
} xkb;
|
||||
|
||||
_GLFWwindow* pointerFocus;
|
||||
@ -496,4 +495,5 @@ GLFWbool _glfwGetGammaRampWayland(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
|
||||
void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
|
||||
|
||||
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
|
||||
GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode);
|
||||
|
||||
|
216
src/wl_window.c
216
src/wl_window.c
@ -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,
|
||||
int refreshRate)
|
||||
{
|
||||
@ -537,7 +508,6 @@ static void xdgToplevelHandleConfigure(void* data,
|
||||
}
|
||||
if (fullscreen && activated)
|
||||
window->wl.wasFullscreen = GLFW_TRUE;
|
||||
_glfwInputWindowFocus(window, activated);
|
||||
}
|
||||
|
||||
static void xdgToplevelHandleClose(void* data,
|
||||
@ -645,6 +615,46 @@ static GLFWbool createXdgSurface(_GLFWwindow* window)
|
||||
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,
|
||||
_GLFWcursorWayland* cursorWayland)
|
||||
{
|
||||
@ -709,22 +719,19 @@ static void incrementCursorImage(_GLFWwindow* window)
|
||||
|
||||
static void handleEvents(int timeout)
|
||||
{
|
||||
struct wl_display* display = _glfw.wl.display;
|
||||
struct pollfd fds[] = {
|
||||
{ wl_display_get_fd(display), POLLIN },
|
||||
struct pollfd fds[] =
|
||||
{
|
||||
{ wl_display_get_fd(_glfw.wl.display), POLLIN },
|
||||
{ _glfw.wl.timerfd, POLLIN },
|
||||
{ _glfw.wl.cursorTimerfd, POLLIN },
|
||||
};
|
||||
ssize_t read_ret;
|
||||
uint64_t repeats;
|
||||
|
||||
while (wl_display_prepare_read(display) != 0)
|
||||
wl_display_dispatch_pending(display);
|
||||
while (wl_display_prepare_read(_glfw.wl.display) != 0)
|
||||
wl_display_dispatch_pending(_glfw.wl.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)
|
||||
// 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 (wl_display_flush(_glfw.wl.display) < 0 && errno != EAGAIN)
|
||||
{
|
||||
_GLFWwindow* window = _glfw.windowListHead;
|
||||
while (window)
|
||||
@ -732,7 +739,8 @@ static void handleEvents(int timeout)
|
||||
_glfwInputWindowCloseRequest(window);
|
||||
window = window->next;
|
||||
}
|
||||
wl_display_cancel_read(display);
|
||||
|
||||
wl_display_cancel_read(_glfw.wl.display);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -740,46 +748,41 @@ static void handleEvents(int timeout)
|
||||
{
|
||||
if (fds[0].revents & POLLIN)
|
||||
{
|
||||
wl_display_read_events(display);
|
||||
wl_display_dispatch_pending(display);
|
||||
wl_display_read_events(_glfw.wl.display);
|
||||
wl_display_dispatch_pending(_glfw.wl.display);
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_display_cancel_read(display);
|
||||
}
|
||||
wl_display_cancel_read(_glfw.wl.display);
|
||||
|
||||
if (fds[1].revents & POLLIN)
|
||||
{
|
||||
read_ret = read(_glfw.wl.timerfd, &repeats, sizeof(repeats));
|
||||
if (read_ret != 8)
|
||||
return;
|
||||
uint64_t repeats;
|
||||
|
||||
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,
|
||||
_glfw.wl.keyboardLastKey,
|
||||
_glfw.wl.keyboardLastScancode,
|
||||
GLFW_REPEAT,
|
||||
GLFW_PRESS,
|
||||
_glfw.wl.xkb.modifiers);
|
||||
_glfwInputTextWayland(_glfw.wl.keyboardFocus,
|
||||
_glfw.wl.keyboardLastScancode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fds[2].revents & POLLIN)
|
||||
{
|
||||
read_ret = read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats));
|
||||
if (read_ret != 8)
|
||||
return;
|
||||
uint64_t repeats;
|
||||
|
||||
if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8)
|
||||
incrementCursorImage(_glfw.wl.pointerFocus);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_display_cancel_read(display);
|
||||
}
|
||||
wl_display_cancel_read(_glfw.wl.display);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -791,9 +794,7 @@ int _glfwCreateWindowWayland(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
window->wl.transparent = fbconfig->transparent;
|
||||
|
||||
if (!createSurface(window, wndconfig))
|
||||
if (!createSurface(window, wndconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1024,21 +1002,24 @@ void _glfwShowWindowWayland(_GLFWwindow* window)
|
||||
{
|
||||
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);
|
||||
|
||||
window->wl.visible = GLFW_TRUE;
|
||||
_glfwInputWindowDamage(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;
|
||||
wl_surface_attach(window->wl.surface, NULL, 0, 0);
|
||||
wl_surface_commit(window->wl.surface);
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwRequestWindowAttentionWayland(_GLFWwindow* window)
|
||||
@ -1214,10 +1195,57 @@ void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode)
|
||||
|
||||
const char* _glfwGetScancodeNameWayland(int scancode)
|
||||
{
|
||||
// TODO
|
||||
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED,
|
||||
"Wayland: Key names not yet implemented");
|
||||
if (scancode < 0 || scancode > 255 ||
|
||||
_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 _glfwGetKeyScancodeWayland(int key)
|
||||
|
@ -601,7 +601,11 @@ static void detectEWMH(void)
|
||||
//
|
||||
static GLFWbool initExtensions(void)
|
||||
{
|
||||
#if defined(__OpenBSD__)
|
||||
_glfw.x11.vidmode.handle = _glfwPlatformLoadModule("libXxf86vm.so");
|
||||
#else
|
||||
_glfw.x11.vidmode.handle = _glfwPlatformLoadModule("libXxf86vm.so.1");
|
||||
#endif
|
||||
if (_glfw.x11.vidmode.handle)
|
||||
{
|
||||
_glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension)
|
||||
@ -621,6 +625,8 @@ static GLFWbool initExtensions(void)
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
_glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi-6.so");
|
||||
#elif defined(__OpenBSD__)
|
||||
_glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi.so");
|
||||
#else
|
||||
_glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi.so.6");
|
||||
#endif
|
||||
@ -651,6 +657,8 @@ static GLFWbool initExtensions(void)
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
_glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr-2.so");
|
||||
#elif defined(__OpenBSD__)
|
||||
_glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr.so");
|
||||
#else
|
||||
_glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr.so.2");
|
||||
#endif
|
||||
@ -743,6 +751,8 @@ static GLFWbool initExtensions(void)
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
_glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor-1.so");
|
||||
#elif defined(__OpenBSD__)
|
||||
_glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor.so");
|
||||
#else
|
||||
_glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor.so.1");
|
||||
#endif
|
||||
@ -764,6 +774,8 @@ static GLFWbool initExtensions(void)
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
_glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama-1.so");
|
||||
#elif defined(__OpenBSD__)
|
||||
_glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama.so");
|
||||
#else
|
||||
_glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama.so.1");
|
||||
#endif
|
||||
@ -817,6 +829,8 @@ static GLFWbool initExtensions(void)
|
||||
{
|
||||
#if defined(__CYGWIN__)
|
||||
_glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb-1.so");
|
||||
#elif defined(__OpenBSD__)
|
||||
_glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb.so");
|
||||
#else
|
||||
_glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb.so.1");
|
||||
#endif
|
||||
@ -830,6 +844,8 @@ static GLFWbool initExtensions(void)
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
_glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender-1.so");
|
||||
#elif defined(__OpenBSD__)
|
||||
_glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender.so");
|
||||
#else
|
||||
_glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender.so.1");
|
||||
#endif
|
||||
@ -857,6 +873,8 @@ static GLFWbool initExtensions(void)
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
_glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext-6.so");
|
||||
#elif defined(__OpenBSD__)
|
||||
_glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext.so");
|
||||
#else
|
||||
_glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext.so.6");
|
||||
#endif
|
||||
@ -1203,6 +1221,8 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform)
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
void* module = _glfwPlatformLoadModule("libX11-6.so");
|
||||
#elif defined(__OpenBSD__)
|
||||
void* module = _glfwPlatformLoadModule("libX11.so");
|
||||
#else
|
||||
void* module = _glfwPlatformLoadModule("libX11.so.6");
|
||||
#endif
|
||||
|
@ -429,44 +429,13 @@ static char** parseUriList(char* text, int* count)
|
||||
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
|
||||
// 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;
|
||||
static const unsigned int offsets[] =
|
||||
uint32_t codepoint = 0, count = 0;
|
||||
static const uint32_t offsets[] =
|
||||
{
|
||||
0x00000000u, 0x00003080u, 0x000e2080u,
|
||||
0x03c82080u, 0xfa082080u, 0x82082080u
|
||||
@ -474,13 +443,13 @@ static unsigned int decodeUTF8(const char** s)
|
||||
|
||||
do
|
||||
{
|
||||
ch = (ch << 6) + (unsigned char) **s;
|
||||
codepoint = (codepoint << 6) + (unsigned char) **s;
|
||||
(*s)++;
|
||||
count++;
|
||||
} while ((**s & 0xc0) == 0x80);
|
||||
|
||||
assert(count <= 6);
|
||||
return ch - offsets[count - 1];
|
||||
return codepoint - offsets[count - 1];
|
||||
}
|
||||
|
||||
// Convert the specified Latin-1 string to UTF-8
|
||||
@ -497,7 +466,7 @@ static char* convertLatin1toUTF8(const char* source)
|
||||
char* tp = target;
|
||||
|
||||
for (sp = source; *sp; sp++)
|
||||
tp += encodeUTF8(tp, *sp);
|
||||
tp += _glfwEncodeUTF8(tp, *sp);
|
||||
|
||||
return target;
|
||||
}
|
||||
@ -1317,9 +1286,9 @@ static void processEvent(XEvent *event)
|
||||
|
||||
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
|
||||
|
||||
const long character = _glfwKeySym2Unicode(keysym);
|
||||
if (character != -1)
|
||||
_glfwInputChar(window, character, mods, plain);
|
||||
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
|
||||
if (codepoint != GLFW_INVALID_CODEPOINT)
|
||||
_glfwInputChar(window, codepoint, mods, plain);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -2105,8 +2074,8 @@ void _glfwSetWindowIconX11(_GLFWwindow* window, int count, const GLFWimage* imag
|
||||
for (int i = 0; i < count; i++)
|
||||
longCount += 2 + images[i].width * images[i].height;
|
||||
|
||||
long* icon = _glfw_calloc(longCount, sizeof(long));
|
||||
long* target = icon;
|
||||
unsigned long* icon = _glfw_calloc(longCount, sizeof(unsigned long));
|
||||
unsigned long* target = icon;
|
||||
|
||||
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++)
|
||||
{
|
||||
*target++ = (images[i].pixels[j * 4 + 0] << 16) |
|
||||
(images[i].pixels[j * 4 + 1] << 8) |
|
||||
(images[i].pixels[j * 4 + 2] << 0) |
|
||||
(images[i].pixels[j * 4 + 3] << 24);
|
||||
*target++ = (((unsigned long) images[i].pixels[j * 4 + 0]) << 16) |
|
||||
(((unsigned long) images[i].pixels[j * 4 + 1]) << 8) |
|
||||
(((unsigned long) images[i].pixels[j * 4 + 2]) << 0) |
|
||||
(((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,
|
||||
_glfw.x11.NET_WM_ICON,
|
||||
XA_CARDINAL, 32,
|
||||
@ -2893,11 +2868,11 @@ const char* _glfwGetScancodeNameX11(int scancode)
|
||||
if (keysym == NoSymbol)
|
||||
return NULL;
|
||||
|
||||
const long ch = _glfwKeySym2Unicode(keysym);
|
||||
if (ch == -1)
|
||||
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
|
||||
if (codepoint == GLFW_INVALID_CODEPOINT)
|
||||
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)
|
||||
return NULL;
|
||||
|
||||
|
@ -907,7 +907,7 @@ static const struct codepair {
|
||||
|
||||
// Convert XKB KeySym to Unicode
|
||||
//
|
||||
long _glfwKeySym2Unicode(unsigned int keysym)
|
||||
uint32_t _glfwKeySym2Unicode(unsigned int keysym)
|
||||
{
|
||||
int min = 0;
|
||||
int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
|
||||
@ -937,6 +937,6 @@ long _glfwKeySym2Unicode(unsigned int keysym)
|
||||
}
|
||||
|
||||
// No matching Unicode value found
|
||||
return -1;
|
||||
return GLFW_INVALID_CODEPOINT;
|
||||
}
|
||||
|
||||
|
@ -24,5 +24,7 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
long _glfwKeySym2Unicode(unsigned int keysym);
|
||||
#define GLFW_INVALID_CODEPOINT 0xffffffffu
|
||||
|
||||
uint32_t _glfwKeySym2Unicode(unsigned int keysym);
|
||||
|
||||
|
@ -113,6 +113,12 @@ int main(int argc, char** argv)
|
||||
|
||||
{
|
||||
const GLFWgammaramp* ramp = glfwGetGammaRamp(monitor);
|
||||
if (!ramp)
|
||||
{
|
||||
glfwTerminate();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
const size_t array_size = ramp->size * sizeof(short);
|
||||
orig_ramp.size = ramp->size;
|
||||
orig_ramp.red = malloc(array_size);
|
||||
|
@ -38,7 +38,7 @@
|
||||
|
||||
#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)
|
||||
{
|
||||
@ -181,8 +181,8 @@ static GLFWwindow* create_window(GLFWmonitor* monitor)
|
||||
}
|
||||
else
|
||||
{
|
||||
width = 640;
|
||||
height = 480;
|
||||
width = windowed_width;
|
||||
height = windowed_height;
|
||||
}
|
||||
|
||||
window = glfwCreateWindow(width, height, "Iconify", monitor, NULL);
|
||||
|
@ -121,7 +121,7 @@ int main(int argc, char** argv)
|
||||
nk_glfw3_new_frame();
|
||||
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"))
|
||||
{
|
||||
@ -149,6 +149,16 @@ int main(int argc, char** argv)
|
||||
glfwIconifyWindow(window);
|
||||
if (nk_button_label(nk, "Restore"))
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user