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