ScrapExplorer - x11_init.c

Home / ext / glfw / src Lines: 1 | Size: 70515 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1//======================================================================== 2// GLFW 3.5 X11 - www.glfw.org 3//------------------------------------------------------------------------ 4// Copyright (c) 2002-2006 Marcus Geelnard 5// Copyright (c) 2006-2019 Camilla Löwy <[email protected]> 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 28#include "internal.h" 29 30#if defined(_GLFW_X11) 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// 47static 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// 213static 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// 440static 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 461static void inputMethodDestroyCallback(XIM im, XPointer clientData, XPointer callData) 462{ 463 _glfw.x11.im = NULL; 464} 465 466static 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// 497static 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// 514static 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 _glfwReleaseErrorHandlerX11(); 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// 606static 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 createKeyTables(); 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// 993static 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// 1028static 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// 1037static 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// 1051static 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// 1082static 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// 1098void _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// 1107void _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// 1117void _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// 1128Cursor _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 1166GLFWbool _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 1321int _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 1555void _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 1658
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.