volviewer

Volumetric Data Toy Viewer
git clone anongit@rnpnr.xyz:volviewer.git
Log | Files | Refs | Feed | LICENSE

wl_init.c (45125B)


      1 //========================================================================
      2 // GLFW 3.4 Wayland (modified for raylib) - www.glfw.org; www.raylib.com
      3 //------------------------------------------------------------------------
      4 // Copyright (c) 2014 Jonas Ã…dahl <jadahl@gmail.com>
      5 // Copyright (c) 2024 M374LX <wilsalx@gmail.com>
      6 //
      7 // This software is provided 'as-is', without any express or implied
      8 // warranty. In no event will the authors be held liable for any damages
      9 // arising from the use of this software.
     10 //
     11 // Permission is granted to anyone to use this software for any purpose,
     12 // including commercial applications, and to alter it and redistribute it
     13 // freely, subject to the following restrictions:
     14 //
     15 // 1. The origin of this software must not be misrepresented; you must not
     16 //    claim that you wrote the original software. If you use this software
     17 //    in a product, an acknowledgment in the product documentation would
     18 //    be appreciated but is not required.
     19 //
     20 // 2. Altered source versions must be plainly marked as such, and must not
     21 //    be misrepresented as being the original software.
     22 //
     23 // 3. This notice may not be removed or altered from any source
     24 //    distribution.
     25 //
     26 //========================================================================
     27 
     28 #include "internal.h"
     29 
     30 #if defined(_GLFW_WAYLAND)
     31 
     32 #include <errno.h>
     33 #include <limits.h>
     34 #include <linux/input.h>
     35 #include <stdio.h>
     36 #include <stdlib.h>
     37 #include <string.h>
     38 #include <sys/mman.h>
     39 #include <sys/timerfd.h>
     40 #include <unistd.h>
     41 #include <time.h>
     42 #include <assert.h>
     43 
     44 #include "wayland-client-protocol.h"
     45 #include "xdg-shell-client-protocol.h"
     46 #include "xdg-decoration-unstable-v1-client-protocol.h"
     47 #include "viewporter-client-protocol.h"
     48 #include "relative-pointer-unstable-v1-client-protocol.h"
     49 #include "pointer-constraints-unstable-v1-client-protocol.h"
     50 #include "fractional-scale-v1-client-protocol.h"
     51 #include "xdg-activation-v1-client-protocol.h"
     52 #include "idle-inhibit-unstable-v1-client-protocol.h"
     53 
     54 // NOTE: Versions of wayland-scanner prior to 1.17.91 named every global array of
     55 //       wl_interface pointers 'types', making it impossible to combine several unmodified
     56 //       private-code files into a single compilation unit
     57 // HACK: We override this name with a macro for each file, allowing them to coexist
     58 
     59 #define types _glfw_wayland_types
     60 #include "wayland-client-protocol-code.h"
     61 #undef types
     62 
     63 #define types _glfw_xdg_shell_types
     64 #include "xdg-shell-client-protocol-code.h"
     65 #undef types
     66 
     67 #define types _glfw_xdg_decoration_types
     68 #include "xdg-decoration-unstable-v1-client-protocol-code.h"
     69 #undef types
     70 
     71 #define types _glfw_viewporter_types
     72 #include "viewporter-client-protocol-code.h"
     73 #undef types
     74 
     75 #define types _glfw_relative_pointer_types
     76 #include "relative-pointer-unstable-v1-client-protocol-code.h"
     77 #undef types
     78 
     79 #define types _glfw_pointer_constraints_types
     80 #include "pointer-constraints-unstable-v1-client-protocol-code.h"
     81 #undef types
     82 
     83 #define types _glfw_fractional_scale_types
     84 #include "fractional-scale-v1-client-protocol-code.h"
     85 #undef types
     86 
     87 #define types _glfw_xdg_activation_types
     88 #include "xdg-activation-v1-client-protocol-code.h"
     89 #undef types
     90 
     91 #define types _glfw_idle_inhibit_types
     92 #include "idle-inhibit-unstable-v1-client-protocol-code.h"
     93 #undef types
     94 
     95 static void wmBaseHandlePing(void* userData,
     96                              struct xdg_wm_base* wmBase,
     97                              uint32_t serial)
     98 {
     99     xdg_wm_base_pong(wmBase, serial);
    100 }
    101 
    102 static const struct xdg_wm_base_listener wmBaseListener =
    103 {
    104     wmBaseHandlePing
    105 };
    106 
    107 static void registryHandleGlobal(void* userData,
    108                                  struct wl_registry* registry,
    109                                  uint32_t name,
    110                                  const char* interface,
    111                                  uint32_t version)
    112 {
    113     if (strcmp(interface, "wl_compositor") == 0)
    114     {
    115         _glfw.wl.compositor =
    116             wl_registry_bind(registry, name, &wl_compositor_interface,
    117                              _glfw_min(3, version));
    118     }
    119     else if (strcmp(interface, "wl_subcompositor") == 0)
    120     {
    121         _glfw.wl.subcompositor =
    122             wl_registry_bind(registry, name, &wl_subcompositor_interface, 1);
    123     }
    124     else if (strcmp(interface, "wl_shm") == 0)
    125     {
    126         _glfw.wl.shm =
    127             wl_registry_bind(registry, name, &wl_shm_interface, 1);
    128     }
    129     else if (strcmp(interface, "wl_output") == 0)
    130     {
    131         _glfwAddOutputWayland(name, version);
    132     }
    133     else if (strcmp(interface, "wl_seat") == 0)
    134     {
    135         if (!_glfw.wl.seat)
    136         {
    137             _glfw.wl.seat =
    138                 wl_registry_bind(registry, name, &wl_seat_interface,
    139                                  _glfw_min(4, version));
    140             _glfwAddSeatListenerWayland(_glfw.wl.seat);
    141         }
    142     }
    143     else if (strcmp(interface, "wl_data_device_manager") == 0)
    144     {
    145         if (!_glfw.wl.dataDeviceManager)
    146         {
    147             _glfw.wl.dataDeviceManager =
    148                 wl_registry_bind(registry, name,
    149                                  &wl_data_device_manager_interface, 1);
    150         }
    151     }
    152     else if (strcmp(interface, "xdg_wm_base") == 0)
    153     {
    154         _glfw.wl.wmBase =
    155             wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
    156         xdg_wm_base_add_listener(_glfw.wl.wmBase, &wmBaseListener, NULL);
    157     }
    158     else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0)
    159     {
    160         _glfw.wl.decorationManager =
    161             wl_registry_bind(registry, name,
    162                              &zxdg_decoration_manager_v1_interface,
    163                              1);
    164     }
    165     else if (strcmp(interface, "wp_viewporter") == 0)
    166     {
    167         _glfw.wl.viewporter =
    168             wl_registry_bind(registry, name, &wp_viewporter_interface, 1);
    169     }
    170     else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0)
    171     {
    172         _glfw.wl.relativePointerManager =
    173             wl_registry_bind(registry, name,
    174                              &zwp_relative_pointer_manager_v1_interface,
    175                              1);
    176     }
    177     else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0)
    178     {
    179         _glfw.wl.pointerConstraints =
    180             wl_registry_bind(registry, name,
    181                              &zwp_pointer_constraints_v1_interface,
    182                              1);
    183     }
    184     else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0)
    185     {
    186         _glfw.wl.idleInhibitManager =
    187             wl_registry_bind(registry, name,
    188                              &zwp_idle_inhibit_manager_v1_interface,
    189                              1);
    190     }
    191     else if (strcmp(interface, "xdg_activation_v1") == 0)
    192     {
    193         _glfw.wl.activationManager =
    194             wl_registry_bind(registry, name,
    195                              &xdg_activation_v1_interface,
    196                              1);
    197     }
    198     else if (strcmp(interface, "wp_fractional_scale_manager_v1") == 0)
    199     {
    200         _glfw.wl.fractionalScaleManager =
    201             wl_registry_bind(registry, name,
    202                              &wp_fractional_scale_manager_v1_interface,
    203                              1);
    204     }
    205 }
    206 
    207 static void registryHandleGlobalRemove(void* userData,
    208                                        struct wl_registry* registry,
    209                                        uint32_t name)
    210 {
    211     for (int i = 0; i < _glfw.monitorCount; ++i)
    212     {
    213         _GLFWmonitor* monitor = _glfw.monitors[i];
    214         if (monitor->wl.name == name)
    215         {
    216             _glfwInputMonitor(monitor, GLFW_DISCONNECTED, 0);
    217             return;
    218         }
    219     }
    220 }
    221 
    222 
    223 static const struct wl_registry_listener registryListener =
    224 {
    225     registryHandleGlobal,
    226     registryHandleGlobalRemove
    227 };
    228 
    229 void libdecorHandleError(struct libdecor* context,
    230                          enum libdecor_error error,
    231                          const char* message)
    232 {
    233     _glfwInputError(GLFW_PLATFORM_ERROR,
    234                     "Wayland: libdecor error %u: %s",
    235                     error, message);
    236 }
    237 
    238 static const struct libdecor_interface libdecorInterface =
    239 {
    240     libdecorHandleError
    241 };
    242 
    243 static void libdecorReadyCallback(void* userData,
    244                                   struct wl_callback* callback,
    245                                   uint32_t time)
    246 {
    247     _glfw.wl.libdecor.ready = GLFW_TRUE;
    248 
    249     assert(_glfw.wl.libdecor.callback == callback);
    250     wl_callback_destroy(_glfw.wl.libdecor.callback);
    251     _glfw.wl.libdecor.callback = NULL;
    252 }
    253 
    254 static const struct wl_callback_listener libdecorReadyListener =
    255 {
    256     libdecorReadyCallback
    257 };
    258 
    259 // Create key code translation tables
    260 //
    261 static void createKeyTablesWayland(void)
    262 {
    263     memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes));
    264     memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes));
    265 
    266     _glfw.wl.keycodes[KEY_GRAVE]      = GLFW_KEY_GRAVE_ACCENT;
    267     _glfw.wl.keycodes[KEY_1]          = GLFW_KEY_1;
    268     _glfw.wl.keycodes[KEY_2]          = GLFW_KEY_2;
    269     _glfw.wl.keycodes[KEY_3]          = GLFW_KEY_3;
    270     _glfw.wl.keycodes[KEY_4]          = GLFW_KEY_4;
    271     _glfw.wl.keycodes[KEY_5]          = GLFW_KEY_5;
    272     _glfw.wl.keycodes[KEY_6]          = GLFW_KEY_6;
    273     _glfw.wl.keycodes[KEY_7]          = GLFW_KEY_7;
    274     _glfw.wl.keycodes[KEY_8]          = GLFW_KEY_8;
    275     _glfw.wl.keycodes[KEY_9]          = GLFW_KEY_9;
    276     _glfw.wl.keycodes[KEY_0]          = GLFW_KEY_0;
    277     _glfw.wl.keycodes[KEY_SPACE]      = GLFW_KEY_SPACE;
    278     _glfw.wl.keycodes[KEY_MINUS]      = GLFW_KEY_MINUS;
    279     _glfw.wl.keycodes[KEY_EQUAL]      = GLFW_KEY_EQUAL;
    280     _glfw.wl.keycodes[KEY_Q]          = GLFW_KEY_Q;
    281     _glfw.wl.keycodes[KEY_W]          = GLFW_KEY_W;
    282     _glfw.wl.keycodes[KEY_E]          = GLFW_KEY_E;
    283     _glfw.wl.keycodes[KEY_R]          = GLFW_KEY_R;
    284     _glfw.wl.keycodes[KEY_T]          = GLFW_KEY_T;
    285     _glfw.wl.keycodes[KEY_Y]          = GLFW_KEY_Y;
    286     _glfw.wl.keycodes[KEY_U]          = GLFW_KEY_U;
    287     _glfw.wl.keycodes[KEY_I]          = GLFW_KEY_I;
    288     _glfw.wl.keycodes[KEY_O]          = GLFW_KEY_O;
    289     _glfw.wl.keycodes[KEY_P]          = GLFW_KEY_P;
    290     _glfw.wl.keycodes[KEY_LEFTBRACE]  = GLFW_KEY_LEFT_BRACKET;
    291     _glfw.wl.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
    292     _glfw.wl.keycodes[KEY_A]          = GLFW_KEY_A;
    293     _glfw.wl.keycodes[KEY_S]          = GLFW_KEY_S;
    294     _glfw.wl.keycodes[KEY_D]          = GLFW_KEY_D;
    295     _glfw.wl.keycodes[KEY_F]          = GLFW_KEY_F;
    296     _glfw.wl.keycodes[KEY_G]          = GLFW_KEY_G;
    297     _glfw.wl.keycodes[KEY_H]          = GLFW_KEY_H;
    298     _glfw.wl.keycodes[KEY_J]          = GLFW_KEY_J;
    299     _glfw.wl.keycodes[KEY_K]          = GLFW_KEY_K;
    300     _glfw.wl.keycodes[KEY_L]          = GLFW_KEY_L;
    301     _glfw.wl.keycodes[KEY_SEMICOLON]  = GLFW_KEY_SEMICOLON;
    302     _glfw.wl.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
    303     _glfw.wl.keycodes[KEY_Z]          = GLFW_KEY_Z;
    304     _glfw.wl.keycodes[KEY_X]          = GLFW_KEY_X;
    305     _glfw.wl.keycodes[KEY_C]          = GLFW_KEY_C;
    306     _glfw.wl.keycodes[KEY_V]          = GLFW_KEY_V;
    307     _glfw.wl.keycodes[KEY_B]          = GLFW_KEY_B;
    308     _glfw.wl.keycodes[KEY_N]          = GLFW_KEY_N;
    309     _glfw.wl.keycodes[KEY_M]          = GLFW_KEY_M;
    310     _glfw.wl.keycodes[KEY_COMMA]      = GLFW_KEY_COMMA;
    311     _glfw.wl.keycodes[KEY_DOT]        = GLFW_KEY_PERIOD;
    312     _glfw.wl.keycodes[KEY_SLASH]      = GLFW_KEY_SLASH;
    313     _glfw.wl.keycodes[KEY_BACKSLASH]  = GLFW_KEY_BACKSLASH;
    314     _glfw.wl.keycodes[KEY_ESC]        = GLFW_KEY_ESCAPE;
    315     _glfw.wl.keycodes[KEY_TAB]        = GLFW_KEY_TAB;
    316     _glfw.wl.keycodes[KEY_LEFTSHIFT]  = GLFW_KEY_LEFT_SHIFT;
    317     _glfw.wl.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
    318     _glfw.wl.keycodes[KEY_LEFTCTRL]   = GLFW_KEY_LEFT_CONTROL;
    319     _glfw.wl.keycodes[KEY_RIGHTCTRL]  = GLFW_KEY_RIGHT_CONTROL;
    320     _glfw.wl.keycodes[KEY_LEFTALT]    = GLFW_KEY_LEFT_ALT;
    321     _glfw.wl.keycodes[KEY_RIGHTALT]   = GLFW_KEY_RIGHT_ALT;
    322     _glfw.wl.keycodes[KEY_LEFTMETA]   = GLFW_KEY_LEFT_SUPER;
    323     _glfw.wl.keycodes[KEY_RIGHTMETA]  = GLFW_KEY_RIGHT_SUPER;
    324     _glfw.wl.keycodes[KEY_COMPOSE]    = GLFW_KEY_MENU;
    325     _glfw.wl.keycodes[KEY_NUMLOCK]    = GLFW_KEY_NUM_LOCK;
    326     _glfw.wl.keycodes[KEY_CAPSLOCK]   = GLFW_KEY_CAPS_LOCK;
    327     _glfw.wl.keycodes[KEY_PRINT]      = GLFW_KEY_PRINT_SCREEN;
    328     _glfw.wl.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
    329     _glfw.wl.keycodes[KEY_PAUSE]      = GLFW_KEY_PAUSE;
    330     _glfw.wl.keycodes[KEY_DELETE]     = GLFW_KEY_DELETE;
    331     _glfw.wl.keycodes[KEY_BACKSPACE]  = GLFW_KEY_BACKSPACE;
    332     _glfw.wl.keycodes[KEY_ENTER]      = GLFW_KEY_ENTER;
    333     _glfw.wl.keycodes[KEY_HOME]       = GLFW_KEY_HOME;
    334     _glfw.wl.keycodes[KEY_END]        = GLFW_KEY_END;
    335     _glfw.wl.keycodes[KEY_PAGEUP]     = GLFW_KEY_PAGE_UP;
    336     _glfw.wl.keycodes[KEY_PAGEDOWN]   = GLFW_KEY_PAGE_DOWN;
    337     _glfw.wl.keycodes[KEY_INSERT]     = GLFW_KEY_INSERT;
    338     _glfw.wl.keycodes[KEY_LEFT]       = GLFW_KEY_LEFT;
    339     _glfw.wl.keycodes[KEY_RIGHT]      = GLFW_KEY_RIGHT;
    340     _glfw.wl.keycodes[KEY_DOWN]       = GLFW_KEY_DOWN;
    341     _glfw.wl.keycodes[KEY_UP]         = GLFW_KEY_UP;
    342     _glfw.wl.keycodes[KEY_F1]         = GLFW_KEY_F1;
    343     _glfw.wl.keycodes[KEY_F2]         = GLFW_KEY_F2;
    344     _glfw.wl.keycodes[KEY_F3]         = GLFW_KEY_F3;
    345     _glfw.wl.keycodes[KEY_F4]         = GLFW_KEY_F4;
    346     _glfw.wl.keycodes[KEY_F5]         = GLFW_KEY_F5;
    347     _glfw.wl.keycodes[KEY_F6]         = GLFW_KEY_F6;
    348     _glfw.wl.keycodes[KEY_F7]         = GLFW_KEY_F7;
    349     _glfw.wl.keycodes[KEY_F8]         = GLFW_KEY_F8;
    350     _glfw.wl.keycodes[KEY_F9]         = GLFW_KEY_F9;
    351     _glfw.wl.keycodes[KEY_F10]        = GLFW_KEY_F10;
    352     _glfw.wl.keycodes[KEY_F11]        = GLFW_KEY_F11;
    353     _glfw.wl.keycodes[KEY_F12]        = GLFW_KEY_F12;
    354     _glfw.wl.keycodes[KEY_F13]        = GLFW_KEY_F13;
    355     _glfw.wl.keycodes[KEY_F14]        = GLFW_KEY_F14;
    356     _glfw.wl.keycodes[KEY_F15]        = GLFW_KEY_F15;
    357     _glfw.wl.keycodes[KEY_F16]        = GLFW_KEY_F16;
    358     _glfw.wl.keycodes[KEY_F17]        = GLFW_KEY_F17;
    359     _glfw.wl.keycodes[KEY_F18]        = GLFW_KEY_F18;
    360     _glfw.wl.keycodes[KEY_F19]        = GLFW_KEY_F19;
    361     _glfw.wl.keycodes[KEY_F20]        = GLFW_KEY_F20;
    362     _glfw.wl.keycodes[KEY_F21]        = GLFW_KEY_F21;
    363     _glfw.wl.keycodes[KEY_F22]        = GLFW_KEY_F22;
    364     _glfw.wl.keycodes[KEY_F23]        = GLFW_KEY_F23;
    365     _glfw.wl.keycodes[KEY_F24]        = GLFW_KEY_F24;
    366     _glfw.wl.keycodes[KEY_KPSLASH]    = GLFW_KEY_KP_DIVIDE;
    367     _glfw.wl.keycodes[KEY_KPASTERISK] = GLFW_KEY_KP_MULTIPLY;
    368     _glfw.wl.keycodes[KEY_KPMINUS]    = GLFW_KEY_KP_SUBTRACT;
    369     _glfw.wl.keycodes[KEY_KPPLUS]     = GLFW_KEY_KP_ADD;
    370     _glfw.wl.keycodes[KEY_KP0]        = GLFW_KEY_KP_0;
    371     _glfw.wl.keycodes[KEY_KP1]        = GLFW_KEY_KP_1;
    372     _glfw.wl.keycodes[KEY_KP2]        = GLFW_KEY_KP_2;
    373     _glfw.wl.keycodes[KEY_KP3]        = GLFW_KEY_KP_3;
    374     _glfw.wl.keycodes[KEY_KP4]        = GLFW_KEY_KP_4;
    375     _glfw.wl.keycodes[KEY_KP5]        = GLFW_KEY_KP_5;
    376     _glfw.wl.keycodes[KEY_KP6]        = GLFW_KEY_KP_6;
    377     _glfw.wl.keycodes[KEY_KP7]        = GLFW_KEY_KP_7;
    378     _glfw.wl.keycodes[KEY_KP8]        = GLFW_KEY_KP_8;
    379     _glfw.wl.keycodes[KEY_KP9]        = GLFW_KEY_KP_9;
    380     _glfw.wl.keycodes[KEY_KPDOT]      = GLFW_KEY_KP_DECIMAL;
    381     _glfw.wl.keycodes[KEY_KPEQUAL]    = GLFW_KEY_KP_EQUAL;
    382     _glfw.wl.keycodes[KEY_KPENTER]    = GLFW_KEY_KP_ENTER;
    383     _glfw.wl.keycodes[KEY_102ND]      = GLFW_KEY_WORLD_2;
    384 
    385     for (int scancode = 0;  scancode < 256;  scancode++)
    386     {
    387         if (_glfw.wl.keycodes[scancode] > 0)
    388             _glfw.wl.scancodes[_glfw.wl.keycodes[scancode]] = scancode;
    389     }
    390 }
    391 
    392 static GLFWbool loadCursorTheme(void)
    393 {
    394     int cursorSize = 16;
    395 
    396     const char* sizeString = getenv("XCURSOR_SIZE");
    397     if (sizeString)
    398     {
    399         errno = 0;
    400         const long cursorSizeLong = strtol(sizeString, NULL, 10);
    401         if (errno == 0 && cursorSizeLong > 0 && cursorSizeLong < INT_MAX)
    402             cursorSize = (int) cursorSizeLong;
    403     }
    404 
    405     const char* themeName = getenv("XCURSOR_THEME");
    406 
    407     _glfw.wl.cursorTheme = wl_cursor_theme_load(themeName, cursorSize, _glfw.wl.shm);
    408     if (!_glfw.wl.cursorTheme)
    409     {
    410         _glfwInputError(GLFW_PLATFORM_ERROR,
    411                         "Wayland: Failed to load default cursor theme");
    412         return GLFW_FALSE;
    413     }
    414 
    415     // If this happens to be NULL, we just fallback to the scale=1 version.
    416     _glfw.wl.cursorThemeHiDPI =
    417         wl_cursor_theme_load(themeName, cursorSize * 2, _glfw.wl.shm);
    418 
    419     _glfw.wl.cursorSurface = wl_compositor_create_surface(_glfw.wl.compositor);
    420     _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
    421     return GLFW_TRUE;
    422 }
    423 
    424 
    425 //////////////////////////////////////////////////////////////////////////
    426 //////                       GLFW platform API                      //////
    427 //////////////////////////////////////////////////////////////////////////
    428 
    429 GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform)
    430 {
    431     const _GLFWplatform wayland =
    432     {
    433         .platformID = GLFW_PLATFORM_WAYLAND,
    434         .init = _glfwInitWayland,
    435         .terminate = _glfwTerminateWayland,
    436         .getCursorPos = _glfwGetCursorPosWayland,
    437         .setCursorPos = _glfwSetCursorPosWayland,
    438         .setCursorMode = _glfwSetCursorModeWayland,
    439         .setRawMouseMotion = _glfwSetRawMouseMotionWayland,
    440         .rawMouseMotionSupported = _glfwRawMouseMotionSupportedWayland,
    441         .createCursor = _glfwCreateCursorWayland,
    442         .createStandardCursor = _glfwCreateStandardCursorWayland,
    443         .destroyCursor = _glfwDestroyCursorWayland,
    444         .setCursor = _glfwSetCursorWayland,
    445         .getScancodeName = _glfwGetScancodeNameWayland,
    446         .getKeyScancode = _glfwGetKeyScancodeWayland,
    447         .setClipboardString = _glfwSetClipboardStringWayland,
    448         .getClipboardString = _glfwGetClipboardStringWayland,
    449 #if defined(GLFW_BUILD_LINUX_JOYSTICK)
    450         .initJoysticks = _glfwInitJoysticksLinux,
    451         .terminateJoysticks = _glfwTerminateJoysticksLinux,
    452         .pollJoystick = _glfwPollJoystickLinux,
    453         .getMappingName = _glfwGetMappingNameLinux,
    454         .updateGamepadGUID = _glfwUpdateGamepadGUIDLinux,
    455 #else
    456         .initJoysticks = _glfwInitJoysticksNull,
    457         .terminateJoysticks = _glfwTerminateJoysticksNull,
    458         .pollJoystick = _glfwPollJoystickNull,
    459         .getMappingName = _glfwGetMappingNameNull,
    460         .updateGamepadGUID = _glfwUpdateGamepadGUIDNull,
    461 #endif
    462         .freeMonitor = _glfwFreeMonitorWayland,
    463         .getMonitorPos = _glfwGetMonitorPosWayland,
    464         .getMonitorContentScale = _glfwGetMonitorContentScaleWayland,
    465         .getMonitorWorkarea = _glfwGetMonitorWorkareaWayland,
    466         .getVideoModes = _glfwGetVideoModesWayland,
    467         .getVideoMode = _glfwGetVideoModeWayland,
    468         .getGammaRamp = _glfwGetGammaRampWayland,
    469         .setGammaRamp = _glfwSetGammaRampWayland,
    470         .createWindow = _glfwCreateWindowWayland,
    471         .destroyWindow = _glfwDestroyWindowWayland,
    472         .setWindowTitle = _glfwSetWindowTitleWayland,
    473         .setWindowIcon = _glfwSetWindowIconWayland,
    474         .getWindowPos = _glfwGetWindowPosWayland,
    475         .setWindowPos = _glfwSetWindowPosWayland,
    476         .getWindowSize = _glfwGetWindowSizeWayland,
    477         .setWindowSize = _glfwSetWindowSizeWayland,
    478         .setWindowSizeLimits = _glfwSetWindowSizeLimitsWayland,
    479         .setWindowAspectRatio = _glfwSetWindowAspectRatioWayland,
    480         .getFramebufferSize = _glfwGetFramebufferSizeWayland,
    481         .getWindowFrameSize = _glfwGetWindowFrameSizeWayland,
    482         .getWindowContentScale = _glfwGetWindowContentScaleWayland,
    483         .iconifyWindow = _glfwIconifyWindowWayland,
    484         .restoreWindow = _glfwRestoreWindowWayland,
    485         .maximizeWindow = _glfwMaximizeWindowWayland,
    486         .showWindow = _glfwShowWindowWayland,
    487         .hideWindow = _glfwHideWindowWayland,
    488         .requestWindowAttention = _glfwRequestWindowAttentionWayland,
    489         .focusWindow = _glfwFocusWindowWayland,
    490         .setWindowMonitor = _glfwSetWindowMonitorWayland,
    491         .windowFocused = _glfwWindowFocusedWayland,
    492         .windowIconified = _glfwWindowIconifiedWayland,
    493         .windowVisible = _glfwWindowVisibleWayland,
    494         .windowMaximized = _glfwWindowMaximizedWayland,
    495         .windowHovered = _glfwWindowHoveredWayland,
    496         .framebufferTransparent = _glfwFramebufferTransparentWayland,
    497         .getWindowOpacity = _glfwGetWindowOpacityWayland,
    498         .setWindowResizable = _glfwSetWindowResizableWayland,
    499         .setWindowDecorated = _glfwSetWindowDecoratedWayland,
    500         .setWindowFloating = _glfwSetWindowFloatingWayland,
    501         .setWindowOpacity = _glfwSetWindowOpacityWayland,
    502         .setWindowMousePassthrough = _glfwSetWindowMousePassthroughWayland,
    503         .pollEvents = _glfwPollEventsWayland,
    504         .waitEvents = _glfwWaitEventsWayland,
    505         .waitEventsTimeout = _glfwWaitEventsTimeoutWayland,
    506         .postEmptyEvent = _glfwPostEmptyEventWayland,
    507         .getEGLPlatform = _glfwGetEGLPlatformWayland,
    508         .getEGLNativeDisplay = _glfwGetEGLNativeDisplayWayland,
    509         .getEGLNativeWindow = _glfwGetEGLNativeWindowWayland,
    510         .getRequiredInstanceExtensions = _glfwGetRequiredInstanceExtensionsWayland,
    511         .getPhysicalDevicePresentationSupport = _glfwGetPhysicalDevicePresentationSupportWayland,
    512         .createWindowSurface = _glfwCreateWindowSurfaceWayland
    513     };
    514 
    515     void* module = _glfwPlatformLoadModule("libwayland-client.so.0");
    516     if (!module)
    517     {
    518         if (platformID == GLFW_PLATFORM_WAYLAND)
    519         {
    520             _glfwInputError(GLFW_PLATFORM_ERROR,
    521                             "Wayland: Failed to load libwayland-client");
    522         }
    523 
    524         return GLFW_FALSE;
    525     }
    526 
    527     PFN_wl_display_connect wl_display_connect = (PFN_wl_display_connect)
    528         _glfwPlatformGetModuleSymbol(module, "wl_display_connect");
    529     if (!wl_display_connect)
    530     {
    531         if (platformID == GLFW_PLATFORM_WAYLAND)
    532         {
    533             _glfwInputError(GLFW_PLATFORM_ERROR,
    534                             "Wayland: Failed to load libwayland-client entry point");
    535         }
    536 
    537         _glfwPlatformFreeModule(module);
    538         return GLFW_FALSE;
    539     }
    540 
    541     struct wl_display* display = wl_display_connect(NULL);
    542     if (!display)
    543     {
    544         if (platformID == GLFW_PLATFORM_WAYLAND)
    545             _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to connect to display");
    546 
    547         _glfwPlatformFreeModule(module);
    548         return GLFW_FALSE;
    549     }
    550 
    551     _glfw.wl.display = display;
    552     _glfw.wl.client.handle = module;
    553 
    554     *platform = wayland;
    555     return GLFW_TRUE;
    556 }
    557 
    558 int _glfwInitWayland(void)
    559 {
    560     // These must be set before any failure checks
    561     _glfw.wl.keyRepeatTimerfd = -1;
    562     _glfw.wl.cursorTimerfd = -1;
    563 
    564     _glfw.wl.tag = glfwGetVersionString();
    565 
    566     _glfw.wl.client.display_flush = (PFN_wl_display_flush)
    567         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_flush");
    568     _glfw.wl.client.display_cancel_read = (PFN_wl_display_cancel_read)
    569         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_cancel_read");
    570     _glfw.wl.client.display_dispatch_pending = (PFN_wl_display_dispatch_pending)
    571         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_dispatch_pending");
    572     _glfw.wl.client.display_read_events = (PFN_wl_display_read_events)
    573         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_read_events");
    574     _glfw.wl.client.display_disconnect = (PFN_wl_display_disconnect)
    575         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_disconnect");
    576     _glfw.wl.client.display_roundtrip = (PFN_wl_display_roundtrip)
    577         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_roundtrip");
    578     _glfw.wl.client.display_get_fd = (PFN_wl_display_get_fd)
    579         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_get_fd");
    580     _glfw.wl.client.display_prepare_read = (PFN_wl_display_prepare_read)
    581         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_prepare_read");
    582     _glfw.wl.client.proxy_marshal = (PFN_wl_proxy_marshal)
    583         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_marshal");
    584     _glfw.wl.client.proxy_add_listener = (PFN_wl_proxy_add_listener)
    585         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_add_listener");
    586     _glfw.wl.client.proxy_destroy = (PFN_wl_proxy_destroy)
    587         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_destroy");
    588     _glfw.wl.client.proxy_marshal_constructor = (PFN_wl_proxy_marshal_constructor)
    589         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_marshal_constructor");
    590     _glfw.wl.client.proxy_marshal_constructor_versioned = (PFN_wl_proxy_marshal_constructor_versioned)
    591         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_marshal_constructor_versioned");
    592     _glfw.wl.client.proxy_get_user_data = (PFN_wl_proxy_get_user_data)
    593         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_user_data");
    594     _glfw.wl.client.proxy_set_user_data = (PFN_wl_proxy_set_user_data)
    595         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_set_user_data");
    596     _glfw.wl.client.proxy_get_tag = (PFN_wl_proxy_get_tag)
    597         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_tag");
    598     _glfw.wl.client.proxy_set_tag = (PFN_wl_proxy_set_tag)
    599         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_set_tag");
    600     _glfw.wl.client.proxy_get_version = (PFN_wl_proxy_get_version)
    601         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_version");
    602     _glfw.wl.client.proxy_marshal_flags = (PFN_wl_proxy_marshal_flags)
    603         _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_marshal_flags");
    604 
    605     if (!_glfw.wl.client.display_flush ||
    606         !_glfw.wl.client.display_cancel_read ||
    607         !_glfw.wl.client.display_dispatch_pending ||
    608         !_glfw.wl.client.display_read_events ||
    609         !_glfw.wl.client.display_disconnect ||
    610         !_glfw.wl.client.display_roundtrip ||
    611         !_glfw.wl.client.display_get_fd ||
    612         !_glfw.wl.client.display_prepare_read ||
    613         !_glfw.wl.client.proxy_marshal ||
    614         !_glfw.wl.client.proxy_add_listener ||
    615         !_glfw.wl.client.proxy_destroy ||
    616         !_glfw.wl.client.proxy_marshal_constructor ||
    617         !_glfw.wl.client.proxy_marshal_constructor_versioned ||
    618         !_glfw.wl.client.proxy_get_user_data ||
    619         !_glfw.wl.client.proxy_set_user_data ||
    620         !_glfw.wl.client.proxy_get_tag ||
    621         !_glfw.wl.client.proxy_set_tag)
    622     {
    623         _glfwInputError(GLFW_PLATFORM_ERROR,
    624                         "Wayland: Failed to load libwayland-client entry point");
    625         return GLFW_FALSE;
    626     }
    627 
    628     _glfw.wl.cursor.handle = _glfwPlatformLoadModule("libwayland-cursor.so.0");
    629     if (!_glfw.wl.cursor.handle)
    630     {
    631         _glfwInputError(GLFW_PLATFORM_ERROR,
    632                         "Wayland: Failed to load libwayland-cursor");
    633         return GLFW_FALSE;
    634     }
    635 
    636     _glfw.wl.cursor.theme_load = (PFN_wl_cursor_theme_load)
    637         _glfwPlatformGetModuleSymbol(_glfw.wl.cursor.handle, "wl_cursor_theme_load");
    638     _glfw.wl.cursor.theme_destroy = (PFN_wl_cursor_theme_destroy)
    639         _glfwPlatformGetModuleSymbol(_glfw.wl.cursor.handle, "wl_cursor_theme_destroy");
    640     _glfw.wl.cursor.theme_get_cursor = (PFN_wl_cursor_theme_get_cursor)
    641         _glfwPlatformGetModuleSymbol(_glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor");
    642     _glfw.wl.cursor.image_get_buffer = (PFN_wl_cursor_image_get_buffer)
    643         _glfwPlatformGetModuleSymbol(_glfw.wl.cursor.handle, "wl_cursor_image_get_buffer");
    644 
    645     _glfw.wl.egl.handle = _glfwPlatformLoadModule("libwayland-egl.so.1");
    646     if (!_glfw.wl.egl.handle)
    647     {
    648         _glfwInputError(GLFW_PLATFORM_ERROR,
    649                         "Wayland: Failed to load libwayland-egl");
    650         return GLFW_FALSE;
    651     }
    652 
    653     _glfw.wl.egl.window_create = (PFN_wl_egl_window_create)
    654         _glfwPlatformGetModuleSymbol(_glfw.wl.egl.handle, "wl_egl_window_create");
    655     _glfw.wl.egl.window_destroy = (PFN_wl_egl_window_destroy)
    656         _glfwPlatformGetModuleSymbol(_glfw.wl.egl.handle, "wl_egl_window_destroy");
    657     _glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize)
    658         _glfwPlatformGetModuleSymbol(_glfw.wl.egl.handle, "wl_egl_window_resize");
    659 
    660     _glfw.wl.xkb.handle = _glfwPlatformLoadModule("libxkbcommon.so.0");
    661     if (!_glfw.wl.xkb.handle)
    662     {
    663         _glfwInputError(GLFW_PLATFORM_ERROR,
    664                         "Wayland: Failed to load libxkbcommon");
    665         return GLFW_FALSE;
    666     }
    667 
    668     _glfw.wl.xkb.context_new = (PFN_xkb_context_new)
    669         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_context_new");
    670     _glfw.wl.xkb.context_unref = (PFN_xkb_context_unref)
    671         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_context_unref");
    672     _glfw.wl.xkb.keymap_new_from_string = (PFN_xkb_keymap_new_from_string)
    673         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_new_from_string");
    674     _glfw.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref)
    675         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_unref");
    676     _glfw.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index)
    677         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
    678     _glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats)
    679         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats");
    680     _glfw.wl.xkb.keymap_key_get_syms_by_level = (PFN_xkb_keymap_key_get_syms_by_level)
    681         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_key_get_syms_by_level");
    682     _glfw.wl.xkb.state_new = (PFN_xkb_state_new)
    683         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_new");
    684     _glfw.wl.xkb.state_unref = (PFN_xkb_state_unref)
    685         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_unref");
    686     _glfw.wl.xkb.state_key_get_syms = (PFN_xkb_state_key_get_syms)
    687         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_key_get_syms");
    688     _glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask)
    689         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_update_mask");
    690     _glfw.wl.xkb.state_key_get_layout = (PFN_xkb_state_key_get_layout)
    691         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_key_get_layout");
    692     _glfw.wl.xkb.state_mod_index_is_active = (PFN_xkb_state_mod_index_is_active)
    693         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_mod_index_is_active");
    694     _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)
    695         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");
    696     _glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref)
    697         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_table_unref");
    698     _glfw.wl.xkb.compose_state_new = (PFN_xkb_compose_state_new)
    699         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_new");
    700     _glfw.wl.xkb.compose_state_unref = (PFN_xkb_compose_state_unref)
    701         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_unref");
    702     _glfw.wl.xkb.compose_state_feed = (PFN_xkb_compose_state_feed)
    703         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_feed");
    704     _glfw.wl.xkb.compose_state_get_status = (PFN_xkb_compose_state_get_status)
    705         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_status");
    706     _glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)
    707         _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");
    708 
    709     if (!_glfw.wl.xkb.context_new ||
    710         !_glfw.wl.xkb.context_unref ||
    711         !_glfw.wl.xkb.keymap_new_from_string ||
    712         !_glfw.wl.xkb.keymap_unref ||
    713         !_glfw.wl.xkb.keymap_mod_get_index ||
    714         !_glfw.wl.xkb.keymap_key_repeats ||
    715         !_glfw.wl.xkb.keymap_key_get_syms_by_level ||
    716         !_glfw.wl.xkb.state_new ||
    717         !_glfw.wl.xkb.state_unref ||
    718         !_glfw.wl.xkb.state_key_get_syms ||
    719         !_glfw.wl.xkb.state_update_mask ||
    720         !_glfw.wl.xkb.state_key_get_layout ||
    721         !_glfw.wl.xkb.state_mod_index_is_active ||
    722         !_glfw.wl.xkb.compose_table_new_from_locale ||
    723         !_glfw.wl.xkb.compose_table_unref ||
    724         !_glfw.wl.xkb.compose_state_new ||
    725         !_glfw.wl.xkb.compose_state_unref ||
    726         !_glfw.wl.xkb.compose_state_feed ||
    727         !_glfw.wl.xkb.compose_state_get_status ||
    728         !_glfw.wl.xkb.compose_state_get_one_sym)
    729     {
    730         _glfwInputError(GLFW_PLATFORM_ERROR,
    731                         "Wayland: Failed to load all entry points from libxkbcommon");
    732         return GLFW_FALSE;
    733     }
    734 
    735     if (_glfw.hints.init.wl.libdecorMode == GLFW_WAYLAND_PREFER_LIBDECOR)
    736         _glfw.wl.libdecor.handle = _glfwPlatformLoadModule("libdecor-0.so.0");
    737 
    738     if (_glfw.wl.libdecor.handle)
    739     {
    740         _glfw.wl.libdecor.libdecor_new_ = (PFN_libdecor_new)
    741             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_new");
    742         _glfw.wl.libdecor.libdecor_unref_ = (PFN_libdecor_unref)
    743             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_unref");
    744         _glfw.wl.libdecor.libdecor_get_fd_ = (PFN_libdecor_get_fd)
    745             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_get_fd");
    746         _glfw.wl.libdecor.libdecor_dispatch_ = (PFN_libdecor_dispatch)
    747             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_dispatch");
    748         _glfw.wl.libdecor.libdecor_decorate_ = (PFN_libdecor_decorate)
    749             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_decorate");
    750         _glfw.wl.libdecor.libdecor_frame_unref_ = (PFN_libdecor_frame_unref)
    751             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_unref");
    752         _glfw.wl.libdecor.libdecor_frame_set_app_id_ = (PFN_libdecor_frame_set_app_id)
    753             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_app_id");
    754         _glfw.wl.libdecor.libdecor_frame_set_title_ = (PFN_libdecor_frame_set_title)
    755             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_title");
    756         _glfw.wl.libdecor.libdecor_frame_set_minimized_ = (PFN_libdecor_frame_set_minimized)
    757             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_minimized");
    758         _glfw.wl.libdecor.libdecor_frame_set_fullscreen_ = (PFN_libdecor_frame_set_fullscreen)
    759             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_fullscreen");
    760         _glfw.wl.libdecor.libdecor_frame_unset_fullscreen_ = (PFN_libdecor_frame_unset_fullscreen)
    761             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_unset_fullscreen");
    762         _glfw.wl.libdecor.libdecor_frame_map_ = (PFN_libdecor_frame_map)
    763             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_map");
    764         _glfw.wl.libdecor.libdecor_frame_commit_ = (PFN_libdecor_frame_commit)
    765             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_commit");
    766         _glfw.wl.libdecor.libdecor_frame_set_min_content_size_ = (PFN_libdecor_frame_set_min_content_size)
    767             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_min_content_size");
    768         _glfw.wl.libdecor.libdecor_frame_set_max_content_size_ = (PFN_libdecor_frame_set_max_content_size)
    769             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_max_content_size");
    770         _glfw.wl.libdecor.libdecor_frame_set_maximized_ = (PFN_libdecor_frame_set_maximized)
    771             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_maximized");
    772         _glfw.wl.libdecor.libdecor_frame_unset_maximized_ = (PFN_libdecor_frame_unset_maximized)
    773             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_unset_maximized");
    774         _glfw.wl.libdecor.libdecor_frame_set_capabilities_ = (PFN_libdecor_frame_set_capabilities)
    775             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_capabilities");
    776         _glfw.wl.libdecor.libdecor_frame_unset_capabilities_ = (PFN_libdecor_frame_unset_capabilities)
    777             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_unset_capabilities");
    778         _glfw.wl.libdecor.libdecor_frame_set_visibility_ = (PFN_libdecor_frame_set_visibility)
    779             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_visibility");
    780         _glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ = (PFN_libdecor_frame_get_xdg_toplevel)
    781             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_get_xdg_toplevel");
    782         _glfw.wl.libdecor.libdecor_configuration_get_content_size_ = (PFN_libdecor_configuration_get_content_size)
    783             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_configuration_get_content_size");
    784         _glfw.wl.libdecor.libdecor_configuration_get_window_state_ = (PFN_libdecor_configuration_get_window_state)
    785             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_configuration_get_window_state");
    786         _glfw.wl.libdecor.libdecor_state_new_ = (PFN_libdecor_state_new)
    787             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_state_new");
    788         _glfw.wl.libdecor.libdecor_state_free_ = (PFN_libdecor_state_free)
    789             _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_state_free");
    790 
    791         if (!_glfw.wl.libdecor.libdecor_new_ ||
    792             !_glfw.wl.libdecor.libdecor_unref_ ||
    793             !_glfw.wl.libdecor.libdecor_get_fd_ ||
    794             !_glfw.wl.libdecor.libdecor_dispatch_ ||
    795             !_glfw.wl.libdecor.libdecor_decorate_ ||
    796             !_glfw.wl.libdecor.libdecor_frame_unref_ ||
    797             !_glfw.wl.libdecor.libdecor_frame_set_app_id_ ||
    798             !_glfw.wl.libdecor.libdecor_frame_set_title_ ||
    799             !_glfw.wl.libdecor.libdecor_frame_set_minimized_ ||
    800             !_glfw.wl.libdecor.libdecor_frame_set_fullscreen_ ||
    801             !_glfw.wl.libdecor.libdecor_frame_unset_fullscreen_ ||
    802             !_glfw.wl.libdecor.libdecor_frame_map_ ||
    803             !_glfw.wl.libdecor.libdecor_frame_commit_ ||
    804             !_glfw.wl.libdecor.libdecor_frame_set_min_content_size_ ||
    805             !_glfw.wl.libdecor.libdecor_frame_set_max_content_size_ ||
    806             !_glfw.wl.libdecor.libdecor_frame_set_maximized_ ||
    807             !_glfw.wl.libdecor.libdecor_frame_unset_maximized_ ||
    808             !_glfw.wl.libdecor.libdecor_frame_set_capabilities_ ||
    809             !_glfw.wl.libdecor.libdecor_frame_unset_capabilities_ ||
    810             !_glfw.wl.libdecor.libdecor_frame_set_visibility_ ||
    811             !_glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ ||
    812             !_glfw.wl.libdecor.libdecor_configuration_get_content_size_ ||
    813             !_glfw.wl.libdecor.libdecor_configuration_get_window_state_ ||
    814             !_glfw.wl.libdecor.libdecor_state_new_ ||
    815             !_glfw.wl.libdecor.libdecor_state_free_)
    816         {
    817             _glfwPlatformFreeModule(_glfw.wl.libdecor.handle);
    818             memset(&_glfw.wl.libdecor, 0, sizeof(_glfw.wl.libdecor));
    819         }
    820     }
    821 
    822     _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
    823     wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);
    824 
    825     createKeyTablesWayland();
    826 
    827     _glfw.wl.xkb.context = xkb_context_new(0);
    828     if (!_glfw.wl.xkb.context)
    829     {
    830         _glfwInputError(GLFW_PLATFORM_ERROR,
    831                         "Wayland: Failed to initialize xkb context");
    832         return GLFW_FALSE;
    833     }
    834 
    835     // Sync so we got all registry objects
    836     wl_display_roundtrip(_glfw.wl.display);
    837 
    838     // Sync so we got all initial output events
    839     wl_display_roundtrip(_glfw.wl.display);
    840 
    841     if (_glfw.wl.libdecor.handle)
    842     {
    843         _glfw.wl.libdecor.context = libdecor_new(_glfw.wl.display, &libdecorInterface);
    844         if (_glfw.wl.libdecor.context)
    845         {
    846             // Perform an initial dispatch and flush to get the init started
    847             libdecor_dispatch(_glfw.wl.libdecor.context, 0);
    848 
    849             // Create sync point to "know" when libdecor is ready for use
    850             _glfw.wl.libdecor.callback = wl_display_sync(_glfw.wl.display);
    851             wl_callback_add_listener(_glfw.wl.libdecor.callback,
    852                                      &libdecorReadyListener,
    853                                      NULL);
    854         }
    855     }
    856 
    857     if (wl_seat_get_version(_glfw.wl.seat) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
    858     {
    859         _glfw.wl.keyRepeatTimerfd =
    860             timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
    861     }
    862 
    863     if (!_glfw.wl.wmBase)
    864     {
    865         _glfwInputError(GLFW_PLATFORM_ERROR,
    866                         "Wayland: Failed to find xdg-shell in your compositor");
    867         return GLFW_FALSE;
    868     }
    869 
    870     if (!_glfw.wl.shm)
    871     {
    872         _glfwInputError(GLFW_PLATFORM_ERROR,
    873                         "Wayland: Failed to find wl_shm in your compositor");
    874         return GLFW_FALSE;
    875     }
    876 
    877     if (!loadCursorTheme())
    878         return GLFW_FALSE;
    879 
    880     if (_glfw.wl.seat && _glfw.wl.dataDeviceManager)
    881     {
    882         _glfw.wl.dataDevice =
    883             wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager,
    884                                                    _glfw.wl.seat);
    885         _glfwAddDataDeviceListenerWayland(_glfw.wl.dataDevice);
    886     }
    887 
    888     return GLFW_TRUE;
    889 }
    890 
    891 void _glfwTerminateWayland(void)
    892 {
    893     _glfwTerminateEGL();
    894     _glfwTerminateOSMesa();
    895 
    896     if (_glfw.wl.libdecor.context)
    897     {
    898         // Allow libdecor to finish receiving all its requested globals
    899         // and ensure the associated sync callback object is destroyed
    900         while (!_glfw.wl.libdecor.ready)
    901             _glfwWaitEventsWayland();
    902 
    903         libdecor_unref(_glfw.wl.libdecor.context);
    904     }
    905 
    906     if (_glfw.wl.libdecor.handle)
    907     {
    908         _glfwPlatformFreeModule(_glfw.wl.libdecor.handle);
    909         _glfw.wl.libdecor.handle = NULL;
    910     }
    911 
    912     if (_glfw.wl.egl.handle)
    913     {
    914         _glfwPlatformFreeModule(_glfw.wl.egl.handle);
    915         _glfw.wl.egl.handle = NULL;
    916     }
    917 
    918     if (_glfw.wl.xkb.composeState)
    919         xkb_compose_state_unref(_glfw.wl.xkb.composeState);
    920     if (_glfw.wl.xkb.keymap)
    921         xkb_keymap_unref(_glfw.wl.xkb.keymap);
    922     if (_glfw.wl.xkb.state)
    923         xkb_state_unref(_glfw.wl.xkb.state);
    924     if (_glfw.wl.xkb.context)
    925         xkb_context_unref(_glfw.wl.xkb.context);
    926     if (_glfw.wl.xkb.handle)
    927     {
    928         _glfwPlatformFreeModule(_glfw.wl.xkb.handle);
    929         _glfw.wl.xkb.handle = NULL;
    930     }
    931 
    932     if (_glfw.wl.cursorTheme)
    933         wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
    934     if (_glfw.wl.cursorThemeHiDPI)
    935         wl_cursor_theme_destroy(_glfw.wl.cursorThemeHiDPI);
    936     if (_glfw.wl.cursor.handle)
    937     {
    938         _glfwPlatformFreeModule(_glfw.wl.cursor.handle);
    939         _glfw.wl.cursor.handle = NULL;
    940     }
    941 
    942     for (unsigned int i = 0; i < _glfw.wl.offerCount; i++)
    943         wl_data_offer_destroy(_glfw.wl.offers[i].offer);
    944 
    945     _glfw_free(_glfw.wl.offers);
    946 
    947     if (_glfw.wl.cursorSurface)
    948         wl_surface_destroy(_glfw.wl.cursorSurface);
    949     if (_glfw.wl.subcompositor)
    950         wl_subcompositor_destroy(_glfw.wl.subcompositor);
    951     if (_glfw.wl.compositor)
    952         wl_compositor_destroy(_glfw.wl.compositor);
    953     if (_glfw.wl.shm)
    954         wl_shm_destroy(_glfw.wl.shm);
    955     if (_glfw.wl.viewporter)
    956         wp_viewporter_destroy(_glfw.wl.viewporter);
    957     if (_glfw.wl.decorationManager)
    958         zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager);
    959     if (_glfw.wl.wmBase)
    960         xdg_wm_base_destroy(_glfw.wl.wmBase);
    961     if (_glfw.wl.selectionOffer)
    962         wl_data_offer_destroy(_glfw.wl.selectionOffer);
    963     if (_glfw.wl.dragOffer)
    964         wl_data_offer_destroy(_glfw.wl.dragOffer);
    965     if (_glfw.wl.selectionSource)
    966         wl_data_source_destroy(_glfw.wl.selectionSource);
    967     if (_glfw.wl.dataDevice)
    968         wl_data_device_destroy(_glfw.wl.dataDevice);
    969     if (_glfw.wl.dataDeviceManager)
    970         wl_data_device_manager_destroy(_glfw.wl.dataDeviceManager);
    971     if (_glfw.wl.pointer)
    972         wl_pointer_destroy(_glfw.wl.pointer);
    973     if (_glfw.wl.keyboard)
    974         wl_keyboard_destroy(_glfw.wl.keyboard);
    975     if (_glfw.wl.seat)
    976         wl_seat_destroy(_glfw.wl.seat);
    977     if (_glfw.wl.relativePointerManager)
    978         zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager);
    979     if (_glfw.wl.pointerConstraints)
    980         zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints);
    981     if (_glfw.wl.idleInhibitManager)
    982         zwp_idle_inhibit_manager_v1_destroy(_glfw.wl.idleInhibitManager);
    983     if (_glfw.wl.activationManager)
    984         xdg_activation_v1_destroy(_glfw.wl.activationManager);
    985     if (_glfw.wl.fractionalScaleManager)
    986         wp_fractional_scale_manager_v1_destroy(_glfw.wl.fractionalScaleManager);
    987     if (_glfw.wl.registry)
    988         wl_registry_destroy(_glfw.wl.registry);
    989     if (_glfw.wl.display)
    990     {
    991         wl_display_flush(_glfw.wl.display);
    992         wl_display_disconnect(_glfw.wl.display);
    993     }
    994 
    995     if (_glfw.wl.keyRepeatTimerfd >= 0)
    996         close(_glfw.wl.keyRepeatTimerfd);
    997     if (_glfw.wl.cursorTimerfd >= 0)
    998         close(_glfw.wl.cursorTimerfd);
    999 
   1000     _glfw_free(_glfw.wl.clipboardString);
   1001 }
   1002 
   1003 #endif // _GLFW_WAYLAND
   1004