]> git.sesse.net Git - pistorm/blob - raylib/external/glfw/src/wl_init.c
Update raylib files and Makefile for Pi 4 testing
[pistorm] / raylib / external / glfw / src / wl_init.c
1 //========================================================================
2 // GLFW 3.4 Wayland - www.glfw.org
3 //------------------------------------------------------------------------
4 // Copyright (c) 2014 Jonas Ã…dahl <jadahl@gmail.com>
5 //
6 // This software is provided 'as-is', without any express or implied
7 // warranty. In no event will the authors be held liable for any damages
8 // arising from the use of this software.
9 //
10 // Permission is granted to anyone to use this software for any purpose,
11 // including commercial applications, and to alter it and redistribute it
12 // freely, subject to the following restrictions:
13 //
14 // 1. The origin of this software must not be misrepresented; you must not
15 //    claim that you wrote the original software. If you use this software
16 //    in a product, an acknowledgment in the product documentation would
17 //    be appreciated but is not required.
18 //
19 // 2. Altered source versions must be plainly marked as such, and must not
20 //    be misrepresented as being the original software.
21 //
22 // 3. This notice may not be removed or altered from any source
23 //    distribution.
24 //
25 //========================================================================
26 // It is fine to use C99 in this file because it will not be built with VS
27 //========================================================================
28
29 #define _POSIX_C_SOURCE 199309L
30
31 #include "internal.h"
32
33 #include <assert.h>
34 #include <errno.h>
35 #include <limits.h>
36 #include <linux/input.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <sys/mman.h>
41 #include <sys/timerfd.h>
42 #include <unistd.h>
43 #include <time.h>
44 #include <wayland-client.h>
45
46
47 static inline int min(int n1, int n2)
48 {
49     return n1 < n2 ? n1 : n2;
50 }
51
52 static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface,
53                                                     int* which)
54 {
55     int focus;
56     _GLFWwindow* window = _glfw.windowListHead;
57     if (!which)
58         which = &focus;
59     while (window)
60     {
61         if (surface == window->wl.decorations.top.surface)
62         {
63             *which = topDecoration;
64             break;
65         }
66         if (surface == window->wl.decorations.left.surface)
67         {
68             *which = leftDecoration;
69             break;
70         }
71         if (surface == window->wl.decorations.right.surface)
72         {
73             *which = rightDecoration;
74             break;
75         }
76         if (surface == window->wl.decorations.bottom.surface)
77         {
78             *which = bottomDecoration;
79             break;
80         }
81         window = window->next;
82     }
83     return window;
84 }
85
86 static void pointerHandleEnter(void* data,
87                                struct wl_pointer* pointer,
88                                uint32_t serial,
89                                struct wl_surface* surface,
90                                wl_fixed_t sx,
91                                wl_fixed_t sy)
92 {
93     // Happens in the case we just destroyed the surface.
94     if (!surface)
95         return;
96
97     int focus = 0;
98     _GLFWwindow* window = wl_surface_get_user_data(surface);
99     if (!window)
100     {
101         window = findWindowFromDecorationSurface(surface, &focus);
102         if (!window)
103             return;
104     }
105
106     window->wl.decorations.focus = focus;
107     _glfw.wl.serial = serial;
108     _glfw.wl.pointerFocus = window;
109
110     window->wl.hovered = GLFW_TRUE;
111
112     _glfwPlatformSetCursor(window, window->wl.currentCursor);
113     _glfwInputCursorEnter(window, GLFW_TRUE);
114 }
115
116 static void pointerHandleLeave(void* data,
117                                struct wl_pointer* pointer,
118                                uint32_t serial,
119                                struct wl_surface* surface)
120 {
121     _GLFWwindow* window = _glfw.wl.pointerFocus;
122
123     if (!window)
124         return;
125
126     window->wl.hovered = GLFW_FALSE;
127
128     _glfw.wl.serial = serial;
129     _glfw.wl.pointerFocus = NULL;
130     _glfwInputCursorEnter(window, GLFW_FALSE);
131     _glfw.wl.cursorPreviousName = NULL;
132 }
133
134 static void setCursor(_GLFWwindow* window, const char* name)
135 {
136     struct wl_buffer* buffer;
137     struct wl_cursor* cursor;
138     struct wl_cursor_image* image;
139     struct wl_surface* surface = _glfw.wl.cursorSurface;
140     struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;
141     int scale = 1;
142
143     if (window->wl.scale > 1 && _glfw.wl.cursorThemeHiDPI)
144     {
145         // We only support up to scale=2 for now, since libwayland-cursor
146         // requires us to load a different theme for each size.
147         scale = 2;
148         theme = _glfw.wl.cursorThemeHiDPI;
149     }
150
151     cursor = wl_cursor_theme_get_cursor(theme, name);
152     if (!cursor)
153     {
154         _glfwInputError(GLFW_PLATFORM_ERROR,
155                         "Wayland: Standard cursor not found");
156         return;
157     }
158     // TODO: handle animated cursors too.
159     image = cursor->images[0];
160
161     if (!image)
162         return;
163
164     buffer = wl_cursor_image_get_buffer(image);
165     if (!buffer)
166         return;
167     wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,
168                           surface,
169                           image->hotspot_x / scale,
170                           image->hotspot_y / scale);
171     wl_surface_set_buffer_scale(surface, scale);
172     wl_surface_attach(surface, buffer, 0, 0);
173     wl_surface_damage(surface, 0, 0,
174                       image->width, image->height);
175     wl_surface_commit(surface);
176     _glfw.wl.cursorPreviousName = name;
177 }
178
179 static void pointerHandleMotion(void* data,
180                                 struct wl_pointer* pointer,
181                                 uint32_t time,
182                                 wl_fixed_t sx,
183                                 wl_fixed_t sy)
184 {
185     _GLFWwindow* window = _glfw.wl.pointerFocus;
186     const char* cursorName = NULL;
187     double x, y;
188
189     if (!window)
190         return;
191
192     if (window->cursorMode == GLFW_CURSOR_DISABLED)
193         return;
194     x = wl_fixed_to_double(sx);
195     y = wl_fixed_to_double(sy);
196
197     switch (window->wl.decorations.focus)
198     {
199         case mainWindow:
200             window->wl.cursorPosX = x;
201             window->wl.cursorPosY = y;
202             _glfwInputCursorPos(window, x, y);
203             _glfw.wl.cursorPreviousName = NULL;
204             return;
205         case topDecoration:
206             if (y < _GLFW_DECORATION_WIDTH)
207                 cursorName = "n-resize";
208             else
209                 cursorName = "left_ptr";
210             break;
211         case leftDecoration:
212             if (y < _GLFW_DECORATION_WIDTH)
213                 cursorName = "nw-resize";
214             else
215                 cursorName = "w-resize";
216             break;
217         case rightDecoration:
218             if (y < _GLFW_DECORATION_WIDTH)
219                 cursorName = "ne-resize";
220             else
221                 cursorName = "e-resize";
222             break;
223         case bottomDecoration:
224             if (x < _GLFW_DECORATION_WIDTH)
225                 cursorName = "sw-resize";
226             else if (x > window->wl.width + _GLFW_DECORATION_WIDTH)
227                 cursorName = "se-resize";
228             else
229                 cursorName = "s-resize";
230             break;
231         default:
232             assert(0);
233     }
234     if (_glfw.wl.cursorPreviousName != cursorName)
235         setCursor(window, cursorName);
236 }
237
238 static void pointerHandleButton(void* data,
239                                 struct wl_pointer* pointer,
240                                 uint32_t serial,
241                                 uint32_t time,
242                                 uint32_t button,
243                                 uint32_t state)
244 {
245     _GLFWwindow* window = _glfw.wl.pointerFocus;
246     int glfwButton;
247     uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
248
249     if (!window)
250         return;
251     if (button == BTN_LEFT)
252     {
253         switch (window->wl.decorations.focus)
254         {
255             case mainWindow:
256                 break;
257             case topDecoration:
258                 if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
259                     edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
260                 else
261                 {
262                     xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
263                 }
264                 break;
265             case leftDecoration:
266                 if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
267                     edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
268                 else
269                     edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
270                 break;
271             case rightDecoration:
272                 if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
273                     edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
274                 else
275                     edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
276                 break;
277             case bottomDecoration:
278                 if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH)
279                     edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
280                 else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH)
281                     edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
282                 else
283                     edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;
284                 break;
285             default:
286                 assert(0);
287         }
288         if (edges != XDG_TOPLEVEL_RESIZE_EDGE_NONE)
289         {
290             xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat,
291                                 serial, edges);
292         }
293     }
294     else if (button == BTN_RIGHT)
295     {
296         if (window->wl.decorations.focus != mainWindow && window->wl.xdg.toplevel)
297         {
298             xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
299                                           _glfw.wl.seat, serial,
300                                           window->wl.cursorPosX,
301                                           window->wl.cursorPosY);
302             return;
303         }
304     }
305
306     // Don’t pass the button to the user if it was related to a decoration.
307     if (window->wl.decorations.focus != mainWindow)
308         return;
309
310     _glfw.wl.serial = serial;
311
312     /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
313      * codes. */
314     glfwButton = button - BTN_LEFT;
315
316     _glfwInputMouseClick(window,
317                          glfwButton,
318                          state == WL_POINTER_BUTTON_STATE_PRESSED
319                                 ? GLFW_PRESS
320                                 : GLFW_RELEASE,
321                          _glfw.wl.xkb.modifiers);
322 }
323
324 static void pointerHandleAxis(void* data,
325                               struct wl_pointer* pointer,
326                               uint32_t time,
327                               uint32_t axis,
328                               wl_fixed_t value)
329 {
330     _GLFWwindow* window = _glfw.wl.pointerFocus;
331     double x = 0.0, y = 0.0;
332     // Wayland scroll events are in pointer motion coordinate space (think two
333     // finger scroll).  The factor 10 is commonly used to convert to "scroll
334     // step means 1.0.
335     const double scrollFactor = 1.0 / 10.0;
336
337     if (!window)
338         return;
339
340     assert(axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL ||
341            axis == WL_POINTER_AXIS_VERTICAL_SCROLL);
342
343     if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
344         x = -wl_fixed_to_double(value) * scrollFactor;
345     else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
346         y = -wl_fixed_to_double(value) * scrollFactor;
347
348     _glfwInputScroll(window, x, y);
349 }
350
351 static const struct wl_pointer_listener pointerListener = {
352     pointerHandleEnter,
353     pointerHandleLeave,
354     pointerHandleMotion,
355     pointerHandleButton,
356     pointerHandleAxis,
357 };
358
359 static void keyboardHandleKeymap(void* data,
360                                  struct wl_keyboard* keyboard,
361                                  uint32_t format,
362                                  int fd,
363                                  uint32_t size)
364 {
365     struct xkb_keymap* keymap;
366     struct xkb_state* state;
367
368 #ifdef HAVE_XKBCOMMON_COMPOSE_H
369     struct xkb_compose_table* composeTable;
370     struct xkb_compose_state* composeState;
371 #endif
372
373     char* mapStr;
374     const char* locale;
375
376     if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
377     {
378         close(fd);
379         return;
380     }
381
382     mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
383     if (mapStr == MAP_FAILED) {
384         close(fd);
385         return;
386     }
387
388     keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context,
389                                         mapStr,
390                                         XKB_KEYMAP_FORMAT_TEXT_V1,
391                                         0);
392     munmap(mapStr, size);
393     close(fd);
394
395     if (!keymap)
396     {
397         _glfwInputError(GLFW_PLATFORM_ERROR,
398                         "Wayland: Failed to compile keymap");
399         return;
400     }
401
402     state = xkb_state_new(keymap);
403     if (!state)
404     {
405         _glfwInputError(GLFW_PLATFORM_ERROR,
406                         "Wayland: Failed to create XKB state");
407         xkb_keymap_unref(keymap);
408         return;
409     }
410
411     // Look up the preferred locale, falling back to "C" as default.
412     locale = getenv("LC_ALL");
413     if (!locale)
414         locale = getenv("LC_CTYPE");
415     if (!locale)
416         locale = getenv("LANG");
417     if (!locale)
418         locale = "C";
419
420 #ifdef HAVE_XKBCOMMON_COMPOSE_H
421     composeTable =
422         xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
423                                           XKB_COMPOSE_COMPILE_NO_FLAGS);
424     if (composeTable)
425     {
426         composeState =
427             xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
428         xkb_compose_table_unref(composeTable);
429         if (composeState)
430             _glfw.wl.xkb.composeState = composeState;
431         else
432             _glfwInputError(GLFW_PLATFORM_ERROR,
433                             "Wayland: Failed to create XKB compose state");
434     }
435     else
436     {
437         _glfwInputError(GLFW_PLATFORM_ERROR,
438                         "Wayland: Failed to create XKB compose table");
439     }
440 #endif
441
442     xkb_keymap_unref(_glfw.wl.xkb.keymap);
443     xkb_state_unref(_glfw.wl.xkb.state);
444     _glfw.wl.xkb.keymap = keymap;
445     _glfw.wl.xkb.state = state;
446
447     _glfw.wl.xkb.controlMask =
448         1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control");
449     _glfw.wl.xkb.altMask =
450         1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
451     _glfw.wl.xkb.shiftMask =
452         1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
453     _glfw.wl.xkb.superMask =
454         1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
455     _glfw.wl.xkb.capsLockMask =
456         1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Lock");
457     _glfw.wl.xkb.numLockMask =
458         1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod2");
459 }
460
461 static void keyboardHandleEnter(void* data,
462                                 struct wl_keyboard* keyboard,
463                                 uint32_t serial,
464                                 struct wl_surface* surface,
465                                 struct wl_array* keys)
466 {
467     // Happens in the case we just destroyed the surface.
468     if (!surface)
469         return;
470
471     _GLFWwindow* window = wl_surface_get_user_data(surface);
472     if (!window)
473     {
474         window = findWindowFromDecorationSurface(surface, NULL);
475         if (!window)
476             return;
477     }
478
479     _glfw.wl.serial = serial;
480     _glfw.wl.keyboardFocus = window;
481     _glfwInputWindowFocus(window, GLFW_TRUE);
482 }
483
484 static void keyboardHandleLeave(void* data,
485                                 struct wl_keyboard* keyboard,
486                                 uint32_t serial,
487                                 struct wl_surface* surface)
488 {
489     _GLFWwindow* window = _glfw.wl.keyboardFocus;
490
491     if (!window)
492         return;
493
494     _glfw.wl.serial = serial;
495     _glfw.wl.keyboardFocus = NULL;
496     _glfwInputWindowFocus(window, GLFW_FALSE);
497 }
498
499 static int toGLFWKeyCode(uint32_t key)
500 {
501     if (key < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
502         return _glfw.wl.keycodes[key];
503
504     return GLFW_KEY_UNKNOWN;
505 }
506
507 #ifdef HAVE_XKBCOMMON_COMPOSE_H
508 static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
509 {
510     if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
511         return sym;
512     if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym)
513             != XKB_COMPOSE_FEED_ACCEPTED)
514         return sym;
515     switch (xkb_compose_state_get_status(_glfw.wl.xkb.composeState))
516     {
517         case XKB_COMPOSE_COMPOSED:
518             return xkb_compose_state_get_one_sym(_glfw.wl.xkb.composeState);
519         case XKB_COMPOSE_COMPOSING:
520         case XKB_COMPOSE_CANCELLED:
521             return XKB_KEY_NoSymbol;
522         case XKB_COMPOSE_NOTHING:
523         default:
524             return sym;
525     }
526 }
527 #endif
528
529 static GLFWbool inputChar(_GLFWwindow* window, uint32_t key)
530 {
531     uint32_t code, numSyms;
532     long cp;
533     const xkb_keysym_t *syms;
534     xkb_keysym_t sym;
535
536     code = key + 8;
537     numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms);
538
539     if (numSyms == 1)
540     {
541 #ifdef HAVE_XKBCOMMON_COMPOSE_H
542         sym = composeSymbol(syms[0]);
543 #else
544         sym = syms[0];
545 #endif
546         cp = _glfwKeySym2Unicode(sym);
547         if (cp != -1)
548         {
549             const int mods = _glfw.wl.xkb.modifiers;
550             const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
551             _glfwInputChar(window, cp, mods, plain);
552         }
553     }
554
555     return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, syms[0]);
556 }
557
558 static void keyboardHandleKey(void* data,
559                               struct wl_keyboard* keyboard,
560                               uint32_t serial,
561                               uint32_t time,
562                               uint32_t key,
563                               uint32_t state)
564 {
565     int keyCode;
566     int action;
567     _GLFWwindow* window = _glfw.wl.keyboardFocus;
568     GLFWbool shouldRepeat;
569     struct itimerspec timer = {};
570
571     if (!window)
572         return;
573
574     keyCode = toGLFWKeyCode(key);
575     action = state == WL_KEYBOARD_KEY_STATE_PRESSED
576             ? GLFW_PRESS : GLFW_RELEASE;
577
578     _glfw.wl.serial = serial;
579     _glfwInputKey(window, keyCode, key, action,
580                   _glfw.wl.xkb.modifiers);
581
582     if (action == GLFW_PRESS)
583     {
584         shouldRepeat = inputChar(window, key);
585
586         if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0)
587         {
588             _glfw.wl.keyboardLastKey = keyCode;
589             _glfw.wl.keyboardLastScancode = key;
590             if (_glfw.wl.keyboardRepeatRate > 1)
591                 timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyboardRepeatRate;
592             else
593                 timer.it_interval.tv_sec = 1;
594             timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000;
595             timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000;
596         }
597     }
598     timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
599 }
600
601 static void keyboardHandleModifiers(void* data,
602                                     struct wl_keyboard* keyboard,
603                                     uint32_t serial,
604                                     uint32_t modsDepressed,
605                                     uint32_t modsLatched,
606                                     uint32_t modsLocked,
607                                     uint32_t group)
608 {
609     xkb_mod_mask_t mask;
610     unsigned int modifiers = 0;
611
612     _glfw.wl.serial = serial;
613
614     if (!_glfw.wl.xkb.keymap)
615         return;
616
617     xkb_state_update_mask(_glfw.wl.xkb.state,
618                           modsDepressed,
619                           modsLatched,
620                           modsLocked,
621                           0,
622                           0,
623                           group);
624
625     mask = xkb_state_serialize_mods(_glfw.wl.xkb.state,
626                                     XKB_STATE_MODS_DEPRESSED |
627                                     XKB_STATE_LAYOUT_DEPRESSED |
628                                     XKB_STATE_MODS_LATCHED |
629                                     XKB_STATE_LAYOUT_LATCHED);
630     if (mask & _glfw.wl.xkb.controlMask)
631         modifiers |= GLFW_MOD_CONTROL;
632     if (mask & _glfw.wl.xkb.altMask)
633         modifiers |= GLFW_MOD_ALT;
634     if (mask & _glfw.wl.xkb.shiftMask)
635         modifiers |= GLFW_MOD_SHIFT;
636     if (mask & _glfw.wl.xkb.superMask)
637         modifiers |= GLFW_MOD_SUPER;
638     if (mask & _glfw.wl.xkb.capsLockMask)
639         modifiers |= GLFW_MOD_CAPS_LOCK;
640     if (mask & _glfw.wl.xkb.numLockMask)
641         modifiers |= GLFW_MOD_NUM_LOCK;
642     _glfw.wl.xkb.modifiers = modifiers;
643 }
644
645 #ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
646 static void keyboardHandleRepeatInfo(void* data,
647                                      struct wl_keyboard* keyboard,
648                                      int32_t rate,
649                                      int32_t delay)
650 {
651     if (keyboard != _glfw.wl.keyboard)
652         return;
653
654     _glfw.wl.keyboardRepeatRate = rate;
655     _glfw.wl.keyboardRepeatDelay = delay;
656 }
657 #endif
658
659 static const struct wl_keyboard_listener keyboardListener = {
660     keyboardHandleKeymap,
661     keyboardHandleEnter,
662     keyboardHandleLeave,
663     keyboardHandleKey,
664     keyboardHandleModifiers,
665 #ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
666     keyboardHandleRepeatInfo,
667 #endif
668 };
669
670 static void seatHandleCapabilities(void* data,
671                                    struct wl_seat* seat,
672                                    enum wl_seat_capability caps)
673 {
674     if ((caps & WL_SEAT_CAPABILITY_POINTER) && !_glfw.wl.pointer)
675     {
676         _glfw.wl.pointer = wl_seat_get_pointer(seat);
677         wl_pointer_add_listener(_glfw.wl.pointer, &pointerListener, NULL);
678     }
679     else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && _glfw.wl.pointer)
680     {
681         wl_pointer_destroy(_glfw.wl.pointer);
682         _glfw.wl.pointer = NULL;
683     }
684
685     if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !_glfw.wl.keyboard)
686     {
687         _glfw.wl.keyboard = wl_seat_get_keyboard(seat);
688         wl_keyboard_add_listener(_glfw.wl.keyboard, &keyboardListener, NULL);
689     }
690     else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && _glfw.wl.keyboard)
691     {
692         wl_keyboard_destroy(_glfw.wl.keyboard);
693         _glfw.wl.keyboard = NULL;
694     }
695 }
696
697 static void seatHandleName(void* data,
698                            struct wl_seat* seat,
699                            const char* name)
700 {
701 }
702
703 static const struct wl_seat_listener seatListener = {
704     seatHandleCapabilities,
705     seatHandleName,
706 };
707
708 static void dataOfferHandleOffer(void* data,
709                                  struct wl_data_offer* dataOffer,
710                                  const char* mimeType)
711 {
712 }
713
714 static const struct wl_data_offer_listener dataOfferListener = {
715     dataOfferHandleOffer,
716 };
717
718 static void dataDeviceHandleDataOffer(void* data,
719                                       struct wl_data_device* dataDevice,
720                                       struct wl_data_offer* id)
721 {
722     if (_glfw.wl.dataOffer)
723         wl_data_offer_destroy(_glfw.wl.dataOffer);
724
725     _glfw.wl.dataOffer = id;
726     wl_data_offer_add_listener(_glfw.wl.dataOffer, &dataOfferListener, NULL);
727 }
728
729 static void dataDeviceHandleEnter(void* data,
730                                   struct wl_data_device* dataDevice,
731                                   uint32_t serial,
732                                   struct wl_surface *surface,
733                                   wl_fixed_t x,
734                                   wl_fixed_t y,
735                                   struct wl_data_offer *id)
736 {
737 }
738
739 static void dataDeviceHandleLeave(void* data,
740                                   struct wl_data_device* dataDevice)
741 {
742 }
743
744 static void dataDeviceHandleMotion(void* data,
745                                    struct wl_data_device* dataDevice,
746                                    uint32_t time,
747                                    wl_fixed_t x,
748                                    wl_fixed_t y)
749 {
750 }
751
752 static void dataDeviceHandleDrop(void* data,
753                                  struct wl_data_device* dataDevice)
754 {
755 }
756
757 static void dataDeviceHandleSelection(void* data,
758                                       struct wl_data_device* dataDevice,
759                                       struct wl_data_offer* id)
760 {
761 }
762
763 static const struct wl_data_device_listener dataDeviceListener = {
764     dataDeviceHandleDataOffer,
765     dataDeviceHandleEnter,
766     dataDeviceHandleLeave,
767     dataDeviceHandleMotion,
768     dataDeviceHandleDrop,
769     dataDeviceHandleSelection,
770 };
771
772 static void wmBaseHandlePing(void* data,
773                              struct xdg_wm_base* wmBase,
774                              uint32_t serial)
775 {
776     xdg_wm_base_pong(wmBase, serial);
777 }
778
779 static const struct xdg_wm_base_listener wmBaseListener = {
780     wmBaseHandlePing
781 };
782
783 static void registryHandleGlobal(void* data,
784                                  struct wl_registry* registry,
785                                  uint32_t name,
786                                  const char* interface,
787                                  uint32_t version)
788 {
789     if (strcmp(interface, "wl_compositor") == 0)
790     {
791         _glfw.wl.compositorVersion = min(3, version);
792         _glfw.wl.compositor =
793             wl_registry_bind(registry, name, &wl_compositor_interface,
794                              _glfw.wl.compositorVersion);
795     }
796     else if (strcmp(interface, "wl_subcompositor") == 0)
797     {
798         _glfw.wl.subcompositor =
799             wl_registry_bind(registry, name, &wl_subcompositor_interface, 1);
800     }
801     else if (strcmp(interface, "wl_shm") == 0)
802     {
803         _glfw.wl.shm =
804             wl_registry_bind(registry, name, &wl_shm_interface, 1);
805     }
806     else if (strcmp(interface, "wl_output") == 0)
807     {
808         _glfwAddOutputWayland(name, version);
809     }
810     else if (strcmp(interface, "wl_seat") == 0)
811     {
812         if (!_glfw.wl.seat)
813         {
814             _glfw.wl.seatVersion = min(4, version);
815             _glfw.wl.seat =
816                 wl_registry_bind(registry, name, &wl_seat_interface,
817                                  _glfw.wl.seatVersion);
818             wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL);
819         }
820     }
821     else if (strcmp(interface, "wl_data_device_manager") == 0)
822     {
823         if (!_glfw.wl.dataDeviceManager)
824         {
825             _glfw.wl.dataDeviceManager =
826                 wl_registry_bind(registry, name,
827                                  &wl_data_device_manager_interface, 1);
828         }
829     }
830     else if (strcmp(interface, "xdg_wm_base") == 0)
831     {
832         _glfw.wl.wmBase =
833             wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
834         xdg_wm_base_add_listener(_glfw.wl.wmBase, &wmBaseListener, NULL);
835     }
836     else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0)
837     {
838         _glfw.wl.decorationManager =
839             wl_registry_bind(registry, name,
840                              &zxdg_decoration_manager_v1_interface,
841                              1);
842     }
843     else if (strcmp(interface, "wp_viewporter") == 0)
844     {
845         _glfw.wl.viewporter =
846             wl_registry_bind(registry, name, &wp_viewporter_interface, 1);
847     }
848     else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0)
849     {
850         _glfw.wl.relativePointerManager =
851             wl_registry_bind(registry, name,
852                              &zwp_relative_pointer_manager_v1_interface,
853                              1);
854     }
855     else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0)
856     {
857         _glfw.wl.pointerConstraints =
858             wl_registry_bind(registry, name,
859                              &zwp_pointer_constraints_v1_interface,
860                              1);
861     }
862     else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0)
863     {
864         _glfw.wl.idleInhibitManager =
865             wl_registry_bind(registry, name,
866                              &zwp_idle_inhibit_manager_v1_interface,
867                              1);
868     }
869 }
870
871 static void registryHandleGlobalRemove(void *data,
872                                        struct wl_registry *registry,
873                                        uint32_t name)
874 {
875     int i;
876     _GLFWmonitor* monitor;
877
878     for (i = 0; i < _glfw.monitorCount; ++i)
879     {
880         monitor = _glfw.monitors[i];
881         if (monitor->wl.name == name)
882         {
883             _glfwInputMonitor(monitor, GLFW_DISCONNECTED, 0);
884             return;
885         }
886     }
887 }
888
889
890 static const struct wl_registry_listener registryListener = {
891     registryHandleGlobal,
892     registryHandleGlobalRemove
893 };
894
895 // Create key code translation tables
896 //
897 static void createKeyTables(void)
898 {
899     int scancode;
900
901     memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes));
902     memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes));
903
904     _glfw.wl.keycodes[KEY_GRAVE]      = GLFW_KEY_GRAVE_ACCENT;
905     _glfw.wl.keycodes[KEY_1]          = GLFW_KEY_1;
906     _glfw.wl.keycodes[KEY_2]          = GLFW_KEY_2;
907     _glfw.wl.keycodes[KEY_3]          = GLFW_KEY_3;
908     _glfw.wl.keycodes[KEY_4]          = GLFW_KEY_4;
909     _glfw.wl.keycodes[KEY_5]          = GLFW_KEY_5;
910     _glfw.wl.keycodes[KEY_6]          = GLFW_KEY_6;
911     _glfw.wl.keycodes[KEY_7]          = GLFW_KEY_7;
912     _glfw.wl.keycodes[KEY_8]          = GLFW_KEY_8;
913     _glfw.wl.keycodes[KEY_9]          = GLFW_KEY_9;
914     _glfw.wl.keycodes[KEY_0]          = GLFW_KEY_0;
915     _glfw.wl.keycodes[KEY_SPACE]      = GLFW_KEY_SPACE;
916     _glfw.wl.keycodes[KEY_MINUS]      = GLFW_KEY_MINUS;
917     _glfw.wl.keycodes[KEY_EQUAL]      = GLFW_KEY_EQUAL;
918     _glfw.wl.keycodes[KEY_Q]          = GLFW_KEY_Q;
919     _glfw.wl.keycodes[KEY_W]          = GLFW_KEY_W;
920     _glfw.wl.keycodes[KEY_E]          = GLFW_KEY_E;
921     _glfw.wl.keycodes[KEY_R]          = GLFW_KEY_R;
922     _glfw.wl.keycodes[KEY_T]          = GLFW_KEY_T;
923     _glfw.wl.keycodes[KEY_Y]          = GLFW_KEY_Y;
924     _glfw.wl.keycodes[KEY_U]          = GLFW_KEY_U;
925     _glfw.wl.keycodes[KEY_I]          = GLFW_KEY_I;
926     _glfw.wl.keycodes[KEY_O]          = GLFW_KEY_O;
927     _glfw.wl.keycodes[KEY_P]          = GLFW_KEY_P;
928     _glfw.wl.keycodes[KEY_LEFTBRACE]  = GLFW_KEY_LEFT_BRACKET;
929     _glfw.wl.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
930     _glfw.wl.keycodes[KEY_A]          = GLFW_KEY_A;
931     _glfw.wl.keycodes[KEY_S]          = GLFW_KEY_S;
932     _glfw.wl.keycodes[KEY_D]          = GLFW_KEY_D;
933     _glfw.wl.keycodes[KEY_F]          = GLFW_KEY_F;
934     _glfw.wl.keycodes[KEY_G]          = GLFW_KEY_G;
935     _glfw.wl.keycodes[KEY_H]          = GLFW_KEY_H;
936     _glfw.wl.keycodes[KEY_J]          = GLFW_KEY_J;
937     _glfw.wl.keycodes[KEY_K]          = GLFW_KEY_K;
938     _glfw.wl.keycodes[KEY_L]          = GLFW_KEY_L;
939     _glfw.wl.keycodes[KEY_SEMICOLON]  = GLFW_KEY_SEMICOLON;
940     _glfw.wl.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
941     _glfw.wl.keycodes[KEY_Z]          = GLFW_KEY_Z;
942     _glfw.wl.keycodes[KEY_X]          = GLFW_KEY_X;
943     _glfw.wl.keycodes[KEY_C]          = GLFW_KEY_C;
944     _glfw.wl.keycodes[KEY_V]          = GLFW_KEY_V;
945     _glfw.wl.keycodes[KEY_B]          = GLFW_KEY_B;
946     _glfw.wl.keycodes[KEY_N]          = GLFW_KEY_N;
947     _glfw.wl.keycodes[KEY_M]          = GLFW_KEY_M;
948     _glfw.wl.keycodes[KEY_COMMA]      = GLFW_KEY_COMMA;
949     _glfw.wl.keycodes[KEY_DOT]        = GLFW_KEY_PERIOD;
950     _glfw.wl.keycodes[KEY_SLASH]      = GLFW_KEY_SLASH;
951     _glfw.wl.keycodes[KEY_BACKSLASH]  = GLFW_KEY_BACKSLASH;
952     _glfw.wl.keycodes[KEY_ESC]        = GLFW_KEY_ESCAPE;
953     _glfw.wl.keycodes[KEY_TAB]        = GLFW_KEY_TAB;
954     _glfw.wl.keycodes[KEY_LEFTSHIFT]  = GLFW_KEY_LEFT_SHIFT;
955     _glfw.wl.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
956     _glfw.wl.keycodes[KEY_LEFTCTRL]   = GLFW_KEY_LEFT_CONTROL;
957     _glfw.wl.keycodes[KEY_RIGHTCTRL]  = GLFW_KEY_RIGHT_CONTROL;
958     _glfw.wl.keycodes[KEY_LEFTALT]    = GLFW_KEY_LEFT_ALT;
959     _glfw.wl.keycodes[KEY_RIGHTALT]   = GLFW_KEY_RIGHT_ALT;
960     _glfw.wl.keycodes[KEY_LEFTMETA]   = GLFW_KEY_LEFT_SUPER;
961     _glfw.wl.keycodes[KEY_RIGHTMETA]  = GLFW_KEY_RIGHT_SUPER;
962     _glfw.wl.keycodes[KEY_MENU]       = GLFW_KEY_MENU;
963     _glfw.wl.keycodes[KEY_NUMLOCK]    = GLFW_KEY_NUM_LOCK;
964     _glfw.wl.keycodes[KEY_CAPSLOCK]   = GLFW_KEY_CAPS_LOCK;
965     _glfw.wl.keycodes[KEY_PRINT]      = GLFW_KEY_PRINT_SCREEN;
966     _glfw.wl.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
967     _glfw.wl.keycodes[KEY_PAUSE]      = GLFW_KEY_PAUSE;
968     _glfw.wl.keycodes[KEY_DELETE]     = GLFW_KEY_DELETE;
969     _glfw.wl.keycodes[KEY_BACKSPACE]  = GLFW_KEY_BACKSPACE;
970     _glfw.wl.keycodes[KEY_ENTER]      = GLFW_KEY_ENTER;
971     _glfw.wl.keycodes[KEY_HOME]       = GLFW_KEY_HOME;
972     _glfw.wl.keycodes[KEY_END]        = GLFW_KEY_END;
973     _glfw.wl.keycodes[KEY_PAGEUP]     = GLFW_KEY_PAGE_UP;
974     _glfw.wl.keycodes[KEY_PAGEDOWN]   = GLFW_KEY_PAGE_DOWN;
975     _glfw.wl.keycodes[KEY_INSERT]     = GLFW_KEY_INSERT;
976     _glfw.wl.keycodes[KEY_LEFT]       = GLFW_KEY_LEFT;
977     _glfw.wl.keycodes[KEY_RIGHT]      = GLFW_KEY_RIGHT;
978     _glfw.wl.keycodes[KEY_DOWN]       = GLFW_KEY_DOWN;
979     _glfw.wl.keycodes[KEY_UP]         = GLFW_KEY_UP;
980     _glfw.wl.keycodes[KEY_F1]         = GLFW_KEY_F1;
981     _glfw.wl.keycodes[KEY_F2]         = GLFW_KEY_F2;
982     _glfw.wl.keycodes[KEY_F3]         = GLFW_KEY_F3;
983     _glfw.wl.keycodes[KEY_F4]         = GLFW_KEY_F4;
984     _glfw.wl.keycodes[KEY_F5]         = GLFW_KEY_F5;
985     _glfw.wl.keycodes[KEY_F6]         = GLFW_KEY_F6;
986     _glfw.wl.keycodes[KEY_F7]         = GLFW_KEY_F7;
987     _glfw.wl.keycodes[KEY_F8]         = GLFW_KEY_F8;
988     _glfw.wl.keycodes[KEY_F9]         = GLFW_KEY_F9;
989     _glfw.wl.keycodes[KEY_F10]        = GLFW_KEY_F10;
990     _glfw.wl.keycodes[KEY_F11]        = GLFW_KEY_F11;
991     _glfw.wl.keycodes[KEY_F12]        = GLFW_KEY_F12;
992     _glfw.wl.keycodes[KEY_F13]        = GLFW_KEY_F13;
993     _glfw.wl.keycodes[KEY_F14]        = GLFW_KEY_F14;
994     _glfw.wl.keycodes[KEY_F15]        = GLFW_KEY_F15;
995     _glfw.wl.keycodes[KEY_F16]        = GLFW_KEY_F16;
996     _glfw.wl.keycodes[KEY_F17]        = GLFW_KEY_F17;
997     _glfw.wl.keycodes[KEY_F18]        = GLFW_KEY_F18;
998     _glfw.wl.keycodes[KEY_F19]        = GLFW_KEY_F19;
999     _glfw.wl.keycodes[KEY_F20]        = GLFW_KEY_F20;
1000     _glfw.wl.keycodes[KEY_F21]        = GLFW_KEY_F21;
1001     _glfw.wl.keycodes[KEY_F22]        = GLFW_KEY_F22;
1002     _glfw.wl.keycodes[KEY_F23]        = GLFW_KEY_F23;
1003     _glfw.wl.keycodes[KEY_F24]        = GLFW_KEY_F24;
1004     _glfw.wl.keycodes[KEY_KPSLASH]    = GLFW_KEY_KP_DIVIDE;
1005     _glfw.wl.keycodes[KEY_KPDOT]      = GLFW_KEY_KP_MULTIPLY;
1006     _glfw.wl.keycodes[KEY_KPMINUS]    = GLFW_KEY_KP_SUBTRACT;
1007     _glfw.wl.keycodes[KEY_KPPLUS]     = GLFW_KEY_KP_ADD;
1008     _glfw.wl.keycodes[KEY_KP0]        = GLFW_KEY_KP_0;
1009     _glfw.wl.keycodes[KEY_KP1]        = GLFW_KEY_KP_1;
1010     _glfw.wl.keycodes[KEY_KP2]        = GLFW_KEY_KP_2;
1011     _glfw.wl.keycodes[KEY_KP3]        = GLFW_KEY_KP_3;
1012     _glfw.wl.keycodes[KEY_KP4]        = GLFW_KEY_KP_4;
1013     _glfw.wl.keycodes[KEY_KP5]        = GLFW_KEY_KP_5;
1014     _glfw.wl.keycodes[KEY_KP6]        = GLFW_KEY_KP_6;
1015     _glfw.wl.keycodes[KEY_KP7]        = GLFW_KEY_KP_7;
1016     _glfw.wl.keycodes[KEY_KP8]        = GLFW_KEY_KP_8;
1017     _glfw.wl.keycodes[KEY_KP9]        = GLFW_KEY_KP_9;
1018     _glfw.wl.keycodes[KEY_KPCOMMA]    = GLFW_KEY_KP_DECIMAL;
1019     _glfw.wl.keycodes[KEY_KPEQUAL]    = GLFW_KEY_KP_EQUAL;
1020     _glfw.wl.keycodes[KEY_KPENTER]    = GLFW_KEY_KP_ENTER;
1021
1022     for (scancode = 0;  scancode < 256;  scancode++)
1023     {
1024         if (_glfw.wl.keycodes[scancode] > 0)
1025             _glfw.wl.scancodes[_glfw.wl.keycodes[scancode]] = scancode;
1026     }
1027 }
1028
1029
1030 //////////////////////////////////////////////////////////////////////////
1031 //////                       GLFW platform API                      //////
1032 //////////////////////////////////////////////////////////////////////////
1033
1034 int _glfwPlatformInit(void)
1035 {
1036     const char *cursorTheme;
1037     const char *cursorSizeStr;
1038     char *cursorSizeEnd;
1039     long cursorSizeLong;
1040     int cursorSize;
1041     int i;
1042     _GLFWmonitor* monitor;
1043
1044     _glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");
1045     if (!_glfw.wl.cursor.handle)
1046     {
1047         _glfwInputError(GLFW_PLATFORM_ERROR,
1048                         "Wayland: Failed to open libwayland-cursor");
1049         return GLFW_FALSE;
1050     }
1051
1052     _glfw.wl.cursor.theme_load = (PFN_wl_cursor_theme_load)
1053         _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_load");
1054     _glfw.wl.cursor.theme_destroy = (PFN_wl_cursor_theme_destroy)
1055         _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_destroy");
1056     _glfw.wl.cursor.theme_get_cursor = (PFN_wl_cursor_theme_get_cursor)
1057         _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor");
1058     _glfw.wl.cursor.image_get_buffer = (PFN_wl_cursor_image_get_buffer)
1059         _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_image_get_buffer");
1060
1061     _glfw.wl.egl.handle = _glfw_dlopen("libwayland-egl.so.1");
1062     if (!_glfw.wl.egl.handle)
1063     {
1064         _glfwInputError(GLFW_PLATFORM_ERROR,
1065                         "Wayland: Failed to open libwayland-egl");
1066         return GLFW_FALSE;
1067     }
1068
1069     _glfw.wl.egl.window_create = (PFN_wl_egl_window_create)
1070         _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_create");
1071     _glfw.wl.egl.window_destroy = (PFN_wl_egl_window_destroy)
1072         _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_destroy");
1073     _glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize)
1074         _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_resize");
1075
1076     _glfw.wl.xkb.handle = _glfw_dlopen("libxkbcommon.so.0");
1077     if (!_glfw.wl.xkb.handle)
1078     {
1079         _glfwInputError(GLFW_PLATFORM_ERROR,
1080                         "Wayland: Failed to open libxkbcommon");
1081         return GLFW_FALSE;
1082     }
1083
1084     _glfw.wl.xkb.context_new = (PFN_xkb_context_new)
1085         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_new");
1086     _glfw.wl.xkb.context_unref = (PFN_xkb_context_unref)
1087         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_unref");
1088     _glfw.wl.xkb.keymap_new_from_string = (PFN_xkb_keymap_new_from_string)
1089         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_new_from_string");
1090     _glfw.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref)
1091         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_unref");
1092     _glfw.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index)
1093         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
1094     _glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats)
1095         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats");
1096     _glfw.wl.xkb.state_new = (PFN_xkb_state_new)
1097         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new");
1098     _glfw.wl.xkb.state_unref = (PFN_xkb_state_unref)
1099         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_unref");
1100     _glfw.wl.xkb.state_key_get_syms = (PFN_xkb_state_key_get_syms)
1101         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_syms");
1102     _glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask)
1103         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask");
1104     _glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods)
1105         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods");
1106
1107 #ifdef HAVE_XKBCOMMON_COMPOSE_H
1108     _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)
1109         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");
1110     _glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref)
1111         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_unref");
1112     _glfw.wl.xkb.compose_state_new = (PFN_xkb_compose_state_new)
1113         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_new");
1114     _glfw.wl.xkb.compose_state_unref = (PFN_xkb_compose_state_unref)
1115         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_unref");
1116     _glfw.wl.xkb.compose_state_feed = (PFN_xkb_compose_state_feed)
1117         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_feed");
1118     _glfw.wl.xkb.compose_state_get_status = (PFN_xkb_compose_state_get_status)
1119         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status");
1120     _glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)
1121         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");
1122 #endif
1123
1124     _glfw.wl.display = wl_display_connect(NULL);
1125     if (!_glfw.wl.display)
1126     {
1127         _glfwInputError(GLFW_PLATFORM_ERROR,
1128                         "Wayland: Failed to connect to display");
1129         return GLFW_FALSE;
1130     }
1131
1132     _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
1133     wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);
1134
1135     createKeyTables();
1136
1137     _glfw.wl.xkb.context = xkb_context_new(0);
1138     if (!_glfw.wl.xkb.context)
1139     {
1140         _glfwInputError(GLFW_PLATFORM_ERROR,
1141                         "Wayland: Failed to initialize xkb context");
1142         return GLFW_FALSE;
1143     }
1144
1145     // Sync so we got all registry objects
1146     wl_display_roundtrip(_glfw.wl.display);
1147
1148     // Sync so we got all initial output events
1149     wl_display_roundtrip(_glfw.wl.display);
1150
1151     for (i = 0; i < _glfw.monitorCount; ++i)
1152     {
1153         monitor = _glfw.monitors[i];
1154         if (monitor->widthMM <= 0 || monitor->heightMM <= 0)
1155         {
1156             // If Wayland does not provide a physical size, assume the default 96 DPI
1157             monitor->widthMM  = (int) (monitor->modes[monitor->wl.currentMode].width * 25.4f / 96.f);
1158             monitor->heightMM = (int) (monitor->modes[monitor->wl.currentMode].height * 25.4f / 96.f);
1159         }
1160     }
1161
1162     _glfwInitTimerPOSIX();
1163
1164     _glfw.wl.timerfd = -1;
1165     if (_glfw.wl.seatVersion >= 4)
1166         _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
1167
1168     if (!_glfw.wl.wmBase)
1169     {
1170         _glfwInputError(GLFW_PLATFORM_ERROR,
1171                         "Wayland: Failed to find xdg-shell in your compositor");
1172         return GLFW_FALSE;
1173     }
1174
1175     if (_glfw.wl.pointer && _glfw.wl.shm)
1176     {
1177         cursorTheme = getenv("XCURSOR_THEME");
1178         cursorSizeStr = getenv("XCURSOR_SIZE");
1179         cursorSize = 32;
1180         if (cursorSizeStr)
1181         {
1182             errno = 0;
1183             cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10);
1184             if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX)
1185                 cursorSize = (int)cursorSizeLong;
1186         }
1187         _glfw.wl.cursorTheme =
1188             wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm);
1189         if (!_glfw.wl.cursorTheme)
1190         {
1191             _glfwInputError(GLFW_PLATFORM_ERROR,
1192                             "Wayland: Unable to load default cursor theme");
1193             return GLFW_FALSE;
1194         }
1195         // If this happens to be NULL, we just fallback to the scale=1 version.
1196         _glfw.wl.cursorThemeHiDPI =
1197             wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm);
1198         _glfw.wl.cursorSurface =
1199             wl_compositor_create_surface(_glfw.wl.compositor);
1200         _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
1201     }
1202
1203     if (_glfw.wl.seat && _glfw.wl.dataDeviceManager)
1204     {
1205         _glfw.wl.dataDevice =
1206             wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager,
1207                                                    _glfw.wl.seat);
1208         wl_data_device_add_listener(_glfw.wl.dataDevice, &dataDeviceListener, NULL);
1209         _glfw.wl.clipboardString = malloc(4096);
1210         if (!_glfw.wl.clipboardString)
1211         {
1212             _glfwInputError(GLFW_PLATFORM_ERROR,
1213                             "Wayland: Unable to allocate clipboard memory");
1214             return GLFW_FALSE;
1215         }
1216         _glfw.wl.clipboardSize = 4096;
1217     }
1218
1219     return GLFW_TRUE;
1220 }
1221
1222 void _glfwPlatformTerminate(void)
1223 {
1224     _glfwTerminateEGL();
1225     if (_glfw.wl.egl.handle)
1226     {
1227         _glfw_dlclose(_glfw.wl.egl.handle);
1228         _glfw.wl.egl.handle = NULL;
1229     }
1230
1231 #ifdef HAVE_XKBCOMMON_COMPOSE_H
1232     if (_glfw.wl.xkb.composeState)
1233         xkb_compose_state_unref(_glfw.wl.xkb.composeState);
1234 #endif
1235     if (_glfw.wl.xkb.keymap)
1236         xkb_keymap_unref(_glfw.wl.xkb.keymap);
1237     if (_glfw.wl.xkb.state)
1238         xkb_state_unref(_glfw.wl.xkb.state);
1239     if (_glfw.wl.xkb.context)
1240         xkb_context_unref(_glfw.wl.xkb.context);
1241     if (_glfw.wl.xkb.handle)
1242     {
1243         _glfw_dlclose(_glfw.wl.xkb.handle);
1244         _glfw.wl.xkb.handle = NULL;
1245     }
1246
1247     if (_glfw.wl.cursorTheme)
1248         wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
1249     if (_glfw.wl.cursorThemeHiDPI)
1250         wl_cursor_theme_destroy(_glfw.wl.cursorThemeHiDPI);
1251     if (_glfw.wl.cursor.handle)
1252     {
1253         _glfw_dlclose(_glfw.wl.cursor.handle);
1254         _glfw.wl.cursor.handle = NULL;
1255     }
1256
1257     if (_glfw.wl.cursorSurface)
1258         wl_surface_destroy(_glfw.wl.cursorSurface);
1259     if (_glfw.wl.subcompositor)
1260         wl_subcompositor_destroy(_glfw.wl.subcompositor);
1261     if (_glfw.wl.compositor)
1262         wl_compositor_destroy(_glfw.wl.compositor);
1263     if (_glfw.wl.shm)
1264         wl_shm_destroy(_glfw.wl.shm);
1265     if (_glfw.wl.viewporter)
1266         wp_viewporter_destroy(_glfw.wl.viewporter);
1267     if (_glfw.wl.decorationManager)
1268         zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager);
1269     if (_glfw.wl.wmBase)
1270         xdg_wm_base_destroy(_glfw.wl.wmBase);
1271     if (_glfw.wl.dataSource)
1272         wl_data_source_destroy(_glfw.wl.dataSource);
1273     if (_glfw.wl.dataDevice)
1274         wl_data_device_destroy(_glfw.wl.dataDevice);
1275     if (_glfw.wl.dataOffer)
1276         wl_data_offer_destroy(_glfw.wl.dataOffer);
1277     if (_glfw.wl.dataDeviceManager)
1278         wl_data_device_manager_destroy(_glfw.wl.dataDeviceManager);
1279     if (_glfw.wl.pointer)
1280         wl_pointer_destroy(_glfw.wl.pointer);
1281     if (_glfw.wl.keyboard)
1282         wl_keyboard_destroy(_glfw.wl.keyboard);
1283     if (_glfw.wl.seat)
1284         wl_seat_destroy(_glfw.wl.seat);
1285     if (_glfw.wl.relativePointerManager)
1286         zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager);
1287     if (_glfw.wl.pointerConstraints)
1288         zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints);
1289     if (_glfw.wl.idleInhibitManager)
1290         zwp_idle_inhibit_manager_v1_destroy(_glfw.wl.idleInhibitManager);
1291     if (_glfw.wl.registry)
1292         wl_registry_destroy(_glfw.wl.registry);
1293     if (_glfw.wl.display)
1294     {
1295         wl_display_flush(_glfw.wl.display);
1296         wl_display_disconnect(_glfw.wl.display);
1297     }
1298
1299     if (_glfw.wl.timerfd >= 0)
1300         close(_glfw.wl.timerfd);
1301     if (_glfw.wl.cursorTimerfd >= 0)
1302         close(_glfw.wl.cursorTimerfd);
1303
1304     if (_glfw.wl.clipboardString)
1305         free(_glfw.wl.clipboardString);
1306     if (_glfw.wl.clipboardSendString)
1307         free(_glfw.wl.clipboardSendString);
1308 }
1309
1310 const char* _glfwPlatformGetVersionString(void)
1311 {
1312     return _GLFW_VERSION_NUMBER " Wayland EGL OSMesa"
1313 #if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
1314         " clock_gettime"
1315 #else
1316         " gettimeofday"
1317 #endif
1318         " evdev"
1319 #if defined(_GLFW_BUILD_DLL)
1320         " shared"
1321 #endif
1322         ;
1323 }