x11_init.c (70569B)
1 //======================================================================== 2 // GLFW 3.4 X11 (modified for raylib) - www.glfw.org; www.raylib.com 3 //------------------------------------------------------------------------ 4 // Copyright (c) 2002-2006 Marcus Geelnard 5 // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> 6 // Copyright (c) 2024 M374LX <wilsalx@gmail.com> 7 // 8 // This software is provided 'as-is', without any express or implied 9 // warranty. In no event will the authors be held liable for any damages 10 // arising from the use of this software. 11 // 12 // Permission is granted to anyone to use this software for any purpose, 13 // including commercial applications, and to alter it and redistribute it 14 // freely, subject to the following restrictions: 15 // 16 // 1. The origin of this software must not be misrepresented; you must not 17 // claim that you wrote the original software. If you use this software 18 // in a product, an acknowledgment in the product documentation would 19 // be appreciated but is not required. 20 // 21 // 2. Altered source versions must be plainly marked as such, and must not 22 // be misrepresented as being the original software. 23 // 24 // 3. This notice may not be removed or altered from any source 25 // distribution. 26 // 27 //======================================================================== 28 29 #include "internal.h" 30 31 #if defined(_GLFW_X11) 32 33 #include <stdlib.h> 34 #include <string.h> 35 #include <limits.h> 36 #include <stdio.h> 37 #include <locale.h> 38 #include <unistd.h> 39 #include <fcntl.h> 40 #include <errno.h> 41 #include <assert.h> 42 43 44 // Translate the X11 KeySyms for a key to a GLFW key code 45 // NOTE: This is only used as a fallback, in case the XKB method fails 46 // It is layout-dependent and will fail partially on most non-US layouts 47 // 48 static int translateKeySyms(const KeySym* keysyms, int width) 49 { 50 if (width > 1) 51 { 52 switch (keysyms[1]) 53 { 54 case XK_KP_0: return GLFW_KEY_KP_0; 55 case XK_KP_1: return GLFW_KEY_KP_1; 56 case XK_KP_2: return GLFW_KEY_KP_2; 57 case XK_KP_3: return GLFW_KEY_KP_3; 58 case XK_KP_4: return GLFW_KEY_KP_4; 59 case XK_KP_5: return GLFW_KEY_KP_5; 60 case XK_KP_6: return GLFW_KEY_KP_6; 61 case XK_KP_7: return GLFW_KEY_KP_7; 62 case XK_KP_8: return GLFW_KEY_KP_8; 63 case XK_KP_9: return GLFW_KEY_KP_9; 64 case XK_KP_Separator: 65 case XK_KP_Decimal: return GLFW_KEY_KP_DECIMAL; 66 case XK_KP_Equal: return GLFW_KEY_KP_EQUAL; 67 case XK_KP_Enter: return GLFW_KEY_KP_ENTER; 68 default: break; 69 } 70 } 71 72 switch (keysyms[0]) 73 { 74 case XK_Escape: return GLFW_KEY_ESCAPE; 75 case XK_Tab: return GLFW_KEY_TAB; 76 case XK_Shift_L: return GLFW_KEY_LEFT_SHIFT; 77 case XK_Shift_R: return GLFW_KEY_RIGHT_SHIFT; 78 case XK_Control_L: return GLFW_KEY_LEFT_CONTROL; 79 case XK_Control_R: return GLFW_KEY_RIGHT_CONTROL; 80 case XK_Meta_L: 81 case XK_Alt_L: return GLFW_KEY_LEFT_ALT; 82 case XK_Mode_switch: // Mapped to Alt_R on many keyboards 83 case XK_ISO_Level3_Shift: // AltGr on at least some machines 84 case XK_Meta_R: 85 case XK_Alt_R: return GLFW_KEY_RIGHT_ALT; 86 case XK_Super_L: return GLFW_KEY_LEFT_SUPER; 87 case XK_Super_R: return GLFW_KEY_RIGHT_SUPER; 88 case XK_Menu: return GLFW_KEY_MENU; 89 case XK_Num_Lock: return GLFW_KEY_NUM_LOCK; 90 case XK_Caps_Lock: return GLFW_KEY_CAPS_LOCK; 91 case XK_Print: return GLFW_KEY_PRINT_SCREEN; 92 case XK_Scroll_Lock: return GLFW_KEY_SCROLL_LOCK; 93 case XK_Pause: return GLFW_KEY_PAUSE; 94 case XK_Delete: return GLFW_KEY_DELETE; 95 case XK_BackSpace: return GLFW_KEY_BACKSPACE; 96 case XK_Return: return GLFW_KEY_ENTER; 97 case XK_Home: return GLFW_KEY_HOME; 98 case XK_End: return GLFW_KEY_END; 99 case XK_Page_Up: return GLFW_KEY_PAGE_UP; 100 case XK_Page_Down: return GLFW_KEY_PAGE_DOWN; 101 case XK_Insert: return GLFW_KEY_INSERT; 102 case XK_Left: return GLFW_KEY_LEFT; 103 case XK_Right: return GLFW_KEY_RIGHT; 104 case XK_Down: return GLFW_KEY_DOWN; 105 case XK_Up: return GLFW_KEY_UP; 106 case XK_F1: return GLFW_KEY_F1; 107 case XK_F2: return GLFW_KEY_F2; 108 case XK_F3: return GLFW_KEY_F3; 109 case XK_F4: return GLFW_KEY_F4; 110 case XK_F5: return GLFW_KEY_F5; 111 case XK_F6: return GLFW_KEY_F6; 112 case XK_F7: return GLFW_KEY_F7; 113 case XK_F8: return GLFW_KEY_F8; 114 case XK_F9: return GLFW_KEY_F9; 115 case XK_F10: return GLFW_KEY_F10; 116 case XK_F11: return GLFW_KEY_F11; 117 case XK_F12: return GLFW_KEY_F12; 118 case XK_F13: return GLFW_KEY_F13; 119 case XK_F14: return GLFW_KEY_F14; 120 case XK_F15: return GLFW_KEY_F15; 121 case XK_F16: return GLFW_KEY_F16; 122 case XK_F17: return GLFW_KEY_F17; 123 case XK_F18: return GLFW_KEY_F18; 124 case XK_F19: return GLFW_KEY_F19; 125 case XK_F20: return GLFW_KEY_F20; 126 case XK_F21: return GLFW_KEY_F21; 127 case XK_F22: return GLFW_KEY_F22; 128 case XK_F23: return GLFW_KEY_F23; 129 case XK_F24: return GLFW_KEY_F24; 130 case XK_F25: return GLFW_KEY_F25; 131 132 // Numeric keypad 133 case XK_KP_Divide: return GLFW_KEY_KP_DIVIDE; 134 case XK_KP_Multiply: return GLFW_KEY_KP_MULTIPLY; 135 case XK_KP_Subtract: return GLFW_KEY_KP_SUBTRACT; 136 case XK_KP_Add: return GLFW_KEY_KP_ADD; 137 138 // These should have been detected in secondary keysym test above! 139 case XK_KP_Insert: return GLFW_KEY_KP_0; 140 case XK_KP_End: return GLFW_KEY_KP_1; 141 case XK_KP_Down: return GLFW_KEY_KP_2; 142 case XK_KP_Page_Down: return GLFW_KEY_KP_3; 143 case XK_KP_Left: return GLFW_KEY_KP_4; 144 case XK_KP_Right: return GLFW_KEY_KP_6; 145 case XK_KP_Home: return GLFW_KEY_KP_7; 146 case XK_KP_Up: return GLFW_KEY_KP_8; 147 case XK_KP_Page_Up: return GLFW_KEY_KP_9; 148 case XK_KP_Delete: return GLFW_KEY_KP_DECIMAL; 149 case XK_KP_Equal: return GLFW_KEY_KP_EQUAL; 150 case XK_KP_Enter: return GLFW_KEY_KP_ENTER; 151 152 // Last resort: Check for printable keys (should not happen if the XKB 153 // extension is available). This will give a layout dependent mapping 154 // (which is wrong, and we may miss some keys, especially on non-US 155 // keyboards), but it's better than nothing... 156 case XK_a: return GLFW_KEY_A; 157 case XK_b: return GLFW_KEY_B; 158 case XK_c: return GLFW_KEY_C; 159 case XK_d: return GLFW_KEY_D; 160 case XK_e: return GLFW_KEY_E; 161 case XK_f: return GLFW_KEY_F; 162 case XK_g: return GLFW_KEY_G; 163 case XK_h: return GLFW_KEY_H; 164 case XK_i: return GLFW_KEY_I; 165 case XK_j: return GLFW_KEY_J; 166 case XK_k: return GLFW_KEY_K; 167 case XK_l: return GLFW_KEY_L; 168 case XK_m: return GLFW_KEY_M; 169 case XK_n: return GLFW_KEY_N; 170 case XK_o: return GLFW_KEY_O; 171 case XK_p: return GLFW_KEY_P; 172 case XK_q: return GLFW_KEY_Q; 173 case XK_r: return GLFW_KEY_R; 174 case XK_s: return GLFW_KEY_S; 175 case XK_t: return GLFW_KEY_T; 176 case XK_u: return GLFW_KEY_U; 177 case XK_v: return GLFW_KEY_V; 178 case XK_w: return GLFW_KEY_W; 179 case XK_x: return GLFW_KEY_X; 180 case XK_y: return GLFW_KEY_Y; 181 case XK_z: return GLFW_KEY_Z; 182 case XK_1: return GLFW_KEY_1; 183 case XK_2: return GLFW_KEY_2; 184 case XK_3: return GLFW_KEY_3; 185 case XK_4: return GLFW_KEY_4; 186 case XK_5: return GLFW_KEY_5; 187 case XK_6: return GLFW_KEY_6; 188 case XK_7: return GLFW_KEY_7; 189 case XK_8: return GLFW_KEY_8; 190 case XK_9: return GLFW_KEY_9; 191 case XK_0: return GLFW_KEY_0; 192 case XK_space: return GLFW_KEY_SPACE; 193 case XK_minus: return GLFW_KEY_MINUS; 194 case XK_equal: return GLFW_KEY_EQUAL; 195 case XK_bracketleft: return GLFW_KEY_LEFT_BRACKET; 196 case XK_bracketright: return GLFW_KEY_RIGHT_BRACKET; 197 case XK_backslash: return GLFW_KEY_BACKSLASH; 198 case XK_semicolon: return GLFW_KEY_SEMICOLON; 199 case XK_apostrophe: return GLFW_KEY_APOSTROPHE; 200 case XK_grave: return GLFW_KEY_GRAVE_ACCENT; 201 case XK_comma: return GLFW_KEY_COMMA; 202 case XK_period: return GLFW_KEY_PERIOD; 203 case XK_slash: return GLFW_KEY_SLASH; 204 case XK_less: return GLFW_KEY_WORLD_1; // At least in some layouts... 205 default: break; 206 } 207 208 // No matching translation was found 209 return GLFW_KEY_UNKNOWN; 210 } 211 212 // Create key code translation tables 213 // 214 static void createKeyTablesX11(void) 215 { 216 int scancodeMin, scancodeMax; 217 218 memset(_glfw.x11.keycodes, -1, sizeof(_glfw.x11.keycodes)); 219 memset(_glfw.x11.scancodes, -1, sizeof(_glfw.x11.scancodes)); 220 221 if (_glfw.x11.xkb.available) 222 { 223 // Use XKB to determine physical key locations independently of the 224 // current keyboard layout 225 226 XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd); 227 XkbGetNames(_glfw.x11.display, XkbKeyNamesMask | XkbKeyAliasesMask, desc); 228 229 scancodeMin = desc->min_key_code; 230 scancodeMax = desc->max_key_code; 231 232 const struct 233 { 234 int key; 235 char* name; 236 } keymap[] = 237 { 238 { GLFW_KEY_GRAVE_ACCENT, "TLDE" }, 239 { GLFW_KEY_1, "AE01" }, 240 { GLFW_KEY_2, "AE02" }, 241 { GLFW_KEY_3, "AE03" }, 242 { GLFW_KEY_4, "AE04" }, 243 { GLFW_KEY_5, "AE05" }, 244 { GLFW_KEY_6, "AE06" }, 245 { GLFW_KEY_7, "AE07" }, 246 { GLFW_KEY_8, "AE08" }, 247 { GLFW_KEY_9, "AE09" }, 248 { GLFW_KEY_0, "AE10" }, 249 { GLFW_KEY_MINUS, "AE11" }, 250 { GLFW_KEY_EQUAL, "AE12" }, 251 { GLFW_KEY_Q, "AD01" }, 252 { GLFW_KEY_W, "AD02" }, 253 { GLFW_KEY_E, "AD03" }, 254 { GLFW_KEY_R, "AD04" }, 255 { GLFW_KEY_T, "AD05" }, 256 { GLFW_KEY_Y, "AD06" }, 257 { GLFW_KEY_U, "AD07" }, 258 { GLFW_KEY_I, "AD08" }, 259 { GLFW_KEY_O, "AD09" }, 260 { GLFW_KEY_P, "AD10" }, 261 { GLFW_KEY_LEFT_BRACKET, "AD11" }, 262 { GLFW_KEY_RIGHT_BRACKET, "AD12" }, 263 { GLFW_KEY_A, "AC01" }, 264 { GLFW_KEY_S, "AC02" }, 265 { GLFW_KEY_D, "AC03" }, 266 { GLFW_KEY_F, "AC04" }, 267 { GLFW_KEY_G, "AC05" }, 268 { GLFW_KEY_H, "AC06" }, 269 { GLFW_KEY_J, "AC07" }, 270 { GLFW_KEY_K, "AC08" }, 271 { GLFW_KEY_L, "AC09" }, 272 { GLFW_KEY_SEMICOLON, "AC10" }, 273 { GLFW_KEY_APOSTROPHE, "AC11" }, 274 { GLFW_KEY_Z, "AB01" }, 275 { GLFW_KEY_X, "AB02" }, 276 { GLFW_KEY_C, "AB03" }, 277 { GLFW_KEY_V, "AB04" }, 278 { GLFW_KEY_B, "AB05" }, 279 { GLFW_KEY_N, "AB06" }, 280 { GLFW_KEY_M, "AB07" }, 281 { GLFW_KEY_COMMA, "AB08" }, 282 { GLFW_KEY_PERIOD, "AB09" }, 283 { GLFW_KEY_SLASH, "AB10" }, 284 { GLFW_KEY_BACKSLASH, "BKSL" }, 285 { GLFW_KEY_WORLD_1, "LSGT" }, 286 { GLFW_KEY_SPACE, "SPCE" }, 287 { GLFW_KEY_ESCAPE, "ESC" }, 288 { GLFW_KEY_ENTER, "RTRN" }, 289 { GLFW_KEY_TAB, "TAB" }, 290 { GLFW_KEY_BACKSPACE, "BKSP" }, 291 { GLFW_KEY_INSERT, "INS" }, 292 { GLFW_KEY_DELETE, "DELE" }, 293 { GLFW_KEY_RIGHT, "RGHT" }, 294 { GLFW_KEY_LEFT, "LEFT" }, 295 { GLFW_KEY_DOWN, "DOWN" }, 296 { GLFW_KEY_UP, "UP" }, 297 { GLFW_KEY_PAGE_UP, "PGUP" }, 298 { GLFW_KEY_PAGE_DOWN, "PGDN" }, 299 { GLFW_KEY_HOME, "HOME" }, 300 { GLFW_KEY_END, "END" }, 301 { GLFW_KEY_CAPS_LOCK, "CAPS" }, 302 { GLFW_KEY_SCROLL_LOCK, "SCLK" }, 303 { GLFW_KEY_NUM_LOCK, "NMLK" }, 304 { GLFW_KEY_PRINT_SCREEN, "PRSC" }, 305 { GLFW_KEY_PAUSE, "PAUS" }, 306 { GLFW_KEY_F1, "FK01" }, 307 { GLFW_KEY_F2, "FK02" }, 308 { GLFW_KEY_F3, "FK03" }, 309 { GLFW_KEY_F4, "FK04" }, 310 { GLFW_KEY_F5, "FK05" }, 311 { GLFW_KEY_F6, "FK06" }, 312 { GLFW_KEY_F7, "FK07" }, 313 { GLFW_KEY_F8, "FK08" }, 314 { GLFW_KEY_F9, "FK09" }, 315 { GLFW_KEY_F10, "FK10" }, 316 { GLFW_KEY_F11, "FK11" }, 317 { GLFW_KEY_F12, "FK12" }, 318 { GLFW_KEY_F13, "FK13" }, 319 { GLFW_KEY_F14, "FK14" }, 320 { GLFW_KEY_F15, "FK15" }, 321 { GLFW_KEY_F16, "FK16" }, 322 { GLFW_KEY_F17, "FK17" }, 323 { GLFW_KEY_F18, "FK18" }, 324 { GLFW_KEY_F19, "FK19" }, 325 { GLFW_KEY_F20, "FK20" }, 326 { GLFW_KEY_F21, "FK21" }, 327 { GLFW_KEY_F22, "FK22" }, 328 { GLFW_KEY_F23, "FK23" }, 329 { GLFW_KEY_F24, "FK24" }, 330 { GLFW_KEY_F25, "FK25" }, 331 { GLFW_KEY_KP_0, "KP0" }, 332 { GLFW_KEY_KP_1, "KP1" }, 333 { GLFW_KEY_KP_2, "KP2" }, 334 { GLFW_KEY_KP_3, "KP3" }, 335 { GLFW_KEY_KP_4, "KP4" }, 336 { GLFW_KEY_KP_5, "KP5" }, 337 { GLFW_KEY_KP_6, "KP6" }, 338 { GLFW_KEY_KP_7, "KP7" }, 339 { GLFW_KEY_KP_8, "KP8" }, 340 { GLFW_KEY_KP_9, "KP9" }, 341 { GLFW_KEY_KP_DECIMAL, "KPDL" }, 342 { GLFW_KEY_KP_DIVIDE, "KPDV" }, 343 { GLFW_KEY_KP_MULTIPLY, "KPMU" }, 344 { GLFW_KEY_KP_SUBTRACT, "KPSU" }, 345 { GLFW_KEY_KP_ADD, "KPAD" }, 346 { GLFW_KEY_KP_ENTER, "KPEN" }, 347 { GLFW_KEY_KP_EQUAL, "KPEQ" }, 348 { GLFW_KEY_LEFT_SHIFT, "LFSH" }, 349 { GLFW_KEY_LEFT_CONTROL, "LCTL" }, 350 { GLFW_KEY_LEFT_ALT, "LALT" }, 351 { GLFW_KEY_LEFT_SUPER, "LWIN" }, 352 { GLFW_KEY_RIGHT_SHIFT, "RTSH" }, 353 { GLFW_KEY_RIGHT_CONTROL, "RCTL" }, 354 { GLFW_KEY_RIGHT_ALT, "RALT" }, 355 { GLFW_KEY_RIGHT_ALT, "LVL3" }, 356 { GLFW_KEY_RIGHT_ALT, "MDSW" }, 357 { GLFW_KEY_RIGHT_SUPER, "RWIN" }, 358 { GLFW_KEY_MENU, "MENU" } 359 }; 360 361 // Find the X11 key code -> GLFW key code mapping 362 for (int scancode = scancodeMin; scancode <= scancodeMax; scancode++) 363 { 364 int key = GLFW_KEY_UNKNOWN; 365 366 // Map the key name to a GLFW key code. Note: We use the US 367 // keyboard layout. Because function keys aren't mapped correctly 368 // when using traditional KeySym translations, they are mapped 369 // here instead. 370 for (int i = 0; i < sizeof(keymap) / sizeof(keymap[0]); i++) 371 { 372 if (strncmp(desc->names->keys[scancode].name, 373 keymap[i].name, 374 XkbKeyNameLength) == 0) 375 { 376 key = keymap[i].key; 377 break; 378 } 379 } 380 381 // Fall back to key aliases in case the key name did not match 382 for (int i = 0; i < desc->names->num_key_aliases; i++) 383 { 384 if (key != GLFW_KEY_UNKNOWN) 385 break; 386 387 if (strncmp(desc->names->key_aliases[i].real, 388 desc->names->keys[scancode].name, 389 XkbKeyNameLength) != 0) 390 { 391 continue; 392 } 393 394 for (int j = 0; j < sizeof(keymap) / sizeof(keymap[0]); j++) 395 { 396 if (strncmp(desc->names->key_aliases[i].alias, 397 keymap[j].name, 398 XkbKeyNameLength) == 0) 399 { 400 key = keymap[j].key; 401 break; 402 } 403 } 404 } 405 406 _glfw.x11.keycodes[scancode] = key; 407 } 408 409 XkbFreeNames(desc, XkbKeyNamesMask, True); 410 XkbFreeKeyboard(desc, 0, True); 411 } 412 else 413 XDisplayKeycodes(_glfw.x11.display, &scancodeMin, &scancodeMax); 414 415 int width; 416 KeySym* keysyms = XGetKeyboardMapping(_glfw.x11.display, 417 scancodeMin, 418 scancodeMax - scancodeMin + 1, 419 &width); 420 421 for (int scancode = scancodeMin; scancode <= scancodeMax; scancode++) 422 { 423 // Translate the un-translated key codes using traditional X11 KeySym 424 // lookups 425 if (_glfw.x11.keycodes[scancode] < 0) 426 { 427 const size_t base = (scancode - scancodeMin) * width; 428 _glfw.x11.keycodes[scancode] = translateKeySyms(&keysyms[base], width); 429 } 430 431 // Store the reverse translation for faster key name lookup 432 if (_glfw.x11.keycodes[scancode] > 0) 433 _glfw.x11.scancodes[_glfw.x11.keycodes[scancode]] = scancode; 434 } 435 436 XFree(keysyms); 437 } 438 439 // Check whether the IM has a usable style 440 // 441 static GLFWbool hasUsableInputMethodStyle(void) 442 { 443 GLFWbool found = GLFW_FALSE; 444 XIMStyles* styles = NULL; 445 446 if (XGetIMValues(_glfw.x11.im, XNQueryInputStyle, &styles, NULL) != NULL) 447 return GLFW_FALSE; 448 449 for (unsigned int i = 0; i < styles->count_styles; i++) 450 { 451 if (styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) 452 { 453 found = GLFW_TRUE; 454 break; 455 } 456 } 457 458 XFree(styles); 459 return found; 460 } 461 462 static void inputMethodDestroyCallback(XIM im, XPointer clientData, XPointer callData) 463 { 464 _glfw.x11.im = NULL; 465 } 466 467 static void inputMethodInstantiateCallback(Display* display, 468 XPointer clientData, 469 XPointer callData) 470 { 471 if (_glfw.x11.im) 472 return; 473 474 _glfw.x11.im = XOpenIM(_glfw.x11.display, 0, NULL, NULL); 475 if (_glfw.x11.im) 476 { 477 if (!hasUsableInputMethodStyle()) 478 { 479 XCloseIM(_glfw.x11.im); 480 _glfw.x11.im = NULL; 481 } 482 } 483 484 if (_glfw.x11.im) 485 { 486 XIMCallback callback; 487 callback.callback = (XIMProc) inputMethodDestroyCallback; 488 callback.client_data = NULL; 489 XSetIMValues(_glfw.x11.im, XNDestroyCallback, &callback, NULL); 490 491 for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next) 492 _glfwCreateInputContextX11(window); 493 } 494 } 495 496 // Return the atom ID only if it is listed in the specified array 497 // 498 static Atom getAtomIfSupported(Atom* supportedAtoms, 499 unsigned long atomCount, 500 const char* atomName) 501 { 502 const Atom atom = XInternAtom(_glfw.x11.display, atomName, False); 503 504 for (unsigned long i = 0; i < atomCount; i++) 505 { 506 if (supportedAtoms[i] == atom) 507 return atom; 508 } 509 510 return None; 511 } 512 513 // Check whether the running window manager is EWMH-compliant 514 // 515 static void detectEWMH(void) 516 { 517 // First we read the _NET_SUPPORTING_WM_CHECK property on the root window 518 519 Window* windowFromRoot = NULL; 520 if (!_glfwGetWindowPropertyX11(_glfw.x11.root, 521 _glfw.x11.NET_SUPPORTING_WM_CHECK, 522 XA_WINDOW, 523 (unsigned char**) &windowFromRoot)) 524 { 525 return; 526 } 527 528 _glfwGrabErrorHandlerX11(); 529 530 // If it exists, it should be the XID of a top-level window 531 // Then we look for the same property on that window 532 533 Window* windowFromChild = NULL; 534 if (!_glfwGetWindowPropertyX11(*windowFromRoot, 535 _glfw.x11.NET_SUPPORTING_WM_CHECK, 536 XA_WINDOW, 537 (unsigned char**) &windowFromChild)) 538 { 539 XFree(windowFromRoot); 540 return; 541 } 542 543 _glfwReleaseErrorHandlerX11(); 544 545 // If the property exists, it should contain the XID of the window 546 547 if (*windowFromRoot != *windowFromChild) 548 { 549 XFree(windowFromRoot); 550 XFree(windowFromChild); 551 return; 552 } 553 554 XFree(windowFromRoot); 555 XFree(windowFromChild); 556 557 // We are now fairly sure that an EWMH-compliant WM is currently running 558 // We can now start querying the WM about what features it supports by 559 // looking in the _NET_SUPPORTED property on the root window 560 // It should contain a list of supported EWMH protocol and state atoms 561 562 Atom* supportedAtoms = NULL; 563 const unsigned long atomCount = 564 _glfwGetWindowPropertyX11(_glfw.x11.root, 565 _glfw.x11.NET_SUPPORTED, 566 XA_ATOM, 567 (unsigned char**) &supportedAtoms); 568 569 // See which of the atoms we support that are supported by the WM 570 571 _glfw.x11.NET_WM_STATE = 572 getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE"); 573 _glfw.x11.NET_WM_STATE_ABOVE = 574 getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_ABOVE"); 575 _glfw.x11.NET_WM_STATE_FULLSCREEN = 576 getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN"); 577 _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT = 578 getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_VERT"); 579 _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ = 580 getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_HORZ"); 581 _glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION = 582 getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_DEMANDS_ATTENTION"); 583 _glfw.x11.NET_WM_FULLSCREEN_MONITORS = 584 getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS"); 585 _glfw.x11.NET_WM_WINDOW_TYPE = 586 getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE"); 587 _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL = 588 getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL"); 589 _glfw.x11.NET_WORKAREA = 590 getAtomIfSupported(supportedAtoms, atomCount, "_NET_WORKAREA"); 591 _glfw.x11.NET_CURRENT_DESKTOP = 592 getAtomIfSupported(supportedAtoms, atomCount, "_NET_CURRENT_DESKTOP"); 593 _glfw.x11.NET_ACTIVE_WINDOW = 594 getAtomIfSupported(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW"); 595 _glfw.x11.NET_FRAME_EXTENTS = 596 getAtomIfSupported(supportedAtoms, atomCount, "_NET_FRAME_EXTENTS"); 597 _glfw.x11.NET_REQUEST_FRAME_EXTENTS = 598 getAtomIfSupported(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS"); 599 600 if (supportedAtoms) 601 XFree(supportedAtoms); 602 } 603 604 // Look for and initialize supported X11 extensions 605 // 606 static GLFWbool initExtensions(void) 607 { 608 #if defined(__OpenBSD__) || defined(__NetBSD__) 609 _glfw.x11.vidmode.handle = _glfwPlatformLoadModule("libXxf86vm.so"); 610 #else 611 _glfw.x11.vidmode.handle = _glfwPlatformLoadModule("libXxf86vm.so.1"); 612 #endif 613 if (_glfw.x11.vidmode.handle) 614 { 615 _glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension) 616 _glfwPlatformGetModuleSymbol(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension"); 617 _glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp) 618 _glfwPlatformGetModuleSymbol(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp"); 619 _glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp) 620 _glfwPlatformGetModuleSymbol(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp"); 621 _glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize) 622 _glfwPlatformGetModuleSymbol(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize"); 623 624 _glfw.x11.vidmode.available = 625 XF86VidModeQueryExtension(_glfw.x11.display, 626 &_glfw.x11.vidmode.eventBase, 627 &_glfw.x11.vidmode.errorBase); 628 } 629 630 #if defined(__CYGWIN__) 631 _glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi-6.so"); 632 #elif defined(__OpenBSD__) || defined(__NetBSD__) 633 _glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi.so"); 634 #else 635 _glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi.so.6"); 636 #endif 637 if (_glfw.x11.xi.handle) 638 { 639 _glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion) 640 _glfwPlatformGetModuleSymbol(_glfw.x11.xi.handle, "XIQueryVersion"); 641 _glfw.x11.xi.SelectEvents = (PFN_XISelectEvents) 642 _glfwPlatformGetModuleSymbol(_glfw.x11.xi.handle, "XISelectEvents"); 643 644 if (XQueryExtension(_glfw.x11.display, 645 "XInputExtension", 646 &_glfw.x11.xi.majorOpcode, 647 &_glfw.x11.xi.eventBase, 648 &_glfw.x11.xi.errorBase)) 649 { 650 _glfw.x11.xi.major = 2; 651 _glfw.x11.xi.minor = 0; 652 653 if (XIQueryVersion(_glfw.x11.display, 654 &_glfw.x11.xi.major, 655 &_glfw.x11.xi.minor) == Success) 656 { 657 _glfw.x11.xi.available = GLFW_TRUE; 658 } 659 } 660 } 661 662 #if defined(__CYGWIN__) 663 _glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr-2.so"); 664 #elif defined(__OpenBSD__) || defined(__NetBSD__) 665 _glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr.so"); 666 #else 667 _glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr.so.2"); 668 #endif 669 if (_glfw.x11.randr.handle) 670 { 671 _glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma) 672 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRAllocGamma"); 673 _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma) 674 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRFreeGamma"); 675 _glfw.x11.randr.FreeCrtcInfo = (PFN_XRRFreeCrtcInfo) 676 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRFreeCrtcInfo"); 677 _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma) 678 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRFreeGamma"); 679 _glfw.x11.randr.FreeOutputInfo = (PFN_XRRFreeOutputInfo) 680 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRFreeOutputInfo"); 681 _glfw.x11.randr.FreeScreenResources = (PFN_XRRFreeScreenResources) 682 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRFreeScreenResources"); 683 _glfw.x11.randr.GetCrtcGamma = (PFN_XRRGetCrtcGamma) 684 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRGetCrtcGamma"); 685 _glfw.x11.randr.GetCrtcGammaSize = (PFN_XRRGetCrtcGammaSize) 686 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize"); 687 _glfw.x11.randr.GetCrtcInfo = (PFN_XRRGetCrtcInfo) 688 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRGetCrtcInfo"); 689 _glfw.x11.randr.GetOutputInfo = (PFN_XRRGetOutputInfo) 690 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRGetOutputInfo"); 691 _glfw.x11.randr.GetOutputPrimary = (PFN_XRRGetOutputPrimary) 692 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRGetOutputPrimary"); 693 _glfw.x11.randr.GetScreenResourcesCurrent = (PFN_XRRGetScreenResourcesCurrent) 694 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent"); 695 _glfw.x11.randr.QueryExtension = (PFN_XRRQueryExtension) 696 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRQueryExtension"); 697 _glfw.x11.randr.QueryVersion = (PFN_XRRQueryVersion) 698 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRQueryVersion"); 699 _glfw.x11.randr.SelectInput = (PFN_XRRSelectInput) 700 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRSelectInput"); 701 _glfw.x11.randr.SetCrtcConfig = (PFN_XRRSetCrtcConfig) 702 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRSetCrtcConfig"); 703 _glfw.x11.randr.SetCrtcGamma = (PFN_XRRSetCrtcGamma) 704 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRSetCrtcGamma"); 705 _glfw.x11.randr.UpdateConfiguration = (PFN_XRRUpdateConfiguration) 706 _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRUpdateConfiguration"); 707 708 if (XRRQueryExtension(_glfw.x11.display, 709 &_glfw.x11.randr.eventBase, 710 &_glfw.x11.randr.errorBase)) 711 { 712 if (XRRQueryVersion(_glfw.x11.display, 713 &_glfw.x11.randr.major, 714 &_glfw.x11.randr.minor)) 715 { 716 // The GLFW RandR path requires at least version 1.3 717 if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3) 718 _glfw.x11.randr.available = GLFW_TRUE; 719 } 720 else 721 { 722 _glfwInputError(GLFW_PLATFORM_ERROR, 723 "X11: Failed to query RandR version"); 724 } 725 } 726 } 727 728 if (_glfw.x11.randr.available) 729 { 730 XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, 731 _glfw.x11.root); 732 733 if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0])) 734 { 735 // This is likely an older Nvidia driver with broken gamma support 736 // Flag it as useless and fall back to xf86vm gamma, if available 737 _glfw.x11.randr.gammaBroken = GLFW_TRUE; 738 } 739 740 if (!sr->ncrtc) 741 { 742 // A system without CRTCs is likely a system with broken RandR 743 // Disable the RandR monitor path and fall back to core functions 744 _glfw.x11.randr.monitorBroken = GLFW_TRUE; 745 } 746 747 XRRFreeScreenResources(sr); 748 } 749 750 if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) 751 { 752 XRRSelectInput(_glfw.x11.display, _glfw.x11.root, 753 RROutputChangeNotifyMask); 754 } 755 756 #if defined(__CYGWIN__) 757 _glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor-1.so"); 758 #elif defined(__OpenBSD__) || defined(__NetBSD__) 759 _glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor.so"); 760 #else 761 _glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor.so.1"); 762 #endif 763 if (_glfw.x11.xcursor.handle) 764 { 765 _glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate) 766 _glfwPlatformGetModuleSymbol(_glfw.x11.xcursor.handle, "XcursorImageCreate"); 767 _glfw.x11.xcursor.ImageDestroy = (PFN_XcursorImageDestroy) 768 _glfwPlatformGetModuleSymbol(_glfw.x11.xcursor.handle, "XcursorImageDestroy"); 769 _glfw.x11.xcursor.ImageLoadCursor = (PFN_XcursorImageLoadCursor) 770 _glfwPlatformGetModuleSymbol(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor"); 771 _glfw.x11.xcursor.GetTheme = (PFN_XcursorGetTheme) 772 _glfwPlatformGetModuleSymbol(_glfw.x11.xcursor.handle, "XcursorGetTheme"); 773 _glfw.x11.xcursor.GetDefaultSize = (PFN_XcursorGetDefaultSize) 774 _glfwPlatformGetModuleSymbol(_glfw.x11.xcursor.handle, "XcursorGetDefaultSize"); 775 _glfw.x11.xcursor.LibraryLoadImage = (PFN_XcursorLibraryLoadImage) 776 _glfwPlatformGetModuleSymbol(_glfw.x11.xcursor.handle, "XcursorLibraryLoadImage"); 777 } 778 779 #if defined(__CYGWIN__) 780 _glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama-1.so"); 781 #elif defined(__OpenBSD__) || defined(__NetBSD__) 782 _glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama.so"); 783 #else 784 _glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama.so.1"); 785 #endif 786 if (_glfw.x11.xinerama.handle) 787 { 788 _glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive) 789 _glfwPlatformGetModuleSymbol(_glfw.x11.xinerama.handle, "XineramaIsActive"); 790 _glfw.x11.xinerama.QueryExtension = (PFN_XineramaQueryExtension) 791 _glfwPlatformGetModuleSymbol(_glfw.x11.xinerama.handle, "XineramaQueryExtension"); 792 _glfw.x11.xinerama.QueryScreens = (PFN_XineramaQueryScreens) 793 _glfwPlatformGetModuleSymbol(_glfw.x11.xinerama.handle, "XineramaQueryScreens"); 794 795 if (XineramaQueryExtension(_glfw.x11.display, 796 &_glfw.x11.xinerama.major, 797 &_glfw.x11.xinerama.minor)) 798 { 799 if (XineramaIsActive(_glfw.x11.display)) 800 _glfw.x11.xinerama.available = GLFW_TRUE; 801 } 802 } 803 804 _glfw.x11.xkb.major = 1; 805 _glfw.x11.xkb.minor = 0; 806 _glfw.x11.xkb.available = 807 XkbQueryExtension(_glfw.x11.display, 808 &_glfw.x11.xkb.majorOpcode, 809 &_glfw.x11.xkb.eventBase, 810 &_glfw.x11.xkb.errorBase, 811 &_glfw.x11.xkb.major, 812 &_glfw.x11.xkb.minor); 813 814 if (_glfw.x11.xkb.available) 815 { 816 Bool supported; 817 818 if (XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported)) 819 { 820 if (supported) 821 _glfw.x11.xkb.detectable = GLFW_TRUE; 822 } 823 824 XkbStateRec state; 825 if (XkbGetState(_glfw.x11.display, XkbUseCoreKbd, &state) == Success) 826 _glfw.x11.xkb.group = (unsigned int)state.group; 827 828 XkbSelectEventDetails(_glfw.x11.display, XkbUseCoreKbd, XkbStateNotify, 829 XkbGroupStateMask, XkbGroupStateMask); 830 } 831 832 if (_glfw.hints.init.x11.xcbVulkanSurface) 833 { 834 #if defined(__CYGWIN__) 835 _glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb-1.so"); 836 #elif defined(__OpenBSD__) || defined(__NetBSD__) 837 _glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb.so"); 838 #else 839 _glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb.so.1"); 840 #endif 841 } 842 843 if (_glfw.x11.x11xcb.handle) 844 { 845 _glfw.x11.x11xcb.GetXCBConnection = (PFN_XGetXCBConnection) 846 _glfwPlatformGetModuleSymbol(_glfw.x11.x11xcb.handle, "XGetXCBConnection"); 847 } 848 849 #if defined(__CYGWIN__) 850 _glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender-1.so"); 851 #elif defined(__OpenBSD__) || defined(__NetBSD__) 852 _glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender.so"); 853 #else 854 _glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender.so.1"); 855 #endif 856 if (_glfw.x11.xrender.handle) 857 { 858 _glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension) 859 _glfwPlatformGetModuleSymbol(_glfw.x11.xrender.handle, "XRenderQueryExtension"); 860 _glfw.x11.xrender.QueryVersion = (PFN_XRenderQueryVersion) 861 _glfwPlatformGetModuleSymbol(_glfw.x11.xrender.handle, "XRenderQueryVersion"); 862 _glfw.x11.xrender.FindVisualFormat = (PFN_XRenderFindVisualFormat) 863 _glfwPlatformGetModuleSymbol(_glfw.x11.xrender.handle, "XRenderFindVisualFormat"); 864 865 if (XRenderQueryExtension(_glfw.x11.display, 866 &_glfw.x11.xrender.errorBase, 867 &_glfw.x11.xrender.eventBase)) 868 { 869 if (XRenderQueryVersion(_glfw.x11.display, 870 &_glfw.x11.xrender.major, 871 &_glfw.x11.xrender.minor)) 872 { 873 _glfw.x11.xrender.available = GLFW_TRUE; 874 } 875 } 876 } 877 878 #if defined(__CYGWIN__) 879 _glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext-6.so"); 880 #elif defined(__OpenBSD__) || defined(__NetBSD__) 881 _glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext.so"); 882 #else 883 _glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext.so.6"); 884 #endif 885 if (_glfw.x11.xshape.handle) 886 { 887 _glfw.x11.xshape.QueryExtension = (PFN_XShapeQueryExtension) 888 _glfwPlatformGetModuleSymbol(_glfw.x11.xshape.handle, "XShapeQueryExtension"); 889 _glfw.x11.xshape.ShapeCombineRegion = (PFN_XShapeCombineRegion) 890 _glfwPlatformGetModuleSymbol(_glfw.x11.xshape.handle, "XShapeCombineRegion"); 891 _glfw.x11.xshape.QueryVersion = (PFN_XShapeQueryVersion) 892 _glfwPlatformGetModuleSymbol(_glfw.x11.xshape.handle, "XShapeQueryVersion"); 893 _glfw.x11.xshape.ShapeCombineMask = (PFN_XShapeCombineMask) 894 _glfwPlatformGetModuleSymbol(_glfw.x11.xshape.handle, "XShapeCombineMask"); 895 896 if (XShapeQueryExtension(_glfw.x11.display, 897 &_glfw.x11.xshape.errorBase, 898 &_glfw.x11.xshape.eventBase)) 899 { 900 if (XShapeQueryVersion(_glfw.x11.display, 901 &_glfw.x11.xshape.major, 902 &_glfw.x11.xshape.minor)) 903 { 904 _glfw.x11.xshape.available = GLFW_TRUE; 905 } 906 } 907 } 908 909 // Update the key code LUT 910 // FIXME: We should listen to XkbMapNotify events to track changes to 911 // the keyboard mapping. 912 createKeyTablesX11(); 913 914 // String format atoms 915 _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False); 916 _glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False); 917 _glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False); 918 919 // Custom selection property atom 920 _glfw.x11.GLFW_SELECTION = 921 XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False); 922 923 // ICCCM standard clipboard atoms 924 _glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False); 925 _glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False); 926 _glfw.x11.PRIMARY = XInternAtom(_glfw.x11.display, "PRIMARY", False); 927 _glfw.x11.INCR = XInternAtom(_glfw.x11.display, "INCR", False); 928 _glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False); 929 930 // Clipboard manager atoms 931 _glfw.x11.CLIPBOARD_MANAGER = 932 XInternAtom(_glfw.x11.display, "CLIPBOARD_MANAGER", False); 933 _glfw.x11.SAVE_TARGETS = 934 XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False); 935 936 // Xdnd (drag and drop) atoms 937 _glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", False); 938 _glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", False); 939 _glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", False); 940 _glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", False); 941 _glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False); 942 _glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", False); 943 _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False); 944 _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False); 945 _glfw.x11.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False); 946 _glfw.x11.text_uri_list = XInternAtom(_glfw.x11.display, "text/uri-list", False); 947 948 // ICCCM, EWMH and Motif window property atoms 949 // These can be set safely even without WM support 950 // The EWMH atoms that require WM support are handled in detectEWMH 951 _glfw.x11.WM_PROTOCOLS = 952 XInternAtom(_glfw.x11.display, "WM_PROTOCOLS", False); 953 _glfw.x11.WM_STATE = 954 XInternAtom(_glfw.x11.display, "WM_STATE", False); 955 _glfw.x11.WM_DELETE_WINDOW = 956 XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False); 957 _glfw.x11.NET_SUPPORTED = 958 XInternAtom(_glfw.x11.display, "_NET_SUPPORTED", False); 959 _glfw.x11.NET_SUPPORTING_WM_CHECK = 960 XInternAtom(_glfw.x11.display, "_NET_SUPPORTING_WM_CHECK", False); 961 _glfw.x11.NET_WM_ICON = 962 XInternAtom(_glfw.x11.display, "_NET_WM_ICON", False); 963 _glfw.x11.NET_WM_PING = 964 XInternAtom(_glfw.x11.display, "_NET_WM_PING", False); 965 _glfw.x11.NET_WM_PID = 966 XInternAtom(_glfw.x11.display, "_NET_WM_PID", False); 967 _glfw.x11.NET_WM_NAME = 968 XInternAtom(_glfw.x11.display, "_NET_WM_NAME", False); 969 _glfw.x11.NET_WM_ICON_NAME = 970 XInternAtom(_glfw.x11.display, "_NET_WM_ICON_NAME", False); 971 _glfw.x11.NET_WM_BYPASS_COMPOSITOR = 972 XInternAtom(_glfw.x11.display, "_NET_WM_BYPASS_COMPOSITOR", False); 973 _glfw.x11.NET_WM_WINDOW_OPACITY = 974 XInternAtom(_glfw.x11.display, "_NET_WM_WINDOW_OPACITY", False); 975 _glfw.x11.MOTIF_WM_HINTS = 976 XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False); 977 978 // The compositing manager selection name contains the screen number 979 { 980 char name[32]; 981 snprintf(name, sizeof(name), "_NET_WM_CM_S%u", _glfw.x11.screen); 982 _glfw.x11.NET_WM_CM_Sx = XInternAtom(_glfw.x11.display, name, False); 983 } 984 985 // Detect whether an EWMH-conformant window manager is running 986 detectEWMH(); 987 988 return GLFW_TRUE; 989 } 990 991 // Retrieve system content scale via folklore heuristics 992 // 993 static void getSystemContentScale(float* xscale, float* yscale) 994 { 995 // Start by assuming the default X11 DPI 996 // NOTE: Some desktop environments (KDE) may remove the Xft.dpi field when it 997 // would be set to 96, so assume that is the case if we cannot find it 998 float xdpi = 96.f, ydpi = 96.f; 999 1000 // NOTE: Basing the scale on Xft.dpi where available should provide the most 1001 // consistent user experience (matches Qt, Gtk, etc), although not 1002 // always the most accurate one 1003 char* rms = XResourceManagerString(_glfw.x11.display); 1004 if (rms) 1005 { 1006 XrmDatabase db = XrmGetStringDatabase(rms); 1007 if (db) 1008 { 1009 XrmValue value; 1010 char* type = NULL; 1011 1012 if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value)) 1013 { 1014 if (type && strcmp(type, "String") == 0) 1015 xdpi = ydpi = atof(value.addr); 1016 } 1017 1018 XrmDestroyDatabase(db); 1019 } 1020 } 1021 1022 *xscale = xdpi / 96.f; 1023 *yscale = ydpi / 96.f; 1024 } 1025 1026 // Create a blank cursor for hidden and disabled cursor modes 1027 // 1028 static Cursor createHiddenCursor(void) 1029 { 1030 unsigned char pixels[16 * 16 * 4] = { 0 }; 1031 GLFWimage image = { 16, 16, pixels }; 1032 return _glfwCreateNativeCursorX11(&image, 0, 0); 1033 } 1034 1035 // Create a helper window for IPC 1036 // 1037 static Window createHelperWindow(void) 1038 { 1039 XSetWindowAttributes wa; 1040 wa.event_mask = PropertyChangeMask; 1041 1042 return XCreateWindow(_glfw.x11.display, _glfw.x11.root, 1043 0, 0, 1, 1, 0, 0, 1044 InputOnly, 1045 DefaultVisual(_glfw.x11.display, _glfw.x11.screen), 1046 CWEventMask, &wa); 1047 } 1048 1049 // Create the pipe for empty events without assumuing the OS has pipe2(2) 1050 // 1051 static GLFWbool createEmptyEventPipe(void) 1052 { 1053 if (pipe(_glfw.x11.emptyEventPipe) != 0) 1054 { 1055 _glfwInputError(GLFW_PLATFORM_ERROR, 1056 "X11: Failed to create empty event pipe: %s", 1057 strerror(errno)); 1058 return GLFW_FALSE; 1059 } 1060 1061 for (int i = 0; i < 2; i++) 1062 { 1063 const int sf = fcntl(_glfw.x11.emptyEventPipe[i], F_GETFL, 0); 1064 const int df = fcntl(_glfw.x11.emptyEventPipe[i], F_GETFD, 0); 1065 1066 if (sf == -1 || df == -1 || 1067 fcntl(_glfw.x11.emptyEventPipe[i], F_SETFL, sf | O_NONBLOCK) == -1 || 1068 fcntl(_glfw.x11.emptyEventPipe[i], F_SETFD, df | FD_CLOEXEC) == -1) 1069 { 1070 _glfwInputError(GLFW_PLATFORM_ERROR, 1071 "X11: Failed to set flags for empty event pipe: %s", 1072 strerror(errno)); 1073 return GLFW_FALSE; 1074 } 1075 } 1076 1077 return GLFW_TRUE; 1078 } 1079 1080 // X error handler 1081 // 1082 static int errorHandler(Display *display, XErrorEvent* event) 1083 { 1084 if (_glfw.x11.display != display) 1085 return 0; 1086 1087 _glfw.x11.errorCode = event->error_code; 1088 return 0; 1089 } 1090 1091 1092 ////////////////////////////////////////////////////////////////////////// 1093 ////// GLFW internal API ////// 1094 ////////////////////////////////////////////////////////////////////////// 1095 1096 // Sets the X error handler callback 1097 // 1098 void _glfwGrabErrorHandlerX11(void) 1099 { 1100 assert(_glfw.x11.errorHandler == NULL); 1101 _glfw.x11.errorCode = Success; 1102 _glfw.x11.errorHandler = XSetErrorHandler(errorHandler); 1103 } 1104 1105 // Clears the X error handler callback 1106 // 1107 void _glfwReleaseErrorHandlerX11(void) 1108 { 1109 // Synchronize to make sure all commands are processed 1110 XSync(_glfw.x11.display, False); 1111 XSetErrorHandler(_glfw.x11.errorHandler); 1112 _glfw.x11.errorHandler = NULL; 1113 } 1114 1115 // Reports the specified error, appending information about the last X error 1116 // 1117 void _glfwInputErrorX11(int error, const char* message) 1118 { 1119 char buffer[_GLFW_MESSAGE_SIZE]; 1120 XGetErrorText(_glfw.x11.display, _glfw.x11.errorCode, 1121 buffer, sizeof(buffer)); 1122 1123 _glfwInputError(error, "%s: %s", message, buffer); 1124 } 1125 1126 // Creates a native cursor object from the specified image and hotspot 1127 // 1128 Cursor _glfwCreateNativeCursorX11(const GLFWimage* image, int xhot, int yhot) 1129 { 1130 Cursor cursor; 1131 1132 if (!_glfw.x11.xcursor.handle) 1133 return None; 1134 1135 XcursorImage* native = XcursorImageCreate(image->width, image->height); 1136 if (native == NULL) 1137 return None; 1138 1139 native->xhot = xhot; 1140 native->yhot = yhot; 1141 1142 unsigned char* source = (unsigned char*) image->pixels; 1143 XcursorPixel* target = native->pixels; 1144 1145 for (int i = 0; i < image->width * image->height; i++, target++, source += 4) 1146 { 1147 unsigned int alpha = source[3]; 1148 1149 *target = (alpha << 24) | 1150 ((unsigned char) ((source[0] * alpha) / 255) << 16) | 1151 ((unsigned char) ((source[1] * alpha) / 255) << 8) | 1152 ((unsigned char) ((source[2] * alpha) / 255) << 0); 1153 } 1154 1155 cursor = XcursorImageLoadCursor(_glfw.x11.display, native); 1156 XcursorImageDestroy(native); 1157 1158 return cursor; 1159 } 1160 1161 1162 ////////////////////////////////////////////////////////////////////////// 1163 ////// GLFW platform API ////// 1164 ////////////////////////////////////////////////////////////////////////// 1165 1166 GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform) 1167 { 1168 const _GLFWplatform x11 = 1169 { 1170 .platformID = GLFW_PLATFORM_X11, 1171 .init = _glfwInitX11, 1172 .terminate = _glfwTerminateX11, 1173 .getCursorPos = _glfwGetCursorPosX11, 1174 .setCursorPos = _glfwSetCursorPosX11, 1175 .setCursorMode = _glfwSetCursorModeX11, 1176 .setRawMouseMotion = _glfwSetRawMouseMotionX11, 1177 .rawMouseMotionSupported = _glfwRawMouseMotionSupportedX11, 1178 .createCursor = _glfwCreateCursorX11, 1179 .createStandardCursor = _glfwCreateStandardCursorX11, 1180 .destroyCursor = _glfwDestroyCursorX11, 1181 .setCursor = _glfwSetCursorX11, 1182 .getScancodeName = _glfwGetScancodeNameX11, 1183 .getKeyScancode = _glfwGetKeyScancodeX11, 1184 .setClipboardString = _glfwSetClipboardStringX11, 1185 .getClipboardString = _glfwGetClipboardStringX11, 1186 #if defined(GLFW_BUILD_LINUX_JOYSTICK) 1187 .initJoysticks = _glfwInitJoysticksLinux, 1188 .terminateJoysticks = _glfwTerminateJoysticksLinux, 1189 .pollJoystick = _glfwPollJoystickLinux, 1190 .getMappingName = _glfwGetMappingNameLinux, 1191 .updateGamepadGUID = _glfwUpdateGamepadGUIDLinux, 1192 #else 1193 .initJoysticks = _glfwInitJoysticksNull, 1194 .terminateJoysticks = _glfwTerminateJoysticksNull, 1195 .pollJoystick = _glfwPollJoystickNull, 1196 .getMappingName = _glfwGetMappingNameNull, 1197 .updateGamepadGUID = _glfwUpdateGamepadGUIDNull, 1198 #endif 1199 .freeMonitor = _glfwFreeMonitorX11, 1200 .getMonitorPos = _glfwGetMonitorPosX11, 1201 .getMonitorContentScale = _glfwGetMonitorContentScaleX11, 1202 .getMonitorWorkarea = _glfwGetMonitorWorkareaX11, 1203 .getVideoModes = _glfwGetVideoModesX11, 1204 .getVideoMode = _glfwGetVideoModeX11, 1205 .getGammaRamp = _glfwGetGammaRampX11, 1206 .setGammaRamp = _glfwSetGammaRampX11, 1207 .createWindow = _glfwCreateWindowX11, 1208 .destroyWindow = _glfwDestroyWindowX11, 1209 .setWindowTitle = _glfwSetWindowTitleX11, 1210 .setWindowIcon = _glfwSetWindowIconX11, 1211 .getWindowPos = _glfwGetWindowPosX11, 1212 .setWindowPos = _glfwSetWindowPosX11, 1213 .getWindowSize = _glfwGetWindowSizeX11, 1214 .setWindowSize = _glfwSetWindowSizeX11, 1215 .setWindowSizeLimits = _glfwSetWindowSizeLimitsX11, 1216 .setWindowAspectRatio = _glfwSetWindowAspectRatioX11, 1217 .getFramebufferSize = _glfwGetFramebufferSizeX11, 1218 .getWindowFrameSize = _glfwGetWindowFrameSizeX11, 1219 .getWindowContentScale = _glfwGetWindowContentScaleX11, 1220 .iconifyWindow = _glfwIconifyWindowX11, 1221 .restoreWindow = _glfwRestoreWindowX11, 1222 .maximizeWindow = _glfwMaximizeWindowX11, 1223 .showWindow = _glfwShowWindowX11, 1224 .hideWindow = _glfwHideWindowX11, 1225 .requestWindowAttention = _glfwRequestWindowAttentionX11, 1226 .focusWindow = _glfwFocusWindowX11, 1227 .setWindowMonitor = _glfwSetWindowMonitorX11, 1228 .windowFocused = _glfwWindowFocusedX11, 1229 .windowIconified = _glfwWindowIconifiedX11, 1230 .windowVisible = _glfwWindowVisibleX11, 1231 .windowMaximized = _glfwWindowMaximizedX11, 1232 .windowHovered = _glfwWindowHoveredX11, 1233 .framebufferTransparent = _glfwFramebufferTransparentX11, 1234 .getWindowOpacity = _glfwGetWindowOpacityX11, 1235 .setWindowResizable = _glfwSetWindowResizableX11, 1236 .setWindowDecorated = _glfwSetWindowDecoratedX11, 1237 .setWindowFloating = _glfwSetWindowFloatingX11, 1238 .setWindowOpacity = _glfwSetWindowOpacityX11, 1239 .setWindowMousePassthrough = _glfwSetWindowMousePassthroughX11, 1240 .pollEvents = _glfwPollEventsX11, 1241 .waitEvents = _glfwWaitEventsX11, 1242 .waitEventsTimeout = _glfwWaitEventsTimeoutX11, 1243 .postEmptyEvent = _glfwPostEmptyEventX11, 1244 .getEGLPlatform = _glfwGetEGLPlatformX11, 1245 .getEGLNativeDisplay = _glfwGetEGLNativeDisplayX11, 1246 .getEGLNativeWindow = _glfwGetEGLNativeWindowX11, 1247 .getRequiredInstanceExtensions = _glfwGetRequiredInstanceExtensionsX11, 1248 .getPhysicalDevicePresentationSupport = _glfwGetPhysicalDevicePresentationSupportX11, 1249 .createWindowSurface = _glfwCreateWindowSurfaceX11 1250 }; 1251 1252 // HACK: If the application has left the locale as "C" then both wide 1253 // character text input and explicit UTF-8 input via XIM will break 1254 // This sets the CTYPE part of the current locale from the environment 1255 // in the hope that it is set to something more sane than "C" 1256 if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0) 1257 setlocale(LC_CTYPE, ""); 1258 1259 #if defined(__CYGWIN__) 1260 void* module = _glfwPlatformLoadModule("libX11-6.so"); 1261 #elif defined(__OpenBSD__) || defined(__NetBSD__) 1262 void* module = _glfwPlatformLoadModule("libX11.so"); 1263 #else 1264 void* module = _glfwPlatformLoadModule("libX11.so.6"); 1265 #endif 1266 if (!module) 1267 { 1268 if (platformID == GLFW_PLATFORM_X11) 1269 _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to load Xlib"); 1270 1271 return GLFW_FALSE; 1272 } 1273 1274 PFN_XInitThreads XInitThreads = (PFN_XInitThreads) 1275 _glfwPlatformGetModuleSymbol(module, "XInitThreads"); 1276 PFN_XrmInitialize XrmInitialize = (PFN_XrmInitialize) 1277 _glfwPlatformGetModuleSymbol(module, "XrmInitialize"); 1278 PFN_XOpenDisplay XOpenDisplay = (PFN_XOpenDisplay) 1279 _glfwPlatformGetModuleSymbol(module, "XOpenDisplay"); 1280 if (!XInitThreads || !XrmInitialize || !XOpenDisplay) 1281 { 1282 if (platformID == GLFW_PLATFORM_X11) 1283 _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to load Xlib entry point"); 1284 1285 _glfwPlatformFreeModule(module); 1286 return GLFW_FALSE; 1287 } 1288 1289 XInitThreads(); 1290 XrmInitialize(); 1291 1292 Display* display = XOpenDisplay(NULL); 1293 if (!display) 1294 { 1295 if (platformID == GLFW_PLATFORM_X11) 1296 { 1297 const char* name = getenv("DISPLAY"); 1298 if (name) 1299 { 1300 _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, 1301 "X11: Failed to open display %s", name); 1302 } 1303 else 1304 { 1305 _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, 1306 "X11: The DISPLAY environment variable is missing"); 1307 } 1308 } 1309 1310 _glfwPlatformFreeModule(module); 1311 return GLFW_FALSE; 1312 } 1313 1314 _glfw.x11.display = display; 1315 _glfw.x11.xlib.handle = module; 1316 1317 *platform = x11; 1318 return GLFW_TRUE; 1319 } 1320 1321 int _glfwInitX11(void) 1322 { 1323 _glfw.x11.xlib.AllocClassHint = (PFN_XAllocClassHint) 1324 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XAllocClassHint"); 1325 _glfw.x11.xlib.AllocSizeHints = (PFN_XAllocSizeHints) 1326 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XAllocSizeHints"); 1327 _glfw.x11.xlib.AllocWMHints = (PFN_XAllocWMHints) 1328 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XAllocWMHints"); 1329 _glfw.x11.xlib.ChangeProperty = (PFN_XChangeProperty) 1330 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XChangeProperty"); 1331 _glfw.x11.xlib.ChangeWindowAttributes = (PFN_XChangeWindowAttributes) 1332 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XChangeWindowAttributes"); 1333 _glfw.x11.xlib.CheckIfEvent = (PFN_XCheckIfEvent) 1334 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCheckIfEvent"); 1335 _glfw.x11.xlib.CheckTypedWindowEvent = (PFN_XCheckTypedWindowEvent) 1336 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCheckTypedWindowEvent"); 1337 _glfw.x11.xlib.CloseDisplay = (PFN_XCloseDisplay) 1338 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCloseDisplay"); 1339 _glfw.x11.xlib.CloseIM = (PFN_XCloseIM) 1340 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCloseIM"); 1341 _glfw.x11.xlib.ConvertSelection = (PFN_XConvertSelection) 1342 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XConvertSelection"); 1343 _glfw.x11.xlib.CreateColormap = (PFN_XCreateColormap) 1344 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCreateColormap"); 1345 _glfw.x11.xlib.CreateFontCursor = (PFN_XCreateFontCursor) 1346 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCreateFontCursor"); 1347 _glfw.x11.xlib.CreateIC = (PFN_XCreateIC) 1348 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCreateIC"); 1349 _glfw.x11.xlib.CreateRegion = (PFN_XCreateRegion) 1350 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCreateRegion"); 1351 _glfw.x11.xlib.CreateWindow = (PFN_XCreateWindow) 1352 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCreateWindow"); 1353 _glfw.x11.xlib.DefineCursor = (PFN_XDefineCursor) 1354 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XDefineCursor"); 1355 _glfw.x11.xlib.DeleteContext = (PFN_XDeleteContext) 1356 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XDeleteContext"); 1357 _glfw.x11.xlib.DeleteProperty = (PFN_XDeleteProperty) 1358 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XDeleteProperty"); 1359 _glfw.x11.xlib.DestroyIC = (PFN_XDestroyIC) 1360 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XDestroyIC"); 1361 _glfw.x11.xlib.DestroyRegion = (PFN_XDestroyRegion) 1362 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XDestroyRegion"); 1363 _glfw.x11.xlib.DestroyWindow = (PFN_XDestroyWindow) 1364 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XDestroyWindow"); 1365 _glfw.x11.xlib.DisplayKeycodes = (PFN_XDisplayKeycodes) 1366 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XDisplayKeycodes"); 1367 _glfw.x11.xlib.EventsQueued = (PFN_XEventsQueued) 1368 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XEventsQueued"); 1369 _glfw.x11.xlib.FilterEvent = (PFN_XFilterEvent) 1370 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XFilterEvent"); 1371 _glfw.x11.xlib.FindContext = (PFN_XFindContext) 1372 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XFindContext"); 1373 _glfw.x11.xlib.Flush = (PFN_XFlush) 1374 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XFlush"); 1375 _glfw.x11.xlib.Free = (PFN_XFree) 1376 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XFree"); 1377 _glfw.x11.xlib.FreeColormap = (PFN_XFreeColormap) 1378 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XFreeColormap"); 1379 _glfw.x11.xlib.FreeCursor = (PFN_XFreeCursor) 1380 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XFreeCursor"); 1381 _glfw.x11.xlib.FreeEventData = (PFN_XFreeEventData) 1382 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XFreeEventData"); 1383 _glfw.x11.xlib.GetErrorText = (PFN_XGetErrorText) 1384 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetErrorText"); 1385 _glfw.x11.xlib.GetEventData = (PFN_XGetEventData) 1386 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetEventData"); 1387 _glfw.x11.xlib.GetICValues = (PFN_XGetICValues) 1388 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetICValues"); 1389 _glfw.x11.xlib.GetIMValues = (PFN_XGetIMValues) 1390 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetIMValues"); 1391 _glfw.x11.xlib.GetInputFocus = (PFN_XGetInputFocus) 1392 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetInputFocus"); 1393 _glfw.x11.xlib.GetKeyboardMapping = (PFN_XGetKeyboardMapping) 1394 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetKeyboardMapping"); 1395 _glfw.x11.xlib.GetScreenSaver = (PFN_XGetScreenSaver) 1396 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetScreenSaver"); 1397 _glfw.x11.xlib.GetSelectionOwner = (PFN_XGetSelectionOwner) 1398 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetSelectionOwner"); 1399 _glfw.x11.xlib.GetVisualInfo = (PFN_XGetVisualInfo) 1400 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetVisualInfo"); 1401 _glfw.x11.xlib.GetWMNormalHints = (PFN_XGetWMNormalHints) 1402 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetWMNormalHints"); 1403 _glfw.x11.xlib.GetWindowAttributes = (PFN_XGetWindowAttributes) 1404 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetWindowAttributes"); 1405 _glfw.x11.xlib.GetWindowProperty = (PFN_XGetWindowProperty) 1406 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetWindowProperty"); 1407 _glfw.x11.xlib.GrabPointer = (PFN_XGrabPointer) 1408 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGrabPointer"); 1409 _glfw.x11.xlib.IconifyWindow = (PFN_XIconifyWindow) 1410 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XIconifyWindow"); 1411 _glfw.x11.xlib.InternAtom = (PFN_XInternAtom) 1412 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XInternAtom"); 1413 _glfw.x11.xlib.LookupString = (PFN_XLookupString) 1414 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XLookupString"); 1415 _glfw.x11.xlib.MapRaised = (PFN_XMapRaised) 1416 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XMapRaised"); 1417 _glfw.x11.xlib.MapWindow = (PFN_XMapWindow) 1418 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XMapWindow"); 1419 _glfw.x11.xlib.MoveResizeWindow = (PFN_XMoveResizeWindow) 1420 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XMoveResizeWindow"); 1421 _glfw.x11.xlib.MoveWindow = (PFN_XMoveWindow) 1422 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XMoveWindow"); 1423 _glfw.x11.xlib.NextEvent = (PFN_XNextEvent) 1424 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XNextEvent"); 1425 _glfw.x11.xlib.OpenIM = (PFN_XOpenIM) 1426 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XOpenIM"); 1427 _glfw.x11.xlib.PeekEvent = (PFN_XPeekEvent) 1428 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XPeekEvent"); 1429 _glfw.x11.xlib.Pending = (PFN_XPending) 1430 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XPending"); 1431 _glfw.x11.xlib.QueryExtension = (PFN_XQueryExtension) 1432 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XQueryExtension"); 1433 _glfw.x11.xlib.QueryPointer = (PFN_XQueryPointer) 1434 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XQueryPointer"); 1435 _glfw.x11.xlib.RaiseWindow = (PFN_XRaiseWindow) 1436 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XRaiseWindow"); 1437 _glfw.x11.xlib.RegisterIMInstantiateCallback = (PFN_XRegisterIMInstantiateCallback) 1438 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XRegisterIMInstantiateCallback"); 1439 _glfw.x11.xlib.ResizeWindow = (PFN_XResizeWindow) 1440 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XResizeWindow"); 1441 _glfw.x11.xlib.ResourceManagerString = (PFN_XResourceManagerString) 1442 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XResourceManagerString"); 1443 _glfw.x11.xlib.SaveContext = (PFN_XSaveContext) 1444 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSaveContext"); 1445 _glfw.x11.xlib.SelectInput = (PFN_XSelectInput) 1446 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSelectInput"); 1447 _glfw.x11.xlib.SendEvent = (PFN_XSendEvent) 1448 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSendEvent"); 1449 _glfw.x11.xlib.SetClassHint = (PFN_XSetClassHint) 1450 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetClassHint"); 1451 _glfw.x11.xlib.SetErrorHandler = (PFN_XSetErrorHandler) 1452 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetErrorHandler"); 1453 _glfw.x11.xlib.SetICFocus = (PFN_XSetICFocus) 1454 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetICFocus"); 1455 _glfw.x11.xlib.SetIMValues = (PFN_XSetIMValues) 1456 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetIMValues"); 1457 _glfw.x11.xlib.SetInputFocus = (PFN_XSetInputFocus) 1458 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetInputFocus"); 1459 _glfw.x11.xlib.SetLocaleModifiers = (PFN_XSetLocaleModifiers) 1460 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetLocaleModifiers"); 1461 _glfw.x11.xlib.SetScreenSaver = (PFN_XSetScreenSaver) 1462 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetScreenSaver"); 1463 _glfw.x11.xlib.SetSelectionOwner = (PFN_XSetSelectionOwner) 1464 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetSelectionOwner"); 1465 _glfw.x11.xlib.SetWMHints = (PFN_XSetWMHints) 1466 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetWMHints"); 1467 _glfw.x11.xlib.SetWMNormalHints = (PFN_XSetWMNormalHints) 1468 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetWMNormalHints"); 1469 _glfw.x11.xlib.SetWMProtocols = (PFN_XSetWMProtocols) 1470 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetWMProtocols"); 1471 _glfw.x11.xlib.SupportsLocale = (PFN_XSupportsLocale) 1472 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSupportsLocale"); 1473 _glfw.x11.xlib.Sync = (PFN_XSync) 1474 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSync"); 1475 _glfw.x11.xlib.TranslateCoordinates = (PFN_XTranslateCoordinates) 1476 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XTranslateCoordinates"); 1477 _glfw.x11.xlib.UndefineCursor = (PFN_XUndefineCursor) 1478 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XUndefineCursor"); 1479 _glfw.x11.xlib.UngrabPointer = (PFN_XUngrabPointer) 1480 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XUngrabPointer"); 1481 _glfw.x11.xlib.UnmapWindow = (PFN_XUnmapWindow) 1482 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XUnmapWindow"); 1483 _glfw.x11.xlib.UnsetICFocus = (PFN_XUnsetICFocus) 1484 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XUnsetICFocus"); 1485 _glfw.x11.xlib.VisualIDFromVisual = (PFN_XVisualIDFromVisual) 1486 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XVisualIDFromVisual"); 1487 _glfw.x11.xlib.WarpPointer = (PFN_XWarpPointer) 1488 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XWarpPointer"); 1489 _glfw.x11.xkb.FreeKeyboard = (PFN_XkbFreeKeyboard) 1490 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbFreeKeyboard"); 1491 _glfw.x11.xkb.FreeNames = (PFN_XkbFreeNames) 1492 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbFreeNames"); 1493 _glfw.x11.xkb.GetMap = (PFN_XkbGetMap) 1494 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbGetMap"); 1495 _glfw.x11.xkb.GetNames = (PFN_XkbGetNames) 1496 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbGetNames"); 1497 _glfw.x11.xkb.GetState = (PFN_XkbGetState) 1498 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbGetState"); 1499 _glfw.x11.xkb.KeycodeToKeysym = (PFN_XkbKeycodeToKeysym) 1500 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbKeycodeToKeysym"); 1501 _glfw.x11.xkb.QueryExtension = (PFN_XkbQueryExtension) 1502 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbQueryExtension"); 1503 _glfw.x11.xkb.SelectEventDetails = (PFN_XkbSelectEventDetails) 1504 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbSelectEventDetails"); 1505 _glfw.x11.xkb.SetDetectableAutoRepeat = (PFN_XkbSetDetectableAutoRepeat) 1506 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbSetDetectableAutoRepeat"); 1507 _glfw.x11.xrm.DestroyDatabase = (PFN_XrmDestroyDatabase) 1508 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XrmDestroyDatabase"); 1509 _glfw.x11.xrm.GetResource = (PFN_XrmGetResource) 1510 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XrmGetResource"); 1511 _glfw.x11.xrm.GetStringDatabase = (PFN_XrmGetStringDatabase) 1512 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XrmGetStringDatabase"); 1513 _glfw.x11.xrm.UniqueQuark = (PFN_XrmUniqueQuark) 1514 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XrmUniqueQuark"); 1515 _glfw.x11.xlib.UnregisterIMInstantiateCallback = (PFN_XUnregisterIMInstantiateCallback) 1516 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XUnregisterIMInstantiateCallback"); 1517 _glfw.x11.xlib.utf8LookupString = (PFN_Xutf8LookupString) 1518 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "Xutf8LookupString"); 1519 _glfw.x11.xlib.utf8SetWMProperties = (PFN_Xutf8SetWMProperties) 1520 _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "Xutf8SetWMProperties"); 1521 1522 if (_glfw.x11.xlib.utf8LookupString && _glfw.x11.xlib.utf8SetWMProperties) 1523 _glfw.x11.xlib.utf8 = GLFW_TRUE; 1524 1525 _glfw.x11.screen = DefaultScreen(_glfw.x11.display); 1526 _glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen); 1527 _glfw.x11.context = XUniqueContext(); 1528 1529 getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY); 1530 1531 if (!createEmptyEventPipe()) 1532 return GLFW_FALSE; 1533 1534 if (!initExtensions()) 1535 return GLFW_FALSE; 1536 1537 _glfw.x11.helperWindowHandle = createHelperWindow(); 1538 _glfw.x11.hiddenCursorHandle = createHiddenCursor(); 1539 1540 if (XSupportsLocale() && _glfw.x11.xlib.utf8) 1541 { 1542 XSetLocaleModifiers(""); 1543 1544 // If an IM is already present our callback will be called right away 1545 XRegisterIMInstantiateCallback(_glfw.x11.display, 1546 NULL, NULL, NULL, 1547 inputMethodInstantiateCallback, 1548 NULL); 1549 } 1550 1551 _glfwPollMonitorsX11(); 1552 return GLFW_TRUE; 1553 } 1554 1555 void _glfwTerminateX11(void) 1556 { 1557 if (_glfw.x11.helperWindowHandle) 1558 { 1559 if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) == 1560 _glfw.x11.helperWindowHandle) 1561 { 1562 _glfwPushSelectionToManagerX11(); 1563 } 1564 1565 XDestroyWindow(_glfw.x11.display, _glfw.x11.helperWindowHandle); 1566 _glfw.x11.helperWindowHandle = None; 1567 } 1568 1569 if (_glfw.x11.hiddenCursorHandle) 1570 { 1571 XFreeCursor(_glfw.x11.display, _glfw.x11.hiddenCursorHandle); 1572 _glfw.x11.hiddenCursorHandle = (Cursor) 0; 1573 } 1574 1575 _glfw_free(_glfw.x11.primarySelectionString); 1576 _glfw_free(_glfw.x11.clipboardString); 1577 1578 XUnregisterIMInstantiateCallback(_glfw.x11.display, 1579 NULL, NULL, NULL, 1580 inputMethodInstantiateCallback, 1581 NULL); 1582 1583 if (_glfw.x11.im) 1584 { 1585 XCloseIM(_glfw.x11.im); 1586 _glfw.x11.im = NULL; 1587 } 1588 1589 if (_glfw.x11.display) 1590 { 1591 XCloseDisplay(_glfw.x11.display); 1592 _glfw.x11.display = NULL; 1593 } 1594 1595 if (_glfw.x11.x11xcb.handle) 1596 { 1597 _glfwPlatformFreeModule(_glfw.x11.x11xcb.handle); 1598 _glfw.x11.x11xcb.handle = NULL; 1599 } 1600 1601 if (_glfw.x11.xcursor.handle) 1602 { 1603 _glfwPlatformFreeModule(_glfw.x11.xcursor.handle); 1604 _glfw.x11.xcursor.handle = NULL; 1605 } 1606 1607 if (_glfw.x11.randr.handle) 1608 { 1609 _glfwPlatformFreeModule(_glfw.x11.randr.handle); 1610 _glfw.x11.randr.handle = NULL; 1611 } 1612 1613 if (_glfw.x11.xinerama.handle) 1614 { 1615 _glfwPlatformFreeModule(_glfw.x11.xinerama.handle); 1616 _glfw.x11.xinerama.handle = NULL; 1617 } 1618 1619 if (_glfw.x11.xrender.handle) 1620 { 1621 _glfwPlatformFreeModule(_glfw.x11.xrender.handle); 1622 _glfw.x11.xrender.handle = NULL; 1623 } 1624 1625 if (_glfw.x11.vidmode.handle) 1626 { 1627 _glfwPlatformFreeModule(_glfw.x11.vidmode.handle); 1628 _glfw.x11.vidmode.handle = NULL; 1629 } 1630 1631 if (_glfw.x11.xi.handle) 1632 { 1633 _glfwPlatformFreeModule(_glfw.x11.xi.handle); 1634 _glfw.x11.xi.handle = NULL; 1635 } 1636 1637 _glfwTerminateOSMesa(); 1638 // NOTE: These need to be unloaded after XCloseDisplay, as they register 1639 // cleanup callbacks that get called by that function 1640 _glfwTerminateEGL(); 1641 _glfwTerminateGLX(); 1642 1643 if (_glfw.x11.xlib.handle) 1644 { 1645 _glfwPlatformFreeModule(_glfw.x11.xlib.handle); 1646 _glfw.x11.xlib.handle = NULL; 1647 } 1648 1649 if (_glfw.x11.emptyEventPipe[0] || _glfw.x11.emptyEventPipe[1]) 1650 { 1651 close(_glfw.x11.emptyEventPipe[0]); 1652 close(_glfw.x11.emptyEventPipe[1]); 1653 } 1654 } 1655 1656 #endif // _GLFW_X11 1657