1 //========================================================================
2 // GLFW 3.2 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
27 #include "internal.h"
28
29 #include <linux/input.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/mman.h>
34 #include <unistd.h>
35 #include <wayland-client.h>
36 #include <wayland-cursor.h>
37
38
min(int n1,int n2)39 static inline int min(int n1, int n2)
40 {
41 return n1 < n2 ? n1 : n2;
42 }
43
pointerHandleEnter(void * data,struct wl_pointer * pointer,uint32_t serial,struct wl_surface * surface,wl_fixed_t sx,wl_fixed_t sy)44 static void pointerHandleEnter(void* data,
45 struct wl_pointer* pointer,
46 uint32_t serial,
47 struct wl_surface* surface,
48 wl_fixed_t sx,
49 wl_fixed_t sy)
50 {
51 _GLFWwindow* window = wl_surface_get_user_data(surface);
52
53 _glfw.wl.pointerSerial = serial;
54 _glfw.wl.pointerFocus = window;
55
56 _glfwPlatformSetCursor(window, window->wl.currentCursor);
57 _glfwInputCursorEnter(window, GLFW_TRUE);
58 }
59
pointerHandleLeave(void * data,struct wl_pointer * pointer,uint32_t serial,struct wl_surface * surface)60 static void pointerHandleLeave(void* data,
61 struct wl_pointer* pointer,
62 uint32_t serial,
63 struct wl_surface* surface)
64 {
65 _GLFWwindow* window = _glfw.wl.pointerFocus;
66
67 if (!window)
68 return;
69
70 _glfw.wl.pointerSerial = serial;
71 _glfw.wl.pointerFocus = NULL;
72 _glfwInputCursorEnter(window, GLFW_FALSE);
73 }
74
pointerHandleMotion(void * data,struct wl_pointer * pointer,uint32_t time,wl_fixed_t sx,wl_fixed_t sy)75 static void pointerHandleMotion(void* data,
76 struct wl_pointer* pointer,
77 uint32_t time,
78 wl_fixed_t sx,
79 wl_fixed_t sy)
80 {
81 _GLFWwindow* window = _glfw.wl.pointerFocus;
82
83 if (!window)
84 return;
85
86 if (window->cursorMode == GLFW_CURSOR_DISABLED)
87 return;
88 else
89 {
90 window->wl.cursorPosX = wl_fixed_to_double(sx);
91 window->wl.cursorPosY = wl_fixed_to_double(sy);
92 }
93
94 _glfwInputCursorPos(window,
95 wl_fixed_to_double(sx),
96 wl_fixed_to_double(sy));
97 }
98
pointerHandleButton(void * data,struct wl_pointer * wl_pointer,uint32_t serial,uint32_t time,uint32_t button,uint32_t state)99 static void pointerHandleButton(void* data,
100 struct wl_pointer* wl_pointer,
101 uint32_t serial,
102 uint32_t time,
103 uint32_t button,
104 uint32_t state)
105 {
106 _GLFWwindow* window = _glfw.wl.pointerFocus;
107 int glfwButton;
108
109 if (!window)
110 return;
111
112 /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
113 * codes. */
114 glfwButton = button - BTN_LEFT;
115
116 _glfwInputMouseClick(window,
117 glfwButton,
118 state == WL_POINTER_BUTTON_STATE_PRESSED
119 ? GLFW_PRESS
120 : GLFW_RELEASE,
121 _glfw.wl.xkb.modifiers);
122 }
123
pointerHandleAxis(void * data,struct wl_pointer * wl_pointer,uint32_t time,uint32_t axis,wl_fixed_t value)124 static void pointerHandleAxis(void* data,
125 struct wl_pointer* wl_pointer,
126 uint32_t time,
127 uint32_t axis,
128 wl_fixed_t value)
129 {
130 _GLFWwindow* window = _glfw.wl.pointerFocus;
131 double scroll_factor;
132 double x, y;
133
134 if (!window)
135 return;
136
137 /* Wayland scroll events are in pointer motion coordinate space (think
138 * two finger scroll). The factor 10 is commonly used to convert to
139 * "scroll step means 1.0. */
140 scroll_factor = 1.0/10.0;
141
142 switch (axis)
143 {
144 case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
145 x = wl_fixed_to_double(value) * scroll_factor;
146 y = 0.0;
147 break;
148 case WL_POINTER_AXIS_VERTICAL_SCROLL:
149 x = 0.0;
150 y = wl_fixed_to_double(value) * scroll_factor;
151 break;
152 default:
153 break;
154 }
155
156 _glfwInputScroll(window, x, y);
157 }
158
159 static const struct wl_pointer_listener pointerListener = {
160 pointerHandleEnter,
161 pointerHandleLeave,
162 pointerHandleMotion,
163 pointerHandleButton,
164 pointerHandleAxis,
165 };
166
keyboardHandleKeymap(void * data,struct wl_keyboard * keyboard,uint32_t format,int fd,uint32_t size)167 static void keyboardHandleKeymap(void* data,
168 struct wl_keyboard* keyboard,
169 uint32_t format,
170 int fd,
171 uint32_t size)
172 {
173 struct xkb_keymap* keymap;
174 struct xkb_state* state;
175 char* mapStr;
176
177 if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
178 {
179 close(fd);
180 return;
181 }
182
183 mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
184 if (mapStr == MAP_FAILED) {
185 close(fd);
186 return;
187 }
188
189 keymap = xkb_map_new_from_string(_glfw.wl.xkb.context,
190 mapStr,
191 XKB_KEYMAP_FORMAT_TEXT_V1,
192 0);
193 munmap(mapStr, size);
194 close(fd);
195
196 if (!keymap)
197 {
198 _glfwInputError(GLFW_PLATFORM_ERROR,
199 "Wayland: Failed to compile keymap");
200 return;
201 }
202
203 state = xkb_state_new(keymap);
204 if (!state)
205 {
206 _glfwInputError(GLFW_PLATFORM_ERROR,
207 "Wayland: Failed to create XKB state");
208 xkb_map_unref(keymap);
209 return;
210 }
211
212 xkb_keymap_unref(_glfw.wl.xkb.keymap);
213 xkb_state_unref(_glfw.wl.xkb.state);
214 _glfw.wl.xkb.keymap = keymap;
215 _glfw.wl.xkb.state = state;
216
217 _glfw.wl.xkb.control_mask =
218 1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Control");
219 _glfw.wl.xkb.alt_mask =
220 1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
221 _glfw.wl.xkb.shift_mask =
222 1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
223 _glfw.wl.xkb.super_mask =
224 1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
225 }
226
keyboardHandleEnter(void * data,struct wl_keyboard * keyboard,uint32_t serial,struct wl_surface * surface,struct wl_array * keys)227 static void keyboardHandleEnter(void* data,
228 struct wl_keyboard* keyboard,
229 uint32_t serial,
230 struct wl_surface* surface,
231 struct wl_array* keys)
232 {
233 _GLFWwindow* window = wl_surface_get_user_data(surface);
234
235 _glfw.wl.keyboardFocus = window;
236 _glfwInputWindowFocus(window, GLFW_TRUE);
237 }
238
keyboardHandleLeave(void * data,struct wl_keyboard * keyboard,uint32_t serial,struct wl_surface * surface)239 static void keyboardHandleLeave(void* data,
240 struct wl_keyboard* keyboard,
241 uint32_t serial,
242 struct wl_surface* surface)
243 {
244 _GLFWwindow* window = _glfw.wl.keyboardFocus;
245
246 if (!window)
247 return;
248
249 _glfw.wl.keyboardFocus = NULL;
250 _glfwInputWindowFocus(window, GLFW_FALSE);
251 }
252
toGLFWKeyCode(uint32_t key)253 static int toGLFWKeyCode(uint32_t key)
254 {
255 if (key < sizeof(_glfw.wl.publicKeys) / sizeof(_glfw.wl.publicKeys[0]))
256 return _glfw.wl.publicKeys[key];
257
258 return GLFW_KEY_UNKNOWN;
259 }
260
keyboardHandleKey(void * data,struct wl_keyboard * keyboard,uint32_t serial,uint32_t time,uint32_t key,uint32_t state)261 static void keyboardHandleKey(void* data,
262 struct wl_keyboard* keyboard,
263 uint32_t serial,
264 uint32_t time,
265 uint32_t key,
266 uint32_t state)
267 {
268 uint32_t code, num_syms;
269 long cp;
270 int keyCode;
271 int action;
272 const xkb_keysym_t *syms;
273 _GLFWwindow* window = _glfw.wl.keyboardFocus;
274
275 if (!window)
276 return;
277
278 keyCode = toGLFWKeyCode(key);
279 action = state == WL_KEYBOARD_KEY_STATE_PRESSED
280 ? GLFW_PRESS : GLFW_RELEASE;
281
282 _glfwInputKey(window, keyCode, key, action,
283 _glfw.wl.xkb.modifiers);
284
285 code = key + 8;
286 num_syms = xkb_key_get_syms(_glfw.wl.xkb.state, code, &syms);
287
288 if (num_syms == 1)
289 {
290 cp = _glfwKeySym2Unicode(syms[0]);
291 if (cp != -1)
292 {
293 const int mods = _glfw.wl.xkb.modifiers;
294 const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
295 _glfwInputChar(window, cp, mods, plain);
296 }
297 }
298 }
299
keyboardHandleModifiers(void * data,struct wl_keyboard * keyboard,uint32_t serial,uint32_t modsDepressed,uint32_t modsLatched,uint32_t modsLocked,uint32_t group)300 static void keyboardHandleModifiers(void* data,
301 struct wl_keyboard* keyboard,
302 uint32_t serial,
303 uint32_t modsDepressed,
304 uint32_t modsLatched,
305 uint32_t modsLocked,
306 uint32_t group)
307 {
308 xkb_mod_mask_t mask;
309 unsigned int modifiers = 0;
310
311 if (!_glfw.wl.xkb.keymap)
312 return;
313
314 xkb_state_update_mask(_glfw.wl.xkb.state,
315 modsDepressed,
316 modsLatched,
317 modsLocked,
318 0,
319 0,
320 group);
321
322 mask = xkb_state_serialize_mods(_glfw.wl.xkb.state,
323 XKB_STATE_DEPRESSED |
324 XKB_STATE_LATCHED);
325 if (mask & _glfw.wl.xkb.control_mask)
326 modifiers |= GLFW_MOD_CONTROL;
327 if (mask & _glfw.wl.xkb.alt_mask)
328 modifiers |= GLFW_MOD_ALT;
329 if (mask & _glfw.wl.xkb.shift_mask)
330 modifiers |= GLFW_MOD_SHIFT;
331 if (mask & _glfw.wl.xkb.super_mask)
332 modifiers |= GLFW_MOD_SUPER;
333 _glfw.wl.xkb.modifiers = modifiers;
334 }
335
336 static const struct wl_keyboard_listener keyboardListener = {
337 keyboardHandleKeymap,
338 keyboardHandleEnter,
339 keyboardHandleLeave,
340 keyboardHandleKey,
341 keyboardHandleModifiers,
342 };
343
seatHandleCapabilities(void * data,struct wl_seat * seat,enum wl_seat_capability caps)344 static void seatHandleCapabilities(void* data,
345 struct wl_seat* seat,
346 enum wl_seat_capability caps)
347 {
348 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !_glfw.wl.pointer)
349 {
350 _glfw.wl.pointer = wl_seat_get_pointer(seat);
351 wl_pointer_add_listener(_glfw.wl.pointer, &pointerListener, NULL);
352 }
353 else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && _glfw.wl.pointer)
354 {
355 wl_pointer_destroy(_glfw.wl.pointer);
356 _glfw.wl.pointer = NULL;
357 }
358
359 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !_glfw.wl.keyboard)
360 {
361 _glfw.wl.keyboard = wl_seat_get_keyboard(seat);
362 wl_keyboard_add_listener(_glfw.wl.keyboard, &keyboardListener, NULL);
363 }
364 else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && _glfw.wl.keyboard)
365 {
366 wl_keyboard_destroy(_glfw.wl.keyboard);
367 _glfw.wl.keyboard = NULL;
368 }
369 }
370
371 static const struct wl_seat_listener seatListener = {
372 seatHandleCapabilities
373 };
374
registryHandleGlobal(void * data,struct wl_registry * registry,uint32_t name,const char * interface,uint32_t version)375 static void registryHandleGlobal(void* data,
376 struct wl_registry* registry,
377 uint32_t name,
378 const char* interface,
379 uint32_t version)
380 {
381 if (strcmp(interface, "wl_compositor") == 0)
382 {
383 _glfw.wl.wl_compositor_version = min(3, version);
384 _glfw.wl.compositor =
385 wl_registry_bind(registry, name, &wl_compositor_interface,
386 _glfw.wl.wl_compositor_version);
387 }
388 else if (strcmp(interface, "wl_shm") == 0)
389 {
390 _glfw.wl.shm =
391 wl_registry_bind(registry, name, &wl_shm_interface, 1);
392 }
393 else if (strcmp(interface, "wl_shell") == 0)
394 {
395 _glfw.wl.shell =
396 wl_registry_bind(registry, name, &wl_shell_interface, 1);
397 }
398 else if (strcmp(interface, "wl_output") == 0)
399 {
400 _glfwAddOutputWayland(name, version);
401 }
402 else if (strcmp(interface, "wl_seat") == 0)
403 {
404 if (!_glfw.wl.seat)
405 {
406 _glfw.wl.seat =
407 wl_registry_bind(registry, name, &wl_seat_interface, 1);
408 wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL);
409 }
410 }
411 else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0)
412 {
413 _glfw.wl.relativePointerManager =
414 wl_registry_bind(registry, name,
415 &zwp_relative_pointer_manager_v1_interface,
416 1);
417 }
418 else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0)
419 {
420 _glfw.wl.pointerConstraints =
421 wl_registry_bind(registry, name,
422 &zwp_pointer_constraints_v1_interface,
423 1);
424 }
425 }
426
registryHandleGlobalRemove(void * data,struct wl_registry * registry,uint32_t name)427 static void registryHandleGlobalRemove(void *data,
428 struct wl_registry *registry,
429 uint32_t name)
430 {
431 }
432
433
434 static const struct wl_registry_listener registryListener = {
435 registryHandleGlobal,
436 registryHandleGlobalRemove
437 };
438
439 // Create key code translation tables
440 //
createKeyTables(void)441 static void createKeyTables(void)
442 {
443 memset(_glfw.wl.publicKeys, -1, sizeof(_glfw.wl.publicKeys));
444
445 _glfw.wl.publicKeys[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
446 _glfw.wl.publicKeys[KEY_1] = GLFW_KEY_1;
447 _glfw.wl.publicKeys[KEY_2] = GLFW_KEY_2;
448 _glfw.wl.publicKeys[KEY_3] = GLFW_KEY_3;
449 _glfw.wl.publicKeys[KEY_4] = GLFW_KEY_4;
450 _glfw.wl.publicKeys[KEY_5] = GLFW_KEY_5;
451 _glfw.wl.publicKeys[KEY_6] = GLFW_KEY_6;
452 _glfw.wl.publicKeys[KEY_7] = GLFW_KEY_7;
453 _glfw.wl.publicKeys[KEY_8] = GLFW_KEY_8;
454 _glfw.wl.publicKeys[KEY_9] = GLFW_KEY_9;
455 _glfw.wl.publicKeys[KEY_0] = GLFW_KEY_0;
456 _glfw.wl.publicKeys[KEY_MINUS] = GLFW_KEY_MINUS;
457 _glfw.wl.publicKeys[KEY_EQUAL] = GLFW_KEY_EQUAL;
458 _glfw.wl.publicKeys[KEY_Q] = GLFW_KEY_Q;
459 _glfw.wl.publicKeys[KEY_W] = GLFW_KEY_W;
460 _glfw.wl.publicKeys[KEY_E] = GLFW_KEY_E;
461 _glfw.wl.publicKeys[KEY_R] = GLFW_KEY_R;
462 _glfw.wl.publicKeys[KEY_T] = GLFW_KEY_T;
463 _glfw.wl.publicKeys[KEY_Y] = GLFW_KEY_Y;
464 _glfw.wl.publicKeys[KEY_U] = GLFW_KEY_U;
465 _glfw.wl.publicKeys[KEY_I] = GLFW_KEY_I;
466 _glfw.wl.publicKeys[KEY_O] = GLFW_KEY_O;
467 _glfw.wl.publicKeys[KEY_P] = GLFW_KEY_P;
468 _glfw.wl.publicKeys[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
469 _glfw.wl.publicKeys[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
470 _glfw.wl.publicKeys[KEY_A] = GLFW_KEY_A;
471 _glfw.wl.publicKeys[KEY_S] = GLFW_KEY_S;
472 _glfw.wl.publicKeys[KEY_D] = GLFW_KEY_D;
473 _glfw.wl.publicKeys[KEY_F] = GLFW_KEY_F;
474 _glfw.wl.publicKeys[KEY_G] = GLFW_KEY_G;
475 _glfw.wl.publicKeys[KEY_H] = GLFW_KEY_H;
476 _glfw.wl.publicKeys[KEY_J] = GLFW_KEY_J;
477 _glfw.wl.publicKeys[KEY_K] = GLFW_KEY_K;
478 _glfw.wl.publicKeys[KEY_L] = GLFW_KEY_L;
479 _glfw.wl.publicKeys[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
480 _glfw.wl.publicKeys[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
481 _glfw.wl.publicKeys[KEY_Z] = GLFW_KEY_Z;
482 _glfw.wl.publicKeys[KEY_X] = GLFW_KEY_X;
483 _glfw.wl.publicKeys[KEY_C] = GLFW_KEY_C;
484 _glfw.wl.publicKeys[KEY_V] = GLFW_KEY_V;
485 _glfw.wl.publicKeys[KEY_B] = GLFW_KEY_B;
486 _glfw.wl.publicKeys[KEY_N] = GLFW_KEY_N;
487 _glfw.wl.publicKeys[KEY_M] = GLFW_KEY_M;
488 _glfw.wl.publicKeys[KEY_COMMA] = GLFW_KEY_COMMA;
489 _glfw.wl.publicKeys[KEY_DOT] = GLFW_KEY_PERIOD;
490 _glfw.wl.publicKeys[KEY_SLASH] = GLFW_KEY_SLASH;
491 _glfw.wl.publicKeys[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
492 _glfw.wl.publicKeys[KEY_ESC] = GLFW_KEY_ESCAPE;
493 _glfw.wl.publicKeys[KEY_TAB] = GLFW_KEY_TAB;
494 _glfw.wl.publicKeys[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
495 _glfw.wl.publicKeys[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
496 _glfw.wl.publicKeys[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
497 _glfw.wl.publicKeys[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
498 _glfw.wl.publicKeys[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
499 _glfw.wl.publicKeys[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
500 _glfw.wl.publicKeys[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
501 _glfw.wl.publicKeys[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
502 _glfw.wl.publicKeys[KEY_MENU] = GLFW_KEY_MENU;
503 _glfw.wl.publicKeys[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
504 _glfw.wl.publicKeys[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
505 _glfw.wl.publicKeys[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
506 _glfw.wl.publicKeys[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
507 _glfw.wl.publicKeys[KEY_PAUSE] = GLFW_KEY_PAUSE;
508 _glfw.wl.publicKeys[KEY_DELETE] = GLFW_KEY_DELETE;
509 _glfw.wl.publicKeys[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
510 _glfw.wl.publicKeys[KEY_ENTER] = GLFW_KEY_ENTER;
511 _glfw.wl.publicKeys[KEY_HOME] = GLFW_KEY_HOME;
512 _glfw.wl.publicKeys[KEY_END] = GLFW_KEY_END;
513 _glfw.wl.publicKeys[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
514 _glfw.wl.publicKeys[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
515 _glfw.wl.publicKeys[KEY_INSERT] = GLFW_KEY_INSERT;
516 _glfw.wl.publicKeys[KEY_LEFT] = GLFW_KEY_LEFT;
517 _glfw.wl.publicKeys[KEY_RIGHT] = GLFW_KEY_RIGHT;
518 _glfw.wl.publicKeys[KEY_DOWN] = GLFW_KEY_DOWN;
519 _glfw.wl.publicKeys[KEY_UP] = GLFW_KEY_UP;
520 _glfw.wl.publicKeys[KEY_F1] = GLFW_KEY_F1;
521 _glfw.wl.publicKeys[KEY_F2] = GLFW_KEY_F2;
522 _glfw.wl.publicKeys[KEY_F3] = GLFW_KEY_F3;
523 _glfw.wl.publicKeys[KEY_F4] = GLFW_KEY_F4;
524 _glfw.wl.publicKeys[KEY_F5] = GLFW_KEY_F5;
525 _glfw.wl.publicKeys[KEY_F6] = GLFW_KEY_F6;
526 _glfw.wl.publicKeys[KEY_F7] = GLFW_KEY_F7;
527 _glfw.wl.publicKeys[KEY_F8] = GLFW_KEY_F8;
528 _glfw.wl.publicKeys[KEY_F9] = GLFW_KEY_F9;
529 _glfw.wl.publicKeys[KEY_F10] = GLFW_KEY_F10;
530 _glfw.wl.publicKeys[KEY_F11] = GLFW_KEY_F11;
531 _glfw.wl.publicKeys[KEY_F12] = GLFW_KEY_F12;
532 _glfw.wl.publicKeys[KEY_F13] = GLFW_KEY_F13;
533 _glfw.wl.publicKeys[KEY_F14] = GLFW_KEY_F14;
534 _glfw.wl.publicKeys[KEY_F15] = GLFW_KEY_F15;
535 _glfw.wl.publicKeys[KEY_F16] = GLFW_KEY_F16;
536 _glfw.wl.publicKeys[KEY_F17] = GLFW_KEY_F17;
537 _glfw.wl.publicKeys[KEY_F18] = GLFW_KEY_F18;
538 _glfw.wl.publicKeys[KEY_F19] = GLFW_KEY_F19;
539 _glfw.wl.publicKeys[KEY_F20] = GLFW_KEY_F20;
540 _glfw.wl.publicKeys[KEY_F21] = GLFW_KEY_F21;
541 _glfw.wl.publicKeys[KEY_F22] = GLFW_KEY_F22;
542 _glfw.wl.publicKeys[KEY_F23] = GLFW_KEY_F23;
543 _glfw.wl.publicKeys[KEY_F24] = GLFW_KEY_F24;
544 _glfw.wl.publicKeys[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
545 _glfw.wl.publicKeys[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
546 _glfw.wl.publicKeys[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
547 _glfw.wl.publicKeys[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
548 _glfw.wl.publicKeys[KEY_KP0] = GLFW_KEY_KP_0;
549 _glfw.wl.publicKeys[KEY_KP1] = GLFW_KEY_KP_1;
550 _glfw.wl.publicKeys[KEY_KP2] = GLFW_KEY_KP_2;
551 _glfw.wl.publicKeys[KEY_KP3] = GLFW_KEY_KP_3;
552 _glfw.wl.publicKeys[KEY_KP4] = GLFW_KEY_KP_4;
553 _glfw.wl.publicKeys[KEY_KP5] = GLFW_KEY_KP_5;
554 _glfw.wl.publicKeys[KEY_KP6] = GLFW_KEY_KP_6;
555 _glfw.wl.publicKeys[KEY_KP7] = GLFW_KEY_KP_7;
556 _glfw.wl.publicKeys[KEY_KP8] = GLFW_KEY_KP_8;
557 _glfw.wl.publicKeys[KEY_KP9] = GLFW_KEY_KP_9;
558 _glfw.wl.publicKeys[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
559 _glfw.wl.publicKeys[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
560 _glfw.wl.publicKeys[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
561 }
562
563
564 //////////////////////////////////////////////////////////////////////////
565 ////// GLFW platform API //////
566 //////////////////////////////////////////////////////////////////////////
567
_glfwPlatformInit(void)568 int _glfwPlatformInit(void)
569 {
570 _glfw.wl.display = wl_display_connect(NULL);
571 if (!_glfw.wl.display)
572 {
573 _glfwInputError(GLFW_PLATFORM_ERROR,
574 "Wayland: Failed to connect to display");
575 return GLFW_FALSE;
576 }
577
578 _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
579 wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
580
581 _glfw.wl.monitors = calloc(4, sizeof(_GLFWmonitor*));
582 _glfw.wl.monitorsSize = 4;
583
584 createKeyTables();
585
586 _glfw.wl.xkb.context = xkb_context_new(0);
587 if (!_glfw.wl.xkb.context)
588 {
589 _glfwInputError(GLFW_PLATFORM_ERROR,
590 "Wayland: Failed to initialize xkb context");
591 return GLFW_FALSE;
592 }
593
594 // Sync so we got all registry objects
595 wl_display_roundtrip(_glfw.wl.display);
596
597 // Sync so we got all initial output events
598 wl_display_roundtrip(_glfw.wl.display);
599
600 if (!_glfwInitThreadLocalStoragePOSIX())
601 return GLFW_FALSE;
602
603 if (!_glfwInitJoysticksLinux())
604 return GLFW_FALSE;
605
606 _glfwInitTimerPOSIX();
607
608 if (_glfw.wl.pointer && _glfw.wl.shm)
609 {
610 _glfw.wl.cursorTheme = wl_cursor_theme_load(NULL, 32, _glfw.wl.shm);
611 if (!_glfw.wl.cursorTheme)
612 {
613 _glfwInputError(GLFW_PLATFORM_ERROR,
614 "Wayland: Unable to load default cursor theme\n");
615 return GLFW_FALSE;
616 }
617 _glfw.wl.cursorSurface =
618 wl_compositor_create_surface(_glfw.wl.compositor);
619 }
620
621 return GLFW_TRUE;
622 }
623
_glfwPlatformTerminate(void)624 void _glfwPlatformTerminate(void)
625 {
626 _glfwTerminateEGL();
627 _glfwTerminateJoysticksLinux();
628 _glfwTerminateThreadLocalStoragePOSIX();
629
630 if (_glfw.wl.cursorTheme)
631 wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
632 if (_glfw.wl.cursorSurface)
633 wl_surface_destroy(_glfw.wl.cursorSurface);
634 if (_glfw.wl.registry)
635 wl_registry_destroy(_glfw.wl.registry);
636 if (_glfw.wl.display)
637 wl_display_flush(_glfw.wl.display);
638 if (_glfw.wl.display)
639 wl_display_disconnect(_glfw.wl.display);
640 }
641
_glfwPlatformGetVersionString(void)642 const char* _glfwPlatformGetVersionString(void)
643 {
644 return _GLFW_VERSION_NUMBER " Wayland EGL"
645 #if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
646 " clock_gettime"
647 #else
648 " gettimeofday"
649 #endif
650 #if defined(__linux__)
651 " /dev/js"
652 #endif
653 #if defined(_GLFW_BUILD_DLL)
654 " shared"
655 #endif
656 ;
657 }
658
659