wl_init.c (45879B)
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 1042 _glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0"); 1043 if (!_glfw.wl.cursor.handle) 1044 { 1045 _glfwInputError(GLFW_PLATFORM_ERROR, 1046 "Wayland: Failed to open libwayland-cursor"); 1047 return GLFW_FALSE; 1048 } 1049 1050 _glfw.wl.cursor.theme_load = (PFN_wl_cursor_theme_load) 1051 _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_load"); 1052 _glfw.wl.cursor.theme_destroy = (PFN_wl_cursor_theme_destroy) 1053 _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_destroy"); 1054 _glfw.wl.cursor.theme_get_cursor = (PFN_wl_cursor_theme_get_cursor) 1055 _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor"); 1056 _glfw.wl.cursor.image_get_buffer = (PFN_wl_cursor_image_get_buffer) 1057 _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_image_get_buffer"); 1058 1059 _glfw.wl.egl.handle = _glfw_dlopen("libwayland-egl.so.1"); 1060 if (!_glfw.wl.egl.handle) 1061 { 1062 _glfwInputError(GLFW_PLATFORM_ERROR, 1063 "Wayland: Failed to open libwayland-egl"); 1064 return GLFW_FALSE; 1065 } 1066 1067 _glfw.wl.egl.window_create = (PFN_wl_egl_window_create) 1068 _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_create"); 1069 _glfw.wl.egl.window_destroy = (PFN_wl_egl_window_destroy) 1070 _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_destroy"); 1071 _glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize) 1072 _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_resize"); 1073 1074 _glfw.wl.xkb.handle = _glfw_dlopen("libxkbcommon.so.0"); 1075 if (!_glfw.wl.xkb.handle) 1076 { 1077 _glfwInputError(GLFW_PLATFORM_ERROR, 1078 "Wayland: Failed to open libxkbcommon"); 1079 return GLFW_FALSE; 1080 } 1081 1082 _glfw.wl.xkb.context_new = (PFN_xkb_context_new) 1083 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_new"); 1084 _glfw.wl.xkb.context_unref = (PFN_xkb_context_unref) 1085 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_unref"); 1086 _glfw.wl.xkb.keymap_new_from_string = (PFN_xkb_keymap_new_from_string) 1087 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_new_from_string"); 1088 _glfw.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref) 1089 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_unref"); 1090 _glfw.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index) 1091 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index"); 1092 _glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats) 1093 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats"); 1094 _glfw.wl.xkb.state_new = (PFN_xkb_state_new) 1095 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new"); 1096 _glfw.wl.xkb.state_unref = (PFN_xkb_state_unref) 1097 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_unref"); 1098 _glfw.wl.xkb.state_key_get_syms = (PFN_xkb_state_key_get_syms) 1099 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_syms"); 1100 _glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask) 1101 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask"); 1102 _glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods) 1103 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods"); 1104 1105 #ifdef HAVE_XKBCOMMON_COMPOSE_H 1106 _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale) 1107 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale"); 1108 _glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref) 1109 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_unref"); 1110 _glfw.wl.xkb.compose_state_new = (PFN_xkb_compose_state_new) 1111 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_new"); 1112 _glfw.wl.xkb.compose_state_unref = (PFN_xkb_compose_state_unref) 1113 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_unref"); 1114 _glfw.wl.xkb.compose_state_feed = (PFN_xkb_compose_state_feed) 1115 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_feed"); 1116 _glfw.wl.xkb.compose_state_get_status = (PFN_xkb_compose_state_get_status) 1117 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status"); 1118 _glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym) 1119 _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym"); 1120 #endif 1121 1122 _glfw.wl.display = wl_display_connect(NULL); 1123 if (!_glfw.wl.display) 1124 { 1125 _glfwInputError(GLFW_PLATFORM_ERROR, 1126 "Wayland: Failed to connect to display"); 1127 return GLFW_FALSE; 1128 } 1129 1130 _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display); 1131 wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL); 1132 1133 createKeyTables(); 1134 1135 _glfw.wl.xkb.context = xkb_context_new(0); 1136 if (!_glfw.wl.xkb.context) 1137 { 1138 _glfwInputError(GLFW_PLATFORM_ERROR, 1139 "Wayland: Failed to initialize xkb context"); 1140 return GLFW_FALSE; 1141 } 1142 1143 // Sync so we got all registry objects 1144 wl_display_roundtrip(_glfw.wl.display); 1145 1146 // Sync so we got all initial output events 1147 wl_display_roundtrip(_glfw.wl.display); 1148 1149 #ifdef __linux__ 1150 if (!_glfwInitJoysticksLinux()) 1151 return GLFW_FALSE; 1152 #endif 1153 1154 _glfwInitTimerPOSIX(); 1155 1156 _glfw.wl.timerfd = -1; 1157 if (_glfw.wl.seatVersion >= 4) 1158 _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); 1159 1160 if (!_glfw.wl.wmBase) 1161 { 1162 _glfwInputError(GLFW_PLATFORM_ERROR, 1163 "Wayland: Failed to find xdg-shell in your compositor"); 1164 return GLFW_FALSE; 1165 } 1166 1167 if (_glfw.wl.pointer && _glfw.wl.shm) 1168 { 1169 cursorTheme = getenv("XCURSOR_THEME"); 1170 cursorSizeStr = getenv("XCURSOR_SIZE"); 1171 cursorSize = 32; 1172 if (cursorSizeStr) 1173 { 1174 errno = 0; 1175 cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10); 1176 if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX) 1177 cursorSize = (int)cursorSizeLong; 1178 } 1179 _glfw.wl.cursorTheme = 1180 wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm); 1181 if (!_glfw.wl.cursorTheme) 1182 { 1183 _glfwInputError(GLFW_PLATFORM_ERROR, 1184 "Wayland: Unable to load default cursor theme"); 1185 return GLFW_FALSE; 1186 } 1187 // If this happens to be NULL, we just fallback to the scale=1 version. 1188 _glfw.wl.cursorThemeHiDPI = 1189 wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm); 1190 _glfw.wl.cursorSurface = 1191 wl_compositor_create_surface(_glfw.wl.compositor); 1192 _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); 1193 } 1194 1195 if (_glfw.wl.seat && _glfw.wl.dataDeviceManager) 1196 { 1197 _glfw.wl.dataDevice = 1198 wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager, 1199 _glfw.wl.seat); 1200 wl_data_device_add_listener(_glfw.wl.dataDevice, &dataDeviceListener, NULL); 1201 _glfw.wl.clipboardString = malloc(4096); 1202 if (!_glfw.wl.clipboardString) 1203 { 1204 _glfwInputError(GLFW_PLATFORM_ERROR, 1205 "Wayland: Unable to allocate clipboard memory"); 1206 return GLFW_FALSE; 1207 } 1208 _glfw.wl.clipboardSize = 4096; 1209 } 1210 1211 return GLFW_TRUE; 1212 } 1213 1214 void _glfwPlatformTerminate(void) 1215 { 1216 #ifdef __linux__ 1217 _glfwTerminateJoysticksLinux(); 1218 #endif 1219 _glfwTerminateEGL(); 1220 if (_glfw.wl.egl.handle) 1221 { 1222 _glfw_dlclose(_glfw.wl.egl.handle); 1223 _glfw.wl.egl.handle = NULL; 1224 } 1225 1226 #ifdef HAVE_XKBCOMMON_COMPOSE_H 1227 if (_glfw.wl.xkb.composeState) 1228 xkb_compose_state_unref(_glfw.wl.xkb.composeState); 1229 #endif 1230 if (_glfw.wl.xkb.keymap) 1231 xkb_keymap_unref(_glfw.wl.xkb.keymap); 1232 if (_glfw.wl.xkb.state) 1233 xkb_state_unref(_glfw.wl.xkb.state); 1234 if (_glfw.wl.xkb.context) 1235 xkb_context_unref(_glfw.wl.xkb.context); 1236 if (_glfw.wl.xkb.handle) 1237 { 1238 _glfw_dlclose(_glfw.wl.xkb.handle); 1239 _glfw.wl.xkb.handle = NULL; 1240 } 1241 1242 if (_glfw.wl.cursorTheme) 1243 wl_cursor_theme_destroy(_glfw.wl.cursorTheme); 1244 if (_glfw.wl.cursorThemeHiDPI) 1245 wl_cursor_theme_destroy(_glfw.wl.cursorThemeHiDPI); 1246 if (_glfw.wl.cursor.handle) 1247 { 1248 _glfw_dlclose(_glfw.wl.cursor.handle); 1249 _glfw.wl.cursor.handle = NULL; 1250 } 1251 1252 if (_glfw.wl.cursorSurface) 1253 wl_surface_destroy(_glfw.wl.cursorSurface); 1254 if (_glfw.wl.subcompositor) 1255 wl_subcompositor_destroy(_glfw.wl.subcompositor); 1256 if (_glfw.wl.compositor) 1257 wl_compositor_destroy(_glfw.wl.compositor); 1258 if (_glfw.wl.shm) 1259 wl_shm_destroy(_glfw.wl.shm); 1260 if (_glfw.wl.viewporter) 1261 wp_viewporter_destroy(_glfw.wl.viewporter); 1262 if (_glfw.wl.decorationManager) 1263 zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager); 1264 if (_glfw.wl.wmBase) 1265 xdg_wm_base_destroy(_glfw.wl.wmBase); 1266 if (_glfw.wl.dataSource) 1267 wl_data_source_destroy(_glfw.wl.dataSource); 1268 if (_glfw.wl.dataDevice) 1269 wl_data_device_destroy(_glfw.wl.dataDevice); 1270 if (_glfw.wl.dataOffer) 1271 wl_data_offer_destroy(_glfw.wl.dataOffer); 1272 if (_glfw.wl.dataDeviceManager) 1273 wl_data_device_manager_destroy(_glfw.wl.dataDeviceManager); 1274 if (_glfw.wl.pointer) 1275 wl_pointer_destroy(_glfw.wl.pointer); 1276 if (_glfw.wl.keyboard) 1277 wl_keyboard_destroy(_glfw.wl.keyboard); 1278 if (_glfw.wl.seat) 1279 wl_seat_destroy(_glfw.wl.seat); 1280 if (_glfw.wl.relativePointerManager) 1281 zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager); 1282 if (_glfw.wl.pointerConstraints) 1283 zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints); 1284 if (_glfw.wl.idleInhibitManager) 1285 zwp_idle_inhibit_manager_v1_destroy(_glfw.wl.idleInhibitManager); 1286 if (_glfw.wl.registry) 1287 wl_registry_destroy(_glfw.wl.registry); 1288 if (_glfw.wl.display) 1289 { 1290 wl_display_flush(_glfw.wl.display); 1291 wl_display_disconnect(_glfw.wl.display); 1292 } 1293 1294 if (_glfw.wl.timerfd >= 0) 1295 close(_glfw.wl.timerfd); 1296 if (_glfw.wl.cursorTimerfd >= 0) 1297 close(_glfw.wl.cursorTimerfd); 1298 1299 if (_glfw.wl.clipboardString) 1300 free(_glfw.wl.clipboardString); 1301 if (_glfw.wl.clipboardSendString) 1302 free(_glfw.wl.clipboardSendString); 1303 } 1304 1305 const char* _glfwPlatformGetVersionString(void) 1306 { 1307 return _GLFW_VERSION_NUMBER " Wayland EGL OSMesa" 1308 #if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK) 1309 " clock_gettime" 1310 #else 1311 " gettimeofday" 1312 #endif 1313 " evdev" 1314 #if defined(_GLFW_BUILD_DLL) 1315 " shared" 1316 #endif 1317 ; 1318 }