github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/external/glfw/src/x11_init.c (about)

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