Merge upstream/master into origin/application-badge

This commit is contained in:
GamesTrap 2023-04-05 19:55:52 +02:00
commit aec406ec1f
No known key found for this signature in database
GPG Key ID: 31DFD452434ECDA3
19 changed files with 1310 additions and 421 deletions

View File

@ -16,7 +16,7 @@ jobs:
CC: clang CC: clang
CFLAGS: -Werror CFLAGS: -Werror
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Install dependencies - name: Install dependencies
run: | run: |
sudo apt update sudo apt update
@ -39,7 +39,7 @@ jobs:
CC: clang CC: clang
CFLAGS: -Werror CFLAGS: -Werror
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Install dependencies - name: Install dependencies
run: | run: |
sudo apt update sudo apt update
@ -62,7 +62,7 @@ jobs:
CFLAGS: -Werror CFLAGS: -Werror
MACOSX_DEPLOYMENT_TARGET: 10.8 MACOSX_DEPLOYMENT_TARGET: 10.8
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Configure static library - name: Configure static library
run: cmake -S . -B build-static run: cmake -S . -B build-static
@ -80,7 +80,7 @@ jobs:
env: env:
CFLAGS: /WX CFLAGS: /WX
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Configure static library - name: Configure static library
run: cmake -S . -B build-static -G "Visual Studio 17 2022" run: cmake -S . -B build-static -G "Visual Studio 17 2022"

View File

@ -12,7 +12,7 @@ endif()
set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY USE_FOLDERS ON)
string(COMPARE EQUAL ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR} GLFW_STANDALONE) string(COMPARE EQUAL "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_SOURCE_DIR}" GLFW_STANDALONE)
option(BUILD_SHARED_LIBS "Build shared libraries" OFF) option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" ${GLFW_STANDALONE}) option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" ${GLFW_STANDALONE})

View File

@ -203,6 +203,7 @@ video tutorials.
- Aleksey Rybalkin - Aleksey Rybalkin
- Mikko Rytkönen - Mikko Rytkönen
- Riku Salminen - Riku Salminen
- Yoshinori Sano
- Brandon Schaefer - Brandon Schaefer
- Sebastian Schuberth - Sebastian Schuberth
- Jan Schuerkamp - Jan Schuerkamp

View File

@ -312,6 +312,7 @@ information on what to include when reporting a bug.
- [X11] Bugfix: The OSMesa libray was not unloaded on termination - [X11] Bugfix: The OSMesa libray was not unloaded on termination
- [X11] Bugfix: A malformed response during selection transfer could cause a segfault - [X11] Bugfix: A malformed response during selection transfer could cause a segfault
- [X11] Bugfix: Some calls would reset Xlib to the default error handler (#2108) - [X11] Bugfix: Some calls would reset Xlib to the default error handler (#2108)
- [Wayland] Added improved fallback window decorations via libdecor (#1639,#1693)
- [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] Added support for key names via xkbcommon
- [Wayland] Added support for file path drop events (#2040) - [Wayland] Added support for file path drop events (#2040)
@ -383,6 +384,7 @@ information on what to include when reporting a bug.
- [Wayland] Bugfix: `GLFW_DECORATED` was ignored when showing a window with XDG - [Wayland] Bugfix: `GLFW_DECORATED` was ignored when showing a window with XDG
decorations decorations
- [Wayland] Bugfix: Connecting a mouse after `glfwInit` would segfault (#1450) - [Wayland] Bugfix: Connecting a mouse after `glfwInit` would segfault (#1450)
- [Wayland] Bugfix: Joysticks connected after `glfwInit` were not detected (#2198)
- [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
- [Linux] Bugfix: Joysticks without buttons were ignored (#2042,#2043) - [Linux] Bugfix: Joysticks without buttons were ignored (#2042,#2043)

View File

@ -128,6 +128,14 @@ wayland-protocols 1.6, and mandatory at build time. If the running compositor
does not support this protocol, the screensaver may start even for full screen does not support this protocol, the screensaver may start even for full screen
windows. windows.
GLFW uses the [libdecor library](https://gitlab.freedesktop.org/libdecor/libdecor)
for window decorations, where available. This in turn provides good quality
client-side decorations (drawn by the application) on desktop systems that do
not support server-side decorations (drawn by the window manager). On systems
that do not provide either libdecor or xdg-decoration, very basic window
decorations are provided. These do not include the window title or any caption
buttons.
GLFW uses the [xdg-decoration GLFW uses the [xdg-decoration
protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml) protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml)
to request decorations to be drawn around its windows. This protocol is part to request decorations to be drawn around its windows. This protocol is part

View File

@ -144,6 +144,15 @@ the `VK_KHR_xlib_surface` extension. Possible values are `GLFW_TRUE` and
`GLFW_FALSE`. This is ignored on other platforms. `GLFW_FALSE`. This is ignored on other platforms.
@subsubsection init_hints_wayland Wayland specific init hints
@anchor GLFW_WAYLAND_LIBDECOR_hint
__GLFW_WAYLAND_LIBDECOR__ specifies whether to use
[libdecor](https://gitlab.freedesktop.org/libdecor/libdecor) for window
decorations where available. Possible values are `GLFW_WAYLAND_PREFER_LIBDECOR`
and `GLFW_WAYLAND_DISABLE_LIBDECOR`. This is ignored on other platforms.
@subsubsection init_hints_values Supported and default values @subsubsection init_hints_values Supported and default values
Initialization hint | Default value | Supported values Initialization hint | Default value | Supported values
@ -154,6 +163,7 @@ Initialization hint | Default value | Supported v
@ref GLFW_COCOA_CHDIR_RESOURCES | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` @ref GLFW_COCOA_CHDIR_RESOURCES | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_COCOA_MENUBAR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` @ref GLFW_COCOA_MENUBAR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_X11_XCB_VULKAN_SURFACE | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` @ref GLFW_X11_XCB_VULKAN_SURFACE | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_WAYLAND_LIBDECOR | `GLFW_WAYLAND_PREFER_LIBDECOR` | `GLFW_WAYLAND_PREFER_LIBDECOR` or `GLFW_WAYLAND_DISABLE_LIBDECOR`
@subsection platform Runtime platform selection @subsection platform Runtime platform selection

View File

@ -43,6 +43,16 @@ to whatever window is behind it. This can also be changed after window
creation with the matching [window attribute](@ref GLFW_MOUSE_PASSTHROUGH_attrib). creation with the matching [window attribute](@ref GLFW_MOUSE_PASSTHROUGH_attrib).
@subsubsection wayland_libdecor_34 Wayland libdecor decorations
GLFW now supports improved fallback window decorations via
[libdecor](https://gitlab.freedesktop.org/libdecor/libdecor).
Support for libdecor can be toggled before GLFW is initialized with the
[GLFW_WAYLAND_LIBDECOR](@ref GLFW_WAYLAND_LIBDECOR_hint) init hint. It is
enabled by default.
@subsubsection wayland_app_id_34 Wayland app_id specification @subsubsection wayland_app_id_34 Wayland app_id specification
GLFW now supports specifying the app_id for a Wayland window using the GLFW now supports specifying the app_id for a Wayland window using the
@ -267,6 +277,9 @@ then GLFW will fail to initialize.
- @ref GLFW_POSITION_X - @ref GLFW_POSITION_X
- @ref GLFW_POSITION_Y - @ref GLFW_POSITION_Y
- @ref GLFW_ANY_POSITION - @ref GLFW_ANY_POSITION
- @ref GLFW_WAYLAND_LIBDECOR
- @ref GLFW_WAYLAND_PREFER_LIBDECOR
- @ref GLFW_WAYLAND_DISABLE_LIBDECOR
@section news_archive Release notes for earlier versions @section news_archive Release notes for earlier versions

View File

@ -1165,6 +1165,9 @@ extern "C" {
#define GLFW_ANGLE_PLATFORM_TYPE_VULKAN 0x00037007 #define GLFW_ANGLE_PLATFORM_TYPE_VULKAN 0x00037007
#define GLFW_ANGLE_PLATFORM_TYPE_METAL 0x00037008 #define GLFW_ANGLE_PLATFORM_TYPE_METAL 0x00037008
#define GLFW_WAYLAND_PREFER_LIBDECOR 0x00038001
#define GLFW_WAYLAND_DISABLE_LIBDECOR 0x00038002
#define GLFW_ANY_POSITION 0x80000000 #define GLFW_ANY_POSITION 0x80000000
/*! @defgroup shapes Standard cursor shapes /*! @defgroup shapes Standard cursor shapes
@ -1361,6 +1364,11 @@ extern "C" {
* X11 specific [init hint](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint). * X11 specific [init hint](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint).
*/ */
#define GLFW_X11_XCB_VULKAN_SURFACE 0x00052001 #define GLFW_X11_XCB_VULKAN_SURFACE 0x00052001
/*! @brief Wayland specific init hint.
*
* Wayland specific [init hint](@ref GLFW_WAYLAND_LIBDECOR_hint).
*/
#define GLFW_WAYLAND_LIBDECOR 0x00053001
/*! @} */ /*! @} */
/*! @addtogroup init /*! @addtogroup init

View File

@ -62,6 +62,9 @@ static _GLFWinitconfig _glfwInitHints =
{ {
GLFW_TRUE, // X11 XCB Vulkan surface GLFW_TRUE, // X11 XCB Vulkan surface
}, },
{
GLFW_WAYLAND_PREFER_LIBDECOR // Wayland libdecor mode
},
}; };
// The allocation function used when no custom allocator is set // The allocation function used when no custom allocator is set
@ -479,6 +482,9 @@ GLFWAPI void glfwInitHint(int hint, int value)
case GLFW_X11_XCB_VULKAN_SURFACE: case GLFW_X11_XCB_VULKAN_SURFACE:
_glfwInitHints.x11.xcbVulkanSurface = value; _glfwInitHints.x11.xcbVulkanSurface = value;
return; return;
case GLFW_WAYLAND_LIBDECOR:
_glfwInitHints.wl.libdecorMode = value;
return;
} }
_glfwInputError(GLFW_INVALID_ENUM, _glfwInputError(GLFW_INVALID_ENUM,

View File

@ -379,6 +379,9 @@ struct _GLFWinitconfig
struct { struct {
GLFWbool xcbVulkanSurface; GLFWbool xcbVulkanSurface;
} x11; } x11;
struct {
int libdecorMode;
} wl;
}; };
// Window configuration // Window configuration

View File

@ -30,6 +30,7 @@
#include "internal.h" #include "internal.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -123,6 +124,138 @@ GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform)
int _glfwInitNull(void) int _glfwInitNull(void)
{ {
int scancode;
memset(_glfw.null.keycodes, -1, sizeof(_glfw.null.keycodes));
memset(_glfw.null.scancodes, -1, sizeof(_glfw.null.scancodes));
_glfw.null.keycodes[GLFW_NULL_SC_SPACE] = GLFW_KEY_SPACE;
_glfw.null.keycodes[GLFW_NULL_SC_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
_glfw.null.keycodes[GLFW_NULL_SC_COMMA] = GLFW_KEY_COMMA;
_glfw.null.keycodes[GLFW_NULL_SC_MINUS] = GLFW_KEY_MINUS;
_glfw.null.keycodes[GLFW_NULL_SC_PERIOD] = GLFW_KEY_PERIOD;
_glfw.null.keycodes[GLFW_NULL_SC_SLASH] = GLFW_KEY_SLASH;
_glfw.null.keycodes[GLFW_NULL_SC_0] = GLFW_KEY_0;
_glfw.null.keycodes[GLFW_NULL_SC_1] = GLFW_KEY_1;
_glfw.null.keycodes[GLFW_NULL_SC_2] = GLFW_KEY_2;
_glfw.null.keycodes[GLFW_NULL_SC_3] = GLFW_KEY_3;
_glfw.null.keycodes[GLFW_NULL_SC_4] = GLFW_KEY_4;
_glfw.null.keycodes[GLFW_NULL_SC_5] = GLFW_KEY_5;
_glfw.null.keycodes[GLFW_NULL_SC_6] = GLFW_KEY_6;
_glfw.null.keycodes[GLFW_NULL_SC_7] = GLFW_KEY_7;
_glfw.null.keycodes[GLFW_NULL_SC_8] = GLFW_KEY_8;
_glfw.null.keycodes[GLFW_NULL_SC_9] = GLFW_KEY_9;
_glfw.null.keycodes[GLFW_NULL_SC_SEMICOLON] = GLFW_KEY_SEMICOLON;
_glfw.null.keycodes[GLFW_NULL_SC_EQUAL] = GLFW_KEY_EQUAL;
_glfw.null.keycodes[GLFW_NULL_SC_A] = GLFW_KEY_A;
_glfw.null.keycodes[GLFW_NULL_SC_B] = GLFW_KEY_B;
_glfw.null.keycodes[GLFW_NULL_SC_C] = GLFW_KEY_C;
_glfw.null.keycodes[GLFW_NULL_SC_D] = GLFW_KEY_D;
_glfw.null.keycodes[GLFW_NULL_SC_E] = GLFW_KEY_E;
_glfw.null.keycodes[GLFW_NULL_SC_F] = GLFW_KEY_F;
_glfw.null.keycodes[GLFW_NULL_SC_G] = GLFW_KEY_G;
_glfw.null.keycodes[GLFW_NULL_SC_H] = GLFW_KEY_H;
_glfw.null.keycodes[GLFW_NULL_SC_I] = GLFW_KEY_I;
_glfw.null.keycodes[GLFW_NULL_SC_J] = GLFW_KEY_J;
_glfw.null.keycodes[GLFW_NULL_SC_K] = GLFW_KEY_K;
_glfw.null.keycodes[GLFW_NULL_SC_L] = GLFW_KEY_L;
_glfw.null.keycodes[GLFW_NULL_SC_M] = GLFW_KEY_M;
_glfw.null.keycodes[GLFW_NULL_SC_N] = GLFW_KEY_N;
_glfw.null.keycodes[GLFW_NULL_SC_O] = GLFW_KEY_O;
_glfw.null.keycodes[GLFW_NULL_SC_P] = GLFW_KEY_P;
_glfw.null.keycodes[GLFW_NULL_SC_Q] = GLFW_KEY_Q;
_glfw.null.keycodes[GLFW_NULL_SC_R] = GLFW_KEY_R;
_glfw.null.keycodes[GLFW_NULL_SC_S] = GLFW_KEY_S;
_glfw.null.keycodes[GLFW_NULL_SC_T] = GLFW_KEY_T;
_glfw.null.keycodes[GLFW_NULL_SC_U] = GLFW_KEY_U;
_glfw.null.keycodes[GLFW_NULL_SC_V] = GLFW_KEY_V;
_glfw.null.keycodes[GLFW_NULL_SC_W] = GLFW_KEY_W;
_glfw.null.keycodes[GLFW_NULL_SC_X] = GLFW_KEY_X;
_glfw.null.keycodes[GLFW_NULL_SC_Y] = GLFW_KEY_Y;
_glfw.null.keycodes[GLFW_NULL_SC_Z] = GLFW_KEY_Z;
_glfw.null.keycodes[GLFW_NULL_SC_LEFT_BRACKET] = GLFW_KEY_LEFT_BRACKET;
_glfw.null.keycodes[GLFW_NULL_SC_BACKSLASH] = GLFW_KEY_BACKSLASH;
_glfw.null.keycodes[GLFW_NULL_SC_RIGHT_BRACKET] = GLFW_KEY_RIGHT_BRACKET;
_glfw.null.keycodes[GLFW_NULL_SC_GRAVE_ACCENT] = GLFW_KEY_GRAVE_ACCENT;
_glfw.null.keycodes[GLFW_NULL_SC_WORLD_1] = GLFW_KEY_WORLD_1;
_glfw.null.keycodes[GLFW_NULL_SC_WORLD_2] = GLFW_KEY_WORLD_2;
_glfw.null.keycodes[GLFW_NULL_SC_ESCAPE] = GLFW_KEY_ESCAPE;
_glfw.null.keycodes[GLFW_NULL_SC_ENTER] = GLFW_KEY_ENTER;
_glfw.null.keycodes[GLFW_NULL_SC_TAB] = GLFW_KEY_TAB;
_glfw.null.keycodes[GLFW_NULL_SC_BACKSPACE] = GLFW_KEY_BACKSPACE;
_glfw.null.keycodes[GLFW_NULL_SC_INSERT] = GLFW_KEY_INSERT;
_glfw.null.keycodes[GLFW_NULL_SC_DELETE] = GLFW_KEY_DELETE;
_glfw.null.keycodes[GLFW_NULL_SC_RIGHT] = GLFW_KEY_RIGHT;
_glfw.null.keycodes[GLFW_NULL_SC_LEFT] = GLFW_KEY_LEFT;
_glfw.null.keycodes[GLFW_NULL_SC_DOWN] = GLFW_KEY_DOWN;
_glfw.null.keycodes[GLFW_NULL_SC_UP] = GLFW_KEY_UP;
_glfw.null.keycodes[GLFW_NULL_SC_PAGE_UP] = GLFW_KEY_PAGE_UP;
_glfw.null.keycodes[GLFW_NULL_SC_PAGE_DOWN] = GLFW_KEY_PAGE_DOWN;
_glfw.null.keycodes[GLFW_NULL_SC_HOME] = GLFW_KEY_HOME;
_glfw.null.keycodes[GLFW_NULL_SC_END] = GLFW_KEY_END;
_glfw.null.keycodes[GLFW_NULL_SC_CAPS_LOCK] = GLFW_KEY_CAPS_LOCK;
_glfw.null.keycodes[GLFW_NULL_SC_SCROLL_LOCK] = GLFW_KEY_SCROLL_LOCK;
_glfw.null.keycodes[GLFW_NULL_SC_NUM_LOCK] = GLFW_KEY_NUM_LOCK;
_glfw.null.keycodes[GLFW_NULL_SC_PRINT_SCREEN] = GLFW_KEY_PRINT_SCREEN;
_glfw.null.keycodes[GLFW_NULL_SC_PAUSE] = GLFW_KEY_PAUSE;
_glfw.null.keycodes[GLFW_NULL_SC_F1] = GLFW_KEY_F1;
_glfw.null.keycodes[GLFW_NULL_SC_F2] = GLFW_KEY_F2;
_glfw.null.keycodes[GLFW_NULL_SC_F3] = GLFW_KEY_F3;
_glfw.null.keycodes[GLFW_NULL_SC_F4] = GLFW_KEY_F4;
_glfw.null.keycodes[GLFW_NULL_SC_F5] = GLFW_KEY_F5;
_glfw.null.keycodes[GLFW_NULL_SC_F6] = GLFW_KEY_F6;
_glfw.null.keycodes[GLFW_NULL_SC_F7] = GLFW_KEY_F7;
_glfw.null.keycodes[GLFW_NULL_SC_F8] = GLFW_KEY_F8;
_glfw.null.keycodes[GLFW_NULL_SC_F9] = GLFW_KEY_F9;
_glfw.null.keycodes[GLFW_NULL_SC_F10] = GLFW_KEY_F10;
_glfw.null.keycodes[GLFW_NULL_SC_F11] = GLFW_KEY_F11;
_glfw.null.keycodes[GLFW_NULL_SC_F12] = GLFW_KEY_F12;
_glfw.null.keycodes[GLFW_NULL_SC_F13] = GLFW_KEY_F13;
_glfw.null.keycodes[GLFW_NULL_SC_F14] = GLFW_KEY_F14;
_glfw.null.keycodes[GLFW_NULL_SC_F15] = GLFW_KEY_F15;
_glfw.null.keycodes[GLFW_NULL_SC_F16] = GLFW_KEY_F16;
_glfw.null.keycodes[GLFW_NULL_SC_F17] = GLFW_KEY_F17;
_glfw.null.keycodes[GLFW_NULL_SC_F18] = GLFW_KEY_F18;
_glfw.null.keycodes[GLFW_NULL_SC_F19] = GLFW_KEY_F19;
_glfw.null.keycodes[GLFW_NULL_SC_F20] = GLFW_KEY_F20;
_glfw.null.keycodes[GLFW_NULL_SC_F21] = GLFW_KEY_F21;
_glfw.null.keycodes[GLFW_NULL_SC_F22] = GLFW_KEY_F22;
_glfw.null.keycodes[GLFW_NULL_SC_F23] = GLFW_KEY_F23;
_glfw.null.keycodes[GLFW_NULL_SC_F24] = GLFW_KEY_F24;
_glfw.null.keycodes[GLFW_NULL_SC_F25] = GLFW_KEY_F25;
_glfw.null.keycodes[GLFW_NULL_SC_KP_0] = GLFW_KEY_KP_0;
_glfw.null.keycodes[GLFW_NULL_SC_KP_1] = GLFW_KEY_KP_1;
_glfw.null.keycodes[GLFW_NULL_SC_KP_2] = GLFW_KEY_KP_2;
_glfw.null.keycodes[GLFW_NULL_SC_KP_3] = GLFW_KEY_KP_3;
_glfw.null.keycodes[GLFW_NULL_SC_KP_4] = GLFW_KEY_KP_4;
_glfw.null.keycodes[GLFW_NULL_SC_KP_5] = GLFW_KEY_KP_5;
_glfw.null.keycodes[GLFW_NULL_SC_KP_6] = GLFW_KEY_KP_6;
_glfw.null.keycodes[GLFW_NULL_SC_KP_7] = GLFW_KEY_KP_7;
_glfw.null.keycodes[GLFW_NULL_SC_KP_8] = GLFW_KEY_KP_8;
_glfw.null.keycodes[GLFW_NULL_SC_KP_9] = GLFW_KEY_KP_9;
_glfw.null.keycodes[GLFW_NULL_SC_KP_DECIMAL] = GLFW_KEY_KP_DECIMAL;
_glfw.null.keycodes[GLFW_NULL_SC_KP_DIVIDE] = GLFW_KEY_KP_DIVIDE;
_glfw.null.keycodes[GLFW_NULL_SC_KP_MULTIPLY] = GLFW_KEY_KP_MULTIPLY;
_glfw.null.keycodes[GLFW_NULL_SC_KP_SUBTRACT] = GLFW_KEY_KP_SUBTRACT;
_glfw.null.keycodes[GLFW_NULL_SC_KP_ADD] = GLFW_KEY_KP_ADD;
_glfw.null.keycodes[GLFW_NULL_SC_KP_ENTER] = GLFW_KEY_KP_ENTER;
_glfw.null.keycodes[GLFW_NULL_SC_KP_EQUAL] = GLFW_KEY_KP_EQUAL;
_glfw.null.keycodes[GLFW_NULL_SC_LEFT_SHIFT] = GLFW_KEY_LEFT_SHIFT;
_glfw.null.keycodes[GLFW_NULL_SC_LEFT_CONTROL] = GLFW_KEY_LEFT_CONTROL;
_glfw.null.keycodes[GLFW_NULL_SC_LEFT_ALT] = GLFW_KEY_LEFT_ALT;
_glfw.null.keycodes[GLFW_NULL_SC_LEFT_SUPER] = GLFW_KEY_LEFT_SUPER;
_glfw.null.keycodes[GLFW_NULL_SC_RIGHT_SHIFT] = GLFW_KEY_RIGHT_SHIFT;
_glfw.null.keycodes[GLFW_NULL_SC_RIGHT_CONTROL] = GLFW_KEY_RIGHT_CONTROL;
_glfw.null.keycodes[GLFW_NULL_SC_RIGHT_ALT] = GLFW_KEY_RIGHT_ALT;
_glfw.null.keycodes[GLFW_NULL_SC_RIGHT_SUPER] = GLFW_KEY_RIGHT_SUPER;
_glfw.null.keycodes[GLFW_NULL_SC_MENU] = GLFW_KEY_MENU;
for (scancode = GLFW_NULL_SC_FIRST; scancode < GLFW_NULL_SC_LAST; scancode++)
{
if (_glfw.null.keycodes[scancode] > 0)
_glfw.null.scancodes[_glfw.null.keycodes[scancode]] = scancode;
}
_glfwPollMonitorsNull(); _glfwPollMonitorsNull();
return GLFW_TRUE; return GLFW_TRUE;
} }

View File

@ -33,6 +33,128 @@
#define GLFW_NULL_CURSOR_STATE #define GLFW_NULL_CURSOR_STATE
#define GLFW_NULL_LIBRARY_CONTEXT_STATE #define GLFW_NULL_LIBRARY_CONTEXT_STATE
#define GLFW_NULL_SC_FIRST GLFW_NULL_SC_SPACE
#define GLFW_NULL_SC_SPACE 1
#define GLFW_NULL_SC_APOSTROPHE 2
#define GLFW_NULL_SC_COMMA 3
#define GLFW_NULL_SC_MINUS 4
#define GLFW_NULL_SC_PERIOD 5
#define GLFW_NULL_SC_SLASH 6
#define GLFW_NULL_SC_0 7
#define GLFW_NULL_SC_1 8
#define GLFW_NULL_SC_2 9
#define GLFW_NULL_SC_3 10
#define GLFW_NULL_SC_4 11
#define GLFW_NULL_SC_5 12
#define GLFW_NULL_SC_6 13
#define GLFW_NULL_SC_7 14
#define GLFW_NULL_SC_8 15
#define GLFW_NULL_SC_9 16
#define GLFW_NULL_SC_SEMICOLON 17
#define GLFW_NULL_SC_EQUAL 18
#define GLFW_NULL_SC_LEFT_BRACKET 19
#define GLFW_NULL_SC_BACKSLASH 20
#define GLFW_NULL_SC_RIGHT_BRACKET 21
#define GLFW_NULL_SC_GRAVE_ACCENT 22
#define GLFW_NULL_SC_WORLD_1 23
#define GLFW_NULL_SC_WORLD_2 24
#define GLFW_NULL_SC_ESCAPE 25
#define GLFW_NULL_SC_ENTER 26
#define GLFW_NULL_SC_TAB 27
#define GLFW_NULL_SC_BACKSPACE 28
#define GLFW_NULL_SC_INSERT 29
#define GLFW_NULL_SC_DELETE 30
#define GLFW_NULL_SC_RIGHT 31
#define GLFW_NULL_SC_LEFT 32
#define GLFW_NULL_SC_DOWN 33
#define GLFW_NULL_SC_UP 34
#define GLFW_NULL_SC_PAGE_UP 35
#define GLFW_NULL_SC_PAGE_DOWN 36
#define GLFW_NULL_SC_HOME 37
#define GLFW_NULL_SC_END 38
#define GLFW_NULL_SC_CAPS_LOCK 39
#define GLFW_NULL_SC_SCROLL_LOCK 40
#define GLFW_NULL_SC_NUM_LOCK 41
#define GLFW_NULL_SC_PRINT_SCREEN 42
#define GLFW_NULL_SC_PAUSE 43
#define GLFW_NULL_SC_A 44
#define GLFW_NULL_SC_B 45
#define GLFW_NULL_SC_C 46
#define GLFW_NULL_SC_D 47
#define GLFW_NULL_SC_E 48
#define GLFW_NULL_SC_F 49
#define GLFW_NULL_SC_G 50
#define GLFW_NULL_SC_H 51
#define GLFW_NULL_SC_I 52
#define GLFW_NULL_SC_J 53
#define GLFW_NULL_SC_K 54
#define GLFW_NULL_SC_L 55
#define GLFW_NULL_SC_M 56
#define GLFW_NULL_SC_N 57
#define GLFW_NULL_SC_O 58
#define GLFW_NULL_SC_P 59
#define GLFW_NULL_SC_Q 60
#define GLFW_NULL_SC_R 61
#define GLFW_NULL_SC_S 62
#define GLFW_NULL_SC_T 63
#define GLFW_NULL_SC_U 64
#define GLFW_NULL_SC_V 65
#define GLFW_NULL_SC_W 66
#define GLFW_NULL_SC_X 67
#define GLFW_NULL_SC_Y 68
#define GLFW_NULL_SC_Z 69
#define GLFW_NULL_SC_F1 70
#define GLFW_NULL_SC_F2 71
#define GLFW_NULL_SC_F3 72
#define GLFW_NULL_SC_F4 73
#define GLFW_NULL_SC_F5 74
#define GLFW_NULL_SC_F6 75
#define GLFW_NULL_SC_F7 76
#define GLFW_NULL_SC_F8 77
#define GLFW_NULL_SC_F9 78
#define GLFW_NULL_SC_F10 79
#define GLFW_NULL_SC_F11 80
#define GLFW_NULL_SC_F12 81
#define GLFW_NULL_SC_F13 82
#define GLFW_NULL_SC_F14 83
#define GLFW_NULL_SC_F15 84
#define GLFW_NULL_SC_F16 85
#define GLFW_NULL_SC_F17 86
#define GLFW_NULL_SC_F18 87
#define GLFW_NULL_SC_F19 88
#define GLFW_NULL_SC_F20 89
#define GLFW_NULL_SC_F21 90
#define GLFW_NULL_SC_F22 91
#define GLFW_NULL_SC_F23 92
#define GLFW_NULL_SC_F24 93
#define GLFW_NULL_SC_F25 94
#define GLFW_NULL_SC_KP_0 95
#define GLFW_NULL_SC_KP_1 96
#define GLFW_NULL_SC_KP_2 97
#define GLFW_NULL_SC_KP_3 98
#define GLFW_NULL_SC_KP_4 99
#define GLFW_NULL_SC_KP_5 100
#define GLFW_NULL_SC_KP_6 101
#define GLFW_NULL_SC_KP_7 102
#define GLFW_NULL_SC_KP_8 103
#define GLFW_NULL_SC_KP_9 104
#define GLFW_NULL_SC_KP_DECIMAL 105
#define GLFW_NULL_SC_KP_DIVIDE 106
#define GLFW_NULL_SC_KP_MULTIPLY 107
#define GLFW_NULL_SC_KP_SUBTRACT 108
#define GLFW_NULL_SC_KP_ADD 109
#define GLFW_NULL_SC_KP_ENTER 110
#define GLFW_NULL_SC_KP_EQUAL 111
#define GLFW_NULL_SC_LEFT_SHIFT 112
#define GLFW_NULL_SC_LEFT_CONTROL 113
#define GLFW_NULL_SC_LEFT_ALT 114
#define GLFW_NULL_SC_LEFT_SUPER 115
#define GLFW_NULL_SC_RIGHT_SHIFT 116
#define GLFW_NULL_SC_RIGHT_CONTROL 117
#define GLFW_NULL_SC_RIGHT_ALT 118
#define GLFW_NULL_SC_RIGHT_SUPER 119
#define GLFW_NULL_SC_MENU 120
#define GLFW_NULL_SC_LAST GLFW_NULL_SC_MENU
// Null-specific per-window data // Null-specific per-window data
// //
@ -68,6 +190,8 @@ typedef struct _GLFWlibraryNull
int ycursor; int ycursor;
char* clipboardString; char* clipboardString;
_GLFWwindow* focusedWindow; _GLFWwindow* focusedWindow;
uint16_t keycodes[GLFW_NULL_SC_LAST + 1];
uint8_t scancodes[GLFW_KEY_LAST + 1];
} _GLFWlibraryNull; } _GLFWlibraryNull;
void _glfwPollMonitorsNull(void); void _glfwPollMonitorsNull(void);

View File

@ -580,7 +580,7 @@ EGLNativeWindowType _glfwGetEGLNativeWindowNull(_GLFWwindow* window)
const char* _glfwGetScancodeNameNull(int scancode) const char* _glfwGetScancodeNameNull(int scancode)
{ {
if (scancode < GLFW_KEY_SPACE || scancode > GLFW_KEY_LAST) if (scancode < GLFW_NULL_SC_FIRST || scancode > GLFW_NULL_SC_LAST)
{ {
_glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode %i", scancode); _glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode %i", scancode);
return NULL; return NULL;
@ -588,117 +588,117 @@ const char* _glfwGetScancodeNameNull(int scancode)
switch (scancode) switch (scancode)
{ {
case GLFW_KEY_APOSTROPHE: case GLFW_NULL_SC_APOSTROPHE:
return "'"; return "'";
case GLFW_KEY_COMMA: case GLFW_NULL_SC_COMMA:
return ","; return ",";
case GLFW_KEY_MINUS: case GLFW_NULL_SC_MINUS:
case GLFW_KEY_KP_SUBTRACT: case GLFW_NULL_SC_KP_SUBTRACT:
return "-"; return "-";
case GLFW_KEY_PERIOD: case GLFW_NULL_SC_PERIOD:
case GLFW_KEY_KP_DECIMAL: case GLFW_NULL_SC_KP_DECIMAL:
return "."; return ".";
case GLFW_KEY_SLASH: case GLFW_NULL_SC_SLASH:
case GLFW_KEY_KP_DIVIDE: case GLFW_NULL_SC_KP_DIVIDE:
return "/"; return "/";
case GLFW_KEY_SEMICOLON: case GLFW_NULL_SC_SEMICOLON:
return ";"; return ";";
case GLFW_KEY_EQUAL: case GLFW_NULL_SC_EQUAL:
case GLFW_KEY_KP_EQUAL: case GLFW_NULL_SC_KP_EQUAL:
return "="; return "=";
case GLFW_KEY_LEFT_BRACKET: case GLFW_NULL_SC_LEFT_BRACKET:
return "["; return "[";
case GLFW_KEY_RIGHT_BRACKET: case GLFW_NULL_SC_RIGHT_BRACKET:
return "]"; return "]";
case GLFW_KEY_KP_MULTIPLY: case GLFW_NULL_SC_KP_MULTIPLY:
return "*"; return "*";
case GLFW_KEY_KP_ADD: case GLFW_NULL_SC_KP_ADD:
return "+"; return "+";
case GLFW_KEY_BACKSLASH: case GLFW_NULL_SC_BACKSLASH:
case GLFW_KEY_WORLD_1: case GLFW_NULL_SC_WORLD_1:
case GLFW_KEY_WORLD_2: case GLFW_NULL_SC_WORLD_2:
return "\\"; return "\\";
case GLFW_KEY_0: case GLFW_NULL_SC_0:
case GLFW_KEY_KP_0: case GLFW_NULL_SC_KP_0:
return "0"; return "0";
case GLFW_KEY_1: case GLFW_NULL_SC_1:
case GLFW_KEY_KP_1: case GLFW_NULL_SC_KP_1:
return "1"; return "1";
case GLFW_KEY_2: case GLFW_NULL_SC_2:
case GLFW_KEY_KP_2: case GLFW_NULL_SC_KP_2:
return "2"; return "2";
case GLFW_KEY_3: case GLFW_NULL_SC_3:
case GLFW_KEY_KP_3: case GLFW_NULL_SC_KP_3:
return "3"; return "3";
case GLFW_KEY_4: case GLFW_NULL_SC_4:
case GLFW_KEY_KP_4: case GLFW_NULL_SC_KP_4:
return "4"; return "4";
case GLFW_KEY_5: case GLFW_NULL_SC_5:
case GLFW_KEY_KP_5: case GLFW_NULL_SC_KP_5:
return "5"; return "5";
case GLFW_KEY_6: case GLFW_NULL_SC_6:
case GLFW_KEY_KP_6: case GLFW_NULL_SC_KP_6:
return "6"; return "6";
case GLFW_KEY_7: case GLFW_NULL_SC_7:
case GLFW_KEY_KP_7: case GLFW_NULL_SC_KP_7:
return "7"; return "7";
case GLFW_KEY_8: case GLFW_NULL_SC_8:
case GLFW_KEY_KP_8: case GLFW_NULL_SC_KP_8:
return "8"; return "8";
case GLFW_KEY_9: case GLFW_NULL_SC_9:
case GLFW_KEY_KP_9: case GLFW_NULL_SC_KP_9:
return "9"; return "9";
case GLFW_KEY_A: case GLFW_NULL_SC_A:
return "a"; return "a";
case GLFW_KEY_B: case GLFW_NULL_SC_B:
return "b"; return "b";
case GLFW_KEY_C: case GLFW_NULL_SC_C:
return "c"; return "c";
case GLFW_KEY_D: case GLFW_NULL_SC_D:
return "d"; return "d";
case GLFW_KEY_E: case GLFW_NULL_SC_E:
return "e"; return "e";
case GLFW_KEY_F: case GLFW_NULL_SC_F:
return "f"; return "f";
case GLFW_KEY_G: case GLFW_NULL_SC_G:
return "g"; return "g";
case GLFW_KEY_H: case GLFW_NULL_SC_H:
return "h"; return "h";
case GLFW_KEY_I: case GLFW_NULL_SC_I:
return "i"; return "i";
case GLFW_KEY_J: case GLFW_NULL_SC_J:
return "j"; return "j";
case GLFW_KEY_K: case GLFW_NULL_SC_K:
return "k"; return "k";
case GLFW_KEY_L: case GLFW_NULL_SC_L:
return "l"; return "l";
case GLFW_KEY_M: case GLFW_NULL_SC_M:
return "m"; return "m";
case GLFW_KEY_N: case GLFW_NULL_SC_N:
return "n"; return "n";
case GLFW_KEY_O: case GLFW_NULL_SC_O:
return "o"; return "o";
case GLFW_KEY_P: case GLFW_NULL_SC_P:
return "p"; return "p";
case GLFW_KEY_Q: case GLFW_NULL_SC_Q:
return "q"; return "q";
case GLFW_KEY_R: case GLFW_NULL_SC_R:
return "r"; return "r";
case GLFW_KEY_S: case GLFW_NULL_SC_S:
return "s"; return "s";
case GLFW_KEY_T: case GLFW_NULL_SC_T:
return "t"; return "t";
case GLFW_KEY_U: case GLFW_NULL_SC_U:
return "u"; return "u";
case GLFW_KEY_V: case GLFW_NULL_SC_V:
return "v"; return "v";
case GLFW_KEY_W: case GLFW_NULL_SC_W:
return "w"; return "w";
case GLFW_KEY_X: case GLFW_NULL_SC_X:
return "x"; return "x";
case GLFW_KEY_Y: case GLFW_NULL_SC_Y:
return "y"; return "y";
case GLFW_KEY_Z: case GLFW_NULL_SC_Z:
return "z"; return "z";
} }
@ -707,7 +707,7 @@ const char* _glfwGetScancodeNameNull(int scancode)
int _glfwGetKeyScancodeNull(int key) int _glfwGetKeyScancodeNull(int key)
{ {
return key; return _glfw.null.scancodes[key];
} }
void _glfwGetRequiredInstanceExtensionsNull(char** extensions) void _glfwGetRequiredInstanceExtensionsNull(char** extensions)

View File

@ -384,7 +384,7 @@ static GLFWbool createHelperWindow(void)
if (!_glfw.win32.helperWindowClass) if (!_glfw.win32.helperWindowClass)
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WIn32: Failed to register helper window class"); "Win32: Failed to register helper window class");
return GLFW_FALSE; return GLFW_FALSE;
} }

View File

@ -102,10 +102,9 @@ static void registryHandleGlobal(void* userData,
{ {
if (strcmp(interface, "wl_compositor") == 0) if (strcmp(interface, "wl_compositor") == 0)
{ {
_glfw.wl.compositorVersion = _glfw_min(3, version);
_glfw.wl.compositor = _glfw.wl.compositor =
wl_registry_bind(registry, name, &wl_compositor_interface, wl_registry_bind(registry, name, &wl_compositor_interface,
_glfw.wl.compositorVersion); _glfw_min(3, version));
} }
else if (strcmp(interface, "wl_subcompositor") == 0) else if (strcmp(interface, "wl_subcompositor") == 0)
{ {
@ -125,10 +124,9 @@ static void registryHandleGlobal(void* userData,
{ {
if (!_glfw.wl.seat) if (!_glfw.wl.seat)
{ {
_glfw.wl.seatVersion = _glfw_min(4, version);
_glfw.wl.seat = _glfw.wl.seat =
wl_registry_bind(registry, name, &wl_seat_interface, wl_registry_bind(registry, name, &wl_seat_interface,
_glfw.wl.seatVersion); _glfw_min(4, version));
_glfwAddSeatListenerWayland(_glfw.wl.seat); _glfwAddSeatListenerWayland(_glfw.wl.seat);
} }
} }
@ -204,6 +202,20 @@ static const struct wl_registry_listener registryListener =
registryHandleGlobalRemove registryHandleGlobalRemove
}; };
void libdecorHandleError(struct libdecor* context,
enum libdecor_error error,
const char* message)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: libdecor error %u: %s",
error, message);
}
static const struct libdecor_interface libdecorInterface =
{
libdecorHandleError
};
// Create key code translation tables // Create key code translation tables
// //
static void createKeyTables(void) static void createKeyTables(void)
@ -339,7 +351,7 @@ static void createKeyTables(void)
static GLFWbool loadCursorTheme(void) static GLFWbool loadCursorTheme(void)
{ {
int cursorSize = 32; int cursorSize = 16;
const char* sizeString = getenv("XCURSOR_SIZE"); const char* sizeString = getenv("XCURSOR_SIZE");
if (sizeString) if (sizeString)
@ -514,6 +526,8 @@ int _glfwInitWayland(void)
_glfw.wl.keyRepeatTimerfd = -1; _glfw.wl.keyRepeatTimerfd = -1;
_glfw.wl.cursorTimerfd = -1; _glfw.wl.cursorTimerfd = -1;
_glfw.wl.tag = glfwGetVersionString();
_glfw.wl.client.display_flush = (PFN_wl_display_flush) _glfw.wl.client.display_flush = (PFN_wl_display_flush)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_flush"); _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_flush");
_glfw.wl.client.display_cancel_read = (PFN_wl_display_cancel_read) _glfw.wl.client.display_cancel_read = (PFN_wl_display_cancel_read)
@ -544,6 +558,10 @@ int _glfwInitWayland(void)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_user_data"); _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_user_data");
_glfw.wl.client.proxy_set_user_data = (PFN_wl_proxy_set_user_data) _glfw.wl.client.proxy_set_user_data = (PFN_wl_proxy_set_user_data)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_set_user_data"); _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_set_user_data");
_glfw.wl.client.proxy_get_tag = (PFN_wl_proxy_get_tag)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_tag");
_glfw.wl.client.proxy_set_tag = (PFN_wl_proxy_set_tag)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_set_tag");
_glfw.wl.client.proxy_get_version = (PFN_wl_proxy_get_version) _glfw.wl.client.proxy_get_version = (PFN_wl_proxy_get_version)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_version"); _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_version");
_glfw.wl.client.proxy_marshal_flags = (PFN_wl_proxy_marshal_flags) _glfw.wl.client.proxy_marshal_flags = (PFN_wl_proxy_marshal_flags)
@ -563,7 +581,9 @@ int _glfwInitWayland(void)
!_glfw.wl.client.proxy_marshal_constructor || !_glfw.wl.client.proxy_marshal_constructor ||
!_glfw.wl.client.proxy_marshal_constructor_versioned || !_glfw.wl.client.proxy_marshal_constructor_versioned ||
!_glfw.wl.client.proxy_get_user_data || !_glfw.wl.client.proxy_get_user_data ||
!_glfw.wl.client.proxy_set_user_data) !_glfw.wl.client.proxy_set_user_data ||
!_glfw.wl.client.proxy_get_tag ||
!_glfw.wl.client.proxy_set_tag)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to load libwayland-client entry point"); "Wayland: Failed to load libwayland-client entry point");
@ -651,6 +671,93 @@ int _glfwInitWayland(void)
_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");
if (_glfw.hints.init.wl.libdecorMode == GLFW_WAYLAND_PREFER_LIBDECOR)
_glfw.wl.libdecor.handle = _glfwPlatformLoadModule("libdecor-0.so.0");
if (_glfw.wl.libdecor.handle)
{
_glfw.wl.libdecor.libdecor_new_ = (PFN_libdecor_new)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_new");
_glfw.wl.libdecor.libdecor_unref_ = (PFN_libdecor_unref)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_unref");
_glfw.wl.libdecor.libdecor_get_fd_ = (PFN_libdecor_get_fd)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_get_fd");
_glfw.wl.libdecor.libdecor_dispatch_ = (PFN_libdecor_dispatch)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_dispatch");
_glfw.wl.libdecor.libdecor_decorate_ = (PFN_libdecor_decorate)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_decorate");
_glfw.wl.libdecor.libdecor_frame_unref_ = (PFN_libdecor_frame_unref)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_unref");
_glfw.wl.libdecor.libdecor_frame_set_app_id_ = (PFN_libdecor_frame_set_app_id)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_app_id");
_glfw.wl.libdecor.libdecor_frame_set_title_ = (PFN_libdecor_frame_set_title)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_title");
_glfw.wl.libdecor.libdecor_frame_set_minimized_ = (PFN_libdecor_frame_set_minimized)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_minimized");
_glfw.wl.libdecor.libdecor_frame_set_fullscreen_ = (PFN_libdecor_frame_set_fullscreen)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_fullscreen");
_glfw.wl.libdecor.libdecor_frame_unset_fullscreen_ = (PFN_libdecor_frame_unset_fullscreen)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_unset_fullscreen");
_glfw.wl.libdecor.libdecor_frame_map_ = (PFN_libdecor_frame_map)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_map");
_glfw.wl.libdecor.libdecor_frame_commit_ = (PFN_libdecor_frame_commit)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_commit");
_glfw.wl.libdecor.libdecor_frame_set_min_content_size_ = (PFN_libdecor_frame_set_min_content_size)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_min_content_size");
_glfw.wl.libdecor.libdecor_frame_set_max_content_size_ = (PFN_libdecor_frame_set_max_content_size)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_max_content_size");
_glfw.wl.libdecor.libdecor_frame_set_maximized_ = (PFN_libdecor_frame_set_maximized)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_maximized");
_glfw.wl.libdecor.libdecor_frame_unset_maximized_ = (PFN_libdecor_frame_unset_maximized)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_unset_maximized");
_glfw.wl.libdecor.libdecor_frame_set_capabilities_ = (PFN_libdecor_frame_set_capabilities)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_capabilities");
_glfw.wl.libdecor.libdecor_frame_unset_capabilities_ = (PFN_libdecor_frame_unset_capabilities)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_unset_capabilities");
_glfw.wl.libdecor.libdecor_frame_set_visibility_ = (PFN_libdecor_frame_set_visibility)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_visibility");
_glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ = (PFN_libdecor_frame_get_xdg_toplevel)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_get_xdg_toplevel");
_glfw.wl.libdecor.libdecor_configuration_get_content_size_ = (PFN_libdecor_configuration_get_content_size)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_configuration_get_content_size");
_glfw.wl.libdecor.libdecor_configuration_get_window_state_ = (PFN_libdecor_configuration_get_window_state)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_configuration_get_window_state");
_glfw.wl.libdecor.libdecor_state_new_ = (PFN_libdecor_state_new)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_state_new");
_glfw.wl.libdecor.libdecor_state_free_ = (PFN_libdecor_state_free)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_state_free");
if (!_glfw.wl.libdecor.libdecor_new_ ||
!_glfw.wl.libdecor.libdecor_unref_ ||
!_glfw.wl.libdecor.libdecor_get_fd_ ||
!_glfw.wl.libdecor.libdecor_dispatch_ ||
!_glfw.wl.libdecor.libdecor_decorate_ ||
!_glfw.wl.libdecor.libdecor_frame_unref_ ||
!_glfw.wl.libdecor.libdecor_frame_set_app_id_ ||
!_glfw.wl.libdecor.libdecor_frame_set_title_ ||
!_glfw.wl.libdecor.libdecor_frame_set_minimized_ ||
!_glfw.wl.libdecor.libdecor_frame_set_fullscreen_ ||
!_glfw.wl.libdecor.libdecor_frame_unset_fullscreen_ ||
!_glfw.wl.libdecor.libdecor_frame_map_ ||
!_glfw.wl.libdecor.libdecor_frame_commit_ ||
!_glfw.wl.libdecor.libdecor_frame_set_min_content_size_ ||
!_glfw.wl.libdecor.libdecor_frame_set_max_content_size_ ||
!_glfw.wl.libdecor.libdecor_frame_set_maximized_ ||
!_glfw.wl.libdecor.libdecor_frame_unset_maximized_ ||
!_glfw.wl.libdecor.libdecor_frame_set_capabilities_ ||
!_glfw.wl.libdecor.libdecor_frame_unset_capabilities_ ||
!_glfw.wl.libdecor.libdecor_frame_set_visibility_ ||
!_glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ ||
!_glfw.wl.libdecor.libdecor_configuration_get_content_size_ ||
!_glfw.wl.libdecor.libdecor_configuration_get_window_state_ ||
!_glfw.wl.libdecor.libdecor_state_new_ ||
!_glfw.wl.libdecor.libdecor_state_free_)
{
_glfwPlatformFreeModule(_glfw.wl.libdecor.handle);
memset(&_glfw.wl.libdecor, 0, sizeof(_glfw.wl.libdecor));
}
}
_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);
@ -670,8 +777,17 @@ int _glfwInitWayland(void)
// Sync so we got all initial output events // Sync so we got all initial output events
wl_display_roundtrip(_glfw.wl.display); wl_display_roundtrip(_glfw.wl.display);
if (_glfw.wl.libdecor.handle)
{
_glfw.wl.libdecor.context = libdecor_new(_glfw.wl.display, &libdecorInterface);
// Allow libdecor to receive its globals before proceeding
if (_glfw.wl.libdecor.context)
libdecor_dispatch(_glfw.wl.libdecor.context, 1);
}
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION #ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
if (_glfw.wl.seatVersion >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) if (wl_seat_get_version(_glfw.wl.seat) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
{ {
_glfw.wl.keyRepeatTimerfd = _glfw.wl.keyRepeatTimerfd =
timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
@ -711,6 +827,15 @@ void _glfwTerminateWayland(void)
_glfwTerminateEGL(); _glfwTerminateEGL();
_glfwTerminateOSMesa(); _glfwTerminateOSMesa();
if (_glfw.wl.libdecor.context)
libdecor_unref(_glfw.wl.libdecor.context);
if (_glfw.wl.libdecor.handle)
{
_glfwPlatformFreeModule(_glfw.wl.libdecor.handle);
_glfw.wl.libdecor.handle = NULL;
}
if (_glfw.wl.egl.handle) if (_glfw.wl.egl.handle)
{ {
_glfwPlatformFreeModule(_glfw.wl.egl.handle); _glfwPlatformFreeModule(_glfw.wl.egl.handle);

View File

@ -114,14 +114,15 @@ static void outputHandleScale(void* userData,
{ {
struct _GLFWmonitor* monitor = userData; struct _GLFWmonitor* monitor = userData;
monitor->wl.scale = factor; monitor->wl.contentScale = factor;
for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next) for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next)
{ {
for (int i = 0; i < window->wl.monitorsCount; i++) for (int i = 0; i < window->wl.scaleCount; i++)
{ {
if (window->wl.monitors[i] == monitor) if (window->wl.scales[i].output == monitor->wl.output)
{ {
window->wl.scales[i].factor = monitor->wl.contentScale;
_glfwUpdateContentScaleWayland(window); _glfwUpdateContentScaleWayland(window);
break; break;
} }
@ -187,10 +188,11 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
// The actual name of this output will be set in the geometry handler // The actual name of this output will be set in the geometry handler
_GLFWmonitor* monitor = _glfwAllocMonitor("", 0, 0); _GLFWmonitor* monitor = _glfwAllocMonitor("", 0, 0);
monitor->wl.scale = 1; monitor->wl.contentScale = 1;
monitor->wl.output = output; monitor->wl.output = output;
monitor->wl.name = name; monitor->wl.name = name;
wl_proxy_set_tag((struct wl_proxy*) output, &_glfw.wl.tag);
wl_output_add_listener(output, &outputListener, monitor); wl_output_add_listener(output, &outputListener, monitor);
} }
@ -217,9 +219,9 @@ void _glfwGetMonitorContentScaleWayland(_GLFWmonitor* monitor,
float* xscale, float* yscale) float* xscale, float* yscale)
{ {
if (xscale) if (xscale)
*xscale = (float) monitor->wl.scale; *xscale = (float) monitor->wl.contentScale;
if (yscale) if (yscale)
*yscale = (float) monitor->wl.scale; *yscale = (float) monitor->wl.contentScale;
} }
void _glfwGetMonitorWorkareaWayland(_GLFWmonitor* monitor, void _glfwGetMonitorWorkareaWayland(_GLFWmonitor* monitor,

View File

@ -28,6 +28,8 @@
#include <xkbcommon/xkbcommon.h> #include <xkbcommon/xkbcommon.h>
#include <xkbcommon/xkbcommon-compose.h> #include <xkbcommon/xkbcommon-compose.h>
#include <stdbool.h>
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR; typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
typedef struct VkWaylandSurfaceCreateInfoKHR typedef struct VkWaylandSurfaceCreateInfoKHR
@ -61,6 +63,8 @@ typedef struct wl_proxy* (* PFN_wl_proxy_marshal_constructor)(struct wl_proxy*,u
typedef struct wl_proxy* (* PFN_wl_proxy_marshal_constructor_versioned)(struct wl_proxy*,uint32_t,const struct wl_interface*,uint32_t,...); typedef struct wl_proxy* (* PFN_wl_proxy_marshal_constructor_versioned)(struct wl_proxy*,uint32_t,const struct wl_interface*,uint32_t,...);
typedef void* (* PFN_wl_proxy_get_user_data)(struct wl_proxy*); typedef void* (* PFN_wl_proxy_get_user_data)(struct wl_proxy*);
typedef void (* PFN_wl_proxy_set_user_data)(struct wl_proxy*,void*); typedef void (* PFN_wl_proxy_set_user_data)(struct wl_proxy*,void*);
typedef void (* PFN_wl_proxy_set_tag)(struct wl_proxy*,const char*const*);
typedef const char* const* (* PFN_wl_proxy_get_tag)(struct wl_proxy*);
typedef uint32_t (* PFN_wl_proxy_get_version)(struct wl_proxy*); typedef uint32_t (* PFN_wl_proxy_get_version)(struct wl_proxy*);
typedef struct wl_proxy* (* PFN_wl_proxy_marshal_flags)(struct wl_proxy*,uint32_t,const struct wl_interface*,uint32_t,uint32_t,...); typedef struct wl_proxy* (* PFN_wl_proxy_marshal_flags)(struct wl_proxy*,uint32_t,const struct wl_interface*,uint32_t,uint32_t,...);
#define wl_display_flush _glfw.wl.client.display_flush #define wl_display_flush _glfw.wl.client.display_flush
@ -78,10 +82,13 @@ typedef struct wl_proxy* (* PFN_wl_proxy_marshal_flags)(struct wl_proxy*,uint32_
#define wl_proxy_marshal_constructor_versioned _glfw.wl.client.proxy_marshal_constructor_versioned #define wl_proxy_marshal_constructor_versioned _glfw.wl.client.proxy_marshal_constructor_versioned
#define wl_proxy_get_user_data _glfw.wl.client.proxy_get_user_data #define wl_proxy_get_user_data _glfw.wl.client.proxy_get_user_data
#define wl_proxy_set_user_data _glfw.wl.client.proxy_set_user_data #define wl_proxy_set_user_data _glfw.wl.client.proxy_set_user_data
#define wl_proxy_get_tag _glfw.wl.client.proxy_get_tag
#define wl_proxy_set_tag _glfw.wl.client.proxy_set_tag
#define wl_proxy_get_version _glfw.wl.client.proxy_get_version #define wl_proxy_get_version _glfw.wl.client.proxy_get_version
#define wl_proxy_marshal_flags _glfw.wl.client.proxy_marshal_flags #define wl_proxy_marshal_flags _glfw.wl.client.proxy_marshal_flags
struct wl_shm; struct wl_shm;
struct wl_output;
#define wl_display_interface _glfw_wl_display_interface #define wl_display_interface _glfw_wl_display_interface
#define wl_subcompositor_interface _glfw_wl_subcompositor_interface #define wl_subcompositor_interface _glfw_wl_subcompositor_interface
@ -198,13 +205,129 @@ typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_st
#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
struct libdecor;
struct libdecor_frame;
struct libdecor_state;
struct libdecor_configuration;
enum libdecor_error
{
LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
LIBDECOR_ERROR_INVALID_FRAME_CONFIGURATION,
};
enum libdecor_window_state
{
LIBDECOR_WINDOW_STATE_NONE = 0,
LIBDECOR_WINDOW_STATE_ACTIVE = 1,
LIBDECOR_WINDOW_STATE_MAXIMIZED = 2,
LIBDECOR_WINDOW_STATE_FULLSCREEN = 4,
LIBDECOR_WINDOW_STATE_TILED_LEFT = 8,
LIBDECOR_WINDOW_STATE_TILED_RIGHT = 16,
LIBDECOR_WINDOW_STATE_TILED_TOP = 32,
LIBDECOR_WINDOW_STATE_TILED_BOTTOM = 64
};
enum libdecor_capabilities
{
LIBDECOR_ACTION_MOVE = 1,
LIBDECOR_ACTION_RESIZE = 2,
LIBDECOR_ACTION_MINIMIZE = 4,
LIBDECOR_ACTION_FULLSCREEN = 8,
LIBDECOR_ACTION_CLOSE = 16
};
struct libdecor_interface
{
void (* error)(struct libdecor*,enum libdecor_error,const char*);
void (* reserved0)(void);
void (* reserved1)(void);
void (* reserved2)(void);
void (* reserved3)(void);
void (* reserved4)(void);
void (* reserved5)(void);
void (* reserved6)(void);
void (* reserved7)(void);
void (* reserved8)(void);
void (* reserved9)(void);
};
struct libdecor_frame_interface
{
void (* configure)(struct libdecor_frame*,struct libdecor_configuration*,void*);
void (* close)(struct libdecor_frame*,void*);
void (* commit)(struct libdecor_frame*,void*);
void (* dismiss_popup)(struct libdecor_frame*,const char*,void*);
void (* reserved0)(void);
void (* reserved1)(void);
void (* reserved2)(void);
void (* reserved3)(void);
void (* reserved4)(void);
void (* reserved5)(void);
void (* reserved6)(void);
void (* reserved7)(void);
void (* reserved8)(void);
void (* reserved9)(void);
};
typedef struct libdecor* (* PFN_libdecor_new)(struct wl_display*,const struct libdecor_interface*);
typedef void (* PFN_libdecor_unref)(struct libdecor*);
typedef int (* PFN_libdecor_get_fd)(struct libdecor*);
typedef int (* PFN_libdecor_dispatch)(struct libdecor*,int);
typedef struct libdecor_frame* (* PFN_libdecor_decorate)(struct libdecor*,struct wl_surface*,const struct libdecor_frame_interface*,void*);
typedef void (* PFN_libdecor_frame_unref)(struct libdecor_frame*);
typedef void (* PFN_libdecor_frame_set_app_id)(struct libdecor_frame*,const char*);
typedef void (* PFN_libdecor_frame_set_title)(struct libdecor_frame*,const char*);
typedef void (* PFN_libdecor_frame_set_minimized)(struct libdecor_frame*);
typedef void (* PFN_libdecor_frame_set_fullscreen)(struct libdecor_frame*,struct wl_output*);
typedef void (* PFN_libdecor_frame_unset_fullscreen)(struct libdecor_frame*);
typedef void (* PFN_libdecor_frame_map)(struct libdecor_frame*);
typedef void (* PFN_libdecor_frame_commit)(struct libdecor_frame*,struct libdecor_state*,struct libdecor_configuration*);
typedef void (* PFN_libdecor_frame_set_min_content_size)(struct libdecor_frame*,int,int);
typedef void (* PFN_libdecor_frame_set_max_content_size)(struct libdecor_frame*,int,int);
typedef void (* PFN_libdecor_frame_set_maximized)(struct libdecor_frame*);
typedef void (* PFN_libdecor_frame_unset_maximized)(struct libdecor_frame*);
typedef void (* PFN_libdecor_frame_set_capabilities)(struct libdecor_frame*,enum libdecor_capabilities);
typedef void (* PFN_libdecor_frame_unset_capabilities)(struct libdecor_frame*,enum libdecor_capabilities);
typedef void (* PFN_libdecor_frame_set_visibility)(struct libdecor_frame*,bool visible);
typedef struct xdg_toplevel* (* PFN_libdecor_frame_get_xdg_toplevel)(struct libdecor_frame*);
typedef bool (* PFN_libdecor_configuration_get_content_size)(struct libdecor_configuration*,struct libdecor_frame*,int*,int*);
typedef bool (* PFN_libdecor_configuration_get_window_state)(struct libdecor_configuration*,enum libdecor_window_state*);
typedef struct libdecor_state* (* PFN_libdecor_state_new)(int,int);
typedef void (* PFN_libdecor_state_free)(struct libdecor_state*);
#define libdecor_new _glfw.wl.libdecor.libdecor_new_
#define libdecor_unref _glfw.wl.libdecor.libdecor_unref_
#define libdecor_get_fd _glfw.wl.libdecor.libdecor_get_fd_
#define libdecor_dispatch _glfw.wl.libdecor.libdecor_dispatch_
#define libdecor_decorate _glfw.wl.libdecor.libdecor_decorate_
#define libdecor_frame_unref _glfw.wl.libdecor.libdecor_frame_unref_
#define libdecor_frame_set_app_id _glfw.wl.libdecor.libdecor_frame_set_app_id_
#define libdecor_frame_set_title _glfw.wl.libdecor.libdecor_frame_set_title_
#define libdecor_frame_set_minimized _glfw.wl.libdecor.libdecor_frame_set_minimized_
#define libdecor_frame_set_fullscreen _glfw.wl.libdecor.libdecor_frame_set_fullscreen_
#define libdecor_frame_unset_fullscreen _glfw.wl.libdecor.libdecor_frame_unset_fullscreen_
#define libdecor_frame_map _glfw.wl.libdecor.libdecor_frame_map_
#define libdecor_frame_commit _glfw.wl.libdecor.libdecor_frame_commit_
#define libdecor_frame_set_min_content_size _glfw.wl.libdecor.libdecor_frame_set_min_content_size_
#define libdecor_frame_set_max_content_size _glfw.wl.libdecor.libdecor_frame_set_max_content_size_
#define libdecor_frame_set_maximized _glfw.wl.libdecor.libdecor_frame_set_maximized_
#define libdecor_frame_unset_maximized _glfw.wl.libdecor.libdecor_frame_unset_maximized_
#define libdecor_frame_set_capabilities _glfw.wl.libdecor.libdecor_frame_set_capabilities_
#define libdecor_frame_unset_capabilities _glfw.wl.libdecor.libdecor_frame_unset_capabilities_
#define libdecor_frame_set_visibility _glfw.wl.libdecor.libdecor_frame_set_visibility_
#define libdecor_frame_get_xdg_toplevel _glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_
#define libdecor_configuration_get_content_size _glfw.wl.libdecor.libdecor_configuration_get_content_size_
#define libdecor_configuration_get_window_state _glfw.wl.libdecor.libdecor_configuration_get_window_state_
#define libdecor_state_new _glfw.wl.libdecor.libdecor_state_new_
#define libdecor_state_free _glfw.wl.libdecor.libdecor_state_free_
typedef enum _GLFWdecorationSideWayland typedef enum _GLFWdecorationSideWayland
{ {
mainWindow, GLFW_MAIN_WINDOW,
topDecoration, GLFW_TOP_DECORATION,
leftDecoration, GLFW_LEFT_DECORATION,
rightDecoration, GLFW_RIGHT_DECORATION,
bottomDecoration, GLFW_BOTTOM_DECORATION
} _GLFWdecorationSideWayland; } _GLFWdecorationSideWayland;
typedef struct _GLFWdecorationWayland typedef struct _GLFWdecorationWayland
@ -221,6 +344,12 @@ typedef struct _GLFWofferWayland
GLFWbool text_uri_list; GLFWbool text_uri_list;
} _GLFWofferWayland; } _GLFWofferWayland;
typedef struct _GLFWscaleWayland
{
struct wl_output* output;
int factor;
} _GLFWscaleWayland;
// Wayland-specific per-window data // Wayland-specific per-window data
// //
typedef struct _GLFWwindowWayland typedef struct _GLFWwindowWayland
@ -254,6 +383,11 @@ typedef struct _GLFWwindowWayland
uint32_t decorationMode; uint32_t decorationMode;
} xdg; } xdg;
struct {
struct libdecor_frame* frame;
int mode;
} libdecor;
_GLFWcursor* currentCursor; _GLFWcursor* currentCursor;
double cursorPosX, cursorPosY; double cursorPosX, cursorPosY;
@ -262,10 +396,10 @@ typedef struct _GLFWwindowWayland
// We need to track the monitors the window spans on to calculate the // We need to track the monitors the window spans on to calculate the
// optimal scaling factor. // optimal scaling factor.
int scale; int contentScale;
_GLFWmonitor** monitors; _GLFWscaleWayland* scales;
int monitorsCount; int scaleCount;
int monitorsSize; int scaleSize;
struct zwp_relative_pointer_v1* relativePointer; struct zwp_relative_pointer_v1* relativePointer;
struct zwp_locked_pointer_v1* lockedPointer; struct zwp_locked_pointer_v1* lockedPointer;
@ -311,8 +445,7 @@ typedef struct _GLFWlibraryWayland
_GLFWwindow* dragFocus; _GLFWwindow* dragFocus;
uint32_t dragSerial; uint32_t dragSerial;
int compositorVersion; const char* tag;
int seatVersion;
struct wl_cursor_theme* cursorTheme; struct wl_cursor_theme* cursorTheme;
struct wl_cursor_theme* cursorThemeHiDPI; struct wl_cursor_theme* cursorThemeHiDPI;
@ -391,6 +524,8 @@ typedef struct _GLFWlibraryWayland
PFN_wl_proxy_marshal_constructor_versioned proxy_marshal_constructor_versioned; PFN_wl_proxy_marshal_constructor_versioned proxy_marshal_constructor_versioned;
PFN_wl_proxy_get_user_data proxy_get_user_data; PFN_wl_proxy_get_user_data proxy_get_user_data;
PFN_wl_proxy_set_user_data proxy_set_user_data; PFN_wl_proxy_set_user_data proxy_set_user_data;
PFN_wl_proxy_get_tag proxy_get_tag;
PFN_wl_proxy_set_tag proxy_set_tag;
PFN_wl_proxy_get_version proxy_get_version; PFN_wl_proxy_get_version proxy_get_version;
PFN_wl_proxy_marshal_flags proxy_marshal_flags; PFN_wl_proxy_marshal_flags proxy_marshal_flags;
} client; } client;
@ -411,6 +546,36 @@ typedef struct _GLFWlibraryWayland
PFN_wl_egl_window_destroy window_destroy; PFN_wl_egl_window_destroy window_destroy;
PFN_wl_egl_window_resize window_resize; PFN_wl_egl_window_resize window_resize;
} egl; } egl;
struct {
void* handle;
struct libdecor* context;
PFN_libdecor_new libdecor_new_;
PFN_libdecor_unref libdecor_unref_;
PFN_libdecor_get_fd libdecor_get_fd_;
PFN_libdecor_dispatch libdecor_dispatch_;
PFN_libdecor_decorate libdecor_decorate_;
PFN_libdecor_frame_unref libdecor_frame_unref_;
PFN_libdecor_frame_set_app_id libdecor_frame_set_app_id_;
PFN_libdecor_frame_set_title libdecor_frame_set_title_;
PFN_libdecor_frame_set_minimized libdecor_frame_set_minimized_;
PFN_libdecor_frame_set_fullscreen libdecor_frame_set_fullscreen_;
PFN_libdecor_frame_unset_fullscreen libdecor_frame_unset_fullscreen_;
PFN_libdecor_frame_map libdecor_frame_map_;
PFN_libdecor_frame_commit libdecor_frame_commit_;
PFN_libdecor_frame_set_min_content_size libdecor_frame_set_min_content_size_;
PFN_libdecor_frame_set_max_content_size libdecor_frame_set_max_content_size_;
PFN_libdecor_frame_set_maximized libdecor_frame_set_maximized_;
PFN_libdecor_frame_unset_maximized libdecor_frame_unset_maximized_;
PFN_libdecor_frame_set_capabilities libdecor_frame_set_capabilities_;
PFN_libdecor_frame_unset_capabilities libdecor_frame_unset_capabilities_;
PFN_libdecor_frame_set_visibility libdecor_frame_set_visibility_;
PFN_libdecor_frame_get_xdg_toplevel libdecor_frame_get_xdg_toplevel_;
PFN_libdecor_configuration_get_content_size libdecor_configuration_get_content_size_;
PFN_libdecor_configuration_get_window_state libdecor_configuration_get_window_state_;
PFN_libdecor_state_new libdecor_state_new_;
PFN_libdecor_state_free libdecor_state_free_;
} libdecor;
} _GLFWlibraryWayland; } _GLFWlibraryWayland;
// Wayland-specific per-monitor data // Wayland-specific per-monitor data
@ -423,7 +588,7 @@ typedef struct _GLFWmonitorWayland
int x; int x;
int y; int y;
int scale; int contentScale;
} _GLFWmonitorWayland; } _GLFWmonitorWayland;
// Wayland-specific per-cursor data // Wayland-specific per-cursor data

View File

@ -192,13 +192,16 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
return buffer; return buffer;
} }
static void createFallbackDecoration(_GLFWdecorationWayland* decoration, static void createFallbackDecoration(_GLFWwindow* window,
_GLFWdecorationWayland* decoration,
struct wl_surface* parent, struct wl_surface* parent,
struct wl_buffer* buffer, struct wl_buffer* buffer,
int x, int y, int x, int y,
int width, int height) int width, int height)
{ {
decoration->surface = wl_compositor_create_surface(_glfw.wl.compositor); decoration->surface = wl_compositor_create_surface(_glfw.wl.compositor);
wl_surface_set_user_data(decoration->surface, window);
wl_proxy_set_tag((struct wl_proxy*) decoration->surface, &_glfw.wl.tag);
decoration->subsurface = decoration->subsurface =
wl_subcompositor_get_subsurface(_glfw.wl.subcompositor, wl_subcompositor_get_subsurface(_glfw.wl.subcompositor,
decoration->surface, parent); decoration->surface, parent);
@ -228,19 +231,19 @@ static void createFallbackDecorations(_GLFWwindow* window)
if (!window->wl.decorations.buffer) if (!window->wl.decorations.buffer)
return; return;
createFallbackDecoration(&window->wl.decorations.top, window->wl.surface, createFallbackDecoration(window, &window->wl.decorations.top, window->wl.surface,
window->wl.decorations.buffer, window->wl.decorations.buffer,
0, -GLFW_CAPTION_HEIGHT, 0, -GLFW_CAPTION_HEIGHT,
window->wl.width, GLFW_CAPTION_HEIGHT); window->wl.width, GLFW_CAPTION_HEIGHT);
createFallbackDecoration(&window->wl.decorations.left, window->wl.surface, createFallbackDecoration(window, &window->wl.decorations.left, window->wl.surface,
window->wl.decorations.buffer, window->wl.decorations.buffer,
-GLFW_BORDER_SIZE, -GLFW_CAPTION_HEIGHT, -GLFW_BORDER_SIZE, -GLFW_CAPTION_HEIGHT,
GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT); GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT);
createFallbackDecoration(&window->wl.decorations.right, window->wl.surface, createFallbackDecoration(window, &window->wl.decorations.right, window->wl.surface,
window->wl.decorations.buffer, window->wl.decorations.buffer,
window->wl.width, -GLFW_CAPTION_HEIGHT, window->wl.width, -GLFW_CAPTION_HEIGHT,
GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT); GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT);
createFallbackDecoration(&window->wl.decorations.bottom, window->wl.surface, createFallbackDecoration(window, &window->wl.decorations.bottom, window->wl.surface,
window->wl.decorations.buffer, window->wl.decorations.buffer,
-GLFW_BORDER_SIZE, window->wl.height, -GLFW_BORDER_SIZE, window->wl.height,
window->wl.width + GLFW_BORDER_SIZE * 2, GLFW_BORDER_SIZE); window->wl.width + GLFW_BORDER_SIZE * 2, GLFW_BORDER_SIZE);
@ -306,7 +309,7 @@ static void setContentAreaOpaque(_GLFWwindow* window)
static void resizeWindow(_GLFWwindow* window) static void resizeWindow(_GLFWwindow* window)
{ {
int scale = window->wl.scale; int scale = window->wl.contentScale;
int scaledWidth = window->wl.width * scale; int scaledWidth = window->wl.width * scale;
int scaledHeight = window->wl.height * scale; int scaledHeight = window->wl.height * scale;
@ -342,22 +345,28 @@ static void resizeWindow(_GLFWwindow* window)
void _glfwUpdateContentScaleWayland(_GLFWwindow* window) void _glfwUpdateContentScaleWayland(_GLFWwindow* window)
{ {
if (_glfw.wl.compositorVersion < WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION) if (wl_compositor_get_version(_glfw.wl.compositor) <
WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION)
{
return; return;
}
// Get the scale factor from the highest scale monitor. // Get the scale factor from the highest scale monitor.
int maxScale = 1; int maxScale = 1;
for (int i = 0; i < window->wl.monitorsCount; i++) for (int i = 0; i < window->wl.scaleCount; i++)
maxScale = _glfw_max(window->wl.monitors[i]->wl.scale, maxScale); maxScale = _glfw_max(window->wl.scales[i].factor, maxScale);
// Only change the framebuffer size if the scale changed. // Only change the framebuffer size if the scale changed.
if (window->wl.scale != maxScale) if (window->wl.contentScale != maxScale)
{ {
window->wl.scale = maxScale; window->wl.contentScale = maxScale;
wl_surface_set_buffer_scale(window->wl.surface, maxScale); wl_surface_set_buffer_scale(window->wl.surface, maxScale);
_glfwInputWindowContentScale(window, maxScale, maxScale); _glfwInputWindowContentScale(window, maxScale, maxScale);
resizeWindow(window); resizeWindow(window);
if (window->wl.visible)
_glfwInputWindowDamage(window);
} }
} }
@ -365,18 +374,25 @@ static void surfaceHandleEnter(void* userData,
struct wl_surface* surface, struct wl_surface* surface,
struct wl_output* output) struct wl_output* output)
{ {
if (wl_proxy_get_tag((struct wl_proxy*) output) != &_glfw.wl.tag)
return;
_GLFWwindow* window = userData; _GLFWwindow* window = userData;
_GLFWmonitor* monitor = wl_output_get_user_data(output); _GLFWmonitor* monitor = wl_output_get_user_data(output);
if (!window || !monitor)
return;
if (window->wl.monitorsCount + 1 > window->wl.monitorsSize) if (window->wl.scaleCount + 1 > window->wl.scaleSize)
{ {
++window->wl.monitorsSize; window->wl.scaleSize++;
window->wl.monitors = window->wl.scales =
_glfw_realloc(window->wl.monitors, _glfw_realloc(window->wl.scales,
window->wl.monitorsSize * sizeof(_GLFWmonitor*)); window->wl.scaleSize * sizeof(_GLFWscaleWayland));
} }
window->wl.monitors[window->wl.monitorsCount++] = monitor; window->wl.scaleCount++;
window->wl.scales[window->wl.scaleCount - 1].factor = monitor->wl.contentScale;
window->wl.scales[window->wl.scaleCount - 1].output = output;
_glfwUpdateContentScaleWayland(window); _glfwUpdateContentScaleWayland(window);
} }
@ -385,18 +401,20 @@ static void surfaceHandleLeave(void* userData,
struct wl_surface* surface, struct wl_surface* surface,
struct wl_output* output) struct wl_output* output)
{ {
_GLFWwindow* window = userData; if (wl_proxy_get_tag((struct wl_proxy*) output) != &_glfw.wl.tag)
_GLFWmonitor* monitor = wl_output_get_user_data(output); return;
GLFWbool found = GLFW_FALSE;
for (int i = 0; i < window->wl.monitorsCount - 1; ++i) _GLFWwindow* window = userData;
for (int i = 0; i < window->wl.scaleCount; i++)
{ {
if (monitor == window->wl.monitors[i]) if (window->wl.scales[i].output == output)
found = GLFW_TRUE; {
if (found) window->wl.scales[i] = window->wl.scales[window->wl.scaleCount - 1];
window->wl.monitors[i] = window->wl.monitors[i + 1]; window->wl.scaleCount--;
break;
}
} }
window->wl.monitors[--window->wl.monitorsCount] = NULL;
_glfwUpdateContentScaleWayland(window); _glfwUpdateContentScaleWayland(window);
} }
@ -429,7 +447,12 @@ static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)
// //
static void acquireMonitor(_GLFWwindow* window) static void acquireMonitor(_GLFWwindow* window)
{ {
if (window->wl.xdg.toplevel) if (window->wl.libdecor.frame)
{
libdecor_frame_set_fullscreen(window->wl.libdecor.frame,
window->monitor->wl.output);
}
else if (window->wl.xdg.toplevel)
{ {
xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel, xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel,
window->monitor->wl.output); window->monitor->wl.output);
@ -445,12 +468,15 @@ static void acquireMonitor(_GLFWwindow* window)
// //
static void releaseMonitor(_GLFWwindow* window) static void releaseMonitor(_GLFWwindow* window)
{ {
if (window->wl.xdg.toplevel) if (window->wl.libdecor.frame)
libdecor_frame_unset_fullscreen(window->wl.libdecor.frame);
else if (window->wl.xdg.toplevel)
xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel); xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
setIdleInhibitor(window, GLFW_FALSE); setIdleInhibitor(window, GLFW_FALSE);
if (window->wl.xdg.decorationMode != ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE) if (!window->wl.libdecor.frame &&
window->wl.xdg.decorationMode != ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE)
{ {
if (window->decorated) if (window->decorated)
createFallbackDecorations(window); createFallbackDecorations(window);
@ -593,7 +619,190 @@ static const struct xdg_surface_listener xdgSurfaceListener =
xdgSurfaceHandleConfigure xdgSurfaceHandleConfigure
}; };
static GLFWbool createShellObjects(_GLFWwindow* window) void libdecorFrameHandleConfigure(struct libdecor_frame* frame,
struct libdecor_configuration* config,
void* userData)
{
_GLFWwindow* window = userData;
int width, height;
enum libdecor_window_state windowState;
GLFWbool fullscreen, activated, maximized;
if (libdecor_configuration_get_window_state(config, &windowState))
{
fullscreen = (windowState & LIBDECOR_WINDOW_STATE_FULLSCREEN) != 0;
activated = (windowState & LIBDECOR_WINDOW_STATE_ACTIVE) != 0;
maximized = (windowState & LIBDECOR_WINDOW_STATE_MAXIMIZED) != 0;
}
else
{
fullscreen = window->wl.fullscreen;
activated = window->wl.activated;
maximized = window->wl.maximized;
}
if (!libdecor_configuration_get_content_size(config, frame, &width, &height))
{
width = window->wl.width;
height = window->wl.height;
}
if (!maximized && !fullscreen)
{
if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)
{
const float aspectRatio = (float) width / (float) height;
const float targetRatio = (float) window->numer / (float) window->denom;
if (aspectRatio < targetRatio)
height = width / targetRatio;
else if (aspectRatio > targetRatio)
width = height * targetRatio;
}
}
struct libdecor_state* frameState = libdecor_state_new(width, height);
libdecor_frame_commit(frame, frameState, config);
libdecor_state_free(frameState);
if (window->wl.activated != activated)
{
window->wl.activated = activated;
if (!window->wl.activated)
{
if (window->monitor && window->autoIconify)
libdecor_frame_set_minimized(window->wl.libdecor.frame);
}
}
if (window->wl.maximized != maximized)
{
window->wl.maximized = maximized;
_glfwInputWindowMaximize(window, window->wl.maximized);
}
window->wl.fullscreen = fullscreen;
GLFWbool damaged = GLFW_FALSE;
if (!window->wl.visible)
{
window->wl.visible = GLFW_TRUE;
damaged = GLFW_TRUE;
}
if (width != window->wl.width || height != window->wl.height)
{
window->wl.width = width;
window->wl.height = height;
resizeWindow(window);
_glfwInputWindowSize(window, width, height);
damaged = GLFW_TRUE;
}
if (damaged)
_glfwInputWindowDamage(window);
else
wl_surface_commit(window->wl.surface);
}
void libdecorFrameHandleClose(struct libdecor_frame* frame, void* userData)
{
_GLFWwindow* window = userData;
_glfwInputWindowCloseRequest(window);
}
void libdecorFrameHandleCommit(struct libdecor_frame* frame, void* userData)
{
_GLFWwindow* window = userData;
wl_surface_commit(window->wl.surface);
}
void libdecorFrameHandleDismissPopup(struct libdecor_frame* frame,
const char* seatName,
void* userData)
{
}
static const struct libdecor_frame_interface libdecorFrameInterface =
{
libdecorFrameHandleConfigure,
libdecorFrameHandleClose,
libdecorFrameHandleCommit,
libdecorFrameHandleDismissPopup
};
static GLFWbool createLibdecorFrame(_GLFWwindow* window)
{
window->wl.libdecor.frame = libdecor_decorate(_glfw.wl.libdecor.context,
window->wl.surface,
&libdecorFrameInterface,
window);
if (!window->wl.libdecor.frame)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to create libdecor frame");
return GLFW_FALSE;
}
if (strlen(window->wl.appId))
libdecor_frame_set_app_id(window->wl.libdecor.frame, window->wl.appId);
if (strlen(window->wl.title))
libdecor_frame_set_title(window->wl.libdecor.frame, window->wl.title);
if (window->minwidth != GLFW_DONT_CARE &&
window->minheight != GLFW_DONT_CARE)
{
libdecor_frame_set_min_content_size(window->wl.libdecor.frame,
window->minwidth,
window->minheight);
}
if (window->maxwidth != GLFW_DONT_CARE &&
window->maxheight != GLFW_DONT_CARE)
{
libdecor_frame_set_max_content_size(window->wl.libdecor.frame,
window->maxwidth,
window->maxheight);
}
if (!window->resizable)
{
libdecor_frame_unset_capabilities(window->wl.libdecor.frame,
LIBDECOR_ACTION_RESIZE);
}
if (window->monitor)
{
// HACK: Allow libdecor to finish initialization of itself and its
// plugin so it will create the xdg_toplevel for the frame
// This needs to exist when setting the frame to fullscreen
while (!libdecor_frame_get_xdg_toplevel(window->wl.libdecor.frame))
_glfwWaitEventsWayland();
libdecor_frame_set_fullscreen(window->wl.libdecor.frame,
window->monitor->wl.output);
setIdleInhibitor(window, GLFW_TRUE);
}
else
{
if (window->wl.maximized)
libdecor_frame_set_maximized(window->wl.libdecor.frame);
if (!window->decorated)
libdecor_frame_set_visibility(window->wl.libdecor.frame, false);
setIdleInhibitor(window, GLFW_FALSE);
}
libdecor_frame_map(window->wl.libdecor.frame);
wl_display_roundtrip(_glfw.wl.display);
return GLFW_TRUE;
}
static GLFWbool createXdgShellObjects(_GLFWwindow* window)
{ {
window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase, window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,
window->wl.surface); window->wl.surface);
@ -633,30 +842,30 @@ static GLFWbool createShellObjects(_GLFWwindow* window)
xdg_toplevel_set_maximized(window->wl.xdg.toplevel); xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
setIdleInhibitor(window, GLFW_FALSE); setIdleInhibitor(window, GLFW_FALSE);
}
if (_glfw.wl.decorationManager) if (_glfw.wl.decorationManager)
{ {
window->wl.xdg.decoration = window->wl.xdg.decoration =
zxdg_decoration_manager_v1_get_toplevel_decoration( zxdg_decoration_manager_v1_get_toplevel_decoration(
_glfw.wl.decorationManager, window->wl.xdg.toplevel); _glfw.wl.decorationManager, window->wl.xdg.toplevel);
zxdg_toplevel_decoration_v1_add_listener(window->wl.xdg.decoration, zxdg_toplevel_decoration_v1_add_listener(window->wl.xdg.decoration,
&xdgDecorationListener, &xdgDecorationListener,
window); window);
uint32_t mode; uint32_t mode;
if (window->decorated) if (window->decorated)
mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE; mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
else
mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, mode);
}
else else
{ mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
if (window->decorated)
createFallbackDecorations(window); zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, mode);
} }
else
{
if (window->decorated && !window->monitor)
createFallbackDecorations(window);
} }
if (window->minwidth != GLFW_DONT_CARE && window->minheight != GLFW_DONT_CARE) if (window->minwidth != GLFW_DONT_CARE && window->minheight != GLFW_DONT_CARE)
@ -689,14 +898,27 @@ static GLFWbool createShellObjects(_GLFWwindow* window)
wl_surface_commit(window->wl.surface); wl_surface_commit(window->wl.surface);
wl_display_roundtrip(_glfw.wl.display); wl_display_roundtrip(_glfw.wl.display);
return GLFW_TRUE; return GLFW_TRUE;
} }
static GLFWbool createShellObjects(_GLFWwindow* window)
{
if (_glfw.wl.libdecor.context)
{
if (createLibdecorFrame(window))
return GLFW_TRUE;
}
return createXdgShellObjects(window);
}
static void destroyShellObjects(_GLFWwindow* window) static void destroyShellObjects(_GLFWwindow* window)
{ {
destroyFallbackDecorations(window); destroyFallbackDecorations(window);
if (window->wl.libdecor.frame)
libdecor_frame_unref(window->wl.libdecor.frame);
if (window->wl.xdg.decoration) if (window->wl.xdg.decoration)
zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration); zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);
@ -706,6 +928,7 @@ static void destroyShellObjects(_GLFWwindow* window)
if (window->wl.xdg.surface) if (window->wl.xdg.surface)
xdg_surface_destroy(window->wl.xdg.surface); xdg_surface_destroy(window->wl.xdg.surface);
window->wl.libdecor.frame = NULL;
window->wl.xdg.decoration = NULL; window->wl.xdg.decoration = NULL;
window->wl.xdg.decorationMode = 0; window->wl.xdg.decorationMode = 0;
window->wl.xdg.toplevel = NULL; window->wl.xdg.toplevel = NULL;
@ -723,15 +946,14 @@ static GLFWbool createNativeSurface(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
wl_proxy_set_tag((struct wl_proxy*) window->wl.surface, &_glfw.wl.tag);
wl_surface_add_listener(window->wl.surface, wl_surface_add_listener(window->wl.surface,
&surfaceListener, &surfaceListener,
window); window);
wl_surface_set_user_data(window->wl.surface, window);
window->wl.width = wndconfig->width; window->wl.width = wndconfig->width;
window->wl.height = wndconfig->height; window->wl.height = wndconfig->height;
window->wl.scale = 1; window->wl.contentScale = 1;
window->wl.title = _glfw_strdup(wndconfig->title); window->wl.title = _glfw_strdup(wndconfig->title);
window->wl.appId = _glfw_strdup(wndconfig->wl.appId); window->wl.appId = _glfw_strdup(wndconfig->wl.appId);
@ -758,7 +980,7 @@ static void setCursorImage(_GLFWwindow* window,
buffer = cursorWayland->buffer; buffer = cursorWayland->buffer;
else else
{ {
if (window->wl.scale > 1 && cursorWayland->cursorHiDPI) if (window->wl.contentScale > 1 && cursorWayland->cursorHiDPI)
{ {
wlCursor = cursorWayland->cursorHiDPI; wlCursor = cursorWayland->cursorHiDPI;
scale = 2; scale = 2;
@ -794,7 +1016,7 @@ static void incrementCursorImage(_GLFWwindow* window)
{ {
_GLFWcursor* cursor; _GLFWcursor* cursor;
if (!window || window->wl.decorations.focus != mainWindow) if (!window || window->wl.decorations.focus != GLFW_MAIN_WINDOW)
return; return;
cursor = window->wl.currentCursor; cursor = window->wl.currentCursor;
@ -873,14 +1095,23 @@ static void inputText(_GLFWwindow* window, uint32_t scancode)
static void handleEvents(double* timeout) static void handleEvents(double* timeout)
{ {
#if defined(GLFW_BUILD_LINUX_JOYSTICK)
if (_glfw.joysticksInitialized)
_glfwDetectJoystickConnectionLinux();
#endif
GLFWbool event = GLFW_FALSE; GLFWbool event = GLFW_FALSE;
struct pollfd fds[] = struct pollfd fds[4] =
{ {
{ wl_display_get_fd(_glfw.wl.display), POLLIN }, { wl_display_get_fd(_glfw.wl.display), POLLIN },
{ _glfw.wl.keyRepeatTimerfd, POLLIN }, { _glfw.wl.keyRepeatTimerfd, POLLIN },
{ _glfw.wl.cursorTimerfd, POLLIN }, { _glfw.wl.cursorTimerfd, POLLIN },
{ -1, POLLIN }
}; };
if (_glfw.wl.libdecor.context)
fds[3].fd = libdecor_get_fd(_glfw.wl.libdecor.context);
while (!event) while (!event)
{ {
while (wl_display_prepare_read(_glfw.wl.display) != 0) while (wl_display_prepare_read(_glfw.wl.display) != 0)
@ -902,7 +1133,7 @@ static void handleEvents(double* timeout)
return; return;
} }
if (!_glfwPollPOSIX(fds, 3, timeout)) if (!_glfwPollPOSIX(fds, sizeof(fds) / sizeof(fds[0]), timeout))
{ {
wl_display_cancel_read(_glfw.wl.display); wl_display_cancel_read(_glfw.wl.display);
return; return;
@ -947,6 +1178,9 @@ static void handleEvents(double* timeout)
event = GLFW_TRUE; event = GLFW_TRUE;
} }
} }
if (fds[3].revents & POLLIN)
libdecor_dispatch(_glfw.wl.libdecor.context, 0);
} }
} }
@ -1014,40 +1248,6 @@ static char* readDataOfferAsString(struct wl_data_offer* offer, const char* mime
return string; return string;
} }
static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface,
_GLFWdecorationSideWayland* which)
{
_GLFWdecorationSideWayland focus;
_GLFWwindow* window = _glfw.windowListHead;
if (!which)
which = &focus;
while (window)
{
if (surface == window->wl.decorations.top.surface)
{
*which = topDecoration;
break;
}
if (surface == window->wl.decorations.left.surface)
{
*which = leftDecoration;
break;
}
if (surface == window->wl.decorations.right.surface)
{
*which = rightDecoration;
break;
}
if (surface == window->wl.decorations.bottom.surface)
{
*which = bottomDecoration;
break;
}
window = window->next;
}
return window;
}
static void pointerHandleEnter(void* userData, static void pointerHandleEnter(void* userData,
struct wl_pointer* pointer, struct wl_pointer* pointer,
uint32_t serial, uint32_t serial,
@ -1059,16 +1259,22 @@ static void pointerHandleEnter(void* userData,
if (!surface) if (!surface)
return; return;
_GLFWdecorationSideWayland focus = mainWindow; if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
_GLFWwindow* window = wl_surface_get_user_data(surface); return;
if (!window)
{ _GLFWwindow* window = wl_surface_get_user_data(surface);
window = findWindowFromDecorationSurface(surface, &focus);
if (!window) if (surface == window->wl.decorations.top.surface)
return; window->wl.decorations.focus = GLFW_TOP_DECORATION;
} else if (surface == window->wl.decorations.left.surface)
window->wl.decorations.focus = GLFW_LEFT_DECORATION;
else if (surface == window->wl.decorations.right.surface)
window->wl.decorations.focus = GLFW_RIGHT_DECORATION;
else if (surface == window->wl.decorations.bottom.surface)
window->wl.decorations.focus = GLFW_BOTTOM_DECORATION;
else
window->wl.decorations.focus = GLFW_MAIN_WINDOW;
window->wl.decorations.focus = focus;
_glfw.wl.serial = serial; _glfw.wl.serial = serial;
_glfw.wl.pointerEnterSerial = serial; _glfw.wl.pointerEnterSerial = serial;
_glfw.wl.pointerFocus = window; _glfw.wl.pointerFocus = window;
@ -1084,8 +1290,13 @@ static void pointerHandleLeave(void* userData,
uint32_t serial, uint32_t serial,
struct wl_surface* surface) struct wl_surface* surface)
{ {
_GLFWwindow* window = _glfw.wl.pointerFocus; if (!surface)
return;
if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
return;
_GLFWwindow* window = _glfw.wl.pointerFocus;
if (!window) if (!window)
return; return;
@ -1106,7 +1317,7 @@ static void setCursor(_GLFWwindow* window, const char* name)
struct wl_cursor_theme* theme = _glfw.wl.cursorTheme; struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;
int scale = 1; int scale = 1;
if (window->wl.scale > 1 && _glfw.wl.cursorThemeHiDPI) if (window->wl.contentScale > 1 && _glfw.wl.cursorThemeHiDPI)
{ {
// We only support up to scale=2 for now, since libwayland-cursor // We only support up to scale=2 for now, since libwayland-cursor
// requires us to load a different theme for each size. // requires us to load a different theme for each size.
@ -1164,29 +1375,29 @@ static void pointerHandleMotion(void* userData,
switch (window->wl.decorations.focus) switch (window->wl.decorations.focus)
{ {
case mainWindow: case GLFW_MAIN_WINDOW:
_glfw.wl.cursorPreviousName = NULL; _glfw.wl.cursorPreviousName = NULL;
_glfwInputCursorPos(window, x, y); _glfwInputCursorPos(window, x, y);
return; return;
case topDecoration: case GLFW_TOP_DECORATION:
if (y < GLFW_BORDER_SIZE) if (y < GLFW_BORDER_SIZE)
cursorName = "n-resize"; cursorName = "n-resize";
else else
cursorName = "left_ptr"; cursorName = "left_ptr";
break; break;
case leftDecoration: case GLFW_LEFT_DECORATION:
if (y < GLFW_BORDER_SIZE) if (y < GLFW_BORDER_SIZE)
cursorName = "nw-resize"; cursorName = "nw-resize";
else else
cursorName = "w-resize"; cursorName = "w-resize";
break; break;
case rightDecoration: case GLFW_RIGHT_DECORATION:
if (y < GLFW_BORDER_SIZE) if (y < GLFW_BORDER_SIZE)
cursorName = "ne-resize"; cursorName = "ne-resize";
else else
cursorName = "e-resize"; cursorName = "e-resize";
break; break;
case bottomDecoration: case GLFW_BOTTOM_DECORATION:
if (x < GLFW_BORDER_SIZE) if (x < GLFW_BORDER_SIZE)
cursorName = "sw-resize"; cursorName = "sw-resize";
else if (x > window->wl.width + GLFW_BORDER_SIZE) else if (x > window->wl.width + GLFW_BORDER_SIZE)
@ -1218,27 +1429,27 @@ static void pointerHandleButton(void* userData,
{ {
switch (window->wl.decorations.focus) switch (window->wl.decorations.focus)
{ {
case mainWindow: case GLFW_MAIN_WINDOW:
break; break;
case topDecoration: case GLFW_TOP_DECORATION:
if (window->wl.cursorPosY < GLFW_BORDER_SIZE) if (window->wl.cursorPosY < GLFW_BORDER_SIZE)
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 GLFW_LEFT_DECORATION:
if (window->wl.cursorPosY < GLFW_BORDER_SIZE) if (window->wl.cursorPosY < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
else else
edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT; edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
break; break;
case rightDecoration: case GLFW_RIGHT_DECORATION:
if (window->wl.cursorPosY < GLFW_BORDER_SIZE) if (window->wl.cursorPosY < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
else else
edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
break; break;
case bottomDecoration: case GLFW_BOTTOM_DECORATION:
if (window->wl.cursorPosX < GLFW_BORDER_SIZE) if (window->wl.cursorPosX < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
else if (window->wl.cursorPosX > window->wl.width + GLFW_BORDER_SIZE) else if (window->wl.cursorPosX > window->wl.width + GLFW_BORDER_SIZE)
@ -1258,7 +1469,8 @@ static void pointerHandleButton(void* userData,
} }
else if (button == BTN_RIGHT) else if (button == BTN_RIGHT)
{ {
if (window->wl.decorations.focus != mainWindow && window->wl.xdg.toplevel) if (window->wl.decorations.focus != GLFW_MAIN_WINDOW &&
window->wl.xdg.toplevel)
{ {
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel, xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
_glfw.wl.seat, serial, _glfw.wl.seat, serial,
@ -1269,7 +1481,7 @@ static void pointerHandleButton(void* userData,
} }
// Dont pass the button to the user if it was related to a decoration. // Dont pass the button to the user if it was related to a decoration.
if (window->wl.decorations.focus != mainWindow) if (window->wl.decorations.focus != GLFW_MAIN_WINDOW)
return; return;
_glfw.wl.serial = serial; _glfw.wl.serial = serial;
@ -1423,13 +1635,12 @@ static void keyboardHandleEnter(void* userData,
if (!surface) if (!surface)
return; return;
if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
return;
_GLFWwindow* window = wl_surface_get_user_data(surface); _GLFWwindow* window = wl_surface_get_user_data(surface);
if (!window) if (surface != window->wl.surface)
{ return;
window = findWindowFromDecorationSurface(surface, NULL);
if (!window)
return;
}
_glfw.wl.serial = serial; _glfw.wl.serial = serial;
_glfw.wl.keyboardFocus = window; _glfw.wl.keyboardFocus = window;
@ -1677,9 +1888,12 @@ static void dataDeviceHandleEnter(void* userData,
_GLFWwindow* window = NULL; _GLFWwindow* window = NULL;
if (surface) if (surface)
window = wl_surface_get_user_data(surface); {
if (wl_proxy_get_tag((struct wl_proxy*) surface) == &_glfw.wl.tag)
window = wl_surface_get_user_data(surface);
}
if (window && _glfw.wl.offers[i].text_uri_list) if (surface == window->wl.surface && _glfw.wl.offers[i].text_uri_list)
{ {
_glfw.wl.dragOffer = offer; _glfw.wl.dragOffer = offer;
_glfw.wl.dragFocus = window; _glfw.wl.dragFocus = window;
@ -1692,6 +1906,9 @@ static void dataDeviceHandleEnter(void* userData,
} }
} }
if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
return;
if (_glfw.wl.dragOffer) if (_glfw.wl.dragOffer)
wl_data_offer_accept(offer, serial, "text/uri-list"); wl_data_offer_accept(offer, serial, "text/uri-list");
else else
@ -1890,7 +2107,7 @@ void _glfwDestroyWindowWayland(_GLFWwindow* window)
_glfw_free(window->wl.title); _glfw_free(window->wl.title);
_glfw_free(window->wl.appId); _glfw_free(window->wl.appId);
_glfw_free(window->wl.monitors); _glfw_free(window->wl.scales);
} }
void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title) void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title)
@ -1899,7 +2116,9 @@ void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title)
_glfw_free(window->wl.title); _glfw_free(window->wl.title);
window->wl.title = copy; window->wl.title = copy;
if (window->wl.xdg.toplevel) if (window->wl.libdecor.frame)
libdecor_frame_set_title(window->wl.libdecor.frame, title);
else if (window->wl.xdg.toplevel)
xdg_toplevel_set_title(window->wl.xdg.toplevel, title); xdg_toplevel_set_title(window->wl.xdg.toplevel, title);
} }
@ -1975,6 +2194,16 @@ void _glfwSetWindowSizeWayland(_GLFWwindow* window, int width, int height)
window->wl.width = width; window->wl.width = width;
window->wl.height = height; window->wl.height = height;
resizeWindow(window); resizeWindow(window);
if (window->wl.libdecor.frame)
{
struct libdecor_state* frameState = libdecor_state_new(width, height);
libdecor_frame_commit(window->wl.libdecor.frame, frameState, NULL);
libdecor_state_free(frameState);
}
if (window->wl.visible)
_glfwInputWindowDamage(window);
} }
} }
@ -1982,7 +2211,20 @@ void _glfwSetWindowSizeLimitsWayland(_GLFWwindow* window,
int minwidth, int minheight, int minwidth, int minheight,
int maxwidth, int maxheight) int maxwidth, int maxheight)
{ {
if (window->wl.xdg.toplevel) if (window->wl.libdecor.frame)
{
if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
minwidth = minheight = 0;
if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)
maxwidth = maxheight = 0;
libdecor_frame_set_min_content_size(window->wl.libdecor.frame,
minwidth, minheight);
libdecor_frame_set_max_content_size(window->wl.libdecor.frame,
maxwidth, maxheight);
}
else if (window->wl.xdg.toplevel)
{ {
if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE) if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
minwidth = minheight = 0; minwidth = minheight = 0;
@ -2017,16 +2259,35 @@ void _glfwSetWindowAspectRatioWayland(_GLFWwindow* window, int numer, int denom)
if (window->wl.maximized || window->wl.fullscreen) if (window->wl.maximized || window->wl.fullscreen)
return; return;
int width = window->wl.width, height = window->wl.height;
if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE) if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE)
{ {
const float aspectRatio = (float) window->wl.width / (float) window->wl.height; const float aspectRatio = (float) width / (float) height;
const float targetRatio = (float) numer / (float) denom; const float targetRatio = (float) numer / (float) denom;
if (aspectRatio < targetRatio) if (aspectRatio < targetRatio)
window->wl.height = window->wl.width / targetRatio; height /= targetRatio;
else if (aspectRatio > targetRatio) else if (aspectRatio > targetRatio)
window->wl.width = window->wl.height * targetRatio; width *= targetRatio;
}
if (width != window->wl.width || height != window->wl.height)
{
window->wl.width = width;
window->wl.height = height;
resizeWindow(window); resizeWindow(window);
if (window->wl.libdecor.frame)
{
struct libdecor_state* frameState = libdecor_state_new(width, height);
libdecor_frame_commit(window->wl.libdecor.frame, frameState, NULL);
libdecor_state_free(frameState);
}
_glfwInputWindowSize(window, width, height);
if (window->wl.visible)
_glfwInputWindowDamage(window);
} }
} }
@ -2034,16 +2295,16 @@ void _glfwGetFramebufferSizeWayland(_GLFWwindow* window, int* width, int* height
{ {
_glfwGetWindowSizeWayland(window, width, height); _glfwGetWindowSizeWayland(window, width, height);
if (width) if (width)
*width *= window->wl.scale; *width *= window->wl.contentScale;
if (height) if (height)
*height *= window->wl.scale; *height *= window->wl.contentScale;
} }
void _glfwGetWindowFrameSizeWayland(_GLFWwindow* window, void _glfwGetWindowFrameSizeWayland(_GLFWwindow* window,
int* left, int* top, int* left, int* top,
int* right, int* bottom) int* right, int* bottom)
{ {
if (window->decorated && !window->monitor && window->wl.decorations.top.surface) if (window->wl.decorations.top.surface)
{ {
if (top) if (top)
*top = GLFW_CAPTION_HEIGHT; *top = GLFW_CAPTION_HEIGHT;
@ -2060,14 +2321,16 @@ void _glfwGetWindowContentScaleWayland(_GLFWwindow* window,
float* xscale, float* yscale) float* xscale, float* yscale)
{ {
if (xscale) if (xscale)
*xscale = (float) window->wl.scale; *xscale = (float) window->wl.contentScale;
if (yscale) if (yscale)
*yscale = (float) window->wl.scale; *yscale = (float) window->wl.contentScale;
} }
void _glfwIconifyWindowWayland(_GLFWwindow* window) void _glfwIconifyWindowWayland(_GLFWwindow* window)
{ {
if (window->wl.xdg.toplevel) if (window->wl.libdecor.frame)
libdecor_frame_set_minimized(window->wl.libdecor.frame);
else if (window->wl.xdg.toplevel)
xdg_toplevel_set_minimized(window->wl.xdg.toplevel); xdg_toplevel_set_minimized(window->wl.xdg.toplevel);
} }
@ -2084,7 +2347,9 @@ void _glfwRestoreWindowWayland(_GLFWwindow* window)
if (window->wl.maximized) if (window->wl.maximized)
{ {
if (window->wl.xdg.toplevel) if (window->wl.libdecor.frame)
libdecor_frame_unset_maximized(window->wl.libdecor.frame);
else if (window->wl.xdg.toplevel)
xdg_toplevel_unset_maximized(window->wl.xdg.toplevel); xdg_toplevel_unset_maximized(window->wl.xdg.toplevel);
else else
window->wl.maximized = GLFW_FALSE; window->wl.maximized = GLFW_FALSE;
@ -2094,7 +2359,9 @@ void _glfwRestoreWindowWayland(_GLFWwindow* window)
void _glfwMaximizeWindowWayland(_GLFWwindow* window) void _glfwMaximizeWindowWayland(_GLFWwindow* window)
{ {
if (window->wl.xdg.toplevel) if (window->wl.libdecor.frame)
libdecor_frame_set_maximized(window->wl.libdecor.frame);
else if (window->wl.xdg.toplevel)
xdg_toplevel_set_maximized(window->wl.xdg.toplevel); xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
else else
window->wl.maximized = GLFW_TRUE; window->wl.maximized = GLFW_TRUE;
@ -2102,7 +2369,7 @@ void _glfwMaximizeWindowWayland(_GLFWwindow* window)
void _glfwShowWindowWayland(_GLFWwindow* window) void _glfwShowWindowWayland(_GLFWwindow* window)
{ {
if (!window->wl.xdg.toplevel) if (!window->wl.libdecor.frame && !window->wl.xdg.toplevel)
{ {
// NOTE: The XDG surface and role are created here so command-line applications // 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 // with off-screen windows do not appear in for example the Unity dock
@ -2194,14 +2461,34 @@ GLFWbool _glfwFramebufferTransparentWayland(_GLFWwindow* window)
void _glfwSetWindowResizableWayland(_GLFWwindow* window, GLFWbool enabled) void _glfwSetWindowResizableWayland(_GLFWwindow* window, GLFWbool enabled)
{ {
// TODO if (window->wl.libdecor.frame)
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, {
"Wayland: Window attribute setting not implemented yet"); if (enabled)
{
libdecor_frame_set_capabilities(window->wl.libdecor.frame,
LIBDECOR_ACTION_RESIZE);
}
else
{
libdecor_frame_unset_capabilities(window->wl.libdecor.frame,
LIBDECOR_ACTION_RESIZE);
}
}
else
{
// TODO
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED,
"Wayland: Window attribute setting not implemented yet");
}
} }
void _glfwSetWindowDecoratedWayland(_GLFWwindow* window, GLFWbool enabled) void _glfwSetWindowDecoratedWayland(_GLFWwindow* window, GLFWbool enabled)
{ {
if (window->wl.xdg.decoration) if (window->wl.libdecor.frame)
{
libdecor_frame_set_visibility(window->wl.libdecor.frame, enabled);
}
else if (window->wl.xdg.decoration)
{ {
uint32_t mode; uint32_t mode;
@ -2212,7 +2499,7 @@ void _glfwSetWindowDecoratedWayland(_GLFWwindow* window, GLFWbool enabled)
zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, mode); zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, mode);
} }
else else if (window->wl.xdg.toplevel)
{ {
if (enabled) if (enabled)
createFallbackDecorations(window); createFallbackDecorations(window);
@ -2622,8 +2909,11 @@ void _glfwSetCursorWayland(_GLFWwindow* window, _GLFWcursor* cursor)
// If we're not in the correct window just save the cursor // If we're not in the correct window just save the cursor
// the next time the pointer enters the window the cursor will change // the next time the pointer enters the window the cursor will change
if (window != _glfw.wl.pointerFocus || window->wl.decorations.focus != mainWindow) if (window != _glfw.wl.pointerFocus ||
window->wl.decorations.focus != GLFW_MAIN_WINDOW)
{
return; return;
}
// Update pointer lock to match cursor mode // Update pointer lock to match cursor mode
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)

View File

@ -266,9 +266,10 @@ static void list_vulkan_instance_layers(void)
for (uint32_t i = 0; i < lp_count; i++) for (uint32_t i = 0; i < lp_count; i++)
{ {
printf(" %s (spec version %u) \"%s\"\n", printf(" %s (spec version %u.%u) \"%s\"\n",
lp[i].layerName, lp[i].layerName,
lp[i].specVersion >> 22, VK_VERSION_MAJOR(lp[i].specVersion),
VK_VERSION_MINOR(lp[i].specVersion),
lp[i].description); lp[i].description);
} }
@ -286,9 +287,10 @@ static void list_vulkan_device_layers(VkInstance instance, VkPhysicalDevice devi
for (uint32_t i = 0; i < lp_count; i++) for (uint32_t i = 0; i < lp_count; i++)
{ {
printf(" %s (spec version %u) \"%s\"\n", printf(" %s (spec version %u.%u) \"%s\"\n",
lp[i].layerName, lp[i].layerName,
lp[i].specVersion >> 22, VK_VERSION_MAJOR(lp[i].specVersion),
VK_VERSION_MINOR(lp[i].specVersion),
lp[i].description); lp[i].description);
} }
@ -710,190 +712,187 @@ int main(int argc, char** argv)
glfwWindowHint(GLFW_COCOA_GRAPHICS_SWITCHING, cocoa_graphics_switching); glfwWindowHint(GLFW_COCOA_GRAPHICS_SWITCHING, cocoa_graphics_switching);
GLFWwindow* window = glfwCreateWindow(200, 200, "Version", NULL, NULL); GLFWwindow* window = glfwCreateWindow(200, 200, "Version", NULL, NULL);
if (!window) if (window)
{ {
glfwTerminate(); glfwMakeContextCurrent(window);
exit(EXIT_FAILURE); gladLoadGL(glfwGetProcAddress);
}
glfwMakeContextCurrent(window); const GLenum error = glGetError();
gladLoadGL(glfwGetProcAddress); if (error != GL_NO_ERROR)
printf("*** OpenGL error after make current: 0x%08x ***\n", error);
const GLenum error = glGetError(); // Report client API version
if (error != GL_NO_ERROR)
printf("*** OpenGL error after make current: 0x%08x ***\n", error);
// Report client API version const int client = glfwGetWindowAttrib(window, GLFW_CLIENT_API);
const int major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR);
const int minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR);
const int revision = glfwGetWindowAttrib(window, GLFW_CONTEXT_REVISION);
const int profile = glfwGetWindowAttrib(window, GLFW_OPENGL_PROFILE);
const int client = glfwGetWindowAttrib(window, GLFW_CLIENT_API); printf("%s context version string: \"%s\"\n",
const int major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR);
const int minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR);
const int revision = glfwGetWindowAttrib(window, GLFW_CONTEXT_REVISION);
const int profile = glfwGetWindowAttrib(window, GLFW_OPENGL_PROFILE);
printf("%s context version string: \"%s\"\n",
get_api_name(client),
glGetString(GL_VERSION));
printf("%s context version parsed by GLFW: %u.%u.%u\n",
get_api_name(client),
major, minor, revision);
// Report client API context properties
if (client == GLFW_OPENGL_API)
{
if (major >= 3)
{
GLint flags;
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
printf("%s context flags (0x%08x):", get_api_name(client), flags);
if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
printf(" forward-compatible");
if (flags & 2/*GL_CONTEXT_FLAG_DEBUG_BIT*/)
printf(" debug");
if (flags & GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB)
printf(" robustness");
if (flags & 8/*GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR*/)
printf(" no-error");
putchar('\n');
printf("%s context flags parsed by GLFW:", get_api_name(client));
if (glfwGetWindowAttrib(window, GLFW_OPENGL_FORWARD_COMPAT))
printf(" forward-compatible");
if (glfwGetWindowAttrib(window, GLFW_CONTEXT_DEBUG))
printf(" debug");
if (glfwGetWindowAttrib(window, GLFW_CONTEXT_ROBUSTNESS) == GLFW_LOSE_CONTEXT_ON_RESET)
printf(" robustness");
if (glfwGetWindowAttrib(window, GLFW_CONTEXT_NO_ERROR))
printf(" no-error");
putchar('\n');
}
if (major >= 4 || (major == 3 && minor >= 2))
{
GLint mask;
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
printf("%s profile mask (0x%08x): %s\n",
get_api_name(client),
mask,
get_profile_name_gl(mask));
printf("%s profile mask parsed by GLFW: %s\n",
get_api_name(client),
get_profile_name_glfw(profile));
}
if (GLAD_GL_ARB_robustness)
{
const int robustness = glfwGetWindowAttrib(window, GLFW_CONTEXT_ROBUSTNESS);
GLint strategy;
glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
printf("%s robustness strategy (0x%08x): %s\n",
get_api_name(client),
strategy,
get_strategy_name_gl(strategy));
printf("%s robustness strategy parsed by GLFW: %s\n",
get_api_name(client),
get_strategy_name_glfw(robustness));
}
}
printf("%s context renderer string: \"%s\"\n",
get_api_name(client),
glGetString(GL_RENDERER));
printf("%s context vendor string: \"%s\"\n",
get_api_name(client),
glGetString(GL_VENDOR));
if (major >= 2)
{
printf("%s context shading language version: \"%s\"\n",
get_api_name(client), get_api_name(client),
glGetString(GL_SHADING_LANGUAGE_VERSION)); glGetString(GL_VERSION));
printf("%s context version parsed by GLFW: %u.%u.%u\n",
get_api_name(client),
major, minor, revision);
// Report client API context properties
if (client == GLFW_OPENGL_API)
{
if (major >= 3)
{
GLint flags;
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
printf("%s context flags (0x%08x):", get_api_name(client), flags);
if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
printf(" forward-compatible");
if (flags & 2/*GL_CONTEXT_FLAG_DEBUG_BIT*/)
printf(" debug");
if (flags & GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB)
printf(" robustness");
if (flags & 8/*GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR*/)
printf(" no-error");
putchar('\n');
printf("%s context flags parsed by GLFW:", get_api_name(client));
if (glfwGetWindowAttrib(window, GLFW_OPENGL_FORWARD_COMPAT))
printf(" forward-compatible");
if (glfwGetWindowAttrib(window, GLFW_CONTEXT_DEBUG))
printf(" debug");
if (glfwGetWindowAttrib(window, GLFW_CONTEXT_ROBUSTNESS) == GLFW_LOSE_CONTEXT_ON_RESET)
printf(" robustness");
if (glfwGetWindowAttrib(window, GLFW_CONTEXT_NO_ERROR))
printf(" no-error");
putchar('\n');
}
if (major >= 4 || (major == 3 && minor >= 2))
{
GLint mask;
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
printf("%s profile mask (0x%08x): %s\n",
get_api_name(client),
mask,
get_profile_name_gl(mask));
printf("%s profile mask parsed by GLFW: %s\n",
get_api_name(client),
get_profile_name_glfw(profile));
}
if (GLAD_GL_ARB_robustness)
{
const int robustness = glfwGetWindowAttrib(window, GLFW_CONTEXT_ROBUSTNESS);
GLint strategy;
glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
printf("%s robustness strategy (0x%08x): %s\n",
get_api_name(client),
strategy,
get_strategy_name_gl(strategy));
printf("%s robustness strategy parsed by GLFW: %s\n",
get_api_name(client),
get_strategy_name_glfw(robustness));
}
}
printf("%s context renderer string: \"%s\"\n",
get_api_name(client),
glGetString(GL_RENDERER));
printf("%s context vendor string: \"%s\"\n",
get_api_name(client),
glGetString(GL_VENDOR));
if (major >= 2)
{
printf("%s context shading language version: \"%s\"\n",
get_api_name(client),
glGetString(GL_SHADING_LANGUAGE_VERSION));
}
printf("%s framebuffer:\n", get_api_name(client));
GLint redbits, greenbits, bluebits, alphabits, depthbits, stencilbits;
if (client == GLFW_OPENGL_API && profile == GLFW_OPENGL_CORE_PROFILE)
{
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_BACK_LEFT,
GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE,
&redbits);
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_BACK_LEFT,
GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE,
&greenbits);
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_BACK_LEFT,
GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE,
&bluebits);
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_BACK_LEFT,
GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
&alphabits);
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_DEPTH,
GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE,
&depthbits);
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_STENCIL,
GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
&stencilbits);
}
else
{
glGetIntegerv(GL_RED_BITS, &redbits);
glGetIntegerv(GL_GREEN_BITS, &greenbits);
glGetIntegerv(GL_BLUE_BITS, &bluebits);
glGetIntegerv(GL_ALPHA_BITS, &alphabits);
glGetIntegerv(GL_DEPTH_BITS, &depthbits);
glGetIntegerv(GL_STENCIL_BITS, &stencilbits);
}
printf(" red: %u green: %u blue: %u alpha: %u depth: %u stencil: %u\n",
redbits, greenbits, bluebits, alphabits, depthbits, stencilbits);
if (client == GLFW_OPENGL_ES_API ||
GLAD_GL_ARB_multisample ||
major > 1 || minor >= 3)
{
GLint samples, samplebuffers;
glGetIntegerv(GL_SAMPLES, &samples);
glGetIntegerv(GL_SAMPLE_BUFFERS, &samplebuffers);
printf(" samples: %u sample buffers: %u\n", samples, samplebuffers);
}
if (client == GLFW_OPENGL_API && profile != GLFW_OPENGL_CORE_PROFILE)
{
GLint accumredbits, accumgreenbits, accumbluebits, accumalphabits;
GLint auxbuffers;
glGetIntegerv(GL_ACCUM_RED_BITS, &accumredbits);
glGetIntegerv(GL_ACCUM_GREEN_BITS, &accumgreenbits);
glGetIntegerv(GL_ACCUM_BLUE_BITS, &accumbluebits);
glGetIntegerv(GL_ACCUM_ALPHA_BITS, &accumalphabits);
glGetIntegerv(GL_AUX_BUFFERS, &auxbuffers);
printf(" accum red: %u accum green: %u accum blue: %u accum alpha: %u aux buffers: %u\n",
accumredbits, accumgreenbits, accumbluebits, accumalphabits, auxbuffers);
}
if (list_extensions)
list_context_extensions(client, major, minor);
glfwDestroyWindow(window);
} }
printf("%s framebuffer:\n", get_api_name(client));
GLint redbits, greenbits, bluebits, alphabits, depthbits, stencilbits;
if (client == GLFW_OPENGL_API && profile == GLFW_OPENGL_CORE_PROFILE)
{
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_BACK_LEFT,
GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE,
&redbits);
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_BACK_LEFT,
GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE,
&greenbits);
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_BACK_LEFT,
GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE,
&bluebits);
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_BACK_LEFT,
GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
&alphabits);
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_DEPTH,
GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE,
&depthbits);
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_STENCIL,
GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
&stencilbits);
}
else
{
glGetIntegerv(GL_RED_BITS, &redbits);
glGetIntegerv(GL_GREEN_BITS, &greenbits);
glGetIntegerv(GL_BLUE_BITS, &bluebits);
glGetIntegerv(GL_ALPHA_BITS, &alphabits);
glGetIntegerv(GL_DEPTH_BITS, &depthbits);
glGetIntegerv(GL_STENCIL_BITS, &stencilbits);
}
printf(" red: %u green: %u blue: %u alpha: %u depth: %u stencil: %u\n",
redbits, greenbits, bluebits, alphabits, depthbits, stencilbits);
if (client == GLFW_OPENGL_ES_API ||
GLAD_GL_ARB_multisample ||
major > 1 || minor >= 3)
{
GLint samples, samplebuffers;
glGetIntegerv(GL_SAMPLES, &samples);
glGetIntegerv(GL_SAMPLE_BUFFERS, &samplebuffers);
printf(" samples: %u sample buffers: %u\n", samples, samplebuffers);
}
if (client == GLFW_OPENGL_API && profile != GLFW_OPENGL_CORE_PROFILE)
{
GLint accumredbits, accumgreenbits, accumbluebits, accumalphabits;
GLint auxbuffers;
glGetIntegerv(GL_ACCUM_RED_BITS, &accumredbits);
glGetIntegerv(GL_ACCUM_GREEN_BITS, &accumgreenbits);
glGetIntegerv(GL_ACCUM_BLUE_BITS, &accumbluebits);
glGetIntegerv(GL_ACCUM_ALPHA_BITS, &accumalphabits);
glGetIntegerv(GL_AUX_BUFFERS, &auxbuffers);
printf(" accum red: %u accum green: %u accum blue: %u accum alpha: %u aux buffers: %u\n",
accumredbits, accumgreenbits, accumbluebits, accumalphabits, auxbuffers);
}
if (list_extensions)
list_context_extensions(client, major, minor);
glfwDestroyWindow(window);
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
window = glfwCreateWindow(200, 200, "Version", NULL, NULL); window = glfwCreateWindow(200, 200, "Version", NULL, NULL);