volviewer

Volumetric Data Toy Viewer
git clone anongit@rnpnr.xyz:volviewer.git
Log | Files | Refs | Feed | LICENSE

x11_init.c (70569B)


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