packages feed

bindings-GLFW 3.3.9.0 → 3.3.9.1

raw patch · 44 files changed

+6475/−4285 lines, 44 files

Files

Test.hs view
@@ -61,7 +61,7 @@ versionMajor, versionMinor, versionRevision :: Int versionMajor    = 3 versionMinor    = 3-versionRevision = 2+versionRevision = 9  giveItTime :: IO () giveItTime = threadDelay 500000@@ -280,10 +280,9 @@ test_glfwGetMonitorName p'mon = do     p'name <- c'glfwGetMonitorName p'mon     if p'name == nullPtr-      then assertFailure ""+      then return ()       else do           name <- peekCString p'name-          assertBool "" $ length name `between` (0, 20)           assertBool "" $ all isAscii name  test_glfwGetMonitorWorkarea :: Ptr C'GLFWmonitor -> IO ()
bindings-GLFW.cabal view
@@ -1,5 +1,5 @@ name:         bindings-GLFW-version:      3.3.9.0+version:      3.3.9.1 category:     Graphics  author:       Brian Lewis <brian@lorf.org>@@ -137,9 +137,14 @@       c-sources:         glfw/src/glx_context.c         glfw/src/xkb_unicode.c-        glfw/src/linux_joystick.c         glfw/src/posix_time.c         glfw/src/posix_thread.c+      if os(linux)+        c-sources:+          glfw/src/linux_joystick.c+      if os(freebsd)+        c-sources:+          glfw/src/null_joystick.c       if flag(X)         cc-options: -DBINDINGS_GLFW_USE_X11 -D_GLFW_X11         c-sources:
glfw/include/GLFW/glfw3.h view
@@ -52,7 +52,7 @@  *  This is the reference documentation for OpenGL and OpenGL ES context related  *  functions.  For more task-oriented information, see the @ref context_guide.  */-/*! @defgroup vulkan Vulkan reference+/*! @defgroup vulkan Vulkan support reference  *  @brief Functions and types related to Vulkan.  *  *  This is the reference documentation for Vulkan related functions and types.@@ -190,20 +190,51 @@  #else /*__APPLE__*/    #include <GL/glcorearb.h>+  #if defined(GLFW_INCLUDE_GLEXT)+   #include <GL/glext.h>+  #endif   #endif /*__APPLE__*/ -#elif !defined(GLFW_INCLUDE_NONE)+#elif defined(GLFW_INCLUDE_GLU)   #if defined(__APPLE__) +  #if defined(GLFW_INCLUDE_GLU)+   #include <OpenGL/glu.h>+  #endif++ #else /*__APPLE__*/++  #if defined(GLFW_INCLUDE_GLU)+   #include <GL/glu.h>+  #endif++ #endif /*__APPLE__*/++#elif !defined(GLFW_INCLUDE_NONE) && \+      !defined(__gl_h_) && \+      !defined(__gles1_gl_h_) && \+      !defined(__gles2_gl2_h_) && \+      !defined(__gles2_gl3_h_) && \+      !defined(__gles2_gl31_h_) && \+      !defined(__gles2_gl32_h_) && \+      !defined(__gl_glcorearb_h_) && \+      !defined(__gl2_h_) /*legacy*/ && \+      !defined(__gl3_h_) /*legacy*/ && \+      !defined(__gl31_h_) /*legacy*/ && \+      !defined(__gl32_h_) /*legacy*/ && \+      !defined(__glcorearb_h_) /*legacy*/ && \+      !defined(__GL_H__) /*non-standard*/ && \+      !defined(__gltypes_h_) /*non-standard*/ && \+      !defined(__glee_h_) /*non-standard*/++ #if defined(__APPLE__)+   #if !defined(GLFW_INCLUDE_GLEXT)    #define GL_GLEXT_LEGACY   #endif   #include <OpenGL/gl.h>-  #if defined(GLFW_INCLUDE_GLU)-   #include <OpenGL/glu.h>-  #endif   #else /*__APPLE__*/ @@ -211,9 +242,6 @@   #if defined(GLFW_INCLUDE_GLEXT)    #include <GL/glext.h>   #endif-  #if defined(GLFW_INCLUDE_GLU)-   #include <GL/glu.h>-  #endif   #endif /*__APPLE__*/ @@ -234,13 +262,12 @@  /* We are building GLFW as a Win32 DLL */  #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL)- /* We are calling GLFW as a Win32 DLL */+ /* We are calling a GLFW Win32 DLL */  #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL)- /* We are building GLFW as a shared / dynamic library */+ /* We are building GLFW as a Unix shared library */  #define GLFWAPI __attribute__((visibility("default"))) #else- /* We are building or calling GLFW as a static library */  #define GLFWAPI #endif @@ -251,26 +278,27 @@  /*! @name GLFW version macros  *  @{ */-/*! @brief The major version number of the GLFW library.+/*! @brief The major version number of the GLFW header.  *- *  This is incremented when the API is changed in non-compatible ways.+ *  The major version number of the GLFW header.  This is incremented when the+ *  API is changed in non-compatible ways.  *  @ingroup init  */ #define GLFW_VERSION_MAJOR          3-/*! @brief The minor version number of the GLFW library.+/*! @brief The minor version number of the GLFW header.  *- *  This is incremented when features are added to the API but it remains- *  backward-compatible.+ *  The minor version number of the GLFW header.  This is incremented when+ *  features are added to the API but it remains backward-compatible.  *  @ingroup init  */ #define GLFW_VERSION_MINOR          3-/*! @brief The revision number of the GLFW library.+/*! @brief The revision number of the GLFW header.  *- *  This is incremented when a bug fix release is made that does not contain any- *  API changes.+ *  The revision number of the GLFW header.  This is incremented when a bug fix+ *  release is made that does not contain any API changes.  *  @ingroup init  */-#define GLFW_VERSION_REVISION       2+#define GLFW_VERSION_REVISION       9 /*! @} */  /*! @brief One.@@ -333,10 +361,15 @@ #define GLFW_HAT_RIGHT_DOWN         (GLFW_HAT_RIGHT | GLFW_HAT_DOWN) #define GLFW_HAT_LEFT_UP            (GLFW_HAT_LEFT  | GLFW_HAT_UP) #define GLFW_HAT_LEFT_DOWN          (GLFW_HAT_LEFT  | GLFW_HAT_DOWN)++/*! @ingroup input+ */+#define GLFW_KEY_UNKNOWN            -1+ /*! @} */ -/*! @defgroup keys Keyboard keys- *  @brief Keyboard key IDs.+/*! @defgroup keys Keyboard key tokens+ *  @brief Keyboard key tokens.  *  *  See [key input](@ref input_key) for how these are used.  *@@ -359,9 +392,6 @@  *  @{  */ -/* The unknown key */-#define GLFW_KEY_UNKNOWN            -1- /* Printable keys */ #define GLFW_KEY_SPACE              32 #define GLFW_KEY_APOSTROPHE         39  /* ' */@@ -931,7 +961,7 @@  *  and [attribute](@ref GLFW_CONTEXT_VERSION_MINOR_attrib).  */ #define GLFW_CONTEXT_VERSION_MINOR  0x00022003-/*! @brief Context client API revision number hint and attribute.+/*! @brief Context client API revision number attribute.  *  *  Context client API revision number  *  [attribute](@ref GLFW_CONTEXT_REVISION_attrib).@@ -949,9 +979,9 @@  *  and [attribute](@ref GLFW_OPENGL_FORWARD_COMPAT_attrib).  */ #define GLFW_OPENGL_FORWARD_COMPAT  0x00022006-/*! @brief OpenGL debug context hint and attribute.+/*! @brief Debug mode context hint and attribute.  *- *  OpenGL debug context [hint](@ref GLFW_OPENGL_DEBUG_CONTEXT_hint) and+ *  Debug mode context [hint](@ref GLFW_OPENGL_DEBUG_CONTEXT_hint) and  *  [attribute](@ref GLFW_OPENGL_DEBUG_CONTEXT_attrib).  */ #define GLFW_OPENGL_DEBUG_CONTEXT   0x00022007@@ -1035,6 +1065,9 @@ #define GLFW_EGL_CONTEXT_API        0x00036002 #define GLFW_OSMESA_CONTEXT_API     0x00036003 +#define GLFW_WAYLAND_PREFER_LIBDECOR    0x00038001+#define GLFW_WAYLAND_DISABLE_LIBDECOR   0x00038002+ /*! @defgroup shapes Standard cursor shapes  *  @brief Standard system cursor shapes.  *@@ -1095,6 +1128,11 @@  *  macOS specific [init hint](@ref GLFW_COCOA_MENUBAR_hint).  */ #define GLFW_COCOA_MENUBAR          0x00051002+/*! @brief Wayland specific init hint.+ *+ *  Wayland specific [init hint](@ref GLFW_WAYLAND_LIBDECOR_hint).+ */+#define GLFW_WAYLAND_LIBDECOR       0x00053001 /*! @} */  #define GLFW_DONT_CARE              -1@@ -1190,7 +1228,7 @@  *  *  @ingroup init  */-typedef void (* GLFWerrorfun)(int,const char*);+typedef void (* GLFWerrorfun)(int error_code, const char* description);  /*! @brief The function pointer type for window position callbacks.  *@@ -1213,7 +1251,7 @@  *  *  @ingroup window  */-typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int);+typedef void (* GLFWwindowposfun)(GLFWwindow* window, int xpos, int ypos);  /*! @brief The function pointer type for window size callbacks.  *@@ -1235,7 +1273,7 @@  *  *  @ingroup window  */-typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int);+typedef void (* GLFWwindowsizefun)(GLFWwindow* window, int width, int height);  /*! @brief The function pointer type for window close callbacks.  *@@ -1255,7 +1293,7 @@  *  *  @ingroup window  */-typedef void (* GLFWwindowclosefun)(GLFWwindow*);+typedef void (* GLFWwindowclosefun)(GLFWwindow* window);  /*! @brief The function pointer type for window content refresh callbacks.  *@@ -1275,7 +1313,7 @@  *  *  @ingroup window  */-typedef void (* GLFWwindowrefreshfun)(GLFWwindow*);+typedef void (* GLFWwindowrefreshfun)(GLFWwindow* window);  /*! @brief The function pointer type for window focus callbacks.  *@@ -1296,7 +1334,7 @@  *  *  @ingroup window  */-typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int);+typedef void (* GLFWwindowfocusfun)(GLFWwindow* window, int focused);  /*! @brief The function pointer type for window iconify callbacks.  *@@ -1317,7 +1355,7 @@  *  *  @ingroup window  */-typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int);+typedef void (* GLFWwindowiconifyfun)(GLFWwindow* window, int iconified);  /*! @brief The function pointer type for window maximize callbacks.  *@@ -1328,7 +1366,7 @@  *  @endcode  *  *  @param[in] window The window that was maximized or restored.- *  @param[in] iconified `GLFW_TRUE` if the window was maximized, or+ *  @param[in] maximized `GLFW_TRUE` if the window was maximized, or  *  `GLFW_FALSE` if it was restored.  *  *  @sa @ref window_maximize@@ -1338,7 +1376,7 @@  *  *  @ingroup window  */-typedef void (* GLFWwindowmaximizefun)(GLFWwindow*,int);+typedef void (* GLFWwindowmaximizefun)(GLFWwindow* window, int maximized);  /*! @brief The function pointer type for framebuffer size callbacks.  *@@ -1359,7 +1397,7 @@  *  *  @ingroup window  */-typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int);+typedef void (* GLFWframebuffersizefun)(GLFWwindow* window, int width, int height);  /*! @brief The function pointer type for window content scale callbacks.  *@@ -1380,7 +1418,7 @@  *  *  @ingroup window  */-typedef void (* GLFWwindowcontentscalefun)(GLFWwindow*,float,float);+typedef void (* GLFWwindowcontentscalefun)(GLFWwindow* window, float xscale, float yscale);  /*! @brief The function pointer type for mouse button callbacks.  *@@ -1406,7 +1444,7 @@  *  *  @ingroup input  */-typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int);+typedef void (* GLFWmousebuttonfun)(GLFWwindow* window, int button, int action, int mods);  /*! @brief The function pointer type for cursor position callbacks.  *@@ -1429,7 +1467,7 @@  *  *  @ingroup input  */-typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double);+typedef void (* GLFWcursorposfun)(GLFWwindow* window, double xpos, double ypos);  /*! @brief The function pointer type for cursor enter/leave callbacks.  *@@ -1450,7 +1488,7 @@  *  *  @ingroup input  */-typedef void (* GLFWcursorenterfun)(GLFWwindow*,int);+typedef void (* GLFWcursorenterfun)(GLFWwindow* window, int entered);  /*! @brief The function pointer type for scroll callbacks.  *@@ -1471,7 +1509,7 @@  *  *  @ingroup input  */-typedef void (* GLFWscrollfun)(GLFWwindow*,double,double);+typedef void (* GLFWscrollfun)(GLFWwindow* window, double xoffset, double yoffset);  /*! @brief The function pointer type for keyboard key callbacks.  *@@ -1497,7 +1535,7 @@  *  *  @ingroup input  */-typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int);+typedef void (* GLFWkeyfun)(GLFWwindow* window, int key, int scancode, int action, int mods);  /*! @brief The function pointer type for Unicode character callbacks.  *@@ -1518,7 +1556,7 @@  *  *  @ingroup input  */-typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int);+typedef void (* GLFWcharfun)(GLFWwindow* window, unsigned int codepoint);  /*! @brief The function pointer type for Unicode character with modifiers  *  callbacks.@@ -1545,7 +1583,7 @@  *  *  @ingroup input  */-typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int);+typedef void (* GLFWcharmodsfun)(GLFWwindow* window, unsigned int codepoint, int mods);  /*! @brief The function pointer type for path drop callbacks.  *@@ -1569,7 +1607,7 @@  *  *  @ingroup input  */-typedef void (* GLFWdropfun)(GLFWwindow*,int,const char*[]);+typedef void (* GLFWdropfun)(GLFWwindow* window, int path_count, const char* paths[]);  /*! @brief The function pointer type for monitor configuration callbacks.  *@@ -1590,7 +1628,7 @@  *  *  @ingroup monitor  */-typedef void (* GLFWmonitorfun)(GLFWmonitor*,int);+typedef void (* GLFWmonitorfun)(GLFWmonitor* monitor, int event);  /*! @brief The function pointer type for joystick configuration callbacks.  *@@ -1611,7 +1649,7 @@  *  *  @ingroup input  */-typedef void (* GLFWjoystickfun)(int,int);+typedef void (* GLFWjoystickfun)(int jid, int event);  /*! @brief Video mode type.  *@@ -1753,6 +1791,10 @@  *  bundle, if present.  This can be disabled with the @ref  *  GLFW_COCOA_CHDIR_RESOURCES init hint.  *+ *  @remark @x11 This function will set the `LC_CTYPE` category of the+ *  application locale according to the current environment if that category is+ *  still "C".  This is because the "C" locale breaks Unicode text input.+ *  *  @thread_safety This function must only be called from the main thread.  *  *  @sa @ref intro_init@@ -1776,6 +1818,8 @@  *  call this function, as it is called by @ref glfwInit before it returns  *  failure.  *+ *  This function has no effect if GLFW is not initialized.+ *  *  @errors Possible errors include @ref GLFW_PLATFORM_ERROR.  *  *  @remark This function may be called before @ref glfwInit.@@ -2093,8 +2137,8 @@  *  *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.  *- *  @remark @win32 calculates the returned physical size from the- *  current resolution and system DPI instead of querying the monitor EDID data.+ *  @remark @win32 On Windows 8 and earlier the physical size is calculated from+ *  the current resolution and system DPI instead of querying the monitor EDID data.  *  *  @thread_safety This function must only be called from the main thread.  *@@ -2248,8 +2292,9 @@  *  *  This function returns an array of all video modes supported by the specified  *  monitor.  The returned array is sorted in ascending order, first by color- *  bit depth (the sum of all channel depths) and then by resolution area (the- *  product of width and height).+ *  bit depth (the sum of all channel depths), then by resolution area (the+ *  product of width and height), then resolution width and finally by refresh+ *  rate.  *  *  @param[in] monitor The monitor to query.  *  @param[out] count Where to store the number of video modes in the returned@@ -2772,8 +2817,8 @@  *  @param[in] images The images to create the icon from.  This is ignored if  *  count is zero.  *- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref- *  GLFW_PLATFORM_ERROR.+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ *  GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.  *  *  @pointer_lifetime The specified image data is copied before this function  *  returns.@@ -3183,18 +3228,15 @@  *  previously restored.  If the window is already iconified, this function does  *  nothing.  *- *  If the specified window is a full screen window, the original monitor- *  resolution is restored until the window is restored.+ *  If the specified window is a full screen window, GLFW restores the original+ *  video mode of the monitor.  The window's desired video mode is set again+ *  when the window is restored.  *  *  @param[in] window The window to iconify.  *  *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref  *  GLFW_PLATFORM_ERROR.  *- *  @remark @wayland There is no concept of iconification in wl_shell, this- *  function will emit @ref GLFW_PLATFORM_ERROR when using this deprecated- *  protocol.- *  *  @thread_safety This function must only be called from the main thread.  *  *  @sa @ref window_iconify@@ -3214,8 +3256,8 @@  *  (minimized) or maximized.  If the window is already restored, this function  *  does nothing.  *- *  If the specified window is a full screen window, the resolution chosen for- *  the window is restored on the selected monitor.+ *  If the specified window is an iconified full screen window, its desired+ *  video mode is set again for its monitor when the window is restored.  *  *  @param[in] window The window to restore.  *@@ -3276,6 +3318,11 @@  *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref  *  GLFW_PLATFORM_ERROR.  *+ *  @remark @wayland Because Wayland wants every frame of the desktop to be+ *  complete, this function does not immediately make the window visible.+ *  Instead it will become visible the next time the window framebuffer is+ *  updated after this call.+ *  *  @thread_safety This function must only be called from the main thread.  *  *  @sa @ref window_hide@@ -3478,6 +3525,9 @@  *  errors.  However, this function should not fail as long as it is passed  *  valid arguments and the library has been [initialized](@ref intro_init).  *+ *  @remark @wayland The Wayland protocol provides no way to check whether a+ *  window is iconfied, so @ref GLFW_ICONIFIED always returns `GLFW_FALSE`.+ *  *  @thread_safety This function must only be called from the main thread.  *  *  @sa @ref window_attribs@@ -3769,8 +3819,8 @@  *  *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.  *- *  @remark @wayland The wl_shell protocol has no concept of iconification,- *  this callback will never be called when using this deprecated protocol.+ *  @remark @wayland The XDG-shell protocol has no event for iconification, so+ *  this callback will never be called.  *  *  @thread_safety This function must only be called from the main thread.  *@@ -4190,8 +4240,8 @@  *  @param[in] scancode The scancode of the key to query.  *  @return The UTF-8 encoded, layout-specific name of the key, or `NULL`.  *- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref- *  GLFW_PLATFORM_ERROR.+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ *  GLFW_INVALID_VALUE, @ref GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.  *  *  @remark The contents of the returned string may change when a keyboard  *  layout change event is received.@@ -4213,15 +4263,18 @@  *  *  This function returns the platform-specific scancode of the specified key.  *- *  If the key is `GLFW_KEY_UNKNOWN` or does not exist on the keyboard this- *  method will return `-1`.+ *  If the specified [key token](@ref keys) corresponds to a physical key not+ *  supported on the current platform then this method will return `-1`.+ *  Calling this function with anything other than a key token will return `-1`+ *  and generate a @ref GLFW_INVALID_ENUM error.  *- *  @param[in] key Any [named key](@ref keys).- *  @return The platform-specific scancode for the key, or `-1` if an- *  [error](@ref error_handling) occurred.+ *  @param[in] key Any [key token](@ref keys).+ *  @return The platform-specific scancode for the key, or `-1` if the key is+ *  not supported on the current platform or an [error](@ref error_handling)+ *  occurred.  *- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref- *  GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ *  GLFW_INVALID_ENUM.  *  *  @thread_safety This function may be called from any thread.  *@@ -4238,8 +4291,7 @@  *  *  This function returns the last state reported for the specified key to the  *  specified window.  The returned state is one of `GLFW_PRESS` or- *  `GLFW_RELEASE`.  The higher-level action `GLFW_REPEAT` is only reported to- *  the key callback.+ *  `GLFW_RELEASE`.  The action `GLFW_REPEAT` is only reported to the key callback.  *  *  If the @ref GLFW_STICKY_KEYS input mode is enabled, this function returns  *  `GLFW_PRESS` the first time you call it for a key that was pressed, even if@@ -4400,8 +4452,8 @@  *  @return The handle of the created cursor, or `NULL` if an  *  [error](@ref error_handling) occurred.  *- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref- *  GLFW_PLATFORM_ERROR.+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ *  GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.  *  *  @pointer_lifetime The specified image data is copied before this function  *  returns.@@ -4506,9 +4558,9 @@  *  [character callback](@ref glfwSetCharCallback) instead.  *  *  When a window loses input focus, it will generate synthetic key release- *  events for all pressed keys.  You can tell these events from user-generated- *  events by the fact that the synthetic ones are generated after the focus- *  loss event has been processed, i.e. after the+ *  events for all pressed keys with associated key tokens.  You can tell these+ *  events from user-generated events by the fact that the synthetic ones are+ *  generated after the focus loss event has been processed, i.e. after the  *  [window focus callback](@ref glfwSetWindowFocusCallback) has been called.  *  *  The scancode of a key is specific to that platform or sometimes even to that@@ -5191,6 +5243,8 @@  *  joystick is not present, does not have a mapping or an  *  [error](@ref error_handling) occurred.  *+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref GLFW_INVALID_ENUM.+ *  *  @pointer_lifetime The returned string is allocated and freed by GLFW.  You  *  should not free it yourself.  It is valid until the specified joystick is  *  disconnected, the gamepad mappings are updated or the library is terminated.@@ -5280,8 +5334,8 @@  *  @return The contents of the clipboard as a UTF-8 encoded string, or `NULL`  *  if an [error](@ref error_handling) occurred.  *- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref- *  GLFW_PLATFORM_ERROR.+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ *  GLFW_FORMAT_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.  *  *  @pointer_lifetime The returned string is allocated and freed by GLFW.  You  *  should not free it yourself.  It is valid until the next call to @ref@@ -5405,13 +5459,16 @@  *  thread.  *  *  This function makes the OpenGL or OpenGL ES context of the specified window- *  current on the calling thread.  A context must only be made current on- *  a single thread at a time and each thread can have only a single current- *  context at a time.+ *  current on the calling thread.  It can also detach the current context from+ *  the calling thread without making a new one current by passing in `NULL`.  *- *  When moving a context between threads, you must make it non-current on the- *  old thread before making it current on the new one.+ *  A context must only be made current on a single thread at a time and each+ *  thread can have only a single current context at a time.  Making a context+ *  current detaches any previously current context on the calling thread.  *+ *  When moving a context between threads, you must detach it (make it+ *  non-current) on the old thread before making it current on the new one.+ *  *  By default, making a context non-current implicitly forces a pipeline flush.  *  On machines that support `GL_KHR_context_flush_control`, you can control  *  whether a context performs this flush by setting the@@ -5425,6 +5482,10 @@  *  @param[in] window The window whose context to make current, or `NULL` to  *  detach the current context.  *+ *  @remarks If the previously current context was created via a different+ *  context creation API than the one passed to this function, GLFW will still+ *  detach the previous one from its API before making the new one current.+ *  *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref  *  GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.  *@@ -5625,13 +5686,11 @@  *  This function returns whether the Vulkan loader and any minimally functional  *  ICD have been found.  *- *  The availability of a Vulkan loader and even an ICD does not by itself- *  guarantee that surface creation or even instance creation is possible.- *  For example, on Fermi systems Nvidia will install an ICD that provides no- *  actual Vulkan support.  Call @ref glfwGetRequiredInstanceExtensions to check- *  whether the extensions necessary for Vulkan surface creation are available- *  and @ref glfwGetPhysicalDevicePresentationSupport to check whether a queue- *  family of a physical device supports image presentation.+ *  The availability of a Vulkan loader and even an ICD does not by itself guarantee that+ *  surface creation or even instance creation is possible.  Call @ref+ *  glfwGetRequiredInstanceExtensions to check whether the extensions necessary for Vulkan+ *  surface creation are available and @ref glfwGetPhysicalDevicePresentationSupport to+ *  check whether a queue family of a physical device supports image presentation.  *  *  @return `GLFW_TRUE` if Vulkan is minimally available, or `GLFW_FALSE`  *  otherwise.@@ -5677,10 +5736,6 @@  *  returned array, as it is an error to specify an extension more than once in  *  the `VkInstanceCreateInfo` struct.  *- *  @remark @macos This function currently supports either the- *  `VK_MVK_macos_surface` extension from MoltenVK or `VK_EXT_metal_surface`- *  extension.- *  *  @pointer_lifetime The returned array is allocated and freed by GLFW.  You  *  should not free it yourself.  It is guaranteed to be valid only until the  *  library is terminated.@@ -5762,7 +5817,7 @@  *  GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.  *  *  @remark @macos This function currently always returns `GLFW_TRUE`, as the- *  `VK_MVK_macos_surface` extension does not provide+ *  `VK_MVK_macos_surface` and `VK_EXT_metal_surface` extensions do not provide  *  a `vkGetPhysicalDevice*PresentationSupport` type function.  *  *  @thread_safety This function may be called from any thread.  For@@ -5819,8 +5874,10 @@  *  @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should  *  eliminate almost all occurrences of these errors.  *- *  @remark @macos This function currently only supports the- *  `VK_MVK_macos_surface` extension from MoltenVK.+ *  @remark @macos GLFW prefers the `VK_EXT_metal_surface` extension, with the+ *  `VK_MVK_macos_surface` extension as a fallback.  The name of the selected+ *  extension, if any, is included in the array returned by @ref+ *  glfwGetRequiredInstanceExtensions.  *  *  @remark @macos This function creates and sets a `CAMetalLayer` instance for  *  the window content view, which is required for MoltenVK to function.@@ -5861,6 +5918,7 @@  */ #ifndef GLAPIENTRY  #define GLAPIENTRY APIENTRY+ #define GLFW_GLAPIENTRY_DEFINED #endif  /* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */
glfw/src/cocoa_init.m view
@@ -251,7 +251,7 @@     _glfw.ns.keycodes[0x6D] = GLFW_KEY_F10;     _glfw.ns.keycodes[0x67] = GLFW_KEY_F11;     _glfw.ns.keycodes[0x6F] = GLFW_KEY_F12;-    _glfw.ns.keycodes[0x69] = GLFW_KEY_F13;+    _glfw.ns.keycodes[0x69] = GLFW_KEY_PRINT_SCREEN;     _glfw.ns.keycodes[0x6B] = GLFW_KEY_F14;     _glfw.ns.keycodes[0x71] = GLFW_KEY_F15;     _glfw.ns.keycodes[0x6A] = GLFW_KEY_F16;@@ -428,9 +428,6 @@ {     if (_glfw.hints.init.ns.menubar)     {-        // In case we are unbundled, make us a proper UI application-        [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];-         // Menu bar setup must go between sharedApplication and finishLaunching         // in order to properly emulate the behavior of NSApplicationMain @@ -449,6 +446,11 @@ {     _glfw.ns.finishedLaunching = GLFW_TRUE;     _glfwPlatformPostEmptyEvent();++    // In case we are unbundled, make us a proper UI application+    if (_glfw.hints.init.ns.menubar)+        [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];+     [NSApp stop:nil]; } @@ -473,18 +475,26 @@     if (!bundle)         return NULL; -    CFURLRef url =-        CFBundleCopyAuxiliaryExecutableURL(bundle, CFSTR("libvulkan.1.dylib"));-    if (!url)+    CFURLRef frameworksUrl = CFBundleCopyPrivateFrameworksURL(bundle);+    if (!frameworksUrl)         return NULL; +    CFURLRef loaderUrl = CFURLCreateCopyAppendingPathComponent(+        kCFAllocatorDefault, frameworksUrl, CFSTR("libvulkan.1.dylib"), false);+    if (!loaderUrl)+    {+        CFRelease(frameworksUrl);+        return NULL;+    }+     char path[PATH_MAX];     void* handle = NULL; -    if (CFURLGetFileSystemRepresentation(url, true, (UInt8*) path, sizeof(path) - 1))+    if (CFURLGetFileSystemRepresentation(loaderUrl, true, (UInt8*) path, sizeof(path) - 1))         handle = _glfw_dlopen(path); -    CFRelease(url);+    CFRelease(loaderUrl);+    CFRelease(frameworksUrl);     return handle; } @@ -605,6 +615,8 @@     free(_glfw.ns.clipboardString);      _glfwTerminateNSGL();+    _glfwTerminateEGL();+    _glfwTerminateOSMesa();     _glfwTerminateJoysticksNS();      } // autoreleasepool
glfw/src/cocoa_joystick.h view
@@ -33,6 +33,7 @@ #define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE struct { int dummyJoystick; }  #define _GLFW_PLATFORM_MAPPING_NAME "Mac OS X"+#define GLFW_BUILD_COCOA_MAPPINGS  // Cocoa-specific per-joystick data //
glfw/src/cocoa_joystick.m view
@@ -98,8 +98,7 @@ {     int i; -    if (!js->present)-        return;+    _glfwInputJoystick(js, GLFW_DISCONNECTED);      for (i = 0;  i < CFArrayGetCount(js->ns.axes);  i++)         free((void*) CFArrayGetValueAtIndex(js->ns.axes, i));@@ -114,7 +113,6 @@     CFRelease(js->ns.hats);      _glfwFreeJoystick(js);-    _glfwInputJoystick(js, GLFW_DISCONNECTED); }  // Callback for user-initiated joystick addition@@ -139,6 +137,14 @@             return;     } +    CFArrayRef elements =+        IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);++    // It is reportedly possible for this to fail on macOS 13 Ventura+    // if the application does not have input monitoring permissions+    if (!elements)+        return;+     axes    = CFArrayCreateMutable(NULL, 0, NULL);     buttons = CFArrayCreateMutable(NULL, 0, NULL);     hats    = CFArrayCreateMutable(NULL, 0, NULL);@@ -182,9 +188,6 @@                 name[8], name[9], name[10]);     } -    CFArrayRef elements =-        IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);-     for (i = 0;  i < CFArrayGetCount(elements);  i++)     {         IOHIDElementRef native = (IOHIDElementRef)@@ -294,9 +297,9 @@      for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)     {-        if (_glfw.joysticks[jid].ns.device == device)+        if (_glfw.joysticks[jid].connected && _glfw.joysticks[jid].ns.device == device)         {-            closeJoystick(_glfw.joysticks + jid);+            closeJoystick(&_glfw.joysticks[jid]);             break;         }     }@@ -392,7 +395,10 @@     int jid;      for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)-        closeJoystick(_glfw.joysticks + jid);+    {+        if (_glfw.joysticks[jid].connected)+            closeJoystick(&_glfw.joysticks[jid]);+    }      CFRelease(_glfw.ns.hidManager);     _glfw.ns.hidManager = NULL;@@ -470,7 +476,7 @@         }     } -    return js->present;+    return js->connected; }  void _glfwPlatformUpdateGamepadGUID(char* guid)
glfw/src/cocoa_monitor.m view
@@ -39,18 +39,31 @@  // Get the name of the specified display, or NULL //-static char* getDisplayName(CGDirectDisplayID displayID)+static char* getMonitorName(CGDirectDisplayID displayID, NSScreen* screen) {+    // IOKit doesn't work on Apple Silicon anymore+    // Luckily, 10.15 introduced -[NSScreen localizedName].+    // Use it if available, and fall back to IOKit otherwise.+    if (screen)+    {+        if ([screen respondsToSelector:@selector(localizedName)])+        {+            NSString* name = [screen valueForKey:@"localizedName"];+            if (name)+                return _glfw_strdup([name UTF8String]);+        }+    }+     io_iterator_t it;     io_service_t service;     CFDictionaryRef info; -    if (IOServiceGetMatchingServices(kIOMasterPortDefault,+    if (IOServiceGetMatchingServices(MACH_PORT_NULL,                                      IOServiceMatching("IODisplayConnect"),                                      &it) != 0)     {         // This may happen if a desktop Mac is running headless-        return NULL;+        return _glfw_strdup("Display");     }      while ((service = IOIteratorNext(it)) != 0)@@ -85,11 +98,7 @@     IOObjectRelease(it);      if (!service)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Cocoa: Failed to find service port for display");-        return NULL;-    }+        return _glfw_strdup("Display");      CFDictionaryRef names =         CFDictionaryGetValue(info, CFSTR(kDisplayProductName));@@ -101,7 +110,7 @@     {         // This may happen if a desktop Mac is running headless         CFRelease(info);-        return NULL;+        return _glfw_strdup("Display");     }      const CFIndex size =@@ -209,31 +218,6 @@     } } -// Finds and caches the NSScreen corresponding to the specified monitor-//-static GLFWbool refreshMonitorScreen(_GLFWmonitor* monitor)-{-    if (monitor->ns.screen)-        return GLFW_TRUE;--    for (NSScreen* screen in [NSScreen screens])-    {-        NSNumber* displayID = [screen deviceDescription][@"NSScreenNumber"];--        // HACK: Compare unit numbers instead of display IDs to work around-        //       display replacement on machines with automatic graphics-        //       switching-        if (monitor->ns.unitNumber == CGDisplayUnitNumber([displayID unsignedIntValue]))-        {-            monitor->ns.screen = screen;-            return GLFW_TRUE;-        }-    }--    _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to find a screen for monitor");-    return GLFW_FALSE;-}- // Returns the display refresh rate queried from the I/O registry // static double getFallbackRefreshRate(CGDirectDisplayID displayID)@@ -243,7 +227,7 @@     io_iterator_t it;     io_service_t service; -    if (IOServiceGetMatchingServices(kIOMasterPortDefault,+    if (IOServiceGetMatchingServices(MACH_PORT_NULL,                                      IOServiceMatching("IOFramebuffer"),                                      &it) != 0)     {@@ -277,15 +261,21 @@                                             CFSTR("IOFBCurrentPixelCount"),                                             kCFAllocatorDefault,                                             kNilOptions);-        if (!clockRef || !countRef)-            break;          uint32_t clock = 0, count = 0;-        CFNumberGetValue(clockRef, kCFNumberIntType, &clock);-        CFNumberGetValue(countRef, kCFNumberIntType, &count);-        CFRelease(clockRef);-        CFRelease(countRef); +        if (clockRef)+        {+            CFNumberGetValue(clockRef, kCFNumberIntType, &clock);+            CFRelease(clockRef);+        }++        if (countRef)+        {+            CFNumberGetValue(countRef, kCFNumberIntType, &count);+            CFRelease(countRef);+        }+         if (clock > 0 && count > 0)             refreshRate = clock / (double) count; @@ -328,27 +318,46 @@         if (CGDisplayIsAsleep(displays[i]))             continue; +        const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]);+        NSScreen* screen = nil;++        for (screen in [NSScreen screens])+        {+            NSNumber* screenNumber = [screen deviceDescription][@"NSScreenNumber"];++            // HACK: Compare unit numbers instead of display IDs to work around+            //       display replacement on machines with automatic graphics+            //       switching+            if (CGDisplayUnitNumber([screenNumber unsignedIntValue]) == unitNumber)+                break;+        }+         // HACK: Compare unit numbers instead of display IDs to work around         //       display replacement on machines with automatic graphics         //       switching-        const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]);-        for (uint32_t j = 0;  j < disconnectedCount;  j++)+        uint32_t j;+        for (j = 0;  j < disconnectedCount;  j++)         {             if (disconnected[j] && disconnected[j]->ns.unitNumber == unitNumber)             {+                disconnected[j]->ns.screen = screen;                 disconnected[j] = NULL;                 break;             }         } +        if (j < disconnectedCount)+            continue;+         const CGSize size = CGDisplayScreenSize(displays[i]);-        char* name = getDisplayName(displays[i]);+        char* name = getMonitorName(displays[i], screen);         if (!name)-            name = _glfw_strdup("Unknown");+            continue;          _GLFWmonitor* monitor = _glfwAllocMonitor(name, size.width, size.height);         monitor->ns.displayID  = displays[i];         monitor->ns.unitNumber = unitNumber;+        monitor->ns.screen     = screen;          free(name); @@ -457,8 +466,11 @@ {     @autoreleasepool { -    if (!refreshMonitorScreen(monitor))-        return;+    if (!monitor->ns.screen)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Cocoa: Cannot query content scale without screen");+    }      const NSRect points = [monitor->ns.screen frame];     const NSRect pixels = [monitor->ns.screen convertRectToBacking:points];@@ -477,8 +489,11 @@ {     @autoreleasepool { -    if (!refreshMonitorScreen(monitor))-        return;+    if (!monitor->ns.screen)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Cocoa: Cannot query workarea without screen");+    }      const NSRect frameRect = [monitor->ns.screen visibleFrame]; @@ -521,7 +536,7 @@         }          // Skip duplicate modes-        if (i < *count)+        if (j < *count)             continue;          (*count)++;
glfw/src/cocoa_platform.h view
@@ -31,7 +31,9 @@  // NOTE: All of NSGL was deprecated in the 10.14 SDK //       This disables the pointless warnings for every symbol we use+#ifndef GL_SILENCE_DEPRECATION #define GL_SILENCE_DEPRECATION+#endif  #if defined(__OBJC__) #import <Cocoa/Cocoa.h>@@ -40,8 +42,10 @@ #endif  // NOTE: Many Cocoa enum values have been renamed and we need to build across-//       SDK versions where one is unavailable or the other deprecated-//       We use the newer names in code and these macros to handle compatibility+//       SDK versions where one is unavailable or deprecated.+//       We use the newer names in code and replace them with the older names if+//       the base SDK does not provide the newer names.+ #if MAC_OS_X_VERSION_MAX_ALLOWED < 101200  #define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat  #define NSEventMaskAny NSAnyEventMask@@ -60,6 +64,15 @@  #define NSWindowStyleMaskTitled NSTitledWindowMask #endif +// NOTE: Many Cocoa dynamically linked constants have been renamed and we need+//       to build across SDK versions where one is unavailable or deprecated.+//       We use the newer names in code and replace them with the older names if+//       the deployment target is older than the newer names.++#if MAC_OS_X_VERSION_MIN_REQUIRED < 101300+ #define NSPasteboardTypeURL NSURLPboardType+#endif+ typedef VkFlags VkMacOSSurfaceCreateFlagsMVK; typedef VkFlags VkMetalSurfaceCreateFlagsEXT; @@ -92,7 +105,7 @@ #define _glfw_dlclose(handle) dlclose(handle) #define _glfw_dlsym(handle, name) dlsym(handle, name) -#define _GLFW_EGL_NATIVE_WINDOW  ((EGLNativeWindowType) window->ns.view)+#define _GLFW_EGL_NATIVE_WINDOW  ((EGLNativeWindowType) window->ns.layer) #define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY  #define _GLFW_PLATFORM_WINDOW_STATE         _GLFWwindowNS  ns@@ -121,6 +134,7 @@     id              layer;      GLFWbool        maximized;+    GLFWbool        occluded;     GLFWbool        retina;      // Cached window properties to filter out duplicate events@@ -132,7 +146,6 @@     // since the last cursor motion event was processed     // This is kept to counteract Cocoa doing the same internally     double          cursorWarpDeltaX, cursorWarpDeltaY;- } _GLFWwindowNS;  // Cocoa-specific global data@@ -167,7 +180,6 @@         PFN_LMGetKbdType GetKbdType;         CFStringRef     kPropertyUnicodeKeyLayoutData;     } tis;- } _GLFWlibraryNS;  // Cocoa-specific per-monitor data@@ -179,7 +191,6 @@     uint32_t            unitNumber;     id                  screen;     double              fallbackRefreshRate;- } _GLFWmonitorNS;  // Cocoa-specific per-cursor data@@ -187,7 +198,6 @@ typedef struct _GLFWcursorNS {     id              object;- } _GLFWcursorNS;  // Cocoa-specific global timer data@@ -195,7 +205,6 @@ typedef struct _GLFWtimerNS {     uint64_t        frequency;- } _GLFWtimerNS;  
glfw/src/cocoa_window.m view
@@ -31,25 +31,9 @@ #include <float.h> #include <string.h> -// Returns the style mask corresponding to the window settings-//-static NSUInteger getStyleMask(_GLFWwindow* window)-{-    NSUInteger styleMask = NSWindowStyleMaskMiniaturizable;--    if (window->monitor || !window->decorated)-        styleMask |= NSWindowStyleMaskBorderless;-    else-    {-        styleMask |= NSWindowStyleMaskTitled |-                     NSWindowStyleMaskClosable;--        if (window->resizable)-            styleMask |= NSWindowStyleMaskResizable;-    }--    return styleMask;-}+// HACK: This enum value is missing from framework headers on OS X 10.11 despite+//       having been (according to documentation) added in Mac OS X 10.7+#define NSWindowCollectionBehaviorFullScreenNone (1 << 9)  // Returns whether the cursor is in the content area of the specified window //@@ -114,10 +98,11 @@     else if (_glfw.ns.disabledCursorWindow == window)     {         _glfw.ns.disabledCursorWindow = NULL;-        CGAssociateMouseAndMouseCursorPosition(true);         _glfwPlatformSetCursorPos(window,                                   _glfw.ns.restoreCursorPosX,                                   _glfw.ns.restoreCursorPosY);+        // NOTE: The matching CGAssociateMouseAndMouseCursorPosition call is+        //       made in _glfwPlatformSetCursorPos as part of a workaround     }      if (cursorInContentArea(window))@@ -243,7 +228,7 @@  - (void)windowDidResize:(NSNotification *)notification {-    if (window->context.client != GLFW_NO_API)+    if (window->context.source == GLFW_NATIVE_CONTEXT_API)         [window->context.nsgl.object update];      if (_glfw.ns.disabledCursorWindow == window)@@ -278,7 +263,7 @@  - (void)windowDidMove:(NSNotification *)notification {-    if (window->context.client != GLFW_NO_API)+    if (window->context.source == GLFW_NATIVE_CONTEXT_API)         [window->context.nsgl.object update];      if (_glfw.ns.disabledCursorWindow == window)@@ -322,6 +307,19 @@     _glfwInputWindowFocus(window, GLFW_FALSE); } +- (void)windowDidChangeOcclusionState:(NSNotification* )notification+{+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1090+    if ([window->ns.object respondsToSelector:@selector(occlusionState)])+    {+        if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible)+            window->ns.occluded = GLFW_FALSE;+        else+            window->ns.occluded = GLFW_TRUE;+    }+#endif+}+ @end  @@ -352,9 +350,7 @@         markedText = [[NSMutableAttributedString alloc] init];          [self updateTrackingAreas];-        // NOTE: kUTTypeURL corresponds to NSPasteboardTypeURL but is available-        //       on 10.7 without having been deprecated yet-        [self registerForDraggedTypes:@[(__bridge NSString*) kUTTypeURL]];+        [self registerForDraggedTypes:@[NSPasteboardTypeURL]];     }      return self;@@ -389,7 +385,7 @@  - (void)updateLayer {-    if (window->context.client != GLFW_NO_API)+    if (window->context.source == GLFW_NATIVE_CONTEXT_API)         [window->context.nsgl.object update];      _glfwInputWindowDamage(window);@@ -512,26 +508,25 @@ {     const NSRect contentRect = [window->ns.view frame];     const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];--    if (fbRect.size.width != window->ns.fbWidth ||-        fbRect.size.height != window->ns.fbHeight)-    {-        window->ns.fbWidth  = fbRect.size.width;-        window->ns.fbHeight = fbRect.size.height;-        _glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);-    }-     const float xscale = fbRect.size.width / contentRect.size.width;     const float yscale = fbRect.size.height / contentRect.size.height;      if (xscale != window->ns.xscale || yscale != window->ns.yscale)     {+        if (window->ns.retina && window->ns.layer)+            [window->ns.layer setContentsScale:[window->ns.object backingScaleFactor]];+         window->ns.xscale = xscale;         window->ns.yscale = yscale;         _glfwInputWindowContentScale(window, xscale, yscale);+    } -        if (window->ns.retina && window->ns.layer)-            [window->ns.layer setContentsScale:[window->ns.object backingScaleFactor]];+    if (fbRect.size.width != window->ns.fbWidth ||+        fbRect.size.height != window->ns.fbHeight)+    {+        window->ns.fbWidth  = fbRect.size.width;+        window->ns.fbHeight = fbRect.size.height;+        _glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);     } } @@ -723,14 +718,24 @@     else         characters = (NSString*) string; -    const NSUInteger length = [characters length];-    for (NSUInteger i = 0;  i < length;  i++)+    NSRange range = NSMakeRange(0, [characters length]);+    while (range.length)     {-        const unichar codepoint = [characters characterAtIndex:i];-        if ((codepoint & 0xff00) == 0xf700)-            continue;+        uint32_t codepoint = 0; -        _glfwInputChar(window, codepoint, mods, plain);+        if ([characters getBytes:&codepoint+                       maxLength:sizeof(codepoint)+                      usedLength:NULL+                        encoding:NSUTF32StringEncoding+                         options:0+                           range:range+                  remainingRange:&range])+        {+            if (codepoint >= 0xf700 && codepoint <= 0xf7ff)+                continue;++            _glfwInputChar(window, codepoint, mods, plain);+        }     } } @@ -793,9 +798,21 @@     else         contentRect = NSMakeRect(0, 0, wndconfig->width, wndconfig->height); +    NSUInteger styleMask = NSWindowStyleMaskMiniaturizable;++    if (window->monitor || !window->decorated)+        styleMask |= NSWindowStyleMaskBorderless;+    else+    {+        styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);++        if (window->resizable)+            styleMask |= NSWindowStyleMaskResizable;+    }+     window->ns.object = [[GLFWWindow alloc]         initWithContentRect:contentRect-                  styleMask:getStyleMask(window)+                  styleMask:styleMask                     backing:NSBackingStoreBuffered                       defer:NO]; @@ -821,6 +838,12 @@                 NSWindowCollectionBehaviorManaged;             [window->ns.object setCollectionBehavior:behavior];         }+        else+        {+            const NSWindowCollectionBehavior behavior =+                NSWindowCollectionBehaviorFullScreenNone;+            [window->ns.object setCollectionBehavior:behavior];+        }          if (wndconfig->floating)             [window->ns.object setLevel:NSFloatingWindowLevel];@@ -901,6 +924,11 @@         }         else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)         {+            // EGL implementation on macOS use CALayer* EGLNativeWindowType so we+            // need to get the layer for EGL window surface creation.+            [window->ns.view setWantsLayer:YES];+            window->ns.layer = [window->ns.view layer];+             if (!_glfwInitEGL())                 return GLFW_FALSE;             if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))@@ -913,6 +941,9 @@             if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))                 return GLFW_FALSE;         }++        if (!_glfwRefreshContextAttribs(window, ctxconfig))+            return GLFW_FALSE;     }      if (window->monitor)@@ -920,7 +951,19 @@         _glfwPlatformShowWindow(window);         _glfwPlatformFocusWindow(window);         acquireMonitor(window);++        if (wndconfig->centerCursor)+            _glfwCenterCursorInContentArea(window);     }+    else+    {+        if (wndconfig->visible)+        {+            _glfwPlatformShowWindow(window);+            if (wndconfig->focused)+                _glfwPlatformFocusWindow(window);+        }+    }      return GLFW_TRUE; @@ -1198,9 +1241,10 @@         {             const NSRect contentRect =                 NSMakeRect(xpos, _glfwTransformYNS(ypos + height - 1), width, height);+            const NSUInteger styleMask = [window->ns.object styleMask];             const NSRect frameRect =                 [window->ns.object frameRectForContentRect:contentRect-                                                 styleMask:getStyleMask(window)];+                                                 styleMask:styleMask];              [window->ns.object setFrame:frameRect display:YES];         }@@ -1217,7 +1261,27 @@     // TODO: Solve this in a less terrible way     _glfwPlatformPollEvents(); -    const NSUInteger styleMask = getStyleMask(window);+    NSUInteger styleMask = [window->ns.object styleMask];++    if (window->monitor)+    {+        styleMask &= ~(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable);+        styleMask |= NSWindowStyleMaskBorderless;+    }+    else+    {+        if (window->decorated)+        {+            styleMask &= ~NSWindowStyleMaskBorderless;+            styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);+        }++        if (window->resizable)+            styleMask |= NSWindowStyleMaskResizable;+        else+            styleMask &= ~NSWindowStyleMaskResizable;+    }+     [window->ns.object setStyleMask:styleMask];     // HACK: Changing the style mask can cause the first responder to be cleared     [window->ns.object makeFirstResponder:window->ns.view];@@ -1263,6 +1327,20 @@         else             [window->ns.object setLevel:NSNormalWindowLevel]; +        if (window->resizable)+        {+            const NSWindowCollectionBehavior behavior =+                NSWindowCollectionBehaviorFullScreenPrimary |+                NSWindowCollectionBehaviorManaged;+            [window->ns.object setCollectionBehavior:behavior];+        }+        else+        {+            const NSWindowCollectionBehavior behavior =+                NSWindowCollectionBehaviorFullScreenNone;+            [window->ns.object setCollectionBehavior:behavior];+        }+         [window->ns.object setHasShadow:YES];         // HACK: Clearing NSWindowStyleMaskTitled resets and disables the window         //       title property but the miniwindow title property is unaffected@@ -1296,7 +1374,12 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window) {     @autoreleasepool {-    return [window->ns.object isZoomed];++    if (window->resizable)+        return [window->ns.object isZoomed];+    else+        return GLFW_FALSE;+     } // autoreleasepool } @@ -1328,15 +1411,46 @@ void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled) {     @autoreleasepool {-    [window->ns.object setStyleMask:getStyleMask(window)];++    const NSUInteger styleMask = [window->ns.object styleMask];+    if (enabled)+    {+        [window->ns.object setStyleMask:(styleMask | NSWindowStyleMaskResizable)];+        const NSWindowCollectionBehavior behavior =+            NSWindowCollectionBehaviorFullScreenPrimary |+            NSWindowCollectionBehaviorManaged;+        [window->ns.object setCollectionBehavior:behavior];+    }+    else+    {+        [window->ns.object setStyleMask:(styleMask & ~NSWindowStyleMaskResizable)];+        const NSWindowCollectionBehavior behavior =+            NSWindowCollectionBehaviorFullScreenNone;+        [window->ns.object setCollectionBehavior:behavior];+    }+     } // autoreleasepool }  void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled) {     @autoreleasepool {-    [window->ns.object setStyleMask:getStyleMask(window)];++    NSUInteger styleMask = [window->ns.object styleMask];+    if (enabled)+    {+        styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);+        styleMask &= ~NSWindowStyleMaskBorderless;+    }+    else+    {+        styleMask |= NSWindowStyleMaskBorderless;+        styleMask &= ~(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);+    }++    [window->ns.object setStyleMask:styleMask];     [window->ns.object makeFirstResponder:window->ns.view];+     } // autoreleasepool } @@ -1501,6 +1615,11 @@                                               _glfwTransformYNS(globalPoint.y)));     } +    // HACK: Calling this right after setting the cursor position prevents macOS+    //       from freezing the cursor for a fraction of a second afterwards+    if (window->cursorMode != GLFW_CURSOR_DISABLED)+        CGAssociateMouseAndMouseCursorPosition(true);+     } // autoreleasepool } @@ -1519,7 +1638,7 @@     if (scancode < 0 || scancode > 0xff ||         _glfw.ns.keycodes[scancode] == GLFW_KEY_UNKNOWN)     {-        _glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode");+        _glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode %i", scancode);         return NULL;     } 
glfw/src/context.c view
@@ -48,16 +48,6 @@ // GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) {-    if (ctxconfig->share)-    {-        if (ctxconfig->client == GLFW_NO_API ||-            ctxconfig->share->context.client == GLFW_NO_API)-        {-            _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);-            return GLFW_FALSE;-        }-    }-     if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&         ctxconfig->source != GLFW_EGL_CONTEXT_API &&         ctxconfig->source != GLFW_OSMESA_CONTEXT_API)@@ -78,6 +68,23 @@         return GLFW_FALSE;     } +    if (ctxconfig->share)+    {+        if (ctxconfig->client == GLFW_NO_API ||+            ctxconfig->share->context.client == GLFW_NO_API)+        {+            _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);+            return GLFW_FALSE;+        }++        if (ctxconfig->source != ctxconfig->share->context.source)+        {+            _glfwInputError(GLFW_INVALID_ENUM,+                            "Context creation APIs do not match between contexts");+            return GLFW_FALSE;+        }+    }+     if (ctxconfig->client == GLFW_OPENGL_API)     {         if ((ctxconfig->major < 1 || ctxconfig->minor < 0) ||@@ -196,12 +203,6 @@             continue;         } -        if (desired->doublebuffer != current->doublebuffer)-        {-            // Double buffering is a hard constraint-            continue;-        }-         // Count number of missing buffers         {             missing = 0;@@ -362,6 +363,8 @@      previous = _glfwPlatformGetTls(&_glfw.contextSlot);     glfwMakeContextCurrent((GLFWwindow*) window);+    if (_glfwPlatformGetTls(&_glfw.contextSlot) != window)+        return GLFW_FALSE;      window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)         window->context.getProcAddress("glGetIntegerv");@@ -570,7 +573,9 @@         PFNGLCLEARPROC glClear = (PFNGLCLEARPROC)             window->context.getProcAddress("glClear");         glClear(GL_COLOR_BUFFER_BIT);-        window->context.swapBuffers(window);++        if (window->doublebuffer)+            window->context.swapBuffers(window);     }      glfwMakeContextCurrent((GLFWwindow*) previous);@@ -613,9 +618,11 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle) {     _GLFWwindow* window = (_GLFWwindow*) handle;-    _GLFWwindow* previous = _glfwPlatformGetTls(&_glfw.contextSlot);+    _GLFWwindow* previous;      _GLFW_REQUIRE_INIT();++    previous = _glfwPlatformGetTls(&_glfw.contextSlot);      if (window && window->context.client == GLFW_NO_API)     {
glfw/src/egl_context.c view
@@ -88,14 +88,31 @@ // Return the EGLConfig most closely matching the specified hints // static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,-                                const _GLFWfbconfig* desired,+                                const _GLFWfbconfig* fbconfig,                                 EGLConfig* result) {     EGLConfig* nativeConfigs;     _GLFWfbconfig* usableConfigs;     const _GLFWfbconfig* closest;-    int i, nativeCount, usableCount;+    int i, nativeCount, usableCount, apiBit;+    GLFWbool wrongApiAvailable = GLFW_FALSE; +    if (ctxconfig->client == GLFW_OPENGL_ES_API)+    {+        if (ctxconfig->major == 1)+            apiBit = EGL_OPENGL_ES_BIT;+        else+            apiBit = EGL_OPENGL_ES2_BIT;+    }+    else+        apiBit = EGL_OPENGL_BIT;++    if (fbconfig->stereo)+    {+        _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "EGL: Stereo rendering not supported");+        return GLFW_FALSE;+    }+     eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);     if (!nativeCount)     {@@ -131,7 +148,7 @@             if (!vi.visualid)                 continue; -            if (desired->transparent)+            if (fbconfig->transparent)             {                 int count;                 XVisualInfo* vis =@@ -145,23 +162,10 @@         } #endif // _GLFW_X11 -        if (ctxconfig->client == GLFW_OPENGL_ES_API)-        {-            if (ctxconfig->major == 1)-            {-                if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))-                    continue;-            }-            else-            {-                if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))-                    continue;-            }-        }-        else if (ctxconfig->client == GLFW_OPENGL_API)+        if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & apiBit))         {-            if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))-                continue;+            wrongApiAvailable = GLFW_TRUE;+            continue;         }          u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE);@@ -172,16 +176,57 @@         u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE);         u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE); +#if defined(_GLFW_WAYLAND)+        // NOTE: The wl_surface opaque region is no guarantee that its buffer+        //       is presented as opaque, if it also has an alpha channel+        // HACK: If EGL_EXT_present_opaque is unavailable, ignore any config+        //       with an alpha channel to ensure the buffer is opaque+        if (!_glfw.egl.EXT_present_opaque)+        {+            if (!fbconfig->transparent && u->alphaBits > 0)+                continue;+        }+#endif // _GLFW_WAYLAND+         u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);-        u->doublebuffer = GLFW_TRUE;+        u->doublebuffer = fbconfig->doublebuffer;          u->handle = (uintptr_t) n;         usableCount++;     } -    closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);+    closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);     if (closest)         *result = (EGLConfig) closest->handle;+    else+    {+        if (wrongApiAvailable)+        {+            if (ctxconfig->client == GLFW_OPENGL_ES_API)+            {+                if (ctxconfig->major == 1)+                {+                    _glfwInputError(GLFW_API_UNAVAILABLE,+                                    "EGL: Failed to find support for OpenGL ES 1.x");+                }+                else+                {+                    _glfwInputError(GLFW_API_UNAVAILABLE,+                                    "EGL: Failed to find support for OpenGL ES 2 or later");+                }+            }+            else+            {+                _glfwInputError(GLFW_API_UNAVAILABLE,+                                "EGL: Failed to find support for OpenGL");+            }+        }+        else+        {+            _glfwInputError(GLFW_FORMAT_UNAVAILABLE,+                            "EGL: Failed to find a suitable EGLConfig");+        }+    }      free(nativeConfigs);     free(usableConfigs);@@ -230,6 +275,12 @@         return;     } +#if defined(_GLFW_WAYLAND)+    // NOTE: Swapping buffers on a hidden window on Wayland makes it visible+    if (!window->wl.visible)+        return;+#endif+     eglSwapBuffers(_glfw.egl.display, window->context.egl.surface); } @@ -253,6 +304,7 @@ static GLFWglproc getProcAddressEGL(const char* procname) {     _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);+    assert(window != NULL);      if (window->context.egl.client)     {@@ -314,6 +366,8 @@         "libEGL.dylib", #elif defined(__CYGWIN__)         "libEGL-1.so",+#elif defined(__OpenBSD__) || defined(__NetBSD__)+        "libEGL.so", #else         "libEGL.so.1", #endif@@ -426,6 +480,8 @@         extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");     _glfw.egl.KHR_context_flush_control =         extensionSupportedEGL("EGL_KHR_context_flush_control");+    _glfw.egl.EXT_present_opaque =+        extensionSupportedEGL("EGL_EXT_present_opaque");      return GLFW_TRUE; }@@ -475,11 +531,7 @@         share = ctxconfig->share->context.egl.handle;      if (!chooseEGLConfig(ctxconfig, fbconfig, &config))-    {-        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,-                        "EGL: Failed to find a suitable EGLConfig");         return GLFW_FALSE;-    }      if (ctxconfig->client == GLFW_OPENGL_ES_API)     {@@ -536,18 +588,18 @@             flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;         } -        if (ctxconfig->noerror)-        {-            if (_glfw.egl.KHR_create_context_no_error)-                setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);-        }-         if (ctxconfig->major != 1 || ctxconfig->minor != 0)         {             setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);             setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);         } +        if (ctxconfig->noerror)+        {+            if (_glfw.egl.KHR_create_context_no_error)+                setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);+        }+         if (mask)             setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask); @@ -588,18 +640,24 @@     }      // Set up attributes for surface creation+    index = 0;++    if (fbconfig->sRGB)     {-        int index = 0;+        if (_glfw.egl.KHR_gl_colorspace)+            setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);+    } -        if (fbconfig->sRGB)-        {-            if (_glfw.egl.KHR_gl_colorspace)-                setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);-        }+    if (!fbconfig->doublebuffer)+        setAttrib(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER); -        setAttrib(EGL_NONE, EGL_NONE);-    }+#if defined(_GLFW_WAYLAND)+    if (_glfw.egl.EXT_present_opaque)+        setAttrib(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent);+#endif // _GLFW_WAYLAND +    setAttrib(EGL_NONE, EGL_NONE);+     window->context.egl.surface =         eglCreateWindowSurface(_glfw.egl.display,                                config,@@ -629,6 +687,8 @@             "libGLES_CM.dll", #elif defined(_GLFW_COCOA)             "libGLESv1_CM.dylib",+#elif defined(__OpenBSD__) || defined(__NetBSD__)+            "libGLESv1_CM.so", #else             "libGLESv1_CM.so.1",             "libGLES_CM.so.1",@@ -646,6 +706,8 @@             "libGLESv2.dylib", #elif defined(__CYGWIN__)             "libGLESv2-2.so",+#elif defined(__OpenBSD__) || defined(__NetBSD__)+            "libGLESv2.so", #else             "libGLESv2.so.2", #endif@@ -657,7 +719,10 @@             _GLFW_OPENGL_LIBRARY, #elif defined(_GLFW_WIN32) #elif defined(_GLFW_COCOA)+#elif defined(__OpenBSD__) || defined(__NetBSD__)+            "libGL.so", #else+            "libOpenGL.so.0",             "libGL.so.1", #endif             NULL@@ -720,11 +785,7 @@     const long vimask = VisualScreenMask | VisualIDMask;      if (!chooseEGLConfig(ctxconfig, fbconfig, &native))-    {-        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,-                        "EGL: Failed to find a suitable EGLConfig");         return GLFW_FALSE;-    }      eglGetConfigAttrib(_glfw.egl.display, native,                        EGL_NATIVE_VISUAL_ID, &visualID);@@ -764,7 +825,7 @@     _GLFWwindow* window = (_GLFWwindow*) handle;     _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT); -    if (window->context.client == GLFW_NO_API)+    if (window->context.source != GLFW_EGL_CONTEXT_API)     {         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);         return EGL_NO_CONTEXT;@@ -778,7 +839,7 @@     _GLFWwindow* window = (_GLFWwindow*) handle;     _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE); -    if (window->context.client == GLFW_NO_API)+    if (window->context.source != GLFW_EGL_CONTEXT_API)     {         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);         return EGL_NO_SURFACE;
glfw/src/egl_context.h view
@@ -80,6 +80,8 @@ #define EGL_OPENGL_ES_API 0x30a0 #define EGL_OPENGL_API 0x30a2 #define EGL_NONE 0x3038+#define EGL_RENDER_BUFFER 0x3086+#define EGL_SINGLE_BUFFER 0x3085 #define EGL_EXTENSIONS 0x3055 #define EGL_CONTEXT_CLIENT_VERSION 0x3098 #define EGL_NATIVE_VISUAL_ID 0x302e@@ -106,6 +108,7 @@ #define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097 #define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0 #define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098+#define EGL_PRESENT_OPAQUE_EXT 0x31df  typedef int EGLint; typedef unsigned int EGLBoolean;@@ -162,7 +165,6 @@    EGLSurface       surface;     void*            client;- } _GLFWcontextEGL;  // EGL-specific global data@@ -178,6 +180,7 @@     GLFWbool        KHR_gl_colorspace;     GLFWbool        KHR_get_all_proc_addresses;     GLFWbool        KHR_context_flush_control;+    GLFWbool        EXT_present_opaque;      void*           handle; @@ -197,7 +200,6 @@     PFN_eglSwapInterval         SwapInterval;     PFN_eglQueryString          QueryString;     PFN_eglGetProcAddress       GetProcAddress;- } _GLFWlibraryEGL;  
glfw/src/glx_context.c view
@@ -92,6 +92,9 @@                 continue;         } +        if (getGLXFBConfigAttrib(n, GLX_DOUBLEBUFFER) != desired->doublebuffer)+            continue;+         if (desired->transparent)         {             XVisualInfo* vi = glXGetVisualFromFBConfig(_glfw.x11.display, n);@@ -119,8 +122,6 @@          if (getGLXFBConfigAttrib(n, GLX_STEREO))             u->stereo = GLFW_TRUE;-        if (getGLXFBConfigAttrib(n, GLX_DOUBLEBUFFER))-            u->doublebuffer = GLFW_TRUE;          if (_glfw.glx.ARB_multisample)             u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES);@@ -189,6 +190,7 @@ static void swapIntervalGLX(int interval) {     _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);+    assert(window != NULL);      if (_glfw.glx.EXT_swap_control)     {@@ -225,7 +227,10 @@     else if (_glfw.glx.GetProcAddressARB)         return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);     else+    {+        // NOTE: glvnd provides GLX 1.4, so this can only happen with libGL         return _glfw_dlsym(_glfw.glx.handle, procname);+    } }  static void destroyContextGLX(_GLFWwindow* window)@@ -259,7 +264,10 @@         _GLFW_GLX_LIBRARY, #elif defined(__CYGWIN__)         "libGL-1.so",+#elif defined(__OpenBSD__) || defined(__NetBSD__)+        "libGL.so", #else+        "libGLX.so.0",         "libGL.so.1",         "libGL.so", #endif@@ -306,10 +314,6 @@         _glfw_dlsym(_glfw.glx.handle, "glXCreateWindow");     _glfw.glx.DestroyWindow =         _glfw_dlsym(_glfw.glx.handle, "glXDestroyWindow");-    _glfw.glx.GetProcAddress =-        _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddress");-    _glfw.glx.GetProcAddressARB =-        _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddressARB");     _glfw.glx.GetVisualFromFBConfig =         _glfw_dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig"); @@ -325,8 +329,6 @@         !_glfw.glx.CreateNewContext ||         !_glfw.glx.CreateWindow ||         !_glfw.glx.DestroyWindow ||-        !_glfw.glx.GetProcAddress ||-        !_glfw.glx.GetProcAddressARB ||         !_glfw.glx.GetVisualFromFBConfig)     {         _glfwInputError(GLFW_PLATFORM_ERROR,@@ -334,6 +336,12 @@         return GLFW_FALSE;     } +    // NOTE: Unlike GLX 1.3 entry points these are not required to be present+    _glfw.glx.GetProcAddress = (PFNGLXGETPROCADDRESSPROC)+        _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddress");+    _glfw.glx.GetProcAddressARB = (PFNGLXGETPROCADDRESSPROC)+        _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddressARB");+     if (!glXQueryExtension(_glfw.x11.display,                            &_glfw.glx.errorBase,                            &_glfw.glx.eventBase))@@ -673,7 +681,7 @@     _GLFWwindow* window = (_GLFWwindow*) handle;     _GLFW_REQUIRE_INIT_OR_RETURN(NULL); -    if (window->context.client == GLFW_NO_API)+    if (window->context.source != GLFW_NATIVE_CONTEXT_API)     {         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);         return NULL;@@ -687,7 +695,7 @@     _GLFWwindow* window = (_GLFWwindow*) handle;     _GLFW_REQUIRE_INIT_OR_RETURN(None); -    if (window->context.client == GLFW_NO_API)+    if (window->context.source != GLFW_NATIVE_CONTEXT_API)     {         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);         return None;
glfw/src/glx_context.h view
@@ -117,7 +117,6 @@ {     GLXContext      handle;     GLXWindow       window;- } _GLFWcontextGLX;  // GLX-specific global data@@ -128,7 +127,6 @@     int             eventBase;     int             errorBase; -    // dlopen handle for libGL.so.1     void*           handle;      // GLX 1.3 functions@@ -165,7 +163,6 @@     GLFWbool        EXT_create_context_es2_profile;     GLFWbool        ARB_create_context_no_error;     GLFWbool        ARB_context_flush_control;- } _GLFWlibraryGLX;  GLFWbool _glfwInitGLX(void);
glfw/src/init.c view
@@ -28,7 +28,6 @@ //========================================================================  #include "internal.h"-#include "mappings.h"  #include <string.h> #include <stdlib.h>@@ -37,16 +36,15 @@ #include <assert.h>  -// The global variables below comprise all mutable global data in GLFW-//-// Any other global variable is a bug+// NOTE: The global variables below comprise all mutable global data in GLFW+//       Any other mutable global variable is a bug -// Global state shared between compilation units of GLFW+// This contains all mutable state shared between compilation units of GLFW // _GLFWlibrary _glfw = { GLFW_FALSE };  // These are outside of _glfw so they can be used before initialization and-// after termination+// after termination without special handling when _glfw is cleared to zero // static _GLFWerror _glfwMainThreadError; static GLFWerrorfun _glfwErrorCallback;@@ -56,7 +54,10 @@     {         GLFW_TRUE,  // macOS menu bar         GLFW_TRUE   // macOS bundle chdir-    }+    },+    {+        GLFW_WAYLAND_PREFER_LIBDECOR // Wayland libdecor mode+    }, };  // Terminate the library@@ -113,6 +114,90 @@ //////                       GLFW internal API                      ////// ////////////////////////////////////////////////////////////////////////// +// Encode a Unicode code point to a UTF-8 stream+// Based on cutef8 by Jeff Bezanson (Public Domain)+//+size_t _glfwEncodeUTF8(char* s, uint32_t codepoint)+{+    size_t count = 0;++    if (codepoint < 0x80)+        s[count++] = (char) codepoint;+    else if (codepoint < 0x800)+    {+        s[count++] = (codepoint >> 6) | 0xc0;+        s[count++] = (codepoint & 0x3f) | 0x80;+    }+    else if (codepoint < 0x10000)+    {+        s[count++] = (codepoint >> 12) | 0xe0;+        s[count++] = ((codepoint >> 6) & 0x3f) | 0x80;+        s[count++] = (codepoint & 0x3f) | 0x80;+    }+    else if (codepoint < 0x110000)+    {+        s[count++] = (codepoint >> 18) | 0xf0;+        s[count++] = ((codepoint >> 12) & 0x3f) | 0x80;+        s[count++] = ((codepoint >> 6) & 0x3f) | 0x80;+        s[count++] = (codepoint & 0x3f) | 0x80;+    }++    return count;+}++// Splits and translates a text/uri-list into separate file paths+// NOTE: This function destroys the provided string+//+char** _glfwParseUriList(char* text, int* count)+{+    const char* prefix = "file://";+    char** paths = NULL;+    char* line;++    *count = 0;++    while ((line = strtok(text, "\r\n")))+    {+        char* path;++        text = NULL;++        if (line[0] == '#')+            continue;++        if (strncmp(line, prefix, strlen(prefix)) == 0)+        {+            line += strlen(prefix);+            // TODO: Validate hostname+            while (*line != '/')+                line++;+        }++        (*count)++;++        path = calloc(strlen(line) + 1, 1);+        paths = realloc(paths, *count * sizeof(char*));+        paths[*count - 1] = path;++        while (*line)+        {+            if (line[0] == '%' && line[1] && line[2])+            {+                const char digits[3] = { line[1], line[2], '\0' };+                *path = (char) strtol(digits, NULL, 16);+                line += 2;+            }+            else+                *path = *line;++            path++;+            line++;+        }+    }++    return paths;+}+ char* _glfw_strdup(const char* source) {     const size_t length = strlen(source);@@ -121,6 +206,16 @@     return result; } +int _glfw_min(int a, int b)+{+    return a < b ? a : b;+}++int _glfw_max(int a, int b)+{+    return a > b ? a : b;+}+ float _glfw_fminf(float a, float b) {     if (a != a)@@ -245,24 +340,12 @@      _glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError); +    _glfwInitGamepadMappings();+     _glfw.initialized = GLFW_TRUE;     _glfw.timer.offset = _glfwPlatformGetTimerValue();      glfwDefaultWindowHints();--    {-        int i;--        for (i = 0;  _glfwDefaultMappings[i];  i++)-        {-            if (!glfwUpdateGamepadMappings(_glfwDefaultMappings[i]))-            {-                terminate();-                return GLFW_FALSE;-            }-        }-    }-     return GLFW_TRUE; } @@ -286,6 +369,9 @@             return;         case GLFW_COCOA_MENUBAR:             _glfwInitHints.ns.menubar = value;+            return;+        case GLFW_WAYLAND_LIBDECOR:+            _glfwInitHints.wl.libdecorMode = value;             return;     } 
glfw/src/input.c view
@@ -28,6 +28,7 @@ //========================================================================  #include "internal.h"+#include "mappings.h"  #include <assert.h> #include <float.h>@@ -85,25 +86,13 @@         for (i = 0;  i <= GLFW_GAMEPAD_BUTTON_LAST;  i++)         {             if (!isValidElementForJoystick(mapping->buttons + i, js))-            {-                _glfwInputError(GLFW_INVALID_VALUE,-                                "Invalid button in gamepad mapping %s (%s)",-                                mapping->guid,-                                mapping->name);                 return NULL;-            }         }          for (i = 0;  i <= GLFW_GAMEPAD_AXIS_LAST;  i++)         {             if (!isValidElementForJoystick(mapping->axes + i, js))-            {-                _glfwInputError(GLFW_INVALID_VALUE,-                                "Invalid axis in gamepad mapping %s (%s)",-                                mapping->guid,-                                mapping->name);                 return NULL;-            }         }     } @@ -289,7 +278,7 @@ // Notifies shared code of a Unicode codepoint input event // The 'plain' parameter determines whether to emit a regular character event //-void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain)+void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool plain) {     if (codepoint < 32 || (codepoint > 126 && codepoint < 160))         return;@@ -371,6 +360,11 @@ {     const int jid = (int) (js - _glfw.joysticks); +    if (event == GLFW_CONNECTED)+        js->connected = GLFW_TRUE;+    else if (event == GLFW_DISCONNECTED)+        js->connected = GLFW_FALSE;+     if (_glfw.callbacks.joystick)         _glfw.callbacks.joystick(jid, event); }@@ -408,6 +402,29 @@ //////                       GLFW internal API                      ////// ////////////////////////////////////////////////////////////////////////// +// Adds the built-in set of gamepad mappings+//+void _glfwInitGamepadMappings(void)+{+    int jid;+    size_t i;+    const size_t count = sizeof(_glfwDefaultMappings) / sizeof(char*);+    _glfw.mappings = calloc(count, sizeof(_GLFWmapping));++    for (i = 0;  i < count;  i++)+    {+        if (parseMapping(&_glfw.mappings[_glfw.mappingCount], _glfwDefaultMappings[i]))+            _glfw.mappingCount++;+    }++    for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)+    {+        _GLFWjoystick* js = _glfw.joysticks + jid;+        if (js->connected)+            js->mapping = findValidMapping(js);+    }+}+ // Returns an available joystick object with arrays and name allocated // _GLFWjoystick* _glfwAllocJoystick(const char* name,@@ -421,7 +438,7 @@      for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)     {-        if (!_glfw.joysticks[jid].present)+        if (!_glfw.joysticks[jid].allocated)             break;     } @@ -429,8 +446,7 @@         return NULL;      js = _glfw.joysticks + jid;-    js->present     = GLFW_TRUE;-    js->name        = _glfw_strdup(name);+    js->allocated   = GLFW_TRUE;     js->axes        = calloc(axisCount, sizeof(float));     js->buttons     = calloc(buttonCount + (size_t) hatCount * 4, 1);     js->hats        = calloc(hatCount, 1);@@ -438,6 +454,7 @@     js->buttonCount = buttonCount;     js->hatCount    = hatCount; +    strncpy(js->name, name, sizeof(js->name) - 1);     strncpy(js->guid, guid, sizeof(js->guid) - 1);     js->mapping = findValidMapping(js); @@ -448,7 +465,6 @@ // void _glfwFreeJoystick(_GLFWjoystick* js) {-    free(js->name);     free(js->axes);     free(js->buttons);     free(js->hats);@@ -600,6 +616,12 @@      if (key != GLFW_KEY_UNKNOWN)     {+        if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)+        {+            _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);+            return NULL;+        }+         if (key != GLFW_KEY_KP_EQUAL &&             (key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) &&             (key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_WORLD_2))@@ -620,7 +642,7 @@     if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)     {         _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);-        return GLFW_RELEASE;+        return -1;     }      return _glfwPlatformGetKeyScancode(key);@@ -732,9 +754,16 @@     _GLFWcursor* cursor;      assert(image != NULL);+    assert(image->pixels != NULL);      _GLFW_REQUIRE_INIT_OR_RETURN(NULL); +    if (image->width <= 0 || image->height <= 0)+    {+        _glfwInputError(GLFW_INVALID_VALUE, "Invalid image dimensions for cursor");+        return NULL;+    }+     cursor = calloc(1, sizeof(_GLFWcursor));     cursor->next = _glfw.cursorListHead;     _glfw.cursorListHead = cursor;@@ -926,7 +955,7 @@     }      js = _glfw.joysticks + jid;-    if (!js->present)+    if (!js->connected)         return GLFW_FALSE;      return _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);@@ -951,7 +980,7 @@     }      js = _glfw.joysticks + jid;-    if (!js->present)+    if (!js->connected)         return NULL;      if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_AXES))@@ -980,7 +1009,7 @@     }      js = _glfw.joysticks + jid;-    if (!js->present)+    if (!js->connected)         return NULL;      if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))@@ -1013,7 +1042,7 @@     }      js = _glfw.joysticks + jid;-    if (!js->present)+    if (!js->connected)         return NULL;      if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))@@ -1039,7 +1068,7 @@     }      js = _glfw.joysticks + jid;-    if (!js->present)+    if (!js->connected)         return NULL;      if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))@@ -1064,7 +1093,7 @@     }      js = _glfw.joysticks + jid;-    if (!js->present)+    if (!js->connected)         return NULL;      if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))@@ -1083,7 +1112,7 @@     _GLFW_REQUIRE_INIT();      js = _glfw.joysticks + jid;-    if (!js->present)+    if (!js->allocated)         return;      js->userPointer = pointer;@@ -1099,7 +1128,7 @@     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);      js = _glfw.joysticks + jid;-    if (!js->present)+    if (!js->allocated)         return NULL;      return js->userPointer;@@ -1165,7 +1194,7 @@     for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)     {         _GLFWjoystick* js = _glfw.joysticks + jid;-        if (js->present)+        if (js->connected)             js->mapping = findValidMapping(js);     } @@ -1188,7 +1217,7 @@     }      js = _glfw.joysticks + jid;-    if (!js->present)+    if (!js->connected)         return GLFW_FALSE;      if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))@@ -1213,7 +1242,7 @@     }      js = _glfw.joysticks + jid;-    if (!js->present)+    if (!js->connected)         return NULL;      if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))@@ -1245,7 +1274,7 @@     }      js = _glfw.joysticks + jid;-    if (!js->present)+    if (!js->connected)         return GLFW_FALSE;      if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_ALL))@@ -1354,3 +1383,4 @@     _GLFW_REQUIRE_INIT_OR_RETURN(0);     return _glfwPlatformGetTimerFrequency(); }+
glfw/src/internal.h view
@@ -244,6 +244,9 @@         GLFWbool  menubar;         GLFWbool  chdir;     } ns;+    struct {+        int       libdecorMode;+    } wl; };  // Window configuration@@ -342,9 +345,9 @@     int                 robustness;     int                 release; -    PFNGLGETSTRINGIPROC GetStringi;+    PFNGLGETSTRINGIPROC  GetStringi;     PFNGLGETINTEGERVPROC GetIntegerv;-    PFNGLGETSTRINGPROC  GetString;+    PFNGLGETSTRINGPROC   GetString;      _GLFWmakecontextcurrentfun  makeCurrent;     _GLFWswapbuffersfun         swapBuffers;@@ -375,6 +378,7 @@     GLFWbool            focusOnShow;     GLFWbool            shouldClose;     void*               userPointer;+    GLFWbool            doublebuffer;     GLFWvidmode         videoMode;     _GLFWmonitor*       monitor;     _GLFWcursor*        cursor;@@ -396,23 +400,23 @@     _GLFWcontext        context;      struct {-        GLFWwindowposfun        pos;-        GLFWwindowsizefun       size;-        GLFWwindowclosefun      close;-        GLFWwindowrefreshfun    refresh;-        GLFWwindowfocusfun      focus;-        GLFWwindowiconifyfun    iconify;-        GLFWwindowmaximizefun   maximize;-        GLFWframebuffersizefun  fbsize;+        GLFWwindowposfun          pos;+        GLFWwindowsizefun         size;+        GLFWwindowclosefun        close;+        GLFWwindowrefreshfun      refresh;+        GLFWwindowfocusfun        focus;+        GLFWwindowiconifyfun      iconify;+        GLFWwindowmaximizefun     maximize;+        GLFWframebuffersizefun    fbsize;         GLFWwindowcontentscalefun scale;-        GLFWmousebuttonfun      mouseButton;-        GLFWcursorposfun        cursorPos;-        GLFWcursorenterfun      cursorEnter;-        GLFWscrollfun           scroll;-        GLFWkeyfun              key;-        GLFWcharfun             character;-        GLFWcharmodsfun         charmods;-        GLFWdropfun             drop;+        GLFWmousebuttonfun        mouseButton;+        GLFWcursorposfun          cursorPos;+        GLFWcursorenterfun        cursorEnter;+        GLFWscrollfun             scroll;+        GLFWkeyfun                key;+        GLFWcharfun               character;+        GLFWcharmodsfun           charmods;+        GLFWdropfun               drop;     } callbacks;      // This is defined in the window API's platform.h@@ -423,7 +427,7 @@ // struct _GLFWmonitor {-    char*           name;+    char            name[128];     void*           userPointer;      // Physical dimensions in millimeters.@@ -477,14 +481,15 @@ // struct _GLFWjoystick {-    GLFWbool        present;+    GLFWbool        allocated;+    GLFWbool        connected;     float*          axes;     int             axisCount;     unsigned char*  buttons;     int             buttonCount;     unsigned char*  hats;     int             hatCount;-    char*           name;+    char            name[128];     void*           userPointer;     char            guid[33];     _GLFWmapping*   mapping;@@ -717,7 +722,7 @@ void _glfwInputKey(_GLFWwindow* window,                    int key, int scancode, int action, int mods); void _glfwInputChar(_GLFWwindow* window,-                    unsigned int codepoint, int mods, GLFWbool plain);+                    uint32_t codepoint, int mods, GLFWbool plain); void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset); void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods); void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);@@ -760,6 +765,7 @@ void _glfwFreeGammaArrays(GLFWgammaramp* ramp); void _glfwSplitBPP(int bpp, int* red, int* green, int* blue); +void _glfwInitGamepadMappings(void); _GLFWjoystick* _glfwAllocJoystick(const char* name,                                   const char* guid,                                   int axisCount,@@ -772,7 +778,12 @@ void _glfwTerminateVulkan(void); const char* _glfwGetVulkanResultString(VkResult result); +size_t _glfwEncodeUTF8(char* s, uint32_t codepoint);+char** _glfwParseUriList(char* text, int* count);+ char* _glfw_strdup(const char* source);+int _glfw_min(int a, int b);+int _glfw_max(int a, int b); float _glfw_fminf(float a, float b); float _glfw_fmaxf(float a, float b); 
glfw/src/linux_joystick.c view
@@ -128,7 +128,7 @@ {     for (int jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)     {-        if (!_glfw.joysticks[jid].present)+        if (!_glfw.joysticks[jid].connected)             continue;         if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)             return GLFW_FALSE;@@ -157,7 +157,7 @@     }      // Ensure this device supports the events expected of a joystick-    if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits))+    if (!isBitSet(EV_ABS, evBits))     {         close(linjs.fd);         return GLFW_FALSE;@@ -245,9 +245,9 @@ // static void closeJoystick(_GLFWjoystick* js) {+    _glfwInputJoystick(js, GLFW_DISCONNECTED);     close(js->linjs.fd);     _glfwFreeJoystick(js);-    _glfwInputJoystick(js, GLFW_DISCONNECTED); }  // Lexically compare joysticks by name; used by qsort@@ -283,7 +283,8 @@      // Continue without device connection notifications if inotify fails -    if (regcomp(&_glfw.linjs.regex, "^event[0-9]\\+$", 0) != 0)+    _glfw.linjs.regexCompiled = (regcomp(&_glfw.linjs.regex, "^event[0-9]\\+$", 0) == 0);+    if (!_glfw.linjs.regexCompiled)     {         _glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");         return GLFW_FALSE;@@ -329,7 +330,7 @@     for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)     {         _GLFWjoystick* js = _glfw.joysticks + jid;-        if (js->present)+        if (js->connected)             closeJoystick(js);     } @@ -342,6 +343,9 @@          close(_glfw.linjs.inotify);     }++    if (_glfw.linjs.regexCompiled)+        regfree(&_glfw.linjs.regex); }  void _glfwDetectJoystickConnectionLinux(void)@@ -424,7 +428,7 @@             handleAbsEvent(js, e.code, e.value);     } -    return js->present;+    return js->connected; }  void _glfwPlatformUpdateGamepadGUID(char* guid)
glfw/src/mappings.h view
@@ -31,7 +31,7 @@ // all available in SDL_GameControllerDB.  Do not edit this file.  Any gamepad // mappings not specific to GLFW should be submitted to SDL_GameControllerDB. // This file can be re-generated from mappings.h.in and the upstream-// gamecontrollerdb.txt with the GenerateMappings.cmake script.+// gamecontrollerdb.txt with the 'update_mappings' CMake target. //========================================================================  // All gamepad mappings not labeled GLFW are copied from the@@ -60,95 +60,262 @@  const char* _glfwDefaultMappings[] = {+#if defined(GLFW_BUILD_WIN32_MAPPINGS) "03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,",+"03000000c82d00002038000000000000,8bitdo,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00000951000000000000,8BitDo Dogbone Modkit,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows,",+"03000000c82d000011ab000000000000,8BitDo F30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,",+"03000000c82d00005106000000000000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00000151000000000000,8BitDo M30 ModKit,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,",+"03000000c82d00000310000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,",+"03000000c82d00002028000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00008010000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,",+"03000000c82d00000451000000000000,8BitDo N30 Modkit,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,start:b11,platform:Windows,",+"03000000c82d00000190000000000000,8BitDo N30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,", "03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,", "03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00000360000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00002867000000000000,8BitDo S30 Modkit,a:b0,b:b1,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,",+"03000000c82d00000130000000000000,8BitDo SF30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00000060000000000000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00000061000000000000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d000021ab000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,", "03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00003028000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00000030000000000000,8BitDo SN30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00001290000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d000020ab000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00004028000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00006228000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00000351000000000000,8BitDo SN30 Modkit,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00000121000000000000,8BitDo SN30 Pro for Android,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",+"03000000c82d00000260000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00000261000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00000031000000000000,8BitDo Wireless Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",+"03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,",+"03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,", "03000000a00500003232000000000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,",-"030000008f0e00001200000000000000,Acme,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,",+"03000000a30c00002700000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,",+"03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,",+"030000008f0e00001200000000000000,Acme GA-02,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,",+"03000000c01100000355000011010000,ACRUX USB GAME PAD,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000fa190000f0ff000000000000,Acteck AGJ-3200,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"030000006f0e00001413000000000000,Afterglow,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000006f0e00000263000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000006f0e00001101000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000006f0e00001401000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000006f0e00001402000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000006f0e00001901000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000006f0e00001a01000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000d62000001d57000000000000,Airflo PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000491900001904000000000000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows,",+"03000000710100001904000000000000,Amazon Luna Controller,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b8,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b4,rightstick:b7,rightx:a3,righty:a4,start:b6,x:b3,y:b2,platform:Windows,",+"03000000ef0500000300000000000000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,",+"03000000d6200000e557000000000000,Batarang,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows,",-"030000006b1400000055000000000000,bigben ps3padstreetnew,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",+"030000006f0e00003201000000000000,Battlefield 4 PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000d62000002a79000000000000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"03000000bc2000006012000000000000,Betop 2126F,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"03000000bc2000000055000000000000,Betop BFM Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",+"03000000bc2000006312000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"03000000bc2000006321000000000000,BETOP CONTROLLER,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"03000000bc2000006412000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"03000000c01100000555000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"03000000c01100000655000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"03000000790000000700000000000000,Betop Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,",+"03000000808300000300000000000000,Betop Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,",+"030000006b1400000055000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",+"030000006b1400000103000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,",+"03000000120c0000210e000000000000,Brook Mars,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "0300000066f700000500000000000000,BrutalLegendTest,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,", "03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows,", "03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",-"030000005e0400008e02000000000000,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",+"03000000457500000401000000000000,Cobra,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"030000005e0400008e02000000000000,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",+"030000005e040000a102000000000000,Controller (Xbox 360 Wireless Receiver for Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",+"030000005e040000ff02000000000000,Controller (Xbox One For Windows) - Wired,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",+"030000005e040000ea02000000000000,Controller (Xbox One For Windows) - Wireless,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,", "03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows,", "03000000a306000022f6000000000000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",+"03000000451300000830000000000000,Defender Game Racer X7,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",+"030000007d0400000840000000000000,Destroyer Tiltpad,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,x:b0,y:b3,platform:Windows,", "03000000791d00000103000000000000,Dual Box WII,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",-"030000004f04000023b3000000000000,Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"03000000bd12000002e0000000000000,Dual USB Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows,",+"030000008f0e00000910000000000000,DualShock 2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows,",+"030000006f0e00003001000000000000,EA SPORTS PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000b80500000410000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows,",+"03000000b80500000610000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows,",+"03000000120c0000f61c000000000000,Elite,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"030000008f0e00000f31000000000000,EXEQ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,", "03000000341a00000108000000000000,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",+"030000006f0e00008401000000000000,Faceoff Deluxe+ Audio Wired Controller for Nintendo Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000006f0e00008001000000000000,Faceoff Wired Pro Controller for Nintendo Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000852100000201000000000000,FF-GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "030000000d0f00008500000000000000,Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "030000000d0f00008400000000000000,Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",-"030000000d0f00008800000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,", "030000000d0f00008700000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",+"030000000d0f00008800000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,", "030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,", "78696e70757403000000000000000000,Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows,",+"03000000790000002201000000000000,Game Controller for PC,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"0300000066f700000100000000000000,Game VIB Joystick,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,", "03000000260900002625000000000000,Gamecube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows,",+"03000000790000004618000000000000,GameCube Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,", "030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "03000000280400000140000000000000,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",+"03000000ac0500003d03000000000000,GameSir,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",+"03000000ac0500004d04000000000000,GameSir,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,", "03000000ffff00000000000000000000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",-"03000000451300000010000000000000,Generic USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",+"03000000c01100000140000000000000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"030000009b2800003200000000000000,GC/N64 to USB v3.4,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,",+"030000009b2800006000000000000000,GC/N64 to USB v3.6,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,",+"030000008305000009a0000000000000,Genius,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",+"030000008305000031b0000000000000,Genius Maxfire Blaze 3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",+"03000000451300000010000000000000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",+"030000005c1a00003330000000000000,Genius MaxFire Grandias 12V,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,",+"03000000300f00000b01000000000000,GGE909 Recoil Pad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",+"03000000f0250000c283000000000000,Gioteck,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"03000000f025000021c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"03000000f0250000c383000000000000,Gioteck VX2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"03000000f0250000c483000000000000,Gioteck VX2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"030000007d0400000540000000000000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,", "03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "030000000d0f00004900000000000000,Hatsune Miku Sho Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000001008000001e1000000000000,Havit HV-G60,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows,", "03000000d81400000862000000000000,HitBox Edition Cthulhu+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",+"03000000632500002605000000000000,HJD-X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",+"030000000d0f00002d00000000000000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "030000000d0f00005f00000000000000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "030000000d0f00005e00000000000000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,", "030000000d0f00004000000000000000,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",+"030000000d0f00005400000000000000,Hori Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000000d0f00000900000000000000,Hori Pad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000000d0f00004d00000000000000,Hori Pad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000000d0f00009200000000000000,Hori Pokken Tournament DX Pro Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",+"030000000d0f00001600000000007803,HORI Real Arcade Pro EX-SE (Xbox 360),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows,",+"030000000d0f00009c00000000000000,Hori TAC Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"030000000d0f0000c100000000000000,Horipad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "030000000d0f00006e00000000000000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "030000000d0f00006600000000000000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"030000000d0f00005500000000000000,Horipad 4 FPS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,", "030000000d0f0000ee00000000000000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",-"030000000d0f00004d00000000000000,HORIPAD3 A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "03000000250900000017000000000000,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows,", "030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Windows,", "03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,", "03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,", "03000000830500006020000000000000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Windows,",-"03000000b50700001403000000000000,IMPACT BLACK,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",-"030000006f0e00002401000000000000,INJUSTICE FightStick for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",+"03000000b50700001403000000000000,Impact Black,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",+"030000006f0e00002401000000000000,INJUSTICE FightStick PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",+"03000000ac0500002c02000000000000,IPEGA,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,", "03000000491900000204000000000000,Ipega PG-9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",+"03000000491900000304000000000000,Ipega PG-9087 - Bluetooth Gamepad,+righty:+a5,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows,",+"030000006e0500000a20000000000000,JC-DUX60 ELECOM MMO Gamepad,a:b2,b:b3,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b14,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b15,righttrigger:b13,rightx:a3,righty:a4,start:b20,x:b0,y:b1,platform:Windows,",+"030000006e0500000520000000000000,JC-P301U,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,",+"030000006e0500000320000000000000,JC-U3613M (DInput),a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,",+"030000006e0500000720000000000000,JC-W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows,",+"030000007e0500000620000000000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows,",+"030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows,",+"030000007e0500000720000000000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,",+"030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,",+"03000000bd12000003c0000010010000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000bd12000003c0000000000000,JY-P70UR,a:b1,b:b0,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b4,x:b3,y:b2,platform:Windows,",+"03000000242f00002d00000000000000,JYS Wireless Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"03000000242f00008a00000000000000,JYS Wireless Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,",+"03000000790000000200000000000000,King PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,",+"030000006d040000d1ca000000000000,Logitech ChillStream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000006d040000d2ca000000000000,Logitech Cordless Precision,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows,", "030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "030000006d04000018c2000000000000,Logitech F510 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "030000006d04000019c2000000000000,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000006d0400001ac2000000000000,Logitech Precision Gamepad,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",+"030000006d0400000ac2000000000000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows,",+"03000000380700006652000000000000,Mad Catz C.T.R.L.R,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,", "03000000380700005032000000000000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "03000000380700005082000000000000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",-"03000000380700008433000000000000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",-"03000000380700008483000000000000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b6,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"03000000380700008433000000000000,Mad Catz FightStick TE S+ (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000380700008483000000000000,Mad Catz FightStick TE S+ (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,", "03000000380700008134000000000000,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "03000000380700008184000000000000,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"03000000380700006252000000000000,Mad Catz Micro C.T.R.L.R,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,", "03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,", "03000000380700008532000000000000,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "03000000380700003888000000000000,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "03000000380700001888000000000000,MadCatz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,", "03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",-"030000008305000031b0000000000000,MaxfireBlaze3,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",+"030000002a0600001024000000000000,Matricom,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,",+"030000009f000000adbb000000000000,MaxJoypad Virtual Controller,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,", "03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows,", "03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,", "03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",+"03000000242f00007300000000000000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,",+"0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"03000000d620000010a7000000000000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "030000008f0e00001030000000000000,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows,", "0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,", "03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",-"030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Windows,",+"03000000790000002418000000000000,Mega Drive,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b2,start:b9,x:b3,y:b4,platform:Windows,",+"03000000380700006382000000000000,MLG GamePad PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000c62400002a89000000000000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",+"03000000c62400002b89000000000000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",+"03000000c62400001a89000000000000,MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",+"03000000c62400001b89000000000000,MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",+"03000000efbe0000edfe000000000000,Monect Virtual Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows,",+"03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,",+"030000006b140000010c000000000000,NACON GC-400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",+"03000000921200004b46000000000000,NES 2-port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows,",+"03000000790000004518000000000000,NEXILUX GAMECUBE Controller Adapter,platform:Windows,a:b1,b:b0,x:b2,y:b3,start:b9,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,",+"030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Windows,",+"03000000152000000182000000000000,NGDS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows,", "03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,", "030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",-"030000004b120000014d000000000000,NYKO AIRFLO,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,leftx:h0.6,lefty:h0.12,rightshoulder:b5,rightstick:a2,righttrigger:b7,rightx:h0.9,righty:h0.4,start:b9,x:b2,y:b3,platform:Windows,",+"030000000d0500000308000000000000,Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Windows,",+"03000000550900001472000000000000,NVIDIA Controller v01.04,a:b11,b:b10,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b5,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b4,righttrigger:a5,rightx:a3,righty:a6,start:b3,x:b9,y:b8,platform:Windows,",+"030000004b120000014d000000000000,NYKO AIRFLO,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,rightshoulder:b5,rightstick:a2,righttrigger:b7,start:b9,x:b2,y:b3,platform:Windows,",+"03000000d620000013a7000000000000,NSW wired controller,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",+"03000000782300000a10000000000000,Onlive Wireless Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,platform:Windows,",+"03000000d62000006d57000000000000,OPP PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,", "03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,", "03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",+"030000006f0e00000901000000000000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,", "030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",+"030000004c050000da0c000000000000,PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,",+"030000004c0500003713000000000000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,", "03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",-"030000008f0e00007530000000000000,PS (R) Gamepad,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000d62000009557000000000000,Pro Elite PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000d62000009f31000000000000,Pro Ex mini PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000d6200000c757000000000000,Pro Ex mini PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000632500002306000000000000,PS Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,", "03000000e30500009605000000000000,PS to USB convert cable,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,",-"03000000100800000100000000000000,PS1 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",-"03000000100800000300000000000000,PS2 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",+"03000000100800000100000000000000,PS1 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",+"030000008f0e00007530000000000000,PS1 Controller,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000100800000300000000000000,PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",+"03000000250900008888000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,",+"03000000666600006706000000000000,PS2 Controller,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows,",+"030000006b1400000303000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",+"030000009d0d00001330000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",+"03000000250900000500000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,",+"030000004c0500006802000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b10,lefttrigger:a3~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:a4~,rightx:a2,righty:a5,start:b8,x:b3,y:b0,platform:Windows,",+"03000000632500007505000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,", "03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,",-"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,",-"03000000250900000500000000000000,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,",+"030000008f0e00001431000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000003807000056a8000000000000,PS3 RF pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "03000000100000008200000000000000,PS360+ v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,", "030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,", "030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,", "030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"030000004c050000e60c000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"03000000ff000000cb01000000000000,PSP,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,", "03000000300f00000011000000000000,QanBa Arcade JoyStick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows,", "03000000300f00001611000000000000,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,", "03000000222c00000020000000000000,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows,",@@ -157,320 +324,678 @@ "03000000222c00000223000000000000,Qanba Obsidian Arcade Joystick PS3 Mode,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "03000000222c00000023000000000000,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,", "03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",+"03000000321500000204000000000000,Razer Panthera (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000321500000104000000000000,Razer Panthera (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"03000000321500000507000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",+"03000000321500000707000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",+"03000000321500000011000000000000,Razer Raion Fightpad for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"03000000321500000009000000000000,Razer Serval,+lefty:+a2,-lefty:-a1,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,leftx:a0,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,", "030000000d0f00001100000000000000,REAL ARCADE PRO.3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",-"030000000d0f00008b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",-"030000000d0f00008a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",-"030000000d0f00006b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "030000000d0f00006a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"030000000d0f00006b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000000d0f00008a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"030000000d0f00008b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "030000000d0f00007000000000000000,REAL ARCADE PRO.4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,", "030000000d0f00002200000000000000,REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",-"030000000d0f00005c00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "030000000d0f00005b00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"030000000d0f00005c00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "03000000790000001100000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,",+"03000000bd12000013d0000000000000,Retrolink USB SEGA Saturn Classic,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,lefttrigger:b6,rightshoulder:b2,righttrigger:b7,start:b8,x:b3,y:b4,platform:Windows,", "0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,", "0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,", "030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",-"030000006f0e00001e01000000000000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000006b140000020d000000000000,Revolution Pro Controller 2(1/2),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"030000006b140000130d000000000000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"030000006f0e00001e01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000006f0e00002801000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000006f0e00002f01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "030000004f04000003d0000000000000,run'n'drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,", "03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,", "03000000a306000023f6000000000000,Saitek Cyborg V.1 Game pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,", "03000000300f00001201000000000000,Saitek Dual Analog Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",-"03000000a30600000cff000000000000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,x:b0,y:b1,platform:Windows,",+"03000000a30600000701000000000000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Windows,",+"03000000a30600000cff000000000000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b0,y:b1,platform:Windows,", "03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,", "03000000300f00001001000000000000,Saitek P480 Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,", "03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,", "03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows,",-"03000000300f00001101000000000000,saitek rumble pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",+"03000000a30600002106000000000000,Saitek PS1000,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",+"03000000a306000020f6000000000000,Saitek PS2700,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",+"03000000300f00001101000000000000,Saitek Rumble Pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",+"03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows,", "0300000000050000289b000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,", "030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,",+"03000000a30c00002500000000000000,Sega Genesis Mini 3B controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows,",+"03000000a30c00002400000000000000,Sega Mega Drive Mini 6B controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,", "03000000341a00000208000000000000,SL-6555-SBK,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,",-"030000008f0e00000800000000000000,SpeedLink Strike FX Wireless,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"03000000341a00000908000000000000,SL-6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",+"030000008f0e00000800000000000000,SpeedLink Strike FX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"03000000c01100000591000000000000,Speedlink Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"03000000d11800000094000000000000,Stadia Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b11,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,",+"03000000110100001914000000000000,SteelSeries,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",+"03000000381000001214000000000000,SteelSeries Free,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,",+"03000000110100003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",+"03000000381000001814000000000000,SteelSeries Stratus XL,a:b0,b:b1,back:b18,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b19,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b2,y:b3,platform:Windows,",+"03000000790000001c18000000000000,STK-7024X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,", "03000000ff1100003133000000000000,SVEN X-PAD,a:b2,b:b3,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a4,start:b5,x:b0,y:b1,platform:Windows,",+"03000000d620000011a7000000000000,Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000457500002211000000000000,SZMY-POWER PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000004f04000007d0000000000000,T Mini Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000004f0400000ab1000000000000,T.16000M,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b10,x:b2,y:b3,platform:Windows,", "03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,", "03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",-"030000004f04000015b3000000000000,Thrustmaster Dual Analog 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,",+"030000004f04000015b3000000000000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,",+"030000004f04000023b3000000000000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"030000004f0400000ed0000000000000,ThrustMaster eSwap PRO Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,", "030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows,", "030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,", "03000000666600000488000000000000,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,",+"03000000d62000006000000000000000,Tournament PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"030000005f140000c501000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"03000000b80500000210000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows,", "03000000d90400000200000000000000,TwinShock PS2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",-"03000000380700006652000000000000,UnKnown,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",+"030000006e0500001320000000000000,U4113,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000101c0000171c000000000000,uRage Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"03000000300f00000701000000000000,USB 4-Axis 12-Button Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",+"03000000341a00002308000000000000,USB gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",+"030000005509000000b4000000000000,USB gamepad,a:b10,b:b11,back:b5,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,guide:b14,leftshoulder:b8,leftstick:b6,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:a5,rightx:a2,righty:a3,start:b4,x:b12,y:b13,platform:Windows,",+"030000006b1400000203000000000000,USB gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",+"03000000790000000a00000000000000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,",+"03000000f0250000c183000000000000,USB gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",+"03000000ff1100004133000000000000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,", "03000000632500002305000000000000,USB Vibration Joystick (BM),a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",+"03000000790000001a18000000000000,Venom,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,", "03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",+"030000006f0e00000302000000000000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",+"030000006f0e00000702000000000000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",+"0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:a3,righty:a4,start:b4,x:b2,y:b3,platform:Windows,",+"030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",+"030000005e040000130b000000000000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",+"03000000341a00000608000000000000,Xeox,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,", "03000000450c00002043000000000000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",+"03000000ac0500005b05000000000000,Xiaoji Gamesir-G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,", "03000000172700004431000000000000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,", "03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",-"03000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",+"03000000790000004f18000000000000,ZD-T Android,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",+"03000000120c0000101e000000000000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",+"78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",+"78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",+"78696e70757403000000000000000000,XInput Arcade Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",+"78696e70757404000000000000000000,XInput Flight Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",+"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",+"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",+"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",+#endif // GLFW_BUILD_WIN32_MAPPINGS++#if defined(GLFW_BUILD_COCOA_MAPPINGS)+"030000008f0e00000300000009010000,2In1 USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,",+"03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",+"03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",+"03000000c82d00000650000001000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Mac OS X,",+"03000000c82d00005106000000010000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,platform:Mac OS X,",+"03000000c82d00001590000001000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",+"03000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",+"030000003512000012ab000001000000,8BitDo NES30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,", "03000000022000000090000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",+"03000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",+"03000000c82d00000190000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,", "03000000102800000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,",+"03000000c82d00001290000001000000,8BitDo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,",+"03000000c82d00004028000000010000,8Bitdo SN30 GamePad,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,platform:Mac OS X,",+"03000000c82d00000160000001000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",+"03000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Mac OS X,",+"03000000c82d00000260000001000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",+"03000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",+"03000000c82d00000031000001000000,8BitDo Wireless Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,",+"03000000c82d00001890000001000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,",+"03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a31,start:b11,x:b4,y:b3,platform:Mac OS X,", "03000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,",+"03000000a00500003232000009010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,",+"03000000a30c00002700000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",+"03000000a30c00002800000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",+"03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,",+"03000000ef0500000300000000020000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Mac OS X,",+"03000000491900001904000001010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Mac OS X,",+"03000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X,",+"03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,",+"03000000c62400001b89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,",+"03000000d62000002a79000000010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",+"03000000120c0000200e000000010000,Brook Mars,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",+"03000000120c0000210e000000010000,Brook Mars,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,", "03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X,", "03000000a306000022f6000001030000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,",+"03000000790000004618000000010000,GameCube Controller Adapter,a:b4,b:b0,dpdown:b56,dpleft:b60,dpright:b52,dpup:b48,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X,", "03000000ad1b000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,", "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,",+"03000000c01100000140000000010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",+"030000006f0e00000102000000000000,GameStop Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",+"030000007d0400000540000001010000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,",+"03000000280400000140000000020000,Gravis Gamepad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,",+"030000008f0e00000300000007010000,GreenAsia Inc. USB Joystick,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Mac OS X,",+"030000000d0f00002d00000000100000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000000d0f00005f00000000010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000000d0f00005e00000000010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000000d0f00005f00000000000000,HORI Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000000d0f00005e00000000000000,HORI Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000000d0f00004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",+"030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000000d0f00006e00000000010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000000d0f00006600000000010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000000d0f00006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",+"030000000d0f0000ee00000000010000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000008f0e00001330000011010000,HuiJia SNES Controller,a:b4,b:b2,back:b16,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b12,rightshoulder:b14,start:b18,x:b6,y:b0,platform:Mac OS X,", "03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,", "03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,",+"030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Mac OS X,",+"030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Mac OS X,",+"03000000242f00002d00000007010000,JYS Wireless Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,", "030000006d04000016c2000000020000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000006d04000016c2000000030000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000006d04000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000006d04000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",+"030000006d04000019c2000005030000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000006d0400001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",+"030000006d04000018c2000000010000,Logitech RumblePad 2 USB,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000006d04000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,", "03000000380700005032000000010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,", "03000000380700005082000000010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",+"03000000380700008433000000010000,Mad Catz FightStick TE S+ (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",+"03000000380700008483000000010000,Mad Catz FightStick TE S+ (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",+"03000000790000000600000007010000,Marvo GT-004,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,", "03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X,",+"03000000242f00007300000000020000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Mac OS X,",+"0300000079000000d218000026010000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,",+"03000000d620000010a7000003010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,", "0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X,",+"03000000790000000018000000010000,Mayflash Wii U Pro Controller Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,", "03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,", "03000000d8140000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,",-"030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Mac OS X,",+"030000005e0400002700000001010000,Microsoft SideWinder Plug & Play Game Pad,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,leftx:a0,lefty:a1,righttrigger:b5,x:b2,y:b3,platform:Mac OS X,",+"03000000d62000007162000001000000,Moga Pro 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X,",+"03000000c62400002a89000000010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,",+"03000000c62400002b89000000010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,",+"03000000632500007505000000020000,NEOGEO mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X,",+"03000000921200004b46000003020000,NES 2-port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Mac OS X,",+"030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Mac OS X,",+"03000000d620000011a7000000020000,Nintendo Switch Core (Plus) Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",+"03000000d620000011a7000010050000,Nintendo Switch PowerA Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,",+"030000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,",+"03000000550900001472000025050000,NVIDIA Controller v01.04,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X,",+"030000006f0e00000901000002010000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X,",-"030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,",+"030000004c050000da0c000000010000,Playstation Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",+"030000004c0500003713000000010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,",+"03000000d62000006dca000000010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",+"03000000100800000300000006010000,PS2 Adapter,a:b2,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,", "030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,",+"030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,", "030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",-"030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",+"030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",+"050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",+"03000000321500000204000000010000,Razer Panthera (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",+"03000000321500000104000000010000,Razer Panthera (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,", "03000000321500000010000000010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",+"03000000321500000507000001010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,",+"03000000321500000011000000010000,Razer Raion Fightpad for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",+"03000000321500000009000000020000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X,",+"030000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X,", "0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,", "03000000790000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,", "03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,", "030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",+"030000006b140000130d000000010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",+"03000000c6240000fefa000000000000,Rock Candy Gamepad for PS3,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",+"03000000730700000401000000010000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Mac OS X,", "03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X,", "03000000b40400000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X,", "030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,",+"0300000000f00000f100000000000000,SNES RetroPort,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,rightshoulder:b7,start:b6,x:b0,y:b1,platform:Mac OS X,",+"030000004c050000e60c000000010000,Sony DualSense,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",-"030000005e0400008e02000001000000,Steam Virtual GamePad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",+"03000000d11800000094000000010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X,",+"030000005e0400008e02000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,", "03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X,", "03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,", "03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,",+"050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X,", "03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,", "03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,",+"03000000457500002211000000010000,SZMY-POWER PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X,",+"030000004f0400000ed0000000020000,ThrustMaster eSwap PRO Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,", "030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X,",-"03000000bd12000015d0000000010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,", "03000000bd12000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",+"03000000bd12000015d0000000010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,", "03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X,",+"030000006f0e00000302000025040000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,",+"030000006f0e00000702000003060000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,",+"03000000791d00000103000009010000,Wii Classic Controller,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,", "050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X,", "050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X,", "030000005e0400008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",+"030000006f0e00000104000000000000,Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,", "03000000c6240000045d000000000000,Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",-"030000005e040000e302000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",+"030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",+"030000005e040000050b000003090000,Xbox Elite Wireless Controller Series 2,a:b0,b:b1,back:b31,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b53,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,",+"03000000c62400003a54000000000000,Xbox One PowerA Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,", "030000005e040000d102000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,", "030000005e040000dd02000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",+"030000005e040000e302000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",+"030000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,",+"030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,", "030000005e040000e002000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,",-"030000005e040000fd02000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,",-"030000005e040000ea02000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,", "030000005e040000e002000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,",+"030000005e040000ea02000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",+"030000005e040000fd02000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,", "03000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,", "03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",-"05000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",+"03000000120c0000101e000000010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",+#endif // GLFW_BUILD_COCOA_MAPPINGS++#if defined(GLFW_BUILD_LINUX_MAPPINGS)+"03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",+"05000000c82d00001038000000010000,8Bitdo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",+"05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux,",+"03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",+"05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",+"03000000c82d00000310000011010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux,",+"05000000c82d00008010000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux,", "03000000022000000090000011010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",+"05000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,", "05000000c82d00002038000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,", "03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",-"05000000c82d00003028000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,",+"05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",+"05000000c82d00000061000000010000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",+"03000000c82d000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,",+"030000003512000012ab000010010000,8Bitdo SFC30 GamePad,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux,", "05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,",-"05000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,",+"05000000c82d00003028000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,",+"03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux,",+"03000000c82d00000160000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",+"03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux,",+"03000000c82d00001290000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux,",+"05000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",+"05000000c82d00006228000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",+"03000000c82d00000260000011010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",+"05000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",+"05000000202800000900000000010000,8BitDo SNES30 Gamepad,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,",+"03000000c82d00000031000011010000,8BitDo Wireless Adapter (DInput),a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"030000005e0400008e02000020010000,8BitDo Wireless Adapter (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,",+"05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",+"050000005e040000e002000030110000,8BitDo Zero 2 (XInput),a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,", "05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,",-"030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"05000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,",+"03000000c01100000355000011010000,ACRUX USB GAME PAD,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"030000006f0e00001302000000010000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000006f0e00003901000020060000,Afterglow Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000006f0e00003901000000430000,Afterglow Prismatic Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000006f0e00003901000013020000,Afterglow Prismatic Wired Controller 048-007-NA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",+"030000007c1800000006000010010000,Alienware Dual Compatible Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Linux,",+"05000000491900000204000021000000,Amazon Fire Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b17,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"03000000491900001904000011010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux,",+"05000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,",+"03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",+"03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,",+"03000000a30c00002800000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,", "05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,",+"05000000050b00000045000040000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,",+"03000000503200000110000000000000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,platform:Linux,",+"05000000503200000110000000000000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,platform:Linux,",+"03000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,",+"05000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,",+"03000000120c00000500000010010000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux,",+"03000000ef0500000300000000010000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux,",+"03000000c62400001b89000011010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"03000000d62000002a79000011010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"03000000c21100000791000011010000,Be1 GC101 Controller 1.03 mode,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",+"03000000c31100000791000011010000,Be1 GC101 GAMEPAD 1.03 mode,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"030000005e0400008e02000003030000,Be1 GC101 Xbox 360 Controller mode,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"05000000bc2000000055000001000000,BETOP AX1 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,", "03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,",+"03000000120c0000200e000011010000,Brook Mars,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"03000000120c0000210e000011010000,Brook Mars,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"03000000120c0000f70e000011010000,Brook Universal Fighting Board,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",+"03000000ffff0000ffff000000010000,Chinese-made Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,", "03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",+"030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux,", "03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux,", "03000000a306000022f6000011010000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,", "03000000b40400000a01000000010000,CYPRESS USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,", "03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux,",+"030000004f04000004b3000010010000,Dual Power 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,", "030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,", "03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,",+"03000000bc2000000055000011010000,GameSir G3w,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,", "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,", "030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",-"030000006f0e00001304000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:a0,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:a3,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",-"030000006f0e00001f01000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000008f0e00000800000010010000,Gasia Co. Ltd PS(R) Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",+"030000006f0e00001304000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"03000000451300000010000010010000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,", "03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"0300000079000000d418000000010000,GPD Win 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000007d0400000540000000010000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,", "03000000280400000140000000010000,Gravis GamePad Pro USB ,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,", "030000008f0e00000610000000010000,GreenAsia Electronics 4Axes 12Keys GamePad ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux,", "030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,",-"030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,", "0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",+"03000000f0250000c383000010010000,GT VX2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,", "06000000adde0000efbe000002010000,Hidromancer Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux,", "03000000c9110000f055000011010000,HJC Game GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",+"03000000632500002605000010010000,HJD-X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,", "030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux,", "030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",+"030000000d0f0000c100000011010000,HORI CO. LTD. HORIPAD S,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,", "030000000d0f00006a00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "030000000d0f00006b00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,", "030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",+"030000000d0f00008500000010010000,HORI Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"030000000d0f00008600000002010000,Hori Fighting Commander,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,", "030000000d0f00005f00000011010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,", "030000000d0f00005e00000011010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000000d0f00009200000011010000,Hori Pokken Tournament DX Pro Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",+"030000000d0f0000aa00000011010000,HORI Real Arcade Pro,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",+"030000000d0f0000d800000072056800,HORI Real Arcade Pro S,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,",+"030000000d0f00001600000000010000,Hori Real Arcade Pro.EX-SE (Xbox 360),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux,", "030000000d0f00006e00000011010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,", "030000000d0f00006600000011010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"030000000d0f0000ee00000011010000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "030000000d0f00006700000001010000,HORIPAD ONE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "030000008f0e00001330000010010000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Linux,",+"03000000242e00008816000001010000,Hyperkin X91,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,", "050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,", "03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,",+"03000000d80400008200000003000000,IMS PCU#0 Gamepad Interface,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux,", "03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux,",+"0500000049190000020400001b010000,Ipega PG-9069 - Bluetooth Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b161,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"03000000632500007505000011010000,Ipega PG-9099 - Bluetooth Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,", "030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux,", "03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,",+"03000000300f00000b01000010010000,Jess Tech GGE909 PC Recoil Pad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,", "03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",+"030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux,",+"050000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux,",+"030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux,",+"050000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux,",+"03000000bd12000003c0000010010000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"03000000242f00002d00000011010000,JYS Wireless Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",+"03000000242f00008a00000011010000,JYS Wireless Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux,", "030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000006d040000d1ca000000000000,Logitech ChillStream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,", "030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",-"030000006d04000016c2000011010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,", "030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"030000006d04000016c2000011010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,", "030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000006d0400001ec2000019200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,", "030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",-"030000006d04000015c2000010010000,Logitech Logitech Extreme 3D,a:b0,b:b4,back:b6,guide:b8,leftshoulder:b9,leftstick:h0.8,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:h0.2,start:b7,x:b2,y:b5,platform:Linux,",+"030000006d0400000ac2000010010000,Logitech Inc. WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Linux,", "030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,", "030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux,",+"050000004d4f435554452d3035305800,M54-PC,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,", "05000000380700006652000025010000,Mad Catz C.T.R.L.R ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,", "03000000380700005032000011010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,", "03000000380700005082000011010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux,", "03000000380700008034000011010000,Mad Catz fightstick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,", "03000000380700008084000011010000,Mad Catz fightstick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",-"03000000380700008433000011010000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",-"03000000380700008483000011010000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"03000000380700008433000011010000,Mad Catz FightStick TE S+ (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"03000000380700008483000011010000,Mad Catz FightStick TE S+ (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller (SFIV),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,", "03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,", "03000000380700003888000010010000,MadCatz PC USB Wired Stick 8838,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",-"03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,",+"03000000242f0000f700000001010000,Magic-S Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"03000000120c00000500000000010000,Manta Dualshock 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,",+"03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,",+"03000000790000004318000010010000,Mayflash GameCube Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,",+"03000000242f00007300000011010000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux,",+"0300000079000000d218000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"03000000d620000010a7000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"0300000025090000e803000001010000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,", "03000000780000000600000010010000,Microntek USB Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,",+"030000005e0400000e00000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,", "030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "030000005e0400008e02000062230000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"050000005e040000050b000003090000,Microsoft X-Box One Elite 2 pad,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"030000005e040000e302000003020000,Microsoft X-Box One Elite pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "030000005e040000d102000001010000,Microsoft X-Box One pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000005e040000dd02000003020000,Microsoft X-Box One pad (Firmware 2015),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "030000005e040000d102000003020000,Microsoft X-Box One pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,", "030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,",+"030000005e040000000b000008040000,Microsoft Xbox One Elite 2 pad - Wired,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000005e040000ea02000008040000,Microsoft Xbox One S pad - Wired,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"03000000c62400001a53000000010000,Mini PE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,",+"05000000d6200000e589000001000000,Moga 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,", "05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,",-"030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Linux,",+"05000000d62000007162000001000000,Moga Pro 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,",+"03000000c62400002b89000011010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"05000000c62400002a89000000010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"05000000c62400001a89000000010000,MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"03000000250900006688000000010000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,",+"030000006b140000010c000010010000,NACON GC-400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",+"030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"03000000790000004518000010010000,NEXILUX GAMECUBE Controller Adapter,a:b1,b:b0,x:b2,y:b3,start:b9,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,platform:Linux,",+"030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Linux,",+"060000007e0500003713000000000000,Nintendo 3DS,a:b0,b:b1,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,",+"060000007e0500000820000000000000,Nintendo Combined Joy-Cons (joycond),a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,",+"030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux,",+"03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux,",+"050000007e0500000620000001800000,Nintendo Switch Left Joy-Con,a:b9,b:b8,back:b5,leftshoulder:b2,leftstick:b6,leftx:a1,lefty:a0~,rightshoulder:b4,start:b0,x:b7,y:b10,platform:Linux,",+"030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,", "050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",+"050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,",+"050000007e0500000720000001800000,Nintendo Switch Right Joy-Con,a:b1,b:b2,back:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0~,rightshoulder:b6,start:b8,x:b0,y:b3,platform:Linux,",+"050000007e0500001720000001000000,Nintendo Switch SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux,", "050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,", "05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,", "030000000d0500000308000010010000,Nostromo n45 Dual Analog Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,", "03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",+"03000000550900001472000011010000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,",+"05000000550900001472000001000000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,", "03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"19000000010000000100000001010000,odroidgo2_joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux,",+"19000000010000000200000011000000,odroidgo2_joypad_v11,a:b1,b:b0,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b12,leftshoulder:b4,leftstick:b14,lefttrigger:b13,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b16,start:b17,x:b2,y:b3,platform:Linux,", "030000005e0400000202000000010000,Old Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,",+"03000000c0160000dc27000001010000,OnyxSoft Dual JoyDivision,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:Linux,", "05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,", "05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,",+"03000000830500005020000010010000,Padix Co. Ltd. Rockfire PSX/USB Bridge,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Linux,",+"03000000790000001c18000011010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,", "03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",+"030000006f0e0000b802000001010000,PDP AFTERGLOW Wired Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000006f0e0000b802000013020000,PDP AFTERGLOW Wired Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000006f0e00008001000011010000,PDP CO. LTD. Faceoff Wired Pro Controller for Nintendo Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"030000006f0e00003101000000010000,PDP EA Sports Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000006f0e0000c802000012010000,PDP Kingdom Hearts Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000006f0e00008701000011010000,PDP Rock Candy Wired Controller for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",+"030000006f0e00000901000011010000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",+"030000006f0e0000a802000023020000,PDP Wired Controller for Xbox One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",+"030000006f0e00008501000011010000,PDP Wired Fight Pad Pro for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",+"0500000049190000030400001b010000,PG-9099,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"05000000491900000204000000000000,PG-9118,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"030000004c050000da0c000011010000,Playstation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,",+"030000004c0500003713000011010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",+"03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"03000000d62000006dca000011010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"03000000d62000000228000001010000,PowerA Wired Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"03000000c62400001a58000001010000,PowerA Xbox One Cabled,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"03000000c62400001a54000001010000,PowerA Xbox One Mini Wired Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,", "03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,",-"030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",-"050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,", "03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",-"030000004c0500006802000011810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",-"050000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:a12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:a13,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",+"030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,", "030000004c0500006802000010810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,", "030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",-"060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",-"05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",-"050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"030000004c0500006802000011810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",+"030000006f0e00001402000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"030000008f0e00000300000010010000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",+"050000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",+"050000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:a12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:a13,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",+"050000004c0500006802000000800000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",+"050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",+"05000000504c415953544154494f4e00,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",+"060000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,", "030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",-"050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",-"050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",+"030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",+"030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",-"050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",-"030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,", "030000004c050000cc09000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",-"030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"03000000c01100000140000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",+"050000004c050000c405000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",+"050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",+"050000004c050000cc09000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",+"030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"03000000ff000000cb01000010010000,PSP,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,", "03000000300f00001211000011010000,QanBa Arcade JoyStick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux,",+"030000009b2800004200000001010000,Raphnet Technologies Dual NES to USB v2.0,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Linux,",+"030000009b2800003200000001010000,Raphnet Technologies GC/N64 to USB v3.4,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,",+"030000009b2800006000000001010000,Raphnet Technologies GC/N64 to USB v3.6,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,", "030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,", "030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",-"030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000008916000000fd000024010000,Razer Onza Tournament Edition,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"03000000321500000204000011010000,Razer Panthera (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"03000000321500000104000011010000,Razer Panthera (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"03000000321500000810000011010000,Razer Panthera Evo Arcade Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "03000000321500000010000011010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"03000000321500000507000000010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"03000000321500000011000011010000,Razer Raion Fightpad for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"030000008916000000fe000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"03000000c6240000045d000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,", "050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,", "0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "03000000790000001100000010010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,",-"0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,",-"0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,",+"0300000081170000990a000001010000,Retronic Adapter,a:b0,leftx:a0,lefty:a1,platform:Linux,",+"0300000000f000000300000000010000,RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,", "030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",-"030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",-"030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000006b140000130d000011010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"030000006f0e00001f01000000010000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000006f0e00001e01000011010000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"030000006f0e00004601000001010000,Rock Candy Xbox One Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",-"03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,",+"03000000a30600001005000000010000,Saitek P150,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b2,righttrigger:b5,x:b3,y:b4,platform:Linux,",+"03000000a30600000701000000010000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Linux,",+"03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b0,y:b1,platform:Linux,", "03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux,",+"03000000300f00001201000010010000,Saitek P380,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,", "03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,", "03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux,", "03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",-"03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux,",+"03000000a306000020f6000011010000,Saitek PS2700 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",+"03000000d81d00000e00000010010000,Savior,a:b0,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b9,x:b4,y:b5,platform:Linux,", "03000000f025000021c1000010010000,ShanWan Gioteck PS3 Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",+"03000000632500007505000010010000,SHANWAN PS3/PC Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",+"03000000bc2000000055000010010000,ShanWan PS3/PC Wired GamePad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"030000005f140000c501000010010000,SHANWAN Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",+"03000000632500002305000010010000,ShanWan USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",+"03000000341a00000908000010010000,SL-6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",+"030000004c050000e60c000011810000,Sony DualSense,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",+"050000004c050000e60c000000810000,Sony DualSense ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,", "03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,", "030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",-"03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",-"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",-"03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",-"05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",-"03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",-"03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",+"03000000d11800000094000011010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",+"03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",+"03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",+"03000000de2800000211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,",+"03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",+"03000000de2800004211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,",+"03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",+"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",+"05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,", "03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"03000000381000003014000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"03000000381000003114000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"0500000011010000311400001b010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b32,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"03000000ad1b000038f0000090040000,Street Fighter IV FightStick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000003b07000004a1000000010000,Suncom SFX Plus for USB,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Linux,", "03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,",+"0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,",+"03000000457500002211000010010000,SZMY-POWER CO. LTD. GAMEPAD,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",+"030000008f0e00000d31000010010000,SZMY-POWER CO. LTD. GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"030000008f0e00001431000010010000,SZMY-POWER CO. LTD. PS3 gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,", "030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,", "030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,", "030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"030000004f0400000ed0000011010000,ThrustMaster eSwap PRO Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+"03000000b50700000399000000010000,Thrustmaster Firestorm Digital 2,a:b2,b:b4,back:b11,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b0,righttrigger:b9,start:b1,x:b3,y:b5,platform:Linux,",+"030000004f04000003b3000010010000,Thrustmaster Firestorm Dual Analog 2,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b9,rightx:a2,righty:a3,x:b1,y:b3,platform:Linux,", "030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux,",+"030000004f04000026b3000002040000,Thrustmaster Gamepad GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"03000000c6240000025b000002020000,Thrustmaster GPX Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"030000004f04000007d0000000010000,Thrustmaster T Mini Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",+"030000004f04000012b3000010010000,Thrustmaster vibrating gamepad,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,", "03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,", "03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,",+"030000005e0400008e02000070050000,Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"03000000c01100000591000011010000,Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,", "03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,", "03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",+"03000000790000000600000007010000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux,", "03000000790000001100000000010000,USB Gamepad1,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux,",+"030000006f0e00000302000011010000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",+"030000006f0e00000702000011010000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,", "05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,",-"030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"03000000791d00000103000010010000,Wii Classic Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",+"050000000d0f0000f600000001000000,Wireless HORIPAD Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,", "030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",-"030000005e040000a102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000005e040000a102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux,",+"030000005e040000a102000014010000,Xbox 360 Wireless Receiver (XBOX),a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",+"030000005e040000d102000002010000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"050000005e040000fd02000030110000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"030000005e040000ea02000000000000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "050000005e040000fd02000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"030000005e040000ea02000001030000,Xbox One Wireless Controller (Model 1708),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000005e040000120b000001050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"050000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"050000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",+"030000005e040000120b000005050000,XBox Series pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",+"030000005e0400008e02000000010000,xbox360 Wireless EasySMX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,", "03000000450c00002043000010010000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",+"03000000ac0500005b05000010010000,Xiaoji Gamesir-G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,", "05000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux,", "03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,", "03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",-"64633436313965656664373634323364,Microsoft X-Box 360 pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,",-"61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",-"4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",-"37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",-"35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,",-"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,",-"5477696e20555342204a6f7973746963,Twin USB Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android,",-"34356136633366613530316338376136,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android,",-"4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS,",-"4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS,",-"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS,",--"78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",-"78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",-"78696e70757403000000000000000000,XInput Arcade Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",-"78696e70757404000000000000000000,XInput Flight Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",-"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",-"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",-"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",-NULL+"03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",+#endif // GLFW_BUILD_LINUX_MAPPINGS }; 
glfw/src/monitor.c view
@@ -170,8 +170,7 @@     monitor->widthMM = widthMM;     monitor->heightMM = heightMM; -    if (name)-        monitor->name = _glfw_strdup(name);+    strncpy(monitor->name, name, sizeof(monitor->name) - 1);      return monitor; }@@ -189,7 +188,6 @@     _glfwFreeGammaArrays(&monitor->currentRamp);      free(monitor->modes);-    free(monitor->name);     free(monitor); } @@ -523,6 +521,8 @@     assert(ramp->green != NULL);     assert(ramp->blue != NULL); +    _GLFW_REQUIRE_INIT();+     if (ramp->size <= 0)     {         _glfwInputError(GLFW_INVALID_VALUE,@@ -530,8 +530,6 @@                         ramp->size);         return;     }--    _GLFW_REQUIRE_INIT();      if (!monitor->originalRamp.size)     {
glfw/src/nsgl_context.h view
@@ -25,8 +25,10 @@ //========================================================================  // NOTE: Many Cocoa enum values have been renamed and we need to build across-//       SDK versions where one is unavailable or the other deprecated-//       We use the newer names in code and these macros to handle compatibility+//       SDK versions where one is unavailable or deprecated.+//       We use the newer names in code and replace them with the older names if+//       the base SDK does not provide the newer names.+ #if MAC_OS_X_VERSION_MAX_ALLOWED < 101400  #define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval  #define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity@@ -44,7 +46,6 @@ {     id                pixelFormat;     id                object;- } _GLFWcontextNSGL;  // NSGL-specific global data@@ -53,7 +54,6 @@ {     // dlopen handle for OpenGL.framework (for glfwGetProcAddress)     CFBundleRef     framework;- } _GLFWlibraryNSGL;  
glfw/src/nsgl_context.m view
@@ -51,7 +51,7 @@      // HACK: Simulate vsync with usleep as NSGL swap interval does not apply to     //       windows with a non-visible occlusion state-    if (!([window->ns.object occlusionState] & NSWindowOcclusionStateVisible))+    if (window->ns.occluded)     {         int interval = 0;         [window->context.nsgl.object getValues:&interval@@ -81,12 +81,11 @@     @autoreleasepool {      _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);-    if (window)-    {-        [window->context.nsgl.object setValues:&interval-                                  forParameter:NSOpenGLContextParameterSwapInterval];-    }+    assert(window != NULL); +    [window->context.nsgl.object setValues:&interval+                              forParameter:NSOpenGLContextParameterSwapInterval];+     } // autoreleasepool } @@ -365,7 +364,7 @@     _GLFWwindow* window = (_GLFWwindow*) handle;     _GLFW_REQUIRE_INIT_OR_RETURN(nil); -    if (window->context.client == GLFW_NO_API)+    if (window->context.source != GLFW_NATIVE_CONTEXT_API)     {         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);         return nil;
glfw/src/null_window.c view
@@ -67,6 +67,9 @@             _glfwInputError(GLFW_API_UNAVAILABLE, "Null: EGL not available");             return GLFW_FALSE;         }++        if (!_glfwRefreshContextAttribs(window, ctxconfig))+            return GLFW_FALSE;     }      return GLFW_TRUE;
glfw/src/osmesa_context.c view
@@ -124,6 +124,8 @@         "libOSMesa.8.dylib", #elif defined(__CYGWIN__)         "libOSMesa-8.so",+#elif defined(__OpenBSD__) || defined(__NetBSD__)+        "libOSMesa.so", #else         "libOSMesa.so.8",         "libOSMesa.so.6",@@ -302,6 +304,12 @@      _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); +    if (window->context.source != GLFW_OSMESA_CONTEXT_API)+    {+        _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);+        return GLFW_FALSE;+    }+     if (!OSMesaGetColorBuffer(window->context.osmesa.handle,                               &mesaWidth, &mesaHeight,                               &mesaFormat, &mesaBuffer))@@ -335,6 +343,12 @@      _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); +    if (window->context.source != GLFW_OSMESA_CONTEXT_API)+    {+        _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);+        return GLFW_FALSE;+    }+     if (!OSMesaGetDepthBuffer(window->context.osmesa.handle,                               &mesaWidth, &mesaHeight,                               &mesaBytes, &mesaBuffer))@@ -361,7 +375,7 @@     _GLFWwindow* window = (_GLFWwindow*) handle;     _GLFW_REQUIRE_INIT_OR_RETURN(NULL); -    if (window->context.client == GLFW_NO_API)+    if (window->context.source != GLFW_OSMESA_CONTEXT_API)     {         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);         return NULL;
glfw/src/vulkan.c view
@@ -59,6 +59,8 @@     _glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");     if (!_glfw.vk.handle)         _glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS();+#elif defined(__OpenBSD__) || defined(__NetBSD__)+    _glfw.vk.handle = _glfw_dlopen("libvulkan.so"); #else     _glfw.vk.handle = _glfw_dlopen("libvulkan.so.1"); #endif
glfw/src/wgl_context.c view
@@ -73,18 +73,13 @@     int attribs[40];     int values[sizeof(attribs) / sizeof(attribs[0])]; +    nativeCount = DescribePixelFormat(window->context.wgl.dc,+                                      1,+                                      sizeof(PIXELFORMATDESCRIPTOR),+                                      NULL);+     if (_glfw.wgl.ARB_pixel_format)     {-        const int attrib = WGL_NUMBER_PIXEL_FORMATS_ARB;--        if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc,-                                          1, 0, 1, &attrib, &nativeCount))-        {-            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,-                                 "WGL: Failed to retrieve pixel format attribute");-            return 0;-        }-         addAttrib(WGL_SUPPORT_OPENGL_ARB);         addAttrib(WGL_DRAW_TO_WINDOW_ARB);         addAttrib(WGL_PIXEL_TYPE_ARB);@@ -122,13 +117,6 @@                 addAttrib(WGL_COLORSPACE_EXT);         }     }-    else-    {-        nativeCount = DescribePixelFormat(window->context.wgl.dc,-                                          1,-                                          sizeof(PIXELFORMATDESCRIPTOR),-                                          NULL);-    }      usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig)); @@ -165,6 +153,9 @@             if (findAttribValue(WGL_ACCELERATION_ARB) == WGL_NO_ACCELERATION_ARB)                 continue; +            if (findAttribValue(WGL_DOUBLE_BUFFER_ARB) != fbconfig->doublebuffer)+                continue;+             u->redBits = findAttribValue(WGL_RED_BITS_ARB);             u->greenBits = findAttribValue(WGL_GREEN_BITS_ARB);             u->blueBits = findAttribValue(WGL_BLUE_BITS_ARB);@@ -182,8 +173,6 @@              if (findAttribValue(WGL_STEREO_ARB))                 u->stereo = GLFW_TRUE;-            if (findAttribValue(WGL_DOUBLE_BUFFER_ARB))-                u->doublebuffer = GLFW_TRUE;              if (_glfw.wgl.ARB_multisample)                 u->samples = findAttribValue(WGL_SAMPLES_ARB);@@ -239,6 +228,9 @@             if (pfd.iPixelType != PFD_TYPE_RGBA)                 continue; +            if (!!(pfd.dwFlags & PFD_DOUBLEBUFFER) != fbconfig->doublebuffer)+                continue;+             u->redBits = pfd.cRedBits;             u->greenBits = pfd.cGreenBits;             u->blueBits = pfd.cBlueBits;@@ -256,8 +248,6 @@              if (pfd.dwFlags & PFD_STEREO)                 u->stereo = GLFW_TRUE;-            if (pfd.dwFlags & PFD_DOUBLEBUFFER)-                u->doublebuffer = GLFW_TRUE;         }          u->handle = pixelFormat;@@ -343,6 +333,7 @@ static void swapIntervalWGL(int interval) {     _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);+    assert(window != NULL);      window->context.wgl.interval = interval; @@ -785,7 +776,7 @@     _GLFWwindow* window = (_GLFWwindow*) handle;     _GLFW_REQUIRE_INIT_OR_RETURN(NULL); -    if (window->context.client == GLFW_NO_API)+    if (window->context.source != GLFW_NATIVE_CONTEXT_API)     {         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);         return NULL;
glfw/src/wgl_context.h view
@@ -104,10 +104,6 @@ #define wglMakeCurrent _glfw.wgl.MakeCurrent #define wglShareLists _glfw.wgl.ShareLists -#define _GLFW_RECREATION_NOT_NEEDED 0-#define _GLFW_RECREATION_REQUIRED   1-#define _GLFW_RECREATION_IMPOSSIBLE 2- #define _GLFW_PLATFORM_CONTEXT_STATE            _GLFWcontextWGL wgl #define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE    _GLFWlibraryWGL wgl @@ -119,7 +115,6 @@     HDC       dc;     HGLRC     handle;     int       interval;- } _GLFWcontextWGL;  // WGL-specific global data@@ -152,7 +147,6 @@     GLFWbool                            ARB_create_context_robustness;     GLFWbool                            ARB_create_context_no_error;     GLFWbool                            ARB_context_flush_control;- } _GLFWlibraryWGL;  
glfw/src/win32_init.c view
@@ -39,6 +39,10 @@  #if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG) +#if defined(_GLFW_BUILD_DLL)+ #pragma message("These symbols must be exported by the executable and have no effect in a DLL")+#endif+ // Executables (but not DLLs) exporting this symbol with this value will be // automatically directed to the high-performance GPU on Nvidia Optimus systems // with up-to-date drivers@@ -68,17 +72,16 @@ // static GLFWbool loadLibraries(void) {-    _glfw.win32.winmm.instance = LoadLibraryA("winmm.dll");-    if (!_glfw.win32.winmm.instance)+    if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |+                                GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,+                            (const WCHAR*) &_glfw,+                            (HMODULE*) &_glfw.win32.instance))     {         _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,-                             "Win32: Failed to load winmm.dll");+                             "Win32: Failed to retrieve own module handle");         return GLFW_FALSE;     } -    _glfw.win32.winmm.GetTime = (PFN_timeGetTime)-        GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");-     _glfw.win32.user32.instance = LoadLibraryA("user32.dll");     if (!_glfw.win32.user32.instance)     {@@ -99,6 +102,8 @@         GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow");     _glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)         GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");+    _glfw.win32.user32.GetSystemMetricsForDpi_ = (PFN_GetSystemMetricsForDpi)+        GetProcAddress(_glfw.win32.user32.instance, "GetSystemMetricsForDpi");      _glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");     if (_glfw.win32.dinput8.instance)@@ -143,6 +148,8 @@             GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");         _glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow)             GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");+        _glfw.win32.dwmapi.GetColorizationColor = (PFN_DwmGetColorizationColor)+            GetProcAddress(_glfw.win32.dwmapi.instance, "DwmGetColorizationColor");     }      _glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");@@ -174,9 +181,6 @@     if (_glfw.win32.dinput8.instance)         FreeLibrary(_glfw.win32.dinput8.instance); -    if (_glfw.win32.winmm.instance)-        FreeLibrary(_glfw.win32.winmm.instance);-     if (_glfw.win32.user32.instance)         FreeLibrary(_glfw.win32.user32.instance); @@ -260,7 +264,6 @@     _glfw.win32.keycodes[0x151] = GLFW_KEY_PAGE_DOWN;     _glfw.win32.keycodes[0x149] = GLFW_KEY_PAGE_UP;     _glfw.win32.keycodes[0x045] = GLFW_KEY_PAUSE;-    _glfw.win32.keycodes[0x146] = GLFW_KEY_PAUSE;     _glfw.win32.keycodes[0x039] = GLFW_KEY_SPACE;     _glfw.win32.keycodes[0x00F] = GLFW_KEY_TAB;     _glfw.win32.keycodes[0x03A] = GLFW_KEY_CAPS_LOCK;@@ -342,7 +345,7 @@                         WS_CLIPSIBLINGS | WS_CLIPCHILDREN,                         0, 0, 1, 1,                         NULL, NULL,-                        GetModuleHandleW(NULL),+                        _glfw.win32.instance,                         NULL);      if (!_glfw.win32.helperWindowHandle)@@ -492,7 +495,7 @@             vk = vks[key - GLFW_KEY_KP_0];         }         else-            vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK);+            vk = MapVirtualKeyW(scancode, MAPVK_VSC_TO_VK);          length = ToUnicode(vk, scancode, state,                            chars, sizeof(chars) / sizeof(WCHAR),@@ -500,6 +503,8 @@          if (length == -1)         {+            // This is a dead key, so we need a second simulated key press+            // to make it output its own character (usually a diacritic)             length = ToUnicode(vk, scancode, state,                                chars, sizeof(chars) / sizeof(WCHAR),                                0);@@ -515,7 +520,8 @@     } } -// Replacement for IsWindowsVersionOrGreater as MinGW lacks versionhelpers.h+// Replacement for IsWindowsVersionOrGreater, as we cannot rely on the+// application having a correct embedded manifest // BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp) {@@ -606,6 +612,7 @@      _glfwTerminateWGL();     _glfwTerminateEGL();+    _glfwTerminateOSMesa();      _glfwTerminateJoysticksWin32(); 
glfw/src/win32_joystick.c view
@@ -256,6 +256,8 @@ // static void closeJoystick(_GLFWjoystick* js) {+    _glfwInputJoystick(js, GLFW_DISCONNECTED);+     if (js->win32.device)     {         IDirectInputDevice8_Unacquire(js->win32.device);@@ -263,9 +265,7 @@     }      free(js->win32.objects);-     _glfwFreeJoystick(js);-    _glfwInputJoystick(js, GLFW_DISCONNECTED); }  // DirectInput device object enumeration callback@@ -356,8 +356,8 @@      for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)     {-        _GLFWjoystick* js = _glfw.joysticks + jid;-        if (js->present)+        js = _glfw.joysticks + jid;+        if (js->connected)         {             if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)                 return DIENUM_CONTINUE;@@ -497,7 +497,7 @@ {     if (_glfw.win32.dinput8.instance)     {-        if (FAILED(DirectInput8Create(GetModuleHandle(NULL),+        if (FAILED(DirectInput8Create(_glfw.win32.instance,                                       DIRECTINPUT_VERSION,                                       &IID_IDirectInput8W,                                       (void**) &_glfw.win32.dinput8.api,@@ -541,7 +541,7 @@              for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)             {-                if (_glfw.joysticks[jid].present &&+                if (_glfw.joysticks[jid].connected &&                     _glfw.joysticks[jid].win32.device == NULL &&                     _glfw.joysticks[jid].win32.index == index)                 {@@ -593,7 +593,7 @@     for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)     {         _GLFWjoystick* js = _glfw.joysticks + jid;-        if (js->present)+        if (js->connected)             _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);     } }@@ -609,7 +609,7 @@     {         int i, ai = 0, bi = 0, pi = 0;         HRESULT result;-        DIJOYSTATE state;+        DIJOYSTATE state = {0};          IDirectInputDevice8_Poll(js->win32.device);         result = IDirectInputDevice8_GetDeviceState(js->win32.device,@@ -672,11 +672,11 @@                     };                      // Screams of horror are appropriate at this point-                    int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);-                    if (state < 0 || state > 8)-                        state = 8;+                    int stateIndex = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);+                    if (stateIndex < 0 || stateIndex > 8)+                        stateIndex = 8; -                    _glfwInputJoystickHat(js, pi, states[state]);+                    _glfwInputJoystickHat(js, pi, states[stateIndex]);                     pi++;                     break;                 }@@ -735,6 +735,13 @@             dpad |= GLFW_HAT_DOWN;         if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)             dpad |= GLFW_HAT_LEFT;++        // Treat invalid combinations as neither being pressed+        // while preserving what data can be preserved+        if ((dpad & GLFW_HAT_RIGHT) && (dpad & GLFW_HAT_LEFT))+            dpad &= ~(GLFW_HAT_RIGHT | GLFW_HAT_LEFT);+        if ((dpad & GLFW_HAT_UP) && (dpad & GLFW_HAT_DOWN))+            dpad &= ~(GLFW_HAT_UP | GLFW_HAT_DOWN);          _glfwInputJoystickHat(js, 0, dpad);     }
glfw/src/win32_joystick.h view
@@ -28,6 +28,7 @@ #define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE struct { int dummyLibraryJoystick; }  #define _GLFW_PLATFORM_MAPPING_NAME "Windows"+#define GLFW_BUILD_WIN32_MAPPINGS  // Joystick element (axis, button or slider) //
glfw/src/win32_monitor.c view
@@ -185,6 +185,8 @@                            display.DeviceName) == 0)                 {                     disconnected[i] = NULL;+                    // handle may have changed, update+                    EnumDisplayMonitors(NULL, NULL, monitorCallback, (LPARAM) _glfw.monitors[i]);                     break;                 }             }@@ -316,8 +318,19 @@ {     UINT xdpi, ydpi; +    if (xscale)+        *xscale = 0.f;+    if (yscale)+        *yscale = 0.f;+     if (IsWindows8Point1OrGreater())-        GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);+    {+        if (GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi) != S_OK)+        {+            _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to query monitor DPI");+            return;+        }+    }     else     {         const HDC dc = GetDC(NULL);@@ -369,7 +382,7 @@                                      int* width, int* height) {     MONITORINFO mi = { sizeof(mi) };-    GetMonitorInfo(monitor->win32.handle, &mi);+    GetMonitorInfoW(monitor->win32.handle, &mi);      if (xpos)         *xpos = mi.rcWork.left;
glfw/src/win32_platform.h view
@@ -39,8 +39,8 @@ #endif  // This is a workaround for the fact that glfw3.h needs to export APIENTRY (for-// example to allow applications to correctly declare a GL_ARB_debug_output-// callback) but windows.h assumes no one will define APIENTRY before it does+// example to allow applications to correctly declare a GL_KHR_debug callback)+// but windows.h assumes no one will define APIENTRY before it does #undef APIENTRY  // GLFW on Windows is Unicode only and does not work in MBCS mode@@ -77,6 +77,9 @@ #ifndef WM_DWMCOMPOSITIONCHANGED  #define WM_DWMCOMPOSITIONCHANGED 0x031E #endif+#ifndef WM_DWMCOLORIZATIONCOLORCHANGED+ #define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320+#endif #ifndef WM_COPYGLOBALDATA  #define WM_COPYGLOBALDATA 0x0049 #endif@@ -99,7 +102,7 @@  #define DISPLAY_DEVICE_ACTIVE 0x00000001 #endif #ifndef _WIN32_WINNT_WINBLUE- #define _WIN32_WINNT_WINBLUE 0x0602+ #define _WIN32_WINNT_WINBLUE 0x0603 #endif #ifndef _WIN32_WINNT_WIN8  #define _WIN32_WINNT_WIN8 0x0602@@ -159,7 +162,9 @@ #define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE) -4) #endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/ -// HACK: Define versionhelpers.h functions manually as MinGW lacks the header+// Replacement for versionhelpers.h macros, as we cannot rely on the+// application having a correct embedded manifest+// #define IsWindowsXPOrGreater()                                 \     _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINXP),   \                                         LOBYTE(_WIN32_WINNT_WINXP), 0)@@ -215,10 +220,6 @@  #define DIDFT_OPTIONAL 0x80000000 #endif -// winmm.dll function pointer typedefs-typedef DWORD (WINAPI * PFN_timeGetTime)(void);-#define timeGetTime _glfw.win32.winmm.GetTime- // xinput.dll function pointer typedefs typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*); typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);@@ -236,20 +237,24 @@ typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE); typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND); typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);+typedef int (WINAPI * PFN_GetSystemMetricsForDpi)(int,UINT); #define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_ #define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_ #define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_ #define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_ #define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_ #define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_+#define GetSystemMetricsForDpi _glfw.win32.user32.GetSystemMetricsForDpi_  // dwmapi.dll function pointer typedefs typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*); typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID); typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*);+typedef HRESULT (WINAPI * PFN_DwmGetColorizationColor)(DWORD*,BOOL*); #define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled #define DwmFlush _glfw.win32.dwmapi.Flush #define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow+#define DwmGetColorizationColor _glfw.win32.dwmapi.GetColorizationColor  // shcore.dll function pointer typedefs typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);@@ -316,15 +321,20 @@     GLFWbool            transparent;     GLFWbool            scaleToMonitor; +    // Cached size used to filter out duplicate events+    int                 width, height;+     // The last received cursor position, regardless of source     int                 lastCursorPosX, lastCursorPosY;-+    // The last recevied high surrogate when decoding pairs of UTF-16 messages+    WCHAR               highSurrogate; } _GLFWwindowWin32;  // Win32-specific global data // typedef struct _GLFWlibraryWin32 {+    HINSTANCE           instance;     HWND                helperWindowHandle;     HDEVNOTIFY          deviceNotificationHandle;     DWORD               foregroundLockTimeout;@@ -337,17 +347,14 @@     double              restoreCursorPosX, restoreCursorPosY;     // The window whose disabled cursor mode is active     _GLFWwindow*        disabledCursorWindow;+    // The window the cursor is captured in+    _GLFWwindow*        capturedCursorWindow;     RAWINPUT*           rawInput;     int                 rawInputSize;     UINT                mouseTrailSize;      struct {         HINSTANCE                       instance;-        PFN_timeGetTime                 GetTime;-    } winmm;--    struct {-        HINSTANCE                       instance;         PFN_DirectInput8Create          Create;         IDirectInput8W*                 api;     } dinput8;@@ -366,6 +373,7 @@         PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;         PFN_GetDpiForWindow             GetDpiForWindow_;         PFN_AdjustWindowRectExForDpi    AdjustWindowRectExForDpi_;+        PFN_GetSystemMetricsForDpi      GetSystemMetricsForDpi_;     } user32;      struct {@@ -373,6 +381,7 @@         PFN_DwmIsCompositionEnabled     IsCompositionEnabled;         PFN_DwmFlush                    Flush;         PFN_DwmEnableBlurBehindWindow   EnableBlurBehindWindow;+        PFN_DwmGetColorizationColor     GetColorizationColor;     } dwmapi;      struct {@@ -385,7 +394,6 @@         HINSTANCE                       instance;         PFN_RtlVerifyVersionInfo        RtlVerifyVersionInfo_;     } ntdll;- } _GLFWlibraryWin32;  // Win32-specific per-monitor data@@ -400,7 +408,6 @@     char                publicDisplayName[32];     GLFWbool            modesPruned;     GLFWbool            modeChanged;- } _GLFWmonitorWin32;  // Win32-specific per-cursor data@@ -408,16 +415,13 @@ typedef struct _GLFWcursorWin32 {     HCURSOR             handle;- } _GLFWcursorWin32;  // Win32-specific global timer data // typedef struct _GLFWtimerWin32 {-    GLFWbool            hasPC;     uint64_t            frequency;- } _GLFWtimerWin32;  // Win32-specific thread local storage data@@ -426,7 +430,6 @@ {     GLFWbool            allocated;     DWORD               index;- } _GLFWtlsWin32;  // Win32-specific mutex data@@ -435,7 +438,6 @@ {     GLFWbool            allocated;     CRITICAL_SECTION    section;- } _GLFWmutexWin32;  
glfw/src/win32_time.c view
@@ -38,18 +38,7 @@ // void _glfwInitTimerWin32(void) {-    uint64_t frequency;--    if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))-    {-        _glfw.timer.win32.hasPC = GLFW_TRUE;-        _glfw.timer.win32.frequency = frequency;-    }-    else-    {-        _glfw.timer.win32.hasPC = GLFW_FALSE;-        _glfw.timer.win32.frequency = 1000;-    }+    QueryPerformanceFrequency((LARGE_INTEGER*) &_glfw.timer.win32.frequency); }  @@ -59,14 +48,9 @@  uint64_t _glfwPlatformGetTimerValue(void) {-    if (_glfw.timer.win32.hasPC)-    {-        uint64_t value;-        QueryPerformanceCounter((LARGE_INTEGER*) &value);-        return value;-    }-    else-        return (uint64_t) timeGetTime();+    uint64_t value;+    QueryPerformanceCounter((LARGE_INTEGER*) &value);+    return value; }  uint64_t _glfwPlatformGetTimerFrequency(void)
glfw/src/win32_window.c view
@@ -186,53 +186,38 @@     return handle; } -// Translate content area size to full window size according to styles and DPI-//-static void getFullWindowSize(DWORD style, DWORD exStyle,-                              int contentWidth, int contentHeight,-                              int* fullWidth, int* fullHeight,-                              UINT dpi)-{-    RECT rect = { 0, 0, contentWidth, contentHeight };--    if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())-        AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);-    else-        AdjustWindowRectEx(&rect, style, FALSE, exStyle);--    *fullWidth = rect.right - rect.left;-    *fullHeight = rect.bottom - rect.top;-}- // Enforce the content area aspect ratio based on which edge is being dragged // static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area) {-    int xoff, yoff;-    UINT dpi = USER_DEFAULT_SCREEN_DPI;+    RECT frame = {0};     const float ratio = (float) window->numer / (float) window->denom;+    const DWORD style = getWindowStyle(window);+    const DWORD exStyle = getWindowExStyle(window);      if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())-        dpi = GetDpiForWindow(window->win32.handle);--    getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),-                      0, 0, &xoff, &yoff, dpi);+    {+        AdjustWindowRectExForDpi(&frame, style, FALSE, exStyle,+                                 GetDpiForWindow(window->win32.handle));+    }+    else+        AdjustWindowRectEx(&frame, style, FALSE, exStyle);      if (edge == WMSZ_LEFT  || edge == WMSZ_BOTTOMLEFT ||         edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT)     {-        area->bottom = area->top + yoff +-            (int) ((area->right - area->left - xoff) / ratio);+        area->bottom = area->top + (frame.bottom - frame.top) ++            (int) (((area->right - area->left) - (frame.right - frame.left)) / ratio);     }     else if (edge == WMSZ_TOPLEFT || edge == WMSZ_TOPRIGHT)     {-        area->top = area->bottom - yoff --            (int) ((area->right - area->left - xoff) / ratio);+        area->top = area->bottom - (frame.bottom - frame.top) -+            (int) (((area->right - area->left) - (frame.right - frame.left)) / ratio);     }     else if (edge == WMSZ_TOP || edge == WMSZ_BOTTOM)     {-        area->right = area->left + xoff +-            (int) ((area->bottom - area->top - yoff) * ratio);+        area->right = area->left + (frame.right - frame.left) ++            (int) (((area->bottom - area->top) - (frame.bottom - frame.top)) * ratio);     } } @@ -251,22 +236,26 @@         SetCursor(NULL); } -// Updates the cursor clip rect+// Sets the cursor clip rect to the window content area //-static void updateClipRect(_GLFWwindow* window)+static void captureCursor(_GLFWwindow* window) {-    if (window)-    {-        RECT clipRect;-        GetClientRect(window->win32.handle, &clipRect);-        ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);-        ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);-        ClipCursor(&clipRect);-    }-    else-        ClipCursor(NULL);+    RECT clipRect;+    GetClientRect(window->win32.handle, &clipRect);+    ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);+    ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);+    ClipCursor(&clipRect);+    _glfw.win32.capturedCursorWindow = window; } +// Disabled clip cursor+//+static void releaseCursor(void)+{+    ClipCursor(NULL);+    _glfw.win32.capturedCursorWindow = NULL;+}+ // Enables WM_INPUT messages for the mouse for the specified window // static void enableRawMouseMotion(_GLFWwindow* window)@@ -303,7 +292,7 @@                               &_glfw.win32.restoreCursorPosY);     updateCursorImage(window);     _glfwCenterCursorInContentArea(window);-    updateClipRect(window);+    captureCursor(window);      if (window->rawMouseMotion)         enableRawMouseMotion(window);@@ -317,7 +306,7 @@         disableRawMouseMotion(window);      _glfw.win32.disabledCursorWindow = NULL;-    updateClipRect(NULL);+    releaseCursor();     _glfwPlatformSetCursorPos(window,                               _glfw.win32.restoreCursorPosX,                               _glfw.win32.restoreCursorPosY);@@ -377,12 +366,17 @@ // static void updateFramebufferTransparency(const _GLFWwindow* window) {-    BOOL enabled;+    BOOL composition, opaque;+    DWORD color;      if (!IsWindowsVistaOrGreater())         return; -    if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)+    if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition)+       return;++    if (IsWindows8OrGreater() ||+        (SUCCEEDED(DwmGetColorizationColor(&color, &opaque)) && !opaque))     {         HRGN region = CreateRectRgn(0, 0, -1, -1);         DWM_BLURBEHIND bb = {0};@@ -390,37 +384,18 @@         bb.hRgnBlur = region;         bb.fEnable = TRUE; -        if (SUCCEEDED(DwmEnableBlurBehindWindow(window->win32.handle, &bb)))-        {-            // Decorated windows don't repaint the transparent background-            // leaving a trail behind animations-            // HACK: Making the window layered with a transparency color key-            //       seems to fix this.  Normally, when specifying-            //       a transparency color key to be used when composing the-            //       layered window, all pixels painted by the window in this-            //       color will be transparent.  That doesn't seem to be the-            //       case anymore, at least when used with blur behind window-            //       plus negative region.-            LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);-            exStyle |= WS_EX_LAYERED;-            SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);--            // Using a color key not equal to black to fix the trailing-            // issue.  When set to black, something is making the hit test-            // not resize with the window frame.-            SetLayeredWindowAttributes(window->win32.handle,-                                       RGB(255, 0, 255), 255, LWA_COLORKEY);-        }-+        DwmEnableBlurBehindWindow(window->win32.handle, &bb);         DeleteObject(region);     }     else     {-        LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);-        exStyle &= ~WS_EX_LAYERED;-        SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);-        RedrawWindow(window->win32.handle, NULL, NULL,-                     RDW_ERASE | RDW_INVALIDATE | RDW_FRAME);+        // HACK: Disable framebuffer transparency on Windows 7 when the+        //       colorization color is opaque, because otherwise the window+        //       contents is blended additively with the previous frame instead+        //       of replacing it+        DWM_BLURBEHIND bb = {0};+        bb.dwFlags = DWM_BB_ENABLE;+        DwmEnableBlurBehindWindow(window->win32.handle, &bb);     } } @@ -449,7 +424,7 @@ static void fitToMonitor(_GLFWwindow* window) {     MONITORINFO mi = { sizeof(mi) };-    GetMonitorInfo(window->monitor->win32.handle, &mi);+    GetMonitorInfoW(window->monitor->win32.handle, &mi);     SetWindowPos(window->win32.handle, HWND_TOPMOST,                  mi.rcMonitor.left,                  mi.rcMonitor.top,@@ -470,8 +445,8 @@         //       the OpenGL ICD switches to page flipping         if (IsWindowsXPOrGreater())         {-            SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);-            SystemParametersInfo(SPI_SETMOUSETRAILS, 0, 0, 0);+            SystemParametersInfoW(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);+            SystemParametersInfoW(SPI_SETMOUSETRAILS, 0, 0, 0);         }     } @@ -496,13 +471,63 @@          // HACK: Restore mouse trail length saved in acquireMonitor         if (IsWindowsXPOrGreater())-            SystemParametersInfo(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);+            SystemParametersInfoW(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);     }      _glfwInputMonitorWindow(window->monitor, NULL);     _glfwRestoreVideoModeWin32(window->monitor); } +// Manually maximize the window, for when SW_MAXIMIZE cannot be used+//+static void maximizeWindowManually(_GLFWwindow* window)+{+    RECT rect;+    DWORD style;+    MONITORINFO mi = { sizeof(mi) };++    GetMonitorInfoW(MonitorFromWindow(window->win32.handle,+                                      MONITOR_DEFAULTTONEAREST), &mi);++    rect = mi.rcWork;++    if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE)+    {+        rect.right = _glfw_min(rect.right, rect.left + window->maxwidth);+        rect.bottom = _glfw_min(rect.bottom, rect.top + window->maxheight);+    }++    style = GetWindowLongW(window->win32.handle, GWL_STYLE);+    style |= WS_MAXIMIZE;+    SetWindowLongW(window->win32.handle, GWL_STYLE, style);++    if (window->decorated)+    {+        const DWORD exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);++        if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())+        {+            const UINT dpi = GetDpiForWindow(window->win32.handle);+            AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);+            OffsetRect(&rect, 0, GetSystemMetricsForDpi(SM_CYCAPTION, dpi));+        }+        else+        {+            AdjustWindowRectEx(&rect, style, FALSE, exStyle);+            OffsetRect(&rect, 0, GetSystemMetrics(SM_CYCAPTION));+        }++        rect.bottom = _glfw_min(rect.bottom, mi.rcWork.bottom);+    }++    SetWindowPos(window->win32.handle, HWND_TOP,+                 rect.left,+                 rect.top,+                 rect.right - rect.left,+                 rect.bottom - rect.top,+                 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);+}+ // Window callback function (handles window messages) // static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,@@ -519,8 +544,18 @@             case WM_NCCREATE:             {                 if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())-                    EnableNonClientDpiScaling(hWnd);+                {+                    const CREATESTRUCTW* cs = (const CREATESTRUCTW*) lParam;+                    const _GLFWwndconfig* wndconfig = cs->lpCreateParams; +                    // On per-monitor DPI aware V1 systems, only enable+                    // non-client scaling for windows that scale the client area+                    // We need WM_GETDPISCALEDSIZE from V2 to keep the client+                    // area static when the non-client area is scaled+                    if (wndconfig && wndconfig->scaleToMonitor)+                        EnableNonClientDpiScaling(hWnd);+                }+                 break;             } @@ -645,11 +680,35 @@          case WM_CHAR:         case WM_SYSCHAR:-        case WM_UNICHAR:         {-            const GLFWbool plain = (uMsg != WM_SYSCHAR);+            if (wParam >= 0xd800 && wParam <= 0xdbff)+                window->win32.highSurrogate = (WCHAR) wParam;+            else+            {+                uint32_t codepoint = 0; -            if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR)+                if (wParam >= 0xdc00 && wParam <= 0xdfff)+                {+                    if (window->win32.highSurrogate)+                    {+                        codepoint += (window->win32.highSurrogate - 0xd800) << 10;+                        codepoint += (WCHAR) wParam - 0xdc00;+                        codepoint += 0x10000;+                    }+                }+                else+                    codepoint = (WCHAR) wParam;++                window->win32.highSurrogate = 0;+                _glfwInputChar(window, codepoint, getKeyMods(), uMsg != WM_SYSCHAR);+            }++            return 0;+        }++        case WM_UNICHAR:+        {+            if (wParam == UNICODE_NOCHAR)             {                 // WM_UNICHAR is not sent by Windows, but is sent by some                 // third-party input method engine@@ -657,7 +716,7 @@                 return TRUE;             } -            _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), plain);+            _glfwInputChar(window, (uint32_t) wParam, getKeyMods(), GLFW_TRUE);             return 0;         } @@ -678,6 +737,18 @@                 scancode = MapVirtualKeyW((UINT) wParam, MAPVK_VK_TO_VSC);             } +            // HACK: Alt+PrtSc has a different scancode than just PrtSc+            if (scancode == 0x54)+                scancode = 0x137;++            // HACK: Ctrl+Pause has a different scancode than just Pause+            if (scancode == 0x146)+                scancode = 0x45;++            // HACK: CJK IME sets the extended bit for right Shift+            if (scancode == 0x136)+                scancode = 0x36;+             key = _glfw.win32.keycodes[scancode];              // The Ctrl keys require special handling@@ -944,13 +1015,15 @@          case WM_SIZE:         {+            const int width = LOWORD(lParam);+            const int height = HIWORD(lParam);             const GLFWbool iconified = wParam == SIZE_MINIMIZED;             const GLFWbool maximized = wParam == SIZE_MAXIMIZED ||                                        (window->win32.maximized &&                                         wParam != SIZE_RESTORED); -            if (_glfw.win32.disabledCursorWindow == window)-                updateClipRect(window);+            if (_glfw.win32.capturedCursorWindow == window)+                captureCursor(window);              if (window->win32.iconified != iconified)                 _glfwInputWindowIconify(window, iconified);@@ -958,9 +1031,15 @@             if (window->win32.maximized != maximized)                 _glfwInputWindowMaximize(window, maximized); -            _glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam));-            _glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam));+            if (width != window->win32.width || height != window->win32.height)+            {+                window->win32.width = width;+                window->win32.height = height; +                _glfwInputFramebufferSize(window, width, height);+                _glfwInputWindowSize(window, width, height);+            }+             if (window->monitor && window->win32.iconified != iconified)             {                 if (iconified)@@ -979,8 +1058,8 @@          case WM_MOVE:         {-            if (_glfw.win32.disabledCursorWindow == window)-                updateClipRect(window);+            if (_glfw.win32.capturedCursorWindow == window)+                captureCursor(window);              // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as             // those macros do not handle negative window positions correctly@@ -1004,31 +1083,34 @@          case WM_GETMINMAXINFO:         {-            int xoff, yoff;-            UINT dpi = USER_DEFAULT_SCREEN_DPI;+            RECT frame = {0};             MINMAXINFO* mmi = (MINMAXINFO*) lParam;+            const DWORD style = getWindowStyle(window);+            const DWORD exStyle = getWindowExStyle(window);              if (window->monitor)                 break;              if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())-                dpi = GetDpiForWindow(window->win32.handle);--            getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),-                              0, 0, &xoff, &yoff, dpi);+            {+                AdjustWindowRectExForDpi(&frame, style, FALSE, exStyle,+                                         GetDpiForWindow(window->win32.handle));+            }+            else+                AdjustWindowRectEx(&frame, style, FALSE, exStyle);              if (window->minwidth != GLFW_DONT_CARE &&                 window->minheight != GLFW_DONT_CARE)             {-                mmi->ptMinTrackSize.x = window->minwidth + xoff;-                mmi->ptMinTrackSize.y = window->minheight + yoff;+                mmi->ptMinTrackSize.x = window->minwidth + frame.right - frame.left;+                mmi->ptMinTrackSize.y = window->minheight + frame.bottom - frame.top;             }              if (window->maxwidth != GLFW_DONT_CARE &&                 window->maxheight != GLFW_DONT_CARE)             {-                mmi->ptMaxTrackSize.x = window->maxwidth + xoff;-                mmi->ptMaxTrackSize.y = window->maxheight + yoff;+                mmi->ptMaxTrackSize.x = window->maxwidth + frame.right - frame.left;+                mmi->ptMaxTrackSize.y = window->maxheight + frame.bottom - frame.top;             }              if (!window->decorated)@@ -1039,7 +1121,7 @@                  ZeroMemory(&mi, sizeof(mi));                 mi.cbSize = sizeof(mi);-                GetMonitorInfo(mh, &mi);+                GetMonitorInfoW(mh, &mi);                  mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left;                 mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top;@@ -1073,6 +1155,7 @@         }          case WM_DWMCOMPOSITIONCHANGED:+        case WM_DWMCOLORIZATIONCOLORCHANGED:         {             if (window->win32.transparent)                 updateFramebufferTransparency(window);@@ -1112,9 +1195,11 @@             const float xscale = HIWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;             const float yscale = LOWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI; -            // Only apply the suggested size if the OS is new enough to have-            // sent a WM_GETDPISCALEDSIZE before this-            if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())+            // Resize windowed mode windows that either permit rescaling or that+            // need it to compensate for non-client area scaling+            if (!window->monitor &&+                (window->win32.scaleToMonitor ||+                 _glfwIsWindows10CreatorsUpdateOrGreaterWin32()))             {                 RECT* suggested = (RECT*) lParam;                 SetWindowPos(window->win32.handle, HWND_TOP,@@ -1184,36 +1269,38 @@                               const _GLFWwndconfig* wndconfig,                               const _GLFWfbconfig* fbconfig) {-    int xpos, ypos, fullWidth, fullHeight;+    int frameX, frameY, frameWidth, frameHeight;     WCHAR* wideTitle;     DWORD style = getWindowStyle(window);     DWORD exStyle = getWindowExStyle(window);      if (window->monitor)     {-        GLFWvidmode mode;+        MONITORINFO mi = { sizeof(mi) };+        GetMonitorInfoW(window->monitor->win32.handle, &mi);          // NOTE: This window placement is temporary and approximate, as the         //       correct position and size cannot be known until the monitor         //       video mode has been picked in _glfwSetVideoModeWin32-        _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);-        _glfwPlatformGetVideoMode(window->monitor, &mode);-        fullWidth  = mode.width;-        fullHeight = mode.height;+        frameX = mi.rcMonitor.left;+        frameY = mi.rcMonitor.top;+        frameWidth  = mi.rcMonitor.right - mi.rcMonitor.left;+        frameHeight = mi.rcMonitor.bottom - mi.rcMonitor.top;     }     else     {-        xpos = CW_USEDEFAULT;-        ypos = CW_USEDEFAULT;+        RECT rect = { 0, 0, wndconfig->width, wndconfig->height };          window->win32.maximized = wndconfig->maximized;         if (wndconfig->maximized)             style |= WS_MAXIMIZE; -        getFullWindowSize(style, exStyle,-                          wndconfig->width, wndconfig->height,-                          &fullWidth, &fullHeight,-                          USER_DEFAULT_SCREEN_DPI);+        AdjustWindowRectEx(&rect, style, FALSE, exStyle);++        frameX = CW_USEDEFAULT;+        frameY = CW_USEDEFAULT;+        frameWidth  = rect.right - rect.left;+        frameHeight = rect.bottom - rect.top;     }      wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);@@ -1224,12 +1311,12 @@                                            _GLFW_WNDCLASSNAME,                                            wideTitle,                                            style,-                                           xpos, ypos,-                                           fullWidth, fullHeight,+                                           frameX, frameY,+                                           frameWidth, frameHeight,                                            NULL, // No parent window                                            NULL, // No window menu-                                           GetModuleHandleW(NULL),-                                           NULL);+                                           _glfw.win32.instance,+                                           (LPVOID) wndconfig);      free(wideTitle); @@ -1254,24 +1341,29 @@      window->win32.scaleToMonitor = wndconfig->scaleToMonitor; -    // Adjust window rect to account for DPI scaling of the window frame and-    // (if enabled) DPI scaling of the content area-    // This cannot be done until we know what monitor the window was placed on     if (!window->monitor)     {         RECT rect = { 0, 0, wndconfig->width, wndconfig->height };         WINDOWPLACEMENT wp = { sizeof(wp) };+        const HMONITOR mh = MonitorFromWindow(window->win32.handle,+                                              MONITOR_DEFAULTTONEAREST); +        // Adjust window rect to account for DPI scaling of the window frame and+        // (if enabled) DPI scaling of the content area+        // This cannot be done until we know what monitor the window was placed on+        // Only update the restored window rect as the window may be maximized+         if (wndconfig->scaleToMonitor)         {             float xscale, yscale;-            _glfwPlatformGetWindowContentScale(window, &xscale, &yscale);-            rect.right = (int) (rect.right * xscale);-            rect.bottom = (int) (rect.bottom * yscale);-        }+            _glfwGetMonitorContentScaleWin32(mh, &xscale, &yscale); -        ClientToScreen(window->win32.handle, (POINT*) &rect.left);-        ClientToScreen(window->win32.handle, (POINT*) &rect.right);+            if (xscale > 0.f && yscale > 0.f)+            {+                rect.right = (int) (rect.right * xscale);+                rect.bottom = (int) (rect.bottom * yscale);+            }+        }          if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())         {@@ -1281,11 +1373,30 @@         else             AdjustWindowRectEx(&rect, style, FALSE, exStyle); -        // Only update the restored window rect as the window may be maximized         GetWindowPlacement(window->win32.handle, &wp);+        OffsetRect(&rect,+                   wp.rcNormalPosition.left - rect.left,+                   wp.rcNormalPosition.top - rect.top);+         wp.rcNormalPosition = rect;         wp.showCmd = SW_HIDE;         SetWindowPlacement(window->win32.handle, &wp);++        // Adjust rect of maximized undecorated window, because by default Windows will+        // make such a window cover the whole monitor instead of its workarea++        if (wndconfig->maximized && !wndconfig->decorated)+        {+            MONITORINFO mi = { sizeof(mi) };+            GetMonitorInfoW(mh, &mi);++            SetWindowPos(window->win32.handle, HWND_TOP,+                         mi.rcWork.left,+                         mi.rcWork.top,+                         mi.rcWork.right - mi.rcWork.left,+                         mi.rcWork.bottom - mi.rcWork.top,+                         SWP_NOACTIVATE | SWP_NOZORDER);+        }     }      DragAcceptFiles(window->win32.handle, TRUE);@@ -1296,6 +1407,8 @@         window->win32.transparent = GLFW_TRUE;     } +    _glfwPlatformGetWindowSize(window, &window->win32.width, &window->win32.height);+     return GLFW_TRUE; } @@ -1313,8 +1426,8 @@     ZeroMemory(&wc, sizeof(wc));     wc.cbSize        = sizeof(wc);     wc.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;-    wc.lpfnWndProc   = (WNDPROC) windowProc;-    wc.hInstance     = GetModuleHandleW(NULL);+    wc.lpfnWndProc   = windowProc;+    wc.hInstance     = _glfw.win32.instance;     wc.hCursor       = LoadCursorW(NULL, IDC_ARROW);     wc.lpszClassName = _GLFW_WNDCLASSNAME; @@ -1344,7 +1457,7 @@ // void _glfwUnregisterWindowClassWin32(void) {-    UnregisterClassW(_GLFW_WNDCLASSNAME, GetModuleHandleW(NULL));+    UnregisterClassW(_GLFW_WNDCLASSNAME, _glfw.win32.instance); }  @@ -1383,6 +1496,9 @@             if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))                 return GLFW_FALSE;         }++        if (!_glfwRefreshContextAttribs(window, ctxconfig))+            return GLFW_FALSE;     }      if (window->monitor)@@ -1391,7 +1507,19 @@         _glfwPlatformFocusWindow(window);         acquireMonitor(window);         fitToMonitor(window);++        if (wndconfig->centerCursor)+            _glfwCenterCursorInContentArea(window);     }+    else+    {+        if (wndconfig->visible)+        {+            _glfwPlatformShowWindow(window);+            if (wndconfig->focused)+                _glfwPlatformFocusWindow(window);+        }+    }      return GLFW_TRUE; }@@ -1405,8 +1533,11 @@         window->context.destroy(window);      if (_glfw.win32.disabledCursorWindow == window)-        _glfw.win32.disabledCursorWindow = NULL;+        enableCursor(window); +    if (_glfw.win32.capturedCursorWindow == window)+        releaseCursor();+     if (window->win32.handle)     {         RemovePropW(window->win32.handle, L"GLFW");@@ -1454,8 +1585,8 @@         smallIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICONSM);     } -    SendMessage(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon);-    SendMessage(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon);+    SendMessageW(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon);+    SendMessageW(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon);      if (window->win32.bigIcon)         DestroyIcon(window->win32.bigIcon);@@ -1635,7 +1766,10 @@  void _glfwPlatformMaximizeWindow(_GLFWwindow* window) {-    ShowWindow(window->win32.handle, SW_MAXIMIZE);+    if (IsWindowVisible(window->win32.handle))+        ShowWindow(window->win32.handle, SW_MAXIMIZE);+    else+        maximizeWindowManually(window); }  void _glfwPlatformShowWindow(_GLFWwindow* window)@@ -1722,7 +1856,7 @@          acquireMonitor(window); -        GetMonitorInfo(window->monitor->win32.handle, &mi);+        GetMonitorInfoW(window->monitor->win32.handle, &mi);         SetWindowPos(window->win32.handle, HWND_TOPMOST,                      mi.rcMonitor.left,                      mi.rcMonitor.top,@@ -1797,7 +1931,8 @@  int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) {-    BOOL enabled;+    BOOL composition, opaque;+    DWORD color;      if (!window->win32.transparent)         return GLFW_FALSE;@@ -1805,7 +1940,20 @@     if (!IsWindowsVistaOrGreater())         return GLFW_FALSE; -    return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled;+    if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition)+        return GLFW_FALSE;++    if (!IsWindows8OrGreater())+    {+        // HACK: Disable framebuffer transparency on Windows 7 when the+        //       colorization color is opaque, because otherwise the window+        //       contents is blended additively with the previous frame instead+        //       of replacing it+        if (FAILED(DwmGetColorizationColor(&color, &opaque)) || opaque)+            return GLFW_FALSE;+    }++    return GLFW_TRUE; }  void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)@@ -1965,14 +2113,14 @@  void _glfwPlatformWaitEventsTimeout(double timeout) {-    MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeout * 1e3), QS_ALLEVENTS);+    MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeout * 1e3), QS_ALLINPUT);      _glfwPlatformPollEvents(); }  void _glfwPlatformPostEmptyEvent(void) {-    PostMessage(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0);+    PostMessageW(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0); }  void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)@@ -2004,14 +2152,40 @@  void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) {-    if (mode == GLFW_CURSOR_DISABLED)+    if (_glfwPlatformWindowFocused(window))     {-        if (_glfwPlatformWindowFocused(window))-            disableCursor(window);+        if (mode == GLFW_CURSOR_DISABLED)+        {+            _glfwPlatformGetCursorPos(window,+                                      &_glfw.win32.restoreCursorPosX,+                                      &_glfw.win32.restoreCursorPosY);+            _glfwCenterCursorInContentArea(window);+            if (window->rawMouseMotion)+                enableRawMouseMotion(window);+        }+        else if (_glfw.win32.disabledCursorWindow == window)+        {+            if (window->rawMouseMotion)+                disableRawMouseMotion(window);+        }++        if (mode == GLFW_CURSOR_DISABLED)+            captureCursor(window);+        else+            releaseCursor();++        if (mode == GLFW_CURSOR_DISABLED)+            _glfw.win32.disabledCursorWindow = window;+        else if (_glfw.win32.disabledCursorWindow == window)+        {+            _glfw.win32.disabledCursorWindow = NULL;+            _glfwPlatformSetCursorPos(window,+                                      _glfw.win32.restoreCursorPosX,+                                      _glfw.win32.restoreCursorPosY);+        }     }-    else if (_glfw.win32.disabledCursorWindow == window)-        enableCursor(window);-    else if (cursorInContentArea(window))++    if (cursorInContentArea(window))         updateCursorImage(window); } @@ -2020,7 +2194,7 @@     if (scancode < 0 || scancode > (KF_EXTENDED | 0xff) ||         _glfw.win32.keycodes[scancode] == GLFW_KEY_UNKNOWN)     {-        _glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode");+        _glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode %i", scancode);         return NULL;     } @@ -2216,7 +2390,7 @@      memset(&sci, 0, sizeof(sci));     sci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;-    sci.hinstance = GetModuleHandle(NULL);+    sci.hinstance = _glfw.win32.instance;     sci.hwnd = window->win32.handle;      err = vkCreateWin32SurfaceKHR(instance, &sci, allocator, surface);
glfw/src/window.c view
@@ -205,6 +205,8 @@     window->focusOnShow = wndconfig.focusOnShow;     window->cursorMode  = GLFW_CURSOR_NORMAL; +    window->doublebuffer = fbconfig.doublebuffer;+     window->minwidth    = GLFW_DONT_CARE;     window->minheight   = GLFW_DONT_CARE;     window->maxwidth    = GLFW_DONT_CARE;@@ -219,30 +221,6 @@         return NULL;     } -    if (ctxconfig.client != GLFW_NO_API)-    {-        if (!_glfwRefreshContextAttribs(window, &ctxconfig))-        {-            glfwDestroyWindow((GLFWwindow*) window);-            return NULL;-        }-    }--    if (window->monitor)-    {-        if (wndconfig.centerCursor)-            _glfwCenterCursorInContentArea(window);-    }-    else-    {-        if (wndconfig.visible)-        {-            _glfwPlatformShowWindow(window);-            if (wndconfig.focused)-                _glfwPlatformFocusWindow(window);-        }-    }-     return (GLFWwindow*) window; } @@ -502,12 +480,33 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle,                                int count, const GLFWimage* images) {+    int i;     _GLFWwindow* window = (_GLFWwindow*) handle;+     assert(window != NULL);     assert(count >= 0);     assert(count == 0 || images != NULL);      _GLFW_REQUIRE_INIT();++    if (count < 0)+    {+        _glfwInputError(GLFW_INVALID_VALUE, "Invalid image count for window icon");+        return;+    }++    for (i = 0; i < count; i++)+    {+        assert(images[i].pixels != NULL);++        if (images[i].width <= 0 || images[i].height <= 0)+        {+            _glfwInputError(GLFW_INVALID_VALUE,+                            "Invalid image dimensions for window icon");+            return;+        }+    }+     _glfwPlatformSetWindowIcon(window, count, images); } @@ -1099,3 +1098,4 @@     _GLFW_REQUIRE_INIT();     _glfwPlatformPostEmptyEvent(); }+
glfw/src/wl_init.c view
@@ -26,1286 +26,713 @@ // It is fine to use C99 in this file because it will not be built with VS //======================================================================== -#include "internal.h"--#include <assert.h>-#include <errno.h>-#include <limits.h>-#include <linux/input.h>-#include <stdio.h>-#include <stdlib.h>-#include <string.h>-#include <sys/mman.h>-#include <sys/timerfd.h>-#include <unistd.h>-#include <wayland-client.h>---static inline int min(int n1, int n2)-{-    return n1 < n2 ? n1 : n2;-}--static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface,-                                                    int* which)-{-    int focus;-    _GLFWwindow* window = _glfw.windowListHead;-    if (!which)-        which = &focus;-    while (window)-    {-        if (surface == window->wl.decorations.top.surface)-        {-            *which = topDecoration;-            break;-        }-        if (surface == window->wl.decorations.left.surface)-        {-            *which = leftDecoration;-            break;-        }-        if (surface == window->wl.decorations.right.surface)-        {-            *which = rightDecoration;-            break;-        }-        if (surface == window->wl.decorations.bottom.surface)-        {-            *which = bottomDecoration;-            break;-        }-        window = window->next;-    }-    return window;-}--static void pointerHandleEnter(void* data,-                               struct wl_pointer* pointer,-                               uint32_t serial,-                               struct wl_surface* surface,-                               wl_fixed_t sx,-                               wl_fixed_t sy)-{-    // Happens in the case we just destroyed the surface.-    if (!surface)-        return;--    int focus = 0;-    _GLFWwindow* window = wl_surface_get_user_data(surface);-    if (!window)-    {-        window = findWindowFromDecorationSurface(surface, &focus);-        if (!window)-            return;-    }--    window->wl.decorations.focus = focus;-    _glfw.wl.serial = serial;-    _glfw.wl.pointerFocus = window;--    window->wl.hovered = GLFW_TRUE;--    _glfwPlatformSetCursor(window, window->wl.currentCursor);-    _glfwInputCursorEnter(window, GLFW_TRUE);-}--static void pointerHandleLeave(void* data,-                               struct wl_pointer* pointer,-                               uint32_t serial,-                               struct wl_surface* surface)-{-    _GLFWwindow* window = _glfw.wl.pointerFocus;--    if (!window)-        return;--    window->wl.hovered = GLFW_FALSE;--    _glfw.wl.serial = serial;-    _glfw.wl.pointerFocus = NULL;-    _glfwInputCursorEnter(window, GLFW_FALSE);-    _glfw.wl.cursorPreviousName = NULL;-}--static void setCursor(_GLFWwindow* window, const char* name)-{-    struct wl_buffer* buffer;-    struct wl_cursor* cursor;-    struct wl_cursor_image* image;-    struct wl_surface* surface = _glfw.wl.cursorSurface;-    struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;-    int scale = 1;--    if (window->wl.scale > 1 && _glfw.wl.cursorThemeHiDPI)-    {-        // We only support up to scale=2 for now, since libwayland-cursor-        // requires us to load a different theme for each size.-        scale = 2;-        theme = _glfw.wl.cursorThemeHiDPI;-    }--    cursor = wl_cursor_theme_get_cursor(theme, name);-    if (!cursor)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Standard cursor not found");-        return;-    }-    // TODO: handle animated cursors too.-    image = cursor->images[0];--    if (!image)-        return;--    buffer = wl_cursor_image_get_buffer(image);-    if (!buffer)-        return;-    wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,-                          surface,-                          image->hotspot_x / scale,-                          image->hotspot_y / scale);-    wl_surface_set_buffer_scale(surface, scale);-    wl_surface_attach(surface, buffer, 0, 0);-    wl_surface_damage(surface, 0, 0,-                      image->width, image->height);-    wl_surface_commit(surface);-    _glfw.wl.cursorPreviousName = name;-}--static void pointerHandleMotion(void* data,-                                struct wl_pointer* pointer,-                                uint32_t time,-                                wl_fixed_t sx,-                                wl_fixed_t sy)-{-    _GLFWwindow* window = _glfw.wl.pointerFocus;-    const char* cursorName = NULL;-    double x, y;--    if (!window)-        return;--    if (window->cursorMode == GLFW_CURSOR_DISABLED)-        return;-    x = wl_fixed_to_double(sx);-    y = wl_fixed_to_double(sy);--    switch (window->wl.decorations.focus)-    {-        case mainWindow:-            window->wl.cursorPosX = x;-            window->wl.cursorPosY = y;-            _glfwInputCursorPos(window, x, y);-            _glfw.wl.cursorPreviousName = NULL;-            return;-        case topDecoration:-            if (y < _GLFW_DECORATION_WIDTH)-                cursorName = "n-resize";-            else-                cursorName = "left_ptr";-            break;-        case leftDecoration:-            if (y < _GLFW_DECORATION_WIDTH)-                cursorName = "nw-resize";-            else-                cursorName = "w-resize";-            break;-        case rightDecoration:-            if (y < _GLFW_DECORATION_WIDTH)-                cursorName = "ne-resize";-            else-                cursorName = "e-resize";-            break;-        case bottomDecoration:-            if (x < _GLFW_DECORATION_WIDTH)-                cursorName = "sw-resize";-            else if (x > window->wl.width + _GLFW_DECORATION_WIDTH)-                cursorName = "se-resize";-            else-                cursorName = "s-resize";-            break;-        default:-            assert(0);-    }-    if (_glfw.wl.cursorPreviousName != cursorName)-        setCursor(window, cursorName);-}--static void pointerHandleButton(void* data,-                                struct wl_pointer* pointer,-                                uint32_t serial,-                                uint32_t time,-                                uint32_t button,-                                uint32_t state)-{-    _GLFWwindow* window = _glfw.wl.pointerFocus;-    int glfwButton;--    // Both xdg-shell and wl_shell use the same values.-    uint32_t edges = WL_SHELL_SURFACE_RESIZE_NONE;--    if (!window)-        return;-    if (button == BTN_LEFT)-    {-        switch (window->wl.decorations.focus)-        {-            case mainWindow:-                break;-            case topDecoration:-                if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)-                    edges = WL_SHELL_SURFACE_RESIZE_TOP;-                else-                {-                    if (window->wl.xdg.toplevel)-                        xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);-                    else-                        wl_shell_surface_move(window->wl.shellSurface, _glfw.wl.seat, serial);-                }-                break;-            case leftDecoration:-                if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)-                    edges = WL_SHELL_SURFACE_RESIZE_TOP_LEFT;-                else-                    edges = WL_SHELL_SURFACE_RESIZE_LEFT;-                break;-            case rightDecoration:-                if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)-                    edges = WL_SHELL_SURFACE_RESIZE_TOP_RIGHT;-                else-                    edges = WL_SHELL_SURFACE_RESIZE_RIGHT;-                break;-            case bottomDecoration:-                if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH)-                    edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT;-                else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH)-                    edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT;-                else-                    edges = WL_SHELL_SURFACE_RESIZE_BOTTOM;-                break;-            default:-                assert(0);-        }-        if (edges != WL_SHELL_SURFACE_RESIZE_NONE)-        {-            if (window->wl.xdg.toplevel)-                xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat,-                                    serial, edges);-            else-                wl_shell_surface_resize(window->wl.shellSurface, _glfw.wl.seat,-                                        serial, edges);-        }-    }-    else if (button == BTN_RIGHT)-    {-        if (window->wl.decorations.focus != mainWindow && window->wl.xdg.toplevel)-        {-            xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,-                                          _glfw.wl.seat, serial,-                                          window->wl.cursorPosX,-                                          window->wl.cursorPosY);-            return;-        }-    }--    // Don’t pass the button to the user if it was related to a decoration.-    if (window->wl.decorations.focus != mainWindow)-        return;--    _glfw.wl.serial = serial;--    /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev-     * codes. */-    glfwButton = button - BTN_LEFT;--    _glfwInputMouseClick(window,-                         glfwButton,-                         state == WL_POINTER_BUTTON_STATE_PRESSED-                                ? GLFW_PRESS-                                : GLFW_RELEASE,-                         _glfw.wl.xkb.modifiers);-}--static void pointerHandleAxis(void* data,-                              struct wl_pointer* pointer,-                              uint32_t time,-                              uint32_t axis,-                              wl_fixed_t value)-{-    _GLFWwindow* window = _glfw.wl.pointerFocus;-    double x = 0.0, y = 0.0;-    // Wayland scroll events are in pointer motion coordinate space (think two-    // finger scroll).  The factor 10 is commonly used to convert to "scroll-    // step means 1.0.-    const double scrollFactor = 1.0 / 10.0;--    if (!window)-        return;--    assert(axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL ||-           axis == WL_POINTER_AXIS_VERTICAL_SCROLL);--    if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)-        x = wl_fixed_to_double(value) * scrollFactor;-    else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)-        y = wl_fixed_to_double(value) * scrollFactor;--    _glfwInputScroll(window, x, y);-}--static const struct wl_pointer_listener pointerListener = {-    pointerHandleEnter,-    pointerHandleLeave,-    pointerHandleMotion,-    pointerHandleButton,-    pointerHandleAxis,-};--static void keyboardHandleKeymap(void* data,-                                 struct wl_keyboard* keyboard,-                                 uint32_t format,-                                 int fd,-                                 uint32_t size)-{-    struct xkb_keymap* keymap;-    struct xkb_state* state;--#ifdef HAVE_XKBCOMMON_COMPOSE_H-    struct xkb_compose_table* composeTable;-    struct xkb_compose_state* composeState;-#endif--    char* mapStr;-    const char* locale;--    if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)-    {-        close(fd);-        return;-    }--    mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);-    if (mapStr == MAP_FAILED) {-        close(fd);-        return;-    }--    keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context,-                                        mapStr,-                                        XKB_KEYMAP_FORMAT_TEXT_V1,-                                        0);-    munmap(mapStr, size);-    close(fd);--    if (!keymap)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Failed to compile keymap");-        return;-    }--    state = xkb_state_new(keymap);-    if (!state)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Failed to create XKB state");-        xkb_keymap_unref(keymap);-        return;-    }--    // Look up the preferred locale, falling back to "C" as default.-    locale = getenv("LC_ALL");-    if (!locale)-        locale = getenv("LC_CTYPE");-    if (!locale)-        locale = getenv("LANG");-    if (!locale)-        locale = "C";--#ifdef HAVE_XKBCOMMON_COMPOSE_H-    composeTable =-        xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,-                                          XKB_COMPOSE_COMPILE_NO_FLAGS);-    if (composeTable)-    {-        composeState =-            xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS);-        xkb_compose_table_unref(composeTable);-        if (composeState)-            _glfw.wl.xkb.composeState = composeState;-        else-            _glfwInputError(GLFW_PLATFORM_ERROR,-                            "Wayland: Failed to create XKB compose state");-    }-    else-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Failed to create XKB compose table");-    }-#endif--    xkb_keymap_unref(_glfw.wl.xkb.keymap);-    xkb_state_unref(_glfw.wl.xkb.state);-    _glfw.wl.xkb.keymap = keymap;-    _glfw.wl.xkb.state = state;--    _glfw.wl.xkb.controlMask =-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control");-    _glfw.wl.xkb.altMask =-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");-    _glfw.wl.xkb.shiftMask =-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift");-    _glfw.wl.xkb.superMask =-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");-    _glfw.wl.xkb.capsLockMask =-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Lock");-    _glfw.wl.xkb.numLockMask =-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod2");-}--static void keyboardHandleEnter(void* data,-                                struct wl_keyboard* keyboard,-                                uint32_t serial,-                                struct wl_surface* surface,-                                struct wl_array* keys)-{-    // Happens in the case we just destroyed the surface.-    if (!surface)-        return;--    _GLFWwindow* window = wl_surface_get_user_data(surface);-    if (!window)-    {-        window = findWindowFromDecorationSurface(surface, NULL);-        if (!window)-            return;-    }--    _glfw.wl.serial = serial;-    _glfw.wl.keyboardFocus = window;-    _glfwInputWindowFocus(window, GLFW_TRUE);-}--static void keyboardHandleLeave(void* data,-                                struct wl_keyboard* keyboard,-                                uint32_t serial,-                                struct wl_surface* surface)-{-    _GLFWwindow* window = _glfw.wl.keyboardFocus;--    if (!window)-        return;--    _glfw.wl.serial = serial;-    _glfw.wl.keyboardFocus = NULL;-    _glfwInputWindowFocus(window, GLFW_FALSE);-}--static int toGLFWKeyCode(uint32_t key)-{-    if (key < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))-        return _glfw.wl.keycodes[key];--    return GLFW_KEY_UNKNOWN;-}--#ifdef HAVE_XKBCOMMON_COMPOSE_H-static xkb_keysym_t composeSymbol(xkb_keysym_t sym)-{-    if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)-        return sym;-    if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym)-            != XKB_COMPOSE_FEED_ACCEPTED)-        return sym;-    switch (xkb_compose_state_get_status(_glfw.wl.xkb.composeState))-    {-        case XKB_COMPOSE_COMPOSED:-            return xkb_compose_state_get_one_sym(_glfw.wl.xkb.composeState);-        case XKB_COMPOSE_COMPOSING:-        case XKB_COMPOSE_CANCELLED:-            return XKB_KEY_NoSymbol;-        case XKB_COMPOSE_NOTHING:-        default:-            return sym;-    }-}-#endif--static GLFWbool inputChar(_GLFWwindow* window, uint32_t key)-{-    uint32_t code, numSyms;-    long cp;-    const xkb_keysym_t *syms;-    xkb_keysym_t sym;--    code = key + 8;-    numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms);--    if (numSyms == 1)-    {-#ifdef HAVE_XKBCOMMON_COMPOSE_H-        sym = composeSymbol(syms[0]);-#else-        sym = syms[0];-#endif-        cp = _glfwKeySym2Unicode(sym);-        if (cp != -1)-        {-            const int mods = _glfw.wl.xkb.modifiers;-            const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));-            _glfwInputChar(window, cp, mods, plain);-        }-    }--    return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, syms[0]);-}--static void keyboardHandleKey(void* data,-                              struct wl_keyboard* keyboard,-                              uint32_t serial,-                              uint32_t time,-                              uint32_t key,-                              uint32_t state)-{-    int keyCode;-    int action;-    _GLFWwindow* window = _glfw.wl.keyboardFocus;-    GLFWbool shouldRepeat;-    struct itimerspec timer = {};--    if (!window)-        return;--    keyCode = toGLFWKeyCode(key);-    action = state == WL_KEYBOARD_KEY_STATE_PRESSED-            ? GLFW_PRESS : GLFW_RELEASE;--    _glfw.wl.serial = serial;-    _glfwInputKey(window, keyCode, key, action,-                  _glfw.wl.xkb.modifiers);--    if (action == GLFW_PRESS)-    {-        shouldRepeat = inputChar(window, key);--        if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0)-        {-            _glfw.wl.keyboardLastKey = keyCode;-            _glfw.wl.keyboardLastScancode = key;-            if (_glfw.wl.keyboardRepeatRate > 1)-                timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyboardRepeatRate;-            else-                timer.it_interval.tv_sec = 1;-            timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000;-            timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000;-        }-    }-    timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);-}--static void keyboardHandleModifiers(void* data,-                                    struct wl_keyboard* keyboard,-                                    uint32_t serial,-                                    uint32_t modsDepressed,-                                    uint32_t modsLatched,-                                    uint32_t modsLocked,-                                    uint32_t group)-{-    xkb_mod_mask_t mask;-    unsigned int modifiers = 0;--    _glfw.wl.serial = serial;--    if (!_glfw.wl.xkb.keymap)-        return;--    xkb_state_update_mask(_glfw.wl.xkb.state,-                          modsDepressed,-                          modsLatched,-                          modsLocked,-                          0,-                          0,-                          group);--    mask = xkb_state_serialize_mods(_glfw.wl.xkb.state,-                                    XKB_STATE_MODS_DEPRESSED |-                                    XKB_STATE_LAYOUT_DEPRESSED |-                                    XKB_STATE_MODS_LATCHED |-                                    XKB_STATE_LAYOUT_LATCHED);-    if (mask & _glfw.wl.xkb.controlMask)-        modifiers |= GLFW_MOD_CONTROL;-    if (mask & _glfw.wl.xkb.altMask)-        modifiers |= GLFW_MOD_ALT;-    if (mask & _glfw.wl.xkb.shiftMask)-        modifiers |= GLFW_MOD_SHIFT;-    if (mask & _glfw.wl.xkb.superMask)-        modifiers |= GLFW_MOD_SUPER;-    if (mask & _glfw.wl.xkb.capsLockMask)-        modifiers |= GLFW_MOD_CAPS_LOCK;-    if (mask & _glfw.wl.xkb.numLockMask)-        modifiers |= GLFW_MOD_NUM_LOCK;-    _glfw.wl.xkb.modifiers = modifiers;-}--#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION-static void keyboardHandleRepeatInfo(void* data,-                                     struct wl_keyboard* keyboard,-                                     int32_t rate,-                                     int32_t delay)-{-    if (keyboard != _glfw.wl.keyboard)-        return;--    _glfw.wl.keyboardRepeatRate = rate;-    _glfw.wl.keyboardRepeatDelay = delay;-}-#endif--static const struct wl_keyboard_listener keyboardListener = {-    keyboardHandleKeymap,-    keyboardHandleEnter,-    keyboardHandleLeave,-    keyboardHandleKey,-    keyboardHandleModifiers,-#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION-    keyboardHandleRepeatInfo,-#endif-};--static void seatHandleCapabilities(void* data,-                                   struct wl_seat* seat,-                                   enum wl_seat_capability caps)-{-    if ((caps & WL_SEAT_CAPABILITY_POINTER) && !_glfw.wl.pointer)-    {-        _glfw.wl.pointer = wl_seat_get_pointer(seat);-        wl_pointer_add_listener(_glfw.wl.pointer, &pointerListener, NULL);-    }-    else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && _glfw.wl.pointer)-    {-        wl_pointer_destroy(_glfw.wl.pointer);-        _glfw.wl.pointer = NULL;-    }--    if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !_glfw.wl.keyboard)-    {-        _glfw.wl.keyboard = wl_seat_get_keyboard(seat);-        wl_keyboard_add_listener(_glfw.wl.keyboard, &keyboardListener, NULL);-    }-    else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && _glfw.wl.keyboard)-    {-        wl_keyboard_destroy(_glfw.wl.keyboard);-        _glfw.wl.keyboard = NULL;-    }-}--static void seatHandleName(void* data,-                           struct wl_seat* seat,-                           const char* name)-{-}--static const struct wl_seat_listener seatListener = {-    seatHandleCapabilities,-    seatHandleName,-};--static void dataOfferHandleOffer(void* data,-                                 struct wl_data_offer* dataOffer,-                                 const char* mimeType)-{-}--static const struct wl_data_offer_listener dataOfferListener = {-    dataOfferHandleOffer,-};--static void dataDeviceHandleDataOffer(void* data,-                                      struct wl_data_device* dataDevice,-                                      struct wl_data_offer* id)-{-    if (_glfw.wl.dataOffer)-        wl_data_offer_destroy(_glfw.wl.dataOffer);--    _glfw.wl.dataOffer = id;-    wl_data_offer_add_listener(_glfw.wl.dataOffer, &dataOfferListener, NULL);-}--static void dataDeviceHandleEnter(void* data,-                                  struct wl_data_device* dataDevice,-                                  uint32_t serial,-                                  struct wl_surface *surface,-                                  wl_fixed_t x,-                                  wl_fixed_t y,-                                  struct wl_data_offer *id)-{-}--static void dataDeviceHandleLeave(void* data,-                                  struct wl_data_device* dataDevice)-{-}--static void dataDeviceHandleMotion(void* data,-                                   struct wl_data_device* dataDevice,-                                   uint32_t time,-                                   wl_fixed_t x,-                                   wl_fixed_t y)-{-}--static void dataDeviceHandleDrop(void* data,-                                 struct wl_data_device* dataDevice)-{-}--static void dataDeviceHandleSelection(void* data,-                                      struct wl_data_device* dataDevice,-                                      struct wl_data_offer* id)-{-}--static const struct wl_data_device_listener dataDeviceListener = {-    dataDeviceHandleDataOffer,-    dataDeviceHandleEnter,-    dataDeviceHandleLeave,-    dataDeviceHandleMotion,-    dataDeviceHandleDrop,-    dataDeviceHandleSelection,-};--static void wmBaseHandlePing(void* data,-                             struct xdg_wm_base* wmBase,-                             uint32_t serial)-{-    xdg_wm_base_pong(wmBase, serial);-}--static const struct xdg_wm_base_listener wmBaseListener = {-    wmBaseHandlePing-};--static void registryHandleGlobal(void* data,-                                 struct wl_registry* registry,-                                 uint32_t name,-                                 const char* interface,-                                 uint32_t version)-{-    if (strcmp(interface, "wl_compositor") == 0)-    {-        _glfw.wl.compositorVersion = min(3, version);-        _glfw.wl.compositor =-            wl_registry_bind(registry, name, &wl_compositor_interface,-                             _glfw.wl.compositorVersion);-    }-    else if (strcmp(interface, "wl_subcompositor") == 0)-    {-        _glfw.wl.subcompositor =-            wl_registry_bind(registry, name, &wl_subcompositor_interface, 1);-    }-    else if (strcmp(interface, "wl_shm") == 0)-    {-        _glfw.wl.shm =-            wl_registry_bind(registry, name, &wl_shm_interface, 1);-    }-    else if (strcmp(interface, "wl_shell") == 0)-    {-        _glfw.wl.shell =-            wl_registry_bind(registry, name, &wl_shell_interface, 1);-    }-    else if (strcmp(interface, "wl_output") == 0)-    {-        _glfwAddOutputWayland(name, version);-    }-    else if (strcmp(interface, "wl_seat") == 0)-    {-        if (!_glfw.wl.seat)-        {-            _glfw.wl.seatVersion = min(4, version);-            _glfw.wl.seat =-                wl_registry_bind(registry, name, &wl_seat_interface,-                                 _glfw.wl.seatVersion);-            wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL);-        }-    }-    else if (strcmp(interface, "wl_data_device_manager") == 0)-    {-        if (!_glfw.wl.dataDeviceManager)-        {-            _glfw.wl.dataDeviceManager =-                wl_registry_bind(registry, name,-                                 &wl_data_device_manager_interface, 1);-        }-    }-    else if (strcmp(interface, "xdg_wm_base") == 0)-    {-        _glfw.wl.wmBase =-            wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);-        xdg_wm_base_add_listener(_glfw.wl.wmBase, &wmBaseListener, NULL);-    }-    else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0)-    {-        _glfw.wl.decorationManager =-            wl_registry_bind(registry, name,-                             &zxdg_decoration_manager_v1_interface,-                             1);-    }-    else if (strcmp(interface, "wp_viewporter") == 0)-    {-        _glfw.wl.viewporter =-            wl_registry_bind(registry, name, &wp_viewporter_interface, 1);-    }-    else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0)-    {-        _glfw.wl.relativePointerManager =-            wl_registry_bind(registry, name,-                             &zwp_relative_pointer_manager_v1_interface,-                             1);-    }-    else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0)-    {-        _glfw.wl.pointerConstraints =-            wl_registry_bind(registry, name,-                             &zwp_pointer_constraints_v1_interface,-                             1);-    }-    else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0)-    {-        _glfw.wl.idleInhibitManager =-            wl_registry_bind(registry, name,-                             &zwp_idle_inhibit_manager_v1_interface,-                             1);-    }-}--static void registryHandleGlobalRemove(void *data,-                                       struct wl_registry *registry,-                                       uint32_t name)-{-    int i;-    _GLFWmonitor* monitor;--    for (i = 0; i < _glfw.monitorCount; ++i)-    {-        monitor = _glfw.monitors[i];-        if (monitor->wl.name == name)-        {-            _glfwInputMonitor(monitor, GLFW_DISCONNECTED, 0);-            return;-        }-    }-}---static const struct wl_registry_listener registryListener = {-    registryHandleGlobal,-    registryHandleGlobalRemove-};--// Create key code translation tables-//-static void createKeyTables(void)-{-    int scancode;--    memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes));-    memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes));--    _glfw.wl.keycodes[KEY_GRAVE]      = GLFW_KEY_GRAVE_ACCENT;-    _glfw.wl.keycodes[KEY_1]          = GLFW_KEY_1;-    _glfw.wl.keycodes[KEY_2]          = GLFW_KEY_2;-    _glfw.wl.keycodes[KEY_3]          = GLFW_KEY_3;-    _glfw.wl.keycodes[KEY_4]          = GLFW_KEY_4;-    _glfw.wl.keycodes[KEY_5]          = GLFW_KEY_5;-    _glfw.wl.keycodes[KEY_6]          = GLFW_KEY_6;-    _glfw.wl.keycodes[KEY_7]          = GLFW_KEY_7;-    _glfw.wl.keycodes[KEY_8]          = GLFW_KEY_8;-    _glfw.wl.keycodes[KEY_9]          = GLFW_KEY_9;-    _glfw.wl.keycodes[KEY_0]          = GLFW_KEY_0;-    _glfw.wl.keycodes[KEY_SPACE]      = GLFW_KEY_SPACE;-    _glfw.wl.keycodes[KEY_MINUS]      = GLFW_KEY_MINUS;-    _glfw.wl.keycodes[KEY_EQUAL]      = GLFW_KEY_EQUAL;-    _glfw.wl.keycodes[KEY_Q]          = GLFW_KEY_Q;-    _glfw.wl.keycodes[KEY_W]          = GLFW_KEY_W;-    _glfw.wl.keycodes[KEY_E]          = GLFW_KEY_E;-    _glfw.wl.keycodes[KEY_R]          = GLFW_KEY_R;-    _glfw.wl.keycodes[KEY_T]          = GLFW_KEY_T;-    _glfw.wl.keycodes[KEY_Y]          = GLFW_KEY_Y;-    _glfw.wl.keycodes[KEY_U]          = GLFW_KEY_U;-    _glfw.wl.keycodes[KEY_I]          = GLFW_KEY_I;-    _glfw.wl.keycodes[KEY_O]          = GLFW_KEY_O;-    _glfw.wl.keycodes[KEY_P]          = GLFW_KEY_P;-    _glfw.wl.keycodes[KEY_LEFTBRACE]  = GLFW_KEY_LEFT_BRACKET;-    _glfw.wl.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;-    _glfw.wl.keycodes[KEY_A]          = GLFW_KEY_A;-    _glfw.wl.keycodes[KEY_S]          = GLFW_KEY_S;-    _glfw.wl.keycodes[KEY_D]          = GLFW_KEY_D;-    _glfw.wl.keycodes[KEY_F]          = GLFW_KEY_F;-    _glfw.wl.keycodes[KEY_G]          = GLFW_KEY_G;-    _glfw.wl.keycodes[KEY_H]          = GLFW_KEY_H;-    _glfw.wl.keycodes[KEY_J]          = GLFW_KEY_J;-    _glfw.wl.keycodes[KEY_K]          = GLFW_KEY_K;-    _glfw.wl.keycodes[KEY_L]          = GLFW_KEY_L;-    _glfw.wl.keycodes[KEY_SEMICOLON]  = GLFW_KEY_SEMICOLON;-    _glfw.wl.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;-    _glfw.wl.keycodes[KEY_Z]          = GLFW_KEY_Z;-    _glfw.wl.keycodes[KEY_X]          = GLFW_KEY_X;-    _glfw.wl.keycodes[KEY_C]          = GLFW_KEY_C;-    _glfw.wl.keycodes[KEY_V]          = GLFW_KEY_V;-    _glfw.wl.keycodes[KEY_B]          = GLFW_KEY_B;-    _glfw.wl.keycodes[KEY_N]          = GLFW_KEY_N;-    _glfw.wl.keycodes[KEY_M]          = GLFW_KEY_M;-    _glfw.wl.keycodes[KEY_COMMA]      = GLFW_KEY_COMMA;-    _glfw.wl.keycodes[KEY_DOT]        = GLFW_KEY_PERIOD;-    _glfw.wl.keycodes[KEY_SLASH]      = GLFW_KEY_SLASH;-    _glfw.wl.keycodes[KEY_BACKSLASH]  = GLFW_KEY_BACKSLASH;-    _glfw.wl.keycodes[KEY_ESC]        = GLFW_KEY_ESCAPE;-    _glfw.wl.keycodes[KEY_TAB]        = GLFW_KEY_TAB;-    _glfw.wl.keycodes[KEY_LEFTSHIFT]  = GLFW_KEY_LEFT_SHIFT;-    _glfw.wl.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;-    _glfw.wl.keycodes[KEY_LEFTCTRL]   = GLFW_KEY_LEFT_CONTROL;-    _glfw.wl.keycodes[KEY_RIGHTCTRL]  = GLFW_KEY_RIGHT_CONTROL;-    _glfw.wl.keycodes[KEY_LEFTALT]    = GLFW_KEY_LEFT_ALT;-    _glfw.wl.keycodes[KEY_RIGHTALT]   = GLFW_KEY_RIGHT_ALT;-    _glfw.wl.keycodes[KEY_LEFTMETA]   = GLFW_KEY_LEFT_SUPER;-    _glfw.wl.keycodes[KEY_RIGHTMETA]  = GLFW_KEY_RIGHT_SUPER;-    _glfw.wl.keycodes[KEY_MENU]       = GLFW_KEY_MENU;-    _glfw.wl.keycodes[KEY_NUMLOCK]    = GLFW_KEY_NUM_LOCK;-    _glfw.wl.keycodes[KEY_CAPSLOCK]   = GLFW_KEY_CAPS_LOCK;-    _glfw.wl.keycodes[KEY_PRINT]      = GLFW_KEY_PRINT_SCREEN;-    _glfw.wl.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;-    _glfw.wl.keycodes[KEY_PAUSE]      = GLFW_KEY_PAUSE;-    _glfw.wl.keycodes[KEY_DELETE]     = GLFW_KEY_DELETE;-    _glfw.wl.keycodes[KEY_BACKSPACE]  = GLFW_KEY_BACKSPACE;-    _glfw.wl.keycodes[KEY_ENTER]      = GLFW_KEY_ENTER;-    _glfw.wl.keycodes[KEY_HOME]       = GLFW_KEY_HOME;-    _glfw.wl.keycodes[KEY_END]        = GLFW_KEY_END;-    _glfw.wl.keycodes[KEY_PAGEUP]     = GLFW_KEY_PAGE_UP;-    _glfw.wl.keycodes[KEY_PAGEDOWN]   = GLFW_KEY_PAGE_DOWN;-    _glfw.wl.keycodes[KEY_INSERT]     = GLFW_KEY_INSERT;-    _glfw.wl.keycodes[KEY_LEFT]       = GLFW_KEY_LEFT;-    _glfw.wl.keycodes[KEY_RIGHT]      = GLFW_KEY_RIGHT;-    _glfw.wl.keycodes[KEY_DOWN]       = GLFW_KEY_DOWN;-    _glfw.wl.keycodes[KEY_UP]         = GLFW_KEY_UP;-    _glfw.wl.keycodes[KEY_F1]         = GLFW_KEY_F1;-    _glfw.wl.keycodes[KEY_F2]         = GLFW_KEY_F2;-    _glfw.wl.keycodes[KEY_F3]         = GLFW_KEY_F3;-    _glfw.wl.keycodes[KEY_F4]         = GLFW_KEY_F4;-    _glfw.wl.keycodes[KEY_F5]         = GLFW_KEY_F5;-    _glfw.wl.keycodes[KEY_F6]         = GLFW_KEY_F6;-    _glfw.wl.keycodes[KEY_F7]         = GLFW_KEY_F7;-    _glfw.wl.keycodes[KEY_F8]         = GLFW_KEY_F8;-    _glfw.wl.keycodes[KEY_F9]         = GLFW_KEY_F9;-    _glfw.wl.keycodes[KEY_F10]        = GLFW_KEY_F10;-    _glfw.wl.keycodes[KEY_F11]        = GLFW_KEY_F11;-    _glfw.wl.keycodes[KEY_F12]        = GLFW_KEY_F12;-    _glfw.wl.keycodes[KEY_F13]        = GLFW_KEY_F13;-    _glfw.wl.keycodes[KEY_F14]        = GLFW_KEY_F14;-    _glfw.wl.keycodes[KEY_F15]        = GLFW_KEY_F15;-    _glfw.wl.keycodes[KEY_F16]        = GLFW_KEY_F16;-    _glfw.wl.keycodes[KEY_F17]        = GLFW_KEY_F17;-    _glfw.wl.keycodes[KEY_F18]        = GLFW_KEY_F18;-    _glfw.wl.keycodes[KEY_F19]        = GLFW_KEY_F19;-    _glfw.wl.keycodes[KEY_F20]        = GLFW_KEY_F20;-    _glfw.wl.keycodes[KEY_F21]        = GLFW_KEY_F21;-    _glfw.wl.keycodes[KEY_F22]        = GLFW_KEY_F22;-    _glfw.wl.keycodes[KEY_F23]        = GLFW_KEY_F23;-    _glfw.wl.keycodes[KEY_F24]        = GLFW_KEY_F24;-    _glfw.wl.keycodes[KEY_KPSLASH]    = GLFW_KEY_KP_DIVIDE;-    _glfw.wl.keycodes[KEY_KPDOT]      = GLFW_KEY_KP_MULTIPLY;-    _glfw.wl.keycodes[KEY_KPMINUS]    = GLFW_KEY_KP_SUBTRACT;-    _glfw.wl.keycodes[KEY_KPPLUS]     = GLFW_KEY_KP_ADD;-    _glfw.wl.keycodes[KEY_KP0]        = GLFW_KEY_KP_0;-    _glfw.wl.keycodes[KEY_KP1]        = GLFW_KEY_KP_1;-    _glfw.wl.keycodes[KEY_KP2]        = GLFW_KEY_KP_2;-    _glfw.wl.keycodes[KEY_KP3]        = GLFW_KEY_KP_3;-    _glfw.wl.keycodes[KEY_KP4]        = GLFW_KEY_KP_4;-    _glfw.wl.keycodes[KEY_KP5]        = GLFW_KEY_KP_5;-    _glfw.wl.keycodes[KEY_KP6]        = GLFW_KEY_KP_6;-    _glfw.wl.keycodes[KEY_KP7]        = GLFW_KEY_KP_7;-    _glfw.wl.keycodes[KEY_KP8]        = GLFW_KEY_KP_8;-    _glfw.wl.keycodes[KEY_KP9]        = GLFW_KEY_KP_9;-    _glfw.wl.keycodes[KEY_KPCOMMA]    = GLFW_KEY_KP_DECIMAL;-    _glfw.wl.keycodes[KEY_KPEQUAL]    = GLFW_KEY_KP_EQUAL;-    _glfw.wl.keycodes[KEY_KPENTER]    = GLFW_KEY_KP_ENTER;--    for (scancode = 0;  scancode < 256;  scancode++)-    {-        if (_glfw.wl.keycodes[scancode] > 0)-            _glfw.wl.scancodes[_glfw.wl.keycodes[scancode]] = scancode;-    }-}---//////////////////////////////////////////////////////////////////////////-//////                       GLFW platform API                      //////-//////////////////////////////////////////////////////////////////////////--int _glfwPlatformInit(void)-{-    const char *cursorTheme;-    const char *cursorSizeStr;-    char *cursorSizeEnd;-    long cursorSizeLong;-    int cursorSize;--    _glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");-    if (!_glfw.wl.cursor.handle)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Failed to open libwayland-cursor");-        return GLFW_FALSE;-    }--    _glfw.wl.cursor.theme_load = (PFN_wl_cursor_theme_load)-        _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_load");-    _glfw.wl.cursor.theme_destroy = (PFN_wl_cursor_theme_destroy)-        _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_destroy");-    _glfw.wl.cursor.theme_get_cursor = (PFN_wl_cursor_theme_get_cursor)-        _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor");-    _glfw.wl.cursor.image_get_buffer = (PFN_wl_cursor_image_get_buffer)-        _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_image_get_buffer");--    _glfw.wl.egl.handle = _glfw_dlopen("libwayland-egl.so.1");-    if (!_glfw.wl.egl.handle)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Failed to open libwayland-egl");-        return GLFW_FALSE;-    }--    _glfw.wl.egl.window_create = (PFN_wl_egl_window_create)-        _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_create");-    _glfw.wl.egl.window_destroy = (PFN_wl_egl_window_destroy)-        _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_destroy");-    _glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize)-        _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_resize");--    _glfw.wl.xkb.handle = _glfw_dlopen("libxkbcommon.so.0");-    if (!_glfw.wl.xkb.handle)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Failed to open libxkbcommon");-        return GLFW_FALSE;-    }--    _glfw.wl.xkb.context_new = (PFN_xkb_context_new)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_new");-    _glfw.wl.xkb.context_unref = (PFN_xkb_context_unref)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_unref");-    _glfw.wl.xkb.keymap_new_from_string = (PFN_xkb_keymap_new_from_string)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_new_from_string");-    _glfw.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_unref");-    _glfw.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");-    _glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats");-    _glfw.wl.xkb.state_new = (PFN_xkb_state_new)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new");-    _glfw.wl.xkb.state_unref = (PFN_xkb_state_unref)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_unref");-    _glfw.wl.xkb.state_key_get_syms = (PFN_xkb_state_key_get_syms)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_syms");-    _glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask");-    _glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods");--#ifdef HAVE_XKBCOMMON_COMPOSE_H-    _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");-    _glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_unref");-    _glfw.wl.xkb.compose_state_new = (PFN_xkb_compose_state_new)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_new");-    _glfw.wl.xkb.compose_state_unref = (PFN_xkb_compose_state_unref)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_unref");-    _glfw.wl.xkb.compose_state_feed = (PFN_xkb_compose_state_feed)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_feed");-    _glfw.wl.xkb.compose_state_get_status = (PFN_xkb_compose_state_get_status)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status");-    _glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");-#endif--    _glfw.wl.display = wl_display_connect(NULL);-    if (!_glfw.wl.display)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Failed to connect to display");-        return GLFW_FALSE;-    }--    _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);-    wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);--    createKeyTables();--    _glfw.wl.xkb.context = xkb_context_new(0);-    if (!_glfw.wl.xkb.context)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Failed to initialize xkb context");-        return GLFW_FALSE;-    }--    // Sync so we got all registry objects-    wl_display_roundtrip(_glfw.wl.display);--    // Sync so we got all initial output events-    wl_display_roundtrip(_glfw.wl.display);--#ifdef __linux__-    if (!_glfwInitJoysticksLinux())-        return GLFW_FALSE;-#endif--    _glfwInitTimerPOSIX();--    _glfw.wl.timerfd = -1;-    if (_glfw.wl.seatVersion >= 4)-        _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);--    if (_glfw.wl.pointer && _glfw.wl.shm)-    {-        cursorTheme = getenv("XCURSOR_THEME");-        cursorSizeStr = getenv("XCURSOR_SIZE");-        cursorSize = 32;-        if (cursorSizeStr)-        {-            errno = 0;-            cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10);-            if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX)-                cursorSize = (int)cursorSizeLong;-        }-        _glfw.wl.cursorTheme =-            wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm);-        if (!_glfw.wl.cursorTheme)-        {-            _glfwInputError(GLFW_PLATFORM_ERROR,-                            "Wayland: Unable to load default cursor theme");-            return GLFW_FALSE;-        }-        // If this happens to be NULL, we just fallback to the scale=1 version.-        _glfw.wl.cursorThemeHiDPI =-            wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm);-        _glfw.wl.cursorSurface =-            wl_compositor_create_surface(_glfw.wl.compositor);-        _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);-    }--    if (_glfw.wl.seat && _glfw.wl.dataDeviceManager)-    {-        _glfw.wl.dataDevice =-            wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager,-                                                   _glfw.wl.seat);-        wl_data_device_add_listener(_glfw.wl.dataDevice, &dataDeviceListener, NULL);-        _glfw.wl.clipboardString = malloc(4096);-        if (!_glfw.wl.clipboardString)-        {-            _glfwInputError(GLFW_PLATFORM_ERROR,-                            "Wayland: Unable to allocate clipboard memory");-            return GLFW_FALSE;-        }-        _glfw.wl.clipboardSize = 4096;-    }--    return GLFW_TRUE;-}--void _glfwPlatformTerminate(void)-{-#ifdef __linux__-    _glfwTerminateJoysticksLinux();-#endif-    _glfwTerminateEGL();-    if (_glfw.wl.egl.handle)-    {-        _glfw_dlclose(_glfw.wl.egl.handle);-        _glfw.wl.egl.handle = NULL;-    }--#ifdef HAVE_XKBCOMMON_COMPOSE_H-    if (_glfw.wl.xkb.composeState)-        xkb_compose_state_unref(_glfw.wl.xkb.composeState);-#endif-    if (_glfw.wl.xkb.keymap)-        xkb_keymap_unref(_glfw.wl.xkb.keymap);-    if (_glfw.wl.xkb.state)-        xkb_state_unref(_glfw.wl.xkb.state);-    if (_glfw.wl.xkb.context)-        xkb_context_unref(_glfw.wl.xkb.context);-    if (_glfw.wl.xkb.handle)-    {-        _glfw_dlclose(_glfw.wl.xkb.handle);-        _glfw.wl.xkb.handle = NULL;-    }--    if (_glfw.wl.cursorTheme)-        wl_cursor_theme_destroy(_glfw.wl.cursorTheme);-    if (_glfw.wl.cursorThemeHiDPI)-        wl_cursor_theme_destroy(_glfw.wl.cursorThemeHiDPI);-    if (_glfw.wl.cursor.handle)-    {-        _glfw_dlclose(_glfw.wl.cursor.handle);-        _glfw.wl.cursor.handle = NULL;-    }--    if (_glfw.wl.cursorSurface)-        wl_surface_destroy(_glfw.wl.cursorSurface);-    if (_glfw.wl.subcompositor)-        wl_subcompositor_destroy(_glfw.wl.subcompositor);-    if (_glfw.wl.compositor)-        wl_compositor_destroy(_glfw.wl.compositor);-    if (_glfw.wl.shm)-        wl_shm_destroy(_glfw.wl.shm);-    if (_glfw.wl.shell)-        wl_shell_destroy(_glfw.wl.shell);-    if (_glfw.wl.viewporter)-        wp_viewporter_destroy(_glfw.wl.viewporter);-    if (_glfw.wl.decorationManager)-        zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager);-    if (_glfw.wl.wmBase)-        xdg_wm_base_destroy(_glfw.wl.wmBase);-    if (_glfw.wl.dataSource)-        wl_data_source_destroy(_glfw.wl.dataSource);-    if (_glfw.wl.dataDevice)-        wl_data_device_destroy(_glfw.wl.dataDevice);-    if (_glfw.wl.dataOffer)-        wl_data_offer_destroy(_glfw.wl.dataOffer);-    if (_glfw.wl.dataDeviceManager)-        wl_data_device_manager_destroy(_glfw.wl.dataDeviceManager);-    if (_glfw.wl.pointer)-        wl_pointer_destroy(_glfw.wl.pointer);-    if (_glfw.wl.keyboard)-        wl_keyboard_destroy(_glfw.wl.keyboard);-    if (_glfw.wl.seat)-        wl_seat_destroy(_glfw.wl.seat);-    if (_glfw.wl.relativePointerManager)-        zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager);-    if (_glfw.wl.pointerConstraints)-        zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints);-    if (_glfw.wl.idleInhibitManager)-        zwp_idle_inhibit_manager_v1_destroy(_glfw.wl.idleInhibitManager);-    if (_glfw.wl.registry)-        wl_registry_destroy(_glfw.wl.registry);-    if (_glfw.wl.display)-    {-        wl_display_flush(_glfw.wl.display);-        wl_display_disconnect(_glfw.wl.display);-    }--    if (_glfw.wl.timerfd >= 0)-        close(_glfw.wl.timerfd);-    if (_glfw.wl.cursorTimerfd >= 0)-        close(_glfw.wl.cursorTimerfd);--    if (_glfw.wl.clipboardString)-        free(_glfw.wl.clipboardString);-    if (_glfw.wl.clipboardSendString)-        free(_glfw.wl.clipboardSendString);+#define _POSIX_C_SOURCE 200809L++#include "internal.h"++#include <errno.h>+#include <limits.h>+#include <linux/input.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <sys/mman.h>+#include <sys/timerfd.h>+#include <unistd.h>+#include <wayland-client.h>+#include <assert.h>++static void wmBaseHandlePing(void* userData,+                             struct xdg_wm_base* wmBase,+                             uint32_t serial)+{+    xdg_wm_base_pong(wmBase, serial);+}++static const struct xdg_wm_base_listener wmBaseListener =+{+    wmBaseHandlePing+};++static void registryHandleGlobal(void* userData,+                                 struct wl_registry* registry,+                                 uint32_t name,+                                 const char* interface,+                                 uint32_t version)+{+    if (strcmp(interface, "wl_compositor") == 0)+    {+        _glfw.wl.compositor =+            wl_registry_bind(registry, name, &wl_compositor_interface,+                             _glfw_min(3, version));+    }+    else if (strcmp(interface, "wl_subcompositor") == 0)+    {+        _glfw.wl.subcompositor =+            wl_registry_bind(registry, name, &wl_subcompositor_interface, 1);+    }+    else if (strcmp(interface, "wl_shm") == 0)+    {+        _glfw.wl.shm =+            wl_registry_bind(registry, name, &wl_shm_interface, 1);+    }+    else if (strcmp(interface, "wl_output") == 0)+    {+        _glfwAddOutputWayland(name, version);+    }+    else if (strcmp(interface, "wl_seat") == 0)+    {+        if (!_glfw.wl.seat)+        {+            _glfw.wl.seat =+                wl_registry_bind(registry, name, &wl_seat_interface,+                                 _glfw_min(4, version));+            _glfwAddSeatListenerWayland(_glfw.wl.seat);+        }+    }+    else if (strcmp(interface, "wl_data_device_manager") == 0)+    {+        if (!_glfw.wl.dataDeviceManager)+        {+            _glfw.wl.dataDeviceManager =+                wl_registry_bind(registry, name,+                                 &wl_data_device_manager_interface, 1);+        }+    }+    else if (strcmp(interface, "xdg_wm_base") == 0)+    {+        _glfw.wl.wmBase =+            wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);+        xdg_wm_base_add_listener(_glfw.wl.wmBase, &wmBaseListener, NULL);+    }+    else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0)+    {+        _glfw.wl.decorationManager =+            wl_registry_bind(registry, name,+                             &zxdg_decoration_manager_v1_interface,+                             1);+    }+    else if (strcmp(interface, "wp_viewporter") == 0)+    {+        _glfw.wl.viewporter =+            wl_registry_bind(registry, name, &wp_viewporter_interface, 1);+    }+    else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0)+    {+        _glfw.wl.relativePointerManager =+            wl_registry_bind(registry, name,+                             &zwp_relative_pointer_manager_v1_interface,+                             1);+    }+    else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0)+    {+        _glfw.wl.pointerConstraints =+            wl_registry_bind(registry, name,+                             &zwp_pointer_constraints_v1_interface,+                             1);+    }+    else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0)+    {+        _glfw.wl.idleInhibitManager =+            wl_registry_bind(registry, name,+                             &zwp_idle_inhibit_manager_v1_interface,+                             1);+    }+}++static void registryHandleGlobalRemove(void* userData,+                                       struct wl_registry* registry,+                                       uint32_t name)+{+    int i;++    for (i = 0; i < _glfw.monitorCount; ++i)+    {+        _GLFWmonitor* monitor = _glfw.monitors[i];+        if (monitor->wl.name == name)+        {+            _glfwInputMonitor(monitor, GLFW_DISCONNECTED, 0);+            return;+        }+    }+}+++static const struct wl_registry_listener registryListener =+{+    registryHandleGlobal,+    registryHandleGlobalRemove+};++void libdecorHandleError(struct libdecor* context,+                         enum libdecor_error error,+                         const char* message)+{+    _glfwInputError(GLFW_PLATFORM_ERROR,+                    "Wayland: libdecor error %u: %s",+                    error, message);+}++static const struct libdecor_interface libdecorInterface =+{+    libdecorHandleError+};++static void libdecorReadyCallback(void* userData,+                                  struct wl_callback* callback,+                                  uint32_t time)+{+    _glfw.wl.libdecor.ready = GLFW_TRUE;++    assert(_glfw.wl.libdecor.callback == callback);+    wl_callback_destroy(_glfw.wl.libdecor.callback);+    _glfw.wl.libdecor.callback = NULL;+}++static const struct wl_callback_listener libdecorReadyListener =+{+    libdecorReadyCallback+};++// Create key code translation tables+//+static void createKeyTables(void)+{+    int scancode;++    memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes));+    memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes));++    _glfw.wl.keycodes[KEY_GRAVE]      = GLFW_KEY_GRAVE_ACCENT;+    _glfw.wl.keycodes[KEY_1]          = GLFW_KEY_1;+    _glfw.wl.keycodes[KEY_2]          = GLFW_KEY_2;+    _glfw.wl.keycodes[KEY_3]          = GLFW_KEY_3;+    _glfw.wl.keycodes[KEY_4]          = GLFW_KEY_4;+    _glfw.wl.keycodes[KEY_5]          = GLFW_KEY_5;+    _glfw.wl.keycodes[KEY_6]          = GLFW_KEY_6;+    _glfw.wl.keycodes[KEY_7]          = GLFW_KEY_7;+    _glfw.wl.keycodes[KEY_8]          = GLFW_KEY_8;+    _glfw.wl.keycodes[KEY_9]          = GLFW_KEY_9;+    _glfw.wl.keycodes[KEY_0]          = GLFW_KEY_0;+    _glfw.wl.keycodes[KEY_SPACE]      = GLFW_KEY_SPACE;+    _glfw.wl.keycodes[KEY_MINUS]      = GLFW_KEY_MINUS;+    _glfw.wl.keycodes[KEY_EQUAL]      = GLFW_KEY_EQUAL;+    _glfw.wl.keycodes[KEY_Q]          = GLFW_KEY_Q;+    _glfw.wl.keycodes[KEY_W]          = GLFW_KEY_W;+    _glfw.wl.keycodes[KEY_E]          = GLFW_KEY_E;+    _glfw.wl.keycodes[KEY_R]          = GLFW_KEY_R;+    _glfw.wl.keycodes[KEY_T]          = GLFW_KEY_T;+    _glfw.wl.keycodes[KEY_Y]          = GLFW_KEY_Y;+    _glfw.wl.keycodes[KEY_U]          = GLFW_KEY_U;+    _glfw.wl.keycodes[KEY_I]          = GLFW_KEY_I;+    _glfw.wl.keycodes[KEY_O]          = GLFW_KEY_O;+    _glfw.wl.keycodes[KEY_P]          = GLFW_KEY_P;+    _glfw.wl.keycodes[KEY_LEFTBRACE]  = GLFW_KEY_LEFT_BRACKET;+    _glfw.wl.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;+    _glfw.wl.keycodes[KEY_A]          = GLFW_KEY_A;+    _glfw.wl.keycodes[KEY_S]          = GLFW_KEY_S;+    _glfw.wl.keycodes[KEY_D]          = GLFW_KEY_D;+    _glfw.wl.keycodes[KEY_F]          = GLFW_KEY_F;+    _glfw.wl.keycodes[KEY_G]          = GLFW_KEY_G;+    _glfw.wl.keycodes[KEY_H]          = GLFW_KEY_H;+    _glfw.wl.keycodes[KEY_J]          = GLFW_KEY_J;+    _glfw.wl.keycodes[KEY_K]          = GLFW_KEY_K;+    _glfw.wl.keycodes[KEY_L]          = GLFW_KEY_L;+    _glfw.wl.keycodes[KEY_SEMICOLON]  = GLFW_KEY_SEMICOLON;+    _glfw.wl.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;+    _glfw.wl.keycodes[KEY_Z]          = GLFW_KEY_Z;+    _glfw.wl.keycodes[KEY_X]          = GLFW_KEY_X;+    _glfw.wl.keycodes[KEY_C]          = GLFW_KEY_C;+    _glfw.wl.keycodes[KEY_V]          = GLFW_KEY_V;+    _glfw.wl.keycodes[KEY_B]          = GLFW_KEY_B;+    _glfw.wl.keycodes[KEY_N]          = GLFW_KEY_N;+    _glfw.wl.keycodes[KEY_M]          = GLFW_KEY_M;+    _glfw.wl.keycodes[KEY_COMMA]      = GLFW_KEY_COMMA;+    _glfw.wl.keycodes[KEY_DOT]        = GLFW_KEY_PERIOD;+    _glfw.wl.keycodes[KEY_SLASH]      = GLFW_KEY_SLASH;+    _glfw.wl.keycodes[KEY_BACKSLASH]  = GLFW_KEY_BACKSLASH;+    _glfw.wl.keycodes[KEY_ESC]        = GLFW_KEY_ESCAPE;+    _glfw.wl.keycodes[KEY_TAB]        = GLFW_KEY_TAB;+    _glfw.wl.keycodes[KEY_LEFTSHIFT]  = GLFW_KEY_LEFT_SHIFT;+    _glfw.wl.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;+    _glfw.wl.keycodes[KEY_LEFTCTRL]   = GLFW_KEY_LEFT_CONTROL;+    _glfw.wl.keycodes[KEY_RIGHTCTRL]  = GLFW_KEY_RIGHT_CONTROL;+    _glfw.wl.keycodes[KEY_LEFTALT]    = GLFW_KEY_LEFT_ALT;+    _glfw.wl.keycodes[KEY_RIGHTALT]   = GLFW_KEY_RIGHT_ALT;+    _glfw.wl.keycodes[KEY_LEFTMETA]   = GLFW_KEY_LEFT_SUPER;+    _glfw.wl.keycodes[KEY_RIGHTMETA]  = GLFW_KEY_RIGHT_SUPER;+    _glfw.wl.keycodes[KEY_COMPOSE]    = GLFW_KEY_MENU;+    _glfw.wl.keycodes[KEY_NUMLOCK]    = GLFW_KEY_NUM_LOCK;+    _glfw.wl.keycodes[KEY_CAPSLOCK]   = GLFW_KEY_CAPS_LOCK;+    _glfw.wl.keycodes[KEY_PRINT]      = GLFW_KEY_PRINT_SCREEN;+    _glfw.wl.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;+    _glfw.wl.keycodes[KEY_PAUSE]      = GLFW_KEY_PAUSE;+    _glfw.wl.keycodes[KEY_DELETE]     = GLFW_KEY_DELETE;+    _glfw.wl.keycodes[KEY_BACKSPACE]  = GLFW_KEY_BACKSPACE;+    _glfw.wl.keycodes[KEY_ENTER]      = GLFW_KEY_ENTER;+    _glfw.wl.keycodes[KEY_HOME]       = GLFW_KEY_HOME;+    _glfw.wl.keycodes[KEY_END]        = GLFW_KEY_END;+    _glfw.wl.keycodes[KEY_PAGEUP]     = GLFW_KEY_PAGE_UP;+    _glfw.wl.keycodes[KEY_PAGEDOWN]   = GLFW_KEY_PAGE_DOWN;+    _glfw.wl.keycodes[KEY_INSERT]     = GLFW_KEY_INSERT;+    _glfw.wl.keycodes[KEY_LEFT]       = GLFW_KEY_LEFT;+    _glfw.wl.keycodes[KEY_RIGHT]      = GLFW_KEY_RIGHT;+    _glfw.wl.keycodes[KEY_DOWN]       = GLFW_KEY_DOWN;+    _glfw.wl.keycodes[KEY_UP]         = GLFW_KEY_UP;+    _glfw.wl.keycodes[KEY_F1]         = GLFW_KEY_F1;+    _glfw.wl.keycodes[KEY_F2]         = GLFW_KEY_F2;+    _glfw.wl.keycodes[KEY_F3]         = GLFW_KEY_F3;+    _glfw.wl.keycodes[KEY_F4]         = GLFW_KEY_F4;+    _glfw.wl.keycodes[KEY_F5]         = GLFW_KEY_F5;+    _glfw.wl.keycodes[KEY_F6]         = GLFW_KEY_F6;+    _glfw.wl.keycodes[KEY_F7]         = GLFW_KEY_F7;+    _glfw.wl.keycodes[KEY_F8]         = GLFW_KEY_F8;+    _glfw.wl.keycodes[KEY_F9]         = GLFW_KEY_F9;+    _glfw.wl.keycodes[KEY_F10]        = GLFW_KEY_F10;+    _glfw.wl.keycodes[KEY_F11]        = GLFW_KEY_F11;+    _glfw.wl.keycodes[KEY_F12]        = GLFW_KEY_F12;+    _glfw.wl.keycodes[KEY_F13]        = GLFW_KEY_F13;+    _glfw.wl.keycodes[KEY_F14]        = GLFW_KEY_F14;+    _glfw.wl.keycodes[KEY_F15]        = GLFW_KEY_F15;+    _glfw.wl.keycodes[KEY_F16]        = GLFW_KEY_F16;+    _glfw.wl.keycodes[KEY_F17]        = GLFW_KEY_F17;+    _glfw.wl.keycodes[KEY_F18]        = GLFW_KEY_F18;+    _glfw.wl.keycodes[KEY_F19]        = GLFW_KEY_F19;+    _glfw.wl.keycodes[KEY_F20]        = GLFW_KEY_F20;+    _glfw.wl.keycodes[KEY_F21]        = GLFW_KEY_F21;+    _glfw.wl.keycodes[KEY_F22]        = GLFW_KEY_F22;+    _glfw.wl.keycodes[KEY_F23]        = GLFW_KEY_F23;+    _glfw.wl.keycodes[KEY_F24]        = GLFW_KEY_F24;+    _glfw.wl.keycodes[KEY_KPSLASH]    = GLFW_KEY_KP_DIVIDE;+    _glfw.wl.keycodes[KEY_KPASTERISK] = GLFW_KEY_KP_MULTIPLY;+    _glfw.wl.keycodes[KEY_KPMINUS]    = GLFW_KEY_KP_SUBTRACT;+    _glfw.wl.keycodes[KEY_KPPLUS]     = GLFW_KEY_KP_ADD;+    _glfw.wl.keycodes[KEY_KP0]        = GLFW_KEY_KP_0;+    _glfw.wl.keycodes[KEY_KP1]        = GLFW_KEY_KP_1;+    _glfw.wl.keycodes[KEY_KP2]        = GLFW_KEY_KP_2;+    _glfw.wl.keycodes[KEY_KP3]        = GLFW_KEY_KP_3;+    _glfw.wl.keycodes[KEY_KP4]        = GLFW_KEY_KP_4;+    _glfw.wl.keycodes[KEY_KP5]        = GLFW_KEY_KP_5;+    _glfw.wl.keycodes[KEY_KP6]        = GLFW_KEY_KP_6;+    _glfw.wl.keycodes[KEY_KP7]        = GLFW_KEY_KP_7;+    _glfw.wl.keycodes[KEY_KP8]        = GLFW_KEY_KP_8;+    _glfw.wl.keycodes[KEY_KP9]        = GLFW_KEY_KP_9;+    _glfw.wl.keycodes[KEY_KPDOT]      = GLFW_KEY_KP_DECIMAL;+    _glfw.wl.keycodes[KEY_KPEQUAL]    = GLFW_KEY_KP_EQUAL;+    _glfw.wl.keycodes[KEY_KPENTER]    = GLFW_KEY_KP_ENTER;+    _glfw.wl.keycodes[KEY_102ND]      = GLFW_KEY_WORLD_2;++    for (scancode = 0;  scancode < 256;  scancode++)+    {+        if (_glfw.wl.keycodes[scancode] > 0)+            _glfw.wl.scancodes[_glfw.wl.keycodes[scancode]] = scancode;+    }+}++static GLFWbool loadCursorTheme(void)+{+    int cursorSize = 16;++    const char* sizeString = getenv("XCURSOR_SIZE");+    if (sizeString)+    {+        errno = 0;+        const long cursorSizeLong = strtol(sizeString, NULL, 10);+        if (errno == 0 && cursorSizeLong > 0 && cursorSizeLong < INT_MAX)+            cursorSize = (int) cursorSizeLong;+    }++    const char* themeName = getenv("XCURSOR_THEME");++    _glfw.wl.cursorTheme = wl_cursor_theme_load(themeName, cursorSize, _glfw.wl.shm);+    if (!_glfw.wl.cursorTheme)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to load default cursor theme");+        return GLFW_FALSE;+    }++    // If this happens to be NULL, we just fallback to the scale=1 version.+    _glfw.wl.cursorThemeHiDPI =+        wl_cursor_theme_load(themeName, cursorSize * 2, _glfw.wl.shm);++    _glfw.wl.cursorSurface = wl_compositor_create_surface(_glfw.wl.compositor);+    _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);+    return GLFW_TRUE;+}+++//////////////////////////////////////////////////////////////////////////+//////                       GLFW platform API                      //////+//////////////////////////////////////////////////////////////////////////++int _glfwPlatformInit(void)+{+    // These must be set before any failure checks+    _glfw.wl.keyRepeatTimerfd = -1;+    _glfw.wl.cursorTimerfd = -1;++    _glfw.wl.tag = glfwGetVersionString();++    _glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");+    if (!_glfw.wl.cursor.handle)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to load libwayland-cursor");+        return GLFW_FALSE;+    }++    _glfw.wl.cursor.theme_load = (PFN_wl_cursor_theme_load)+        _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_load");+    _glfw.wl.cursor.theme_destroy = (PFN_wl_cursor_theme_destroy)+        _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_destroy");+    _glfw.wl.cursor.theme_get_cursor = (PFN_wl_cursor_theme_get_cursor)+        _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor");+    _glfw.wl.cursor.image_get_buffer = (PFN_wl_cursor_image_get_buffer)+        _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_image_get_buffer");++    _glfw.wl.egl.handle = _glfw_dlopen("libwayland-egl.so.1");+    if (!_glfw.wl.egl.handle)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to load libwayland-egl");+        return GLFW_FALSE;+    }++    _glfw.wl.egl.window_create = (PFN_wl_egl_window_create)+        _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_create");+    _glfw.wl.egl.window_destroy = (PFN_wl_egl_window_destroy)+        _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_destroy");+    _glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize)+        _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_resize");++    _glfw.wl.xkb.handle = _glfw_dlopen("libxkbcommon.so.0");+    if (!_glfw.wl.xkb.handle)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to load libxkbcommon");+        return GLFW_FALSE;+    }++    _glfw.wl.xkb.context_new = (PFN_xkb_context_new)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_new");+    _glfw.wl.xkb.context_unref = (PFN_xkb_context_unref)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_unref");+    _glfw.wl.xkb.keymap_new_from_string = (PFN_xkb_keymap_new_from_string)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_new_from_string");+    _glfw.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_unref");+    _glfw.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");+    _glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats");+    _glfw.wl.xkb.keymap_key_get_syms_by_level = (PFN_xkb_keymap_key_get_syms_by_level)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_get_syms_by_level");+    _glfw.wl.xkb.state_new = (PFN_xkb_state_new)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new");+    _glfw.wl.xkb.state_unref = (PFN_xkb_state_unref)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_unref");+    _glfw.wl.xkb.state_key_get_syms = (PFN_xkb_state_key_get_syms)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_syms");+    _glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask");+    _glfw.wl.xkb.state_key_get_layout = (PFN_xkb_state_key_get_layout)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_layout");+    _glfw.wl.xkb.state_mod_index_is_active = (PFN_xkb_state_mod_index_is_active)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_mod_index_is_active");++    _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");+    _glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_unref");+    _glfw.wl.xkb.compose_state_new = (PFN_xkb_compose_state_new)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_new");+    _glfw.wl.xkb.compose_state_unref = (PFN_xkb_compose_state_unref)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_unref");+    _glfw.wl.xkb.compose_state_feed = (PFN_xkb_compose_state_feed)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_feed");+    _glfw.wl.xkb.compose_state_get_status = (PFN_xkb_compose_state_get_status)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status");+    _glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");++    _glfw.wl.display = wl_display_connect(NULL);+    if (!_glfw.wl.display)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to connect to display");+        return GLFW_FALSE;+    }++    if (_glfw.hints.init.wl.libdecorMode == GLFW_WAYLAND_PREFER_LIBDECOR)+        _glfw.wl.libdecor.handle = _glfw_dlopen("libdecor-0.so.0");++    if (_glfw.wl.libdecor.handle)+    {+        _glfw.wl.libdecor.libdecor_new_ = (PFN_libdecor_new)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_new");+        _glfw.wl.libdecor.libdecor_unref_ = (PFN_libdecor_unref)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_unref");+        _glfw.wl.libdecor.libdecor_get_fd_ = (PFN_libdecor_get_fd)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_get_fd");+        _glfw.wl.libdecor.libdecor_dispatch_ = (PFN_libdecor_dispatch)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_dispatch");+        _glfw.wl.libdecor.libdecor_decorate_ = (PFN_libdecor_decorate)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_decorate");+        _glfw.wl.libdecor.libdecor_frame_unref_ = (PFN_libdecor_frame_unref)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_unref");+        _glfw.wl.libdecor.libdecor_frame_set_app_id_ = (PFN_libdecor_frame_set_app_id)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_app_id");+        _glfw.wl.libdecor.libdecor_frame_set_title_ = (PFN_libdecor_frame_set_title)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_title");+        _glfw.wl.libdecor.libdecor_frame_set_minimized_ = (PFN_libdecor_frame_set_minimized)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_minimized");+        _glfw.wl.libdecor.libdecor_frame_set_fullscreen_ = (PFN_libdecor_frame_set_fullscreen)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_fullscreen");+        _glfw.wl.libdecor.libdecor_frame_unset_fullscreen_ = (PFN_libdecor_frame_unset_fullscreen)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_unset_fullscreen");+        _glfw.wl.libdecor.libdecor_frame_map_ = (PFN_libdecor_frame_map)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_map");+        _glfw.wl.libdecor.libdecor_frame_commit_ = (PFN_libdecor_frame_commit)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_commit");+        _glfw.wl.libdecor.libdecor_frame_set_min_content_size_ = (PFN_libdecor_frame_set_min_content_size)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_min_content_size");+        _glfw.wl.libdecor.libdecor_frame_set_max_content_size_ = (PFN_libdecor_frame_set_max_content_size)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_max_content_size");+        _glfw.wl.libdecor.libdecor_frame_set_maximized_ = (PFN_libdecor_frame_set_maximized)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_maximized");+        _glfw.wl.libdecor.libdecor_frame_unset_maximized_ = (PFN_libdecor_frame_unset_maximized)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_unset_maximized");+        _glfw.wl.libdecor.libdecor_frame_set_capabilities_ = (PFN_libdecor_frame_set_capabilities)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_capabilities");+        _glfw.wl.libdecor.libdecor_frame_unset_capabilities_ = (PFN_libdecor_frame_unset_capabilities)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_unset_capabilities");+        _glfw.wl.libdecor.libdecor_frame_set_visibility_ = (PFN_libdecor_frame_set_visibility)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_visibility");+        _glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ = (PFN_libdecor_frame_get_xdg_toplevel)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_get_xdg_toplevel");+        _glfw.wl.libdecor.libdecor_configuration_get_content_size_ = (PFN_libdecor_configuration_get_content_size)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_configuration_get_content_size");+        _glfw.wl.libdecor.libdecor_configuration_get_window_state_ = (PFN_libdecor_configuration_get_window_state)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_configuration_get_window_state");+        _glfw.wl.libdecor.libdecor_state_new_ = (PFN_libdecor_state_new)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_state_new");+        _glfw.wl.libdecor.libdecor_state_free_ = (PFN_libdecor_state_free)+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_state_free");++        if (!_glfw.wl.libdecor.libdecor_new_ ||+            !_glfw.wl.libdecor.libdecor_unref_ ||+            !_glfw.wl.libdecor.libdecor_get_fd_ ||+            !_glfw.wl.libdecor.libdecor_dispatch_ ||+            !_glfw.wl.libdecor.libdecor_decorate_ ||+            !_glfw.wl.libdecor.libdecor_frame_unref_ ||+            !_glfw.wl.libdecor.libdecor_frame_set_app_id_ ||+            !_glfw.wl.libdecor.libdecor_frame_set_title_ ||+            !_glfw.wl.libdecor.libdecor_frame_set_minimized_ ||+            !_glfw.wl.libdecor.libdecor_frame_set_fullscreen_ ||+            !_glfw.wl.libdecor.libdecor_frame_unset_fullscreen_ ||+            !_glfw.wl.libdecor.libdecor_frame_map_ ||+            !_glfw.wl.libdecor.libdecor_frame_commit_ ||+            !_glfw.wl.libdecor.libdecor_frame_set_min_content_size_ ||+            !_glfw.wl.libdecor.libdecor_frame_set_max_content_size_ ||+            !_glfw.wl.libdecor.libdecor_frame_set_maximized_ ||+            !_glfw.wl.libdecor.libdecor_frame_unset_maximized_ ||+            !_glfw.wl.libdecor.libdecor_frame_set_capabilities_ ||+            !_glfw.wl.libdecor.libdecor_frame_unset_capabilities_ ||+            !_glfw.wl.libdecor.libdecor_frame_set_visibility_ ||+            !_glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ ||+            !_glfw.wl.libdecor.libdecor_configuration_get_content_size_ ||+            !_glfw.wl.libdecor.libdecor_configuration_get_window_state_ ||+            !_glfw.wl.libdecor.libdecor_state_new_ ||+            !_glfw.wl.libdecor.libdecor_state_free_)+        {+            _glfw_dlclose(_glfw.wl.libdecor.handle);+            memset(&_glfw.wl.libdecor, 0, sizeof(_glfw.wl.libdecor));+        }+    }++    _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);+    wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);++    createKeyTables();++    _glfw.wl.xkb.context = xkb_context_new(0);+    if (!_glfw.wl.xkb.context)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to initialize xkb context");+        return GLFW_FALSE;+    }++    // Sync so we got all registry objects+    wl_display_roundtrip(_glfw.wl.display);++    // Sync so we got all initial output events+    wl_display_roundtrip(_glfw.wl.display);++#ifdef __linux__+    if (!_glfwInitJoysticksLinux())+        return GLFW_FALSE;+#endif++    _glfwInitTimerPOSIX();++    if (_glfw.wl.libdecor.handle)+    {+        _glfw.wl.libdecor.context = libdecor_new(_glfw.wl.display, &libdecorInterface);+        if (_glfw.wl.libdecor.context)+        {+            // Perform an initial dispatch and flush to get the init started+            libdecor_dispatch(_glfw.wl.libdecor.context, 0);++            // Create sync point to "know" when libdecor is ready for use+            _glfw.wl.libdecor.callback = wl_display_sync(_glfw.wl.display);+            wl_callback_add_listener(_glfw.wl.libdecor.callback,+                                     &libdecorReadyListener,+                                     NULL);+        }+    }++#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION+    if (wl_seat_get_version(_glfw.wl.seat) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)+    {+        _glfw.wl.keyRepeatTimerfd =+            timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);+    }+#endif++    if (!_glfw.wl.wmBase)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to find xdg-shell in your compositor");+        return GLFW_FALSE;+    }++    if (!_glfw.wl.shm)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to find wl_shm in your compositor");+        return GLFW_FALSE;+    }++    if (!loadCursorTheme())+        return GLFW_FALSE;++    if (_glfw.wl.seat && _glfw.wl.dataDeviceManager)+    {+        _glfw.wl.dataDevice =+            wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager,+                                                   _glfw.wl.seat);+        _glfwAddDataDeviceListenerWayland(_glfw.wl.dataDevice);+    }++    return GLFW_TRUE;+}++void _glfwPlatformTerminate(void)+{+#ifdef __linux__+    _glfwTerminateJoysticksLinux();+#endif+    _glfwTerminateEGL();+    _glfwTerminateOSMesa();++    if (_glfw.wl.libdecor.callback)+        wl_callback_destroy(_glfw.wl.libdecor.callback);+    if (_glfw.wl.libdecor.context)+        libdecor_unref(_glfw.wl.libdecor.context);++    if (_glfw.wl.libdecor.handle)+    {+        _glfw_dlclose(_glfw.wl.libdecor.handle);+        _glfw.wl.libdecor.handle = NULL;+    }++    if (_glfw.wl.egl.handle)+    {+        _glfw_dlclose(_glfw.wl.egl.handle);+        _glfw.wl.egl.handle = NULL;+    }++    if (_glfw.wl.xkb.composeState)+        xkb_compose_state_unref(_glfw.wl.xkb.composeState);+    if (_glfw.wl.xkb.keymap)+        xkb_keymap_unref(_glfw.wl.xkb.keymap);+    if (_glfw.wl.xkb.state)+        xkb_state_unref(_glfw.wl.xkb.state);+    if (_glfw.wl.xkb.context)+        xkb_context_unref(_glfw.wl.xkb.context);+    if (_glfw.wl.xkb.handle)+    {+        _glfw_dlclose(_glfw.wl.xkb.handle);+        _glfw.wl.xkb.handle = NULL;+    }++    if (_glfw.wl.cursorTheme)+        wl_cursor_theme_destroy(_glfw.wl.cursorTheme);+    if (_glfw.wl.cursorThemeHiDPI)+        wl_cursor_theme_destroy(_glfw.wl.cursorThemeHiDPI);+    if (_glfw.wl.cursor.handle)+    {+        _glfw_dlclose(_glfw.wl.cursor.handle);+        _glfw.wl.cursor.handle = NULL;+    }++    for (unsigned int i = 0; i < _glfw.wl.offerCount; i++)+        wl_data_offer_destroy(_glfw.wl.offers[i].offer);++    free(_glfw.wl.offers);++    if (_glfw.wl.cursorSurface)+        wl_surface_destroy(_glfw.wl.cursorSurface);+    if (_glfw.wl.subcompositor)+        wl_subcompositor_destroy(_glfw.wl.subcompositor);+    if (_glfw.wl.compositor)+        wl_compositor_destroy(_glfw.wl.compositor);+    if (_glfw.wl.shm)+        wl_shm_destroy(_glfw.wl.shm);+    if (_glfw.wl.viewporter)+        wp_viewporter_destroy(_glfw.wl.viewporter);+    if (_glfw.wl.decorationManager)+        zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager);+    if (_glfw.wl.wmBase)+        xdg_wm_base_destroy(_glfw.wl.wmBase);+    if (_glfw.wl.selectionOffer)+        wl_data_offer_destroy(_glfw.wl.selectionOffer);+    if (_glfw.wl.dragOffer)+        wl_data_offer_destroy(_glfw.wl.dragOffer);+    if (_glfw.wl.selectionSource)+        wl_data_source_destroy(_glfw.wl.selectionSource);+    if (_glfw.wl.dataDevice)+        wl_data_device_destroy(_glfw.wl.dataDevice);+    if (_glfw.wl.dataDeviceManager)+        wl_data_device_manager_destroy(_glfw.wl.dataDeviceManager);+    if (_glfw.wl.pointer)+        wl_pointer_destroy(_glfw.wl.pointer);+    if (_glfw.wl.keyboard)+        wl_keyboard_destroy(_glfw.wl.keyboard);+    if (_glfw.wl.seat)+        wl_seat_destroy(_glfw.wl.seat);+    if (_glfw.wl.relativePointerManager)+        zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager);+    if (_glfw.wl.pointerConstraints)+        zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints);+    if (_glfw.wl.idleInhibitManager)+        zwp_idle_inhibit_manager_v1_destroy(_glfw.wl.idleInhibitManager);+    if (_glfw.wl.registry)+        wl_registry_destroy(_glfw.wl.registry);+    if (_glfw.wl.display)+    {+        wl_display_flush(_glfw.wl.display);+        wl_display_disconnect(_glfw.wl.display);+    }++    if (_glfw.wl.keyRepeatTimerfd >= 0)+        close(_glfw.wl.keyRepeatTimerfd);+    if (_glfw.wl.cursorTimerfd >= 0)+        close(_glfw.wl.cursorTimerfd);++    free(_glfw.wl.clipboardString); }  const char* _glfwPlatformGetVersionString(void)
glfw/src/wl_monitor.c view
@@ -35,7 +35,7 @@ #include <math.h>  -static void outputHandleGeometry(void* data,+static void outputHandleGeometry(void* userData,                                  struct wl_output* output,                                  int32_t x,                                  int32_t y,@@ -46,26 +46,25 @@                                  const char* model,                                  int32_t transform) {-    struct _GLFWmonitor *monitor = data;-    char name[1024];+    struct _GLFWmonitor* monitor = userData;      monitor->wl.x = x;     monitor->wl.y = y;     monitor->widthMM = physicalWidth;     monitor->heightMM = physicalHeight; -    snprintf(name, sizeof(name), "%s %s", make, model);-    monitor->name = _glfw_strdup(name);+    if (strlen(monitor->name) == 0)+        snprintf(monitor->name, sizeof(monitor->name), "%s %s", make, model); } -static void outputHandleMode(void* data,+static void outputHandleMode(void* userData,                              struct wl_output* output,                              uint32_t flags,                              int32_t width,                              int32_t height,                              int32_t refresh) {-    struct _GLFWmonitor *monitor = data;+    struct _GLFWmonitor* monitor = userData;     GLFWvidmode mode;      mode.width = width;@@ -84,27 +83,76 @@         monitor->wl.currentMode = monitor->modeCount - 1; } -static void outputHandleDone(void* data, struct wl_output* output)+static void outputHandleDone(void* userData, struct wl_output* output) {-    struct _GLFWmonitor *monitor = data;+    struct _GLFWmonitor* monitor = userData; +    if (monitor->widthMM <= 0 || monitor->heightMM <= 0)+    {+        // If Wayland does not provide a physical size, assume the default 96 DPI+        const GLFWvidmode* mode = &monitor->modes[monitor->wl.currentMode];+        monitor->widthMM  = (int) (mode->width * 25.4f / 96.f);+        monitor->heightMM = (int) (mode->height * 25.4f / 96.f);+    }++    for (int i = 0; i < _glfw.monitorCount; i++)+    {+        if (_glfw.monitors[i] == monitor)+            return;+    }+     _glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST); } -static void outputHandleScale(void* data,+static void outputHandleScale(void* userData,                               struct wl_output* output,                               int32_t factor) {-    struct _GLFWmonitor *monitor = data;+    struct _GLFWmonitor* monitor = userData; -    monitor->wl.scale = factor;+    monitor->wl.contentScale = factor;++    for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next)+    {+        for (int i = 0; i < window->wl.scaleCount; i++)+        {+            if (window->wl.scales[i].output == monitor->wl.output)+            {+                window->wl.scales[i].factor = monitor->wl.contentScale;+                _glfwUpdateContentScaleWayland(window);+                break;+            }+        }+    } } -static const struct wl_output_listener outputListener = {+#ifdef WL_OUTPUT_NAME_SINCE_VERSION++void outputHandleName(void* userData, struct wl_output* wl_output, const char* name)+{+    struct _GLFWmonitor* monitor = userData;++    strncpy(monitor->name, name, sizeof(monitor->name) - 1);+}++void outputHandleDescription(void* userData,+                             struct wl_output* wl_output,+                             const char* description)+{+}++#endif // WL_OUTPUT_NAME_SINCE_VERSION++static const struct wl_output_listener outputListener =+{     outputHandleGeometry,     outputHandleMode,     outputHandleDone,     outputHandleScale,+#ifdef WL_OUTPUT_NAME_SINCE_VERSION+    outputHandleName,+    outputHandleDescription,+#endif };  @@ -114,9 +162,6 @@  void _glfwAddOutputWayland(uint32_t name, uint32_t version) {-    _GLFWmonitor *monitor;-    struct wl_output *output;-     if (version < 2)     {         _glfwInputError(GLFW_PLATFORM_ERROR,@@ -124,23 +169,26 @@         return;     } -    // The actual name of this output will be set in the geometry handler.-    monitor = _glfwAllocMonitor(NULL, 0, 0);+#ifdef WL_OUTPUT_NAME_SINCE_VERSION+    version = _glfw_min(version, WL_OUTPUT_NAME_SINCE_VERSION);+#else+    version = 2;+#endif -    output = wl_registry_bind(_glfw.wl.registry,-                              name,-                              &wl_output_interface,-                              2);+    struct wl_output* output = wl_registry_bind(_glfw.wl.registry,+                                                name,+                                                &wl_output_interface,+                                                version);     if (!output)-    {-        _glfwFreeMonitor(monitor);         return;-    } -    monitor->wl.scale = 1;+    // The actual name of this output will be set in the geometry handler+    _GLFWmonitor* monitor = _glfwAllocMonitor("", 0, 0);+    monitor->wl.contentScale = 1;     monitor->wl.output = output;     monitor->wl.name = name; +    wl_proxy_set_tag((struct wl_proxy*) output, &_glfw.wl.tag);     wl_output_add_listener(output, &outputListener, monitor); } @@ -167,9 +215,9 @@                                          float* xscale, float* yscale) {     if (xscale)-        *xscale = (float) monitor->wl.scale;+        *xscale = (float) monitor->wl.contentScale;     if (yscale)-        *yscale = (float) monitor->wl.scale;+        *yscale = (float) monitor->wl.contentScale; }  void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
glfw/src/wl_platform.h view
@@ -26,11 +26,11 @@  #include <wayland-client.h> #include <xkbcommon/xkbcommon.h>-#ifdef HAVE_XKBCOMMON_COMPOSE_H #include <xkbcommon/xkbcommon-compose.h>-#endif #include <dlfcn.h> +#include <stdbool.h>+ typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;  typedef struct VkWaylandSurfaceCreateInfoKHR@@ -67,7 +67,7 @@ #define _glfw_dlclose(handle) dlclose(handle) #define _glfw_dlsym(handle, name) dlsym(handle, name) -#define _GLFW_EGL_NATIVE_WINDOW         ((EGLNativeWindowType) window->wl.native)+#define _GLFW_EGL_NATIVE_WINDOW         ((EGLNativeWindowType) window->wl.egl.window) #define _GLFW_EGL_NATIVE_DISPLAY        ((EGLNativeDisplayType) _glfw.wl.display)  #define _GLFW_PLATFORM_WINDOW_STATE         _GLFWwindowWayland  wl@@ -112,24 +112,27 @@ typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*); typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*); typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t);+typedef int (* PFN_xkb_keymap_key_get_syms_by_level)(struct xkb_keymap*,xkb_keycode_t,xkb_layout_index_t,xkb_level_index_t,const xkb_keysym_t**); typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*); typedef void (* PFN_xkb_state_unref)(struct xkb_state*); typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**); typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);-typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component);+typedef xkb_layout_index_t (* PFN_xkb_state_key_get_layout)(struct xkb_state*,xkb_keycode_t);+typedef int (* PFN_xkb_state_mod_index_is_active)(struct xkb_state*,xkb_mod_index_t,enum xkb_state_component); #define xkb_context_new _glfw.wl.xkb.context_new #define xkb_context_unref _glfw.wl.xkb.context_unref #define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string #define xkb_keymap_unref _glfw.wl.xkb.keymap_unref #define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index #define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats+#define xkb_keymap_key_get_syms_by_level _glfw.wl.xkb.keymap_key_get_syms_by_level #define xkb_state_new _glfw.wl.xkb.state_new #define xkb_state_unref _glfw.wl.xkb.state_unref #define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms #define xkb_state_update_mask _glfw.wl.xkb.state_update_mask-#define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods+#define xkb_state_key_get_layout _glfw.wl.xkb.state_key_get_layout+#define xkb_state_mod_index_is_active _glfw.wl.xkb.state_mod_index_is_active -#ifdef HAVE_XKBCOMMON_COMPOSE_H typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags); typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*); typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags);@@ -144,21 +147,130 @@ #define xkb_compose_state_feed _glfw.wl.xkb.compose_state_feed #define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status #define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym-#endif -#define _GLFW_DECORATION_WIDTH 4-#define _GLFW_DECORATION_TOP 24-#define _GLFW_DECORATION_VERTICAL (_GLFW_DECORATION_TOP + _GLFW_DECORATION_WIDTH)-#define _GLFW_DECORATION_HORIZONTAL (2 * _GLFW_DECORATION_WIDTH)+struct libdecor;+struct libdecor_frame;+struct libdecor_state;+struct libdecor_configuration; -typedef enum _GLFWdecorationSideWayland+enum libdecor_error {-    mainWindow,-    topDecoration,-    leftDecoration,-    rightDecoration,-    bottomDecoration,+	LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,+	LIBDECOR_ERROR_INVALID_FRAME_CONFIGURATION,+}; +enum libdecor_window_state+{+	LIBDECOR_WINDOW_STATE_NONE = 0,+	LIBDECOR_WINDOW_STATE_ACTIVE = 1,+	LIBDECOR_WINDOW_STATE_MAXIMIZED = 2,+	LIBDECOR_WINDOW_STATE_FULLSCREEN = 4,+	LIBDECOR_WINDOW_STATE_TILED_LEFT = 8,+	LIBDECOR_WINDOW_STATE_TILED_RIGHT = 16,+	LIBDECOR_WINDOW_STATE_TILED_TOP = 32,+	LIBDECOR_WINDOW_STATE_TILED_BOTTOM = 64+};++enum libdecor_capabilities+{+	LIBDECOR_ACTION_MOVE = 1,+	LIBDECOR_ACTION_RESIZE = 2,+	LIBDECOR_ACTION_MINIMIZE = 4,+	LIBDECOR_ACTION_FULLSCREEN = 8,+	LIBDECOR_ACTION_CLOSE = 16+};++struct libdecor_interface+{+	void (* error)(struct libdecor*,enum libdecor_error,const char*);+	void (* reserved0)(void);+	void (* reserved1)(void);+	void (* reserved2)(void);+	void (* reserved3)(void);+	void (* reserved4)(void);+	void (* reserved5)(void);+	void (* reserved6)(void);+	void (* reserved7)(void);+	void (* reserved8)(void);+	void (* reserved9)(void);+};++struct libdecor_frame_interface+{+	void (* configure)(struct libdecor_frame*,struct libdecor_configuration*,void*);+	void (* close)(struct libdecor_frame*,void*);+	void (* commit)(struct libdecor_frame*,void*);+	void (* dismiss_popup)(struct libdecor_frame*,const char*,void*);+	void (* reserved0)(void);+	void (* reserved1)(void);+	void (* reserved2)(void);+	void (* reserved3)(void);+	void (* reserved4)(void);+	void (* reserved5)(void);+	void (* reserved6)(void);+	void (* reserved7)(void);+	void (* reserved8)(void);+	void (* reserved9)(void);+};++typedef struct libdecor* (* PFN_libdecor_new)(struct wl_display*,const struct libdecor_interface*);+typedef void (* PFN_libdecor_unref)(struct libdecor*);+typedef int (* PFN_libdecor_get_fd)(struct libdecor*);+typedef int (* PFN_libdecor_dispatch)(struct libdecor*,int);+typedef struct libdecor_frame* (* PFN_libdecor_decorate)(struct libdecor*,struct wl_surface*,const struct libdecor_frame_interface*,void*);+typedef void (* PFN_libdecor_frame_unref)(struct libdecor_frame*);+typedef void (* PFN_libdecor_frame_set_app_id)(struct libdecor_frame*,const char*);+typedef void (* PFN_libdecor_frame_set_title)(struct libdecor_frame*,const char*);+typedef void (* PFN_libdecor_frame_set_minimized)(struct libdecor_frame*);+typedef void (* PFN_libdecor_frame_set_fullscreen)(struct libdecor_frame*,struct wl_output*);+typedef void (* PFN_libdecor_frame_unset_fullscreen)(struct libdecor_frame*);+typedef void (* PFN_libdecor_frame_map)(struct libdecor_frame*);+typedef void (* PFN_libdecor_frame_commit)(struct libdecor_frame*,struct libdecor_state*,struct libdecor_configuration*);+typedef void (* PFN_libdecor_frame_set_min_content_size)(struct libdecor_frame*,int,int);+typedef void (* PFN_libdecor_frame_set_max_content_size)(struct libdecor_frame*,int,int);+typedef void (* PFN_libdecor_frame_set_maximized)(struct libdecor_frame*);+typedef void (* PFN_libdecor_frame_unset_maximized)(struct libdecor_frame*);+typedef void (* PFN_libdecor_frame_set_capabilities)(struct libdecor_frame*,enum libdecor_capabilities);+typedef void (* PFN_libdecor_frame_unset_capabilities)(struct libdecor_frame*,enum libdecor_capabilities);+typedef void (* PFN_libdecor_frame_set_visibility)(struct libdecor_frame*,bool visible);+typedef struct xdg_toplevel* (* PFN_libdecor_frame_get_xdg_toplevel)(struct libdecor_frame*);+typedef bool (* PFN_libdecor_configuration_get_content_size)(struct libdecor_configuration*,struct libdecor_frame*,int*,int*);+typedef bool (* PFN_libdecor_configuration_get_window_state)(struct libdecor_configuration*,enum libdecor_window_state*);+typedef struct libdecor_state* (* PFN_libdecor_state_new)(int,int);+typedef void (* PFN_libdecor_state_free)(struct libdecor_state*);+#define libdecor_new _glfw.wl.libdecor.libdecor_new_+#define libdecor_unref _glfw.wl.libdecor.libdecor_unref_+#define libdecor_get_fd _glfw.wl.libdecor.libdecor_get_fd_+#define libdecor_dispatch _glfw.wl.libdecor.libdecor_dispatch_+#define libdecor_decorate _glfw.wl.libdecor.libdecor_decorate_+#define libdecor_frame_unref _glfw.wl.libdecor.libdecor_frame_unref_+#define libdecor_frame_set_app_id _glfw.wl.libdecor.libdecor_frame_set_app_id_+#define libdecor_frame_set_title _glfw.wl.libdecor.libdecor_frame_set_title_+#define libdecor_frame_set_minimized _glfw.wl.libdecor.libdecor_frame_set_minimized_+#define libdecor_frame_set_fullscreen _glfw.wl.libdecor.libdecor_frame_set_fullscreen_+#define libdecor_frame_unset_fullscreen _glfw.wl.libdecor.libdecor_frame_unset_fullscreen_+#define libdecor_frame_map _glfw.wl.libdecor.libdecor_frame_map_+#define libdecor_frame_commit _glfw.wl.libdecor.libdecor_frame_commit_+#define libdecor_frame_set_min_content_size _glfw.wl.libdecor.libdecor_frame_set_min_content_size_+#define libdecor_frame_set_max_content_size _glfw.wl.libdecor.libdecor_frame_set_max_content_size_+#define libdecor_frame_set_maximized _glfw.wl.libdecor.libdecor_frame_set_maximized_+#define libdecor_frame_unset_maximized _glfw.wl.libdecor.libdecor_frame_unset_maximized_+#define libdecor_frame_set_capabilities _glfw.wl.libdecor.libdecor_frame_set_capabilities_+#define libdecor_frame_unset_capabilities _glfw.wl.libdecor.libdecor_frame_unset_capabilities_+#define libdecor_frame_set_visibility _glfw.wl.libdecor.libdecor_frame_set_visibility_+#define libdecor_frame_get_xdg_toplevel _glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_+#define libdecor_configuration_get_content_size _glfw.wl.libdecor.libdecor_configuration_get_content_size_+#define libdecor_configuration_get_window_state _glfw.wl.libdecor.libdecor_configuration_get_window_state_+#define libdecor_state_new _glfw.wl.libdecor.libdecor_state_new_+#define libdecor_state_free _glfw.wl.libdecor.libdecor_state_free_++typedef enum _GLFWdecorationSideWayland+{+    GLFW_MAIN_WINDOW,+    GLFW_TOP_DECORATION,+    GLFW_LEFT_DECORATION,+    GLFW_RIGHT_DECORATION,+    GLFW_BOTTOM_DECORATION } _GLFWdecorationSideWayland;  typedef struct _GLFWdecorationWayland@@ -166,9 +278,21 @@     struct wl_surface*          surface;     struct wl_subsurface*       subsurface;     struct wp_viewport*         viewport;- } _GLFWdecorationWayland; +typedef struct _GLFWofferWayland+{+    struct wl_data_offer*       offer;+    GLFWbool                    text_plain_utf8;+    GLFWbool                    text_uri_list;+} _GLFWofferWayland;++typedef struct _GLFWscaleWayland+{+    struct wl_output*           output;+    int                         factor;+} _GLFWscaleWayland;+ // Wayland-specific per-window data // typedef struct _GLFWwindowWayland@@ -176,19 +300,37 @@     int                         width, height;     GLFWbool                    visible;     GLFWbool                    maximized;+    GLFWbool                    activated;+    GLFWbool                    fullscreen;     GLFWbool                    hovered;     GLFWbool                    transparent;     struct wl_surface*          surface;-    struct wl_egl_window*       native;-    struct wl_shell_surface*    shellSurface;     struct wl_callback*         callback;      struct {+        struct wl_egl_window*   window;+    } egl;++    struct {+        int                     width, height;+        GLFWbool                maximized;+        GLFWbool                iconified;+        GLFWbool                activated;+        GLFWbool                fullscreen;+    } pending;++    struct {         struct xdg_surface*     surface;         struct xdg_toplevel*    toplevel;         struct zxdg_toplevel_decoration_v1* decoration;+        uint32_t                decorationMode;     } xdg; +    struct {+        struct libdecor_frame*  frame;+        int                     mode;+    } libdecor;+     _GLFWcursor*                currentCursor;     double                      cursorPosX, cursorPosY; @@ -196,27 +338,21 @@      // We need to track the monitors the window spans on to calculate the     // optimal scaling factor.-    int                         scale;-    _GLFWmonitor**              monitors;-    int                         monitorsCount;-    int                         monitorsSize;+    int                         contentScale;+    _GLFWscaleWayland*          scales;+    int                         scaleCount;+    int                         scaleSize; -    struct {-        struct zwp_relative_pointer_v1*    relativePointer;-        struct zwp_locked_pointer_v1*      lockedPointer;-    } pointerLock;+    struct zwp_relative_pointer_v1* relativePointer;+    struct zwp_locked_pointer_v1*   lockedPointer;      struct zwp_idle_inhibitor_v1*          idleInhibitor; -    GLFWbool                    wasFullscreen;-     struct {-        GLFWbool                           serverSide;         struct wl_buffer*                  buffer;         _GLFWdecorationWayland             top, left, right, bottom;-        int                                focus;+        _GLFWdecorationSideWayland         focus;     } decorations;- } _GLFWwindowWayland;  // Wayland-specific global data@@ -227,15 +363,12 @@     struct wl_registry*         registry;     struct wl_compositor*       compositor;     struct wl_subcompositor*    subcompositor;-    struct wl_shell*            shell;     struct wl_shm*              shm;     struct wl_seat*             seat;     struct wl_pointer*          pointer;     struct wl_keyboard*         keyboard;     struct wl_data_device_manager*          dataDeviceManager;     struct wl_data_device*      dataDevice;-    struct wl_data_offer*       dataOffer;-    struct wl_data_source*      dataSource;     struct xdg_wm_base*         wmBase;     struct zxdg_decoration_manager_v1*      decorationManager;     struct wp_viewporter*       viewporter;@@ -243,44 +376,49 @@     struct zwp_pointer_constraints_v1*      pointerConstraints;     struct zwp_idle_inhibit_manager_v1*     idleInhibitManager; -    int                         compositorVersion;-    int                         seatVersion;+    _GLFWofferWayland*          offers;+    unsigned int                offerCount; +    struct wl_data_offer*       selectionOffer;+    struct wl_data_source*      selectionSource;++    struct wl_data_offer*       dragOffer;+    _GLFWwindow*                dragFocus;+    uint32_t                    dragSerial;++    const char*                 tag;+     struct wl_cursor_theme*     cursorTheme;     struct wl_cursor_theme*     cursorThemeHiDPI;     struct wl_surface*          cursorSurface;     const char*                 cursorPreviousName;     int                         cursorTimerfd;     uint32_t                    serial;+    uint32_t                    pointerEnterSerial; -    int32_t                     keyboardRepeatRate;-    int32_t                     keyboardRepeatDelay;-    int                         keyboardLastKey;-    int                         keyboardLastScancode;+    int                         keyRepeatTimerfd;+    int32_t                     keyRepeatRate;+    int32_t                     keyRepeatDelay;+    int                         keyRepeatScancode;+     char*                       clipboardString;-    size_t                      clipboardSize;-    char*                       clipboardSendString;-    size_t                      clipboardSendSize;-    int                         timerfd;     short int                   keycodes[256];     short int                   scancodes[GLFW_KEY_LAST + 1];+    char                        keynames[GLFW_KEY_LAST + 1][5];      struct {         void*                   handle;         struct xkb_context*     context;         struct xkb_keymap*      keymap;         struct xkb_state*       state;--#ifdef HAVE_XKBCOMMON_COMPOSE_H         struct xkb_compose_state* composeState;-#endif -        xkb_mod_mask_t          controlMask;-        xkb_mod_mask_t          altMask;-        xkb_mod_mask_t          shiftMask;-        xkb_mod_mask_t          superMask;-        xkb_mod_mask_t          capsLockMask;-        xkb_mod_mask_t          numLockMask;+        xkb_mod_index_t         controlIndex;+        xkb_mod_index_t         altIndex;+        xkb_mod_index_t         shiftIndex;+        xkb_mod_index_t         superIndex;+        xkb_mod_index_t         capsLockIndex;+        xkb_mod_index_t         numLockIndex;         unsigned int            modifiers;          PFN_xkb_context_new context_new;@@ -289,13 +427,14 @@         PFN_xkb_keymap_unref keymap_unref;         PFN_xkb_keymap_mod_get_index keymap_mod_get_index;         PFN_xkb_keymap_key_repeats keymap_key_repeats;+        PFN_xkb_keymap_key_get_syms_by_level keymap_key_get_syms_by_level;         PFN_xkb_state_new state_new;         PFN_xkb_state_unref state_unref;         PFN_xkb_state_key_get_syms state_key_get_syms;         PFN_xkb_state_update_mask state_update_mask;-        PFN_xkb_state_serialize_mods state_serialize_mods;+        PFN_xkb_state_key_get_layout state_key_get_layout;+        PFN_xkb_state_mod_index_is_active state_mod_index_is_active; -#ifdef HAVE_XKBCOMMON_COMPOSE_H         PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;         PFN_xkb_compose_table_unref compose_table_unref;         PFN_xkb_compose_state_new compose_state_new;@@ -303,7 +442,6 @@         PFN_xkb_compose_state_feed compose_state_feed;         PFN_xkb_compose_state_get_status compose_state_get_status;         PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;-#endif     } xkb;      _GLFWwindow*                pointerFocus;@@ -326,6 +464,37 @@         PFN_wl_egl_window_resize window_resize;     } egl; +    struct {+        void*                   handle;+        struct libdecor*        context;+        struct wl_callback*     callback;+        GLFWbool                ready;+        PFN_libdecor_new        libdecor_new_;+        PFN_libdecor_unref      libdecor_unref_;+        PFN_libdecor_get_fd     libdecor_get_fd_;+        PFN_libdecor_dispatch   libdecor_dispatch_;+        PFN_libdecor_decorate   libdecor_decorate_;+        PFN_libdecor_frame_unref libdecor_frame_unref_;+        PFN_libdecor_frame_set_app_id libdecor_frame_set_app_id_;+        PFN_libdecor_frame_set_title libdecor_frame_set_title_;+        PFN_libdecor_frame_set_minimized libdecor_frame_set_minimized_;+        PFN_libdecor_frame_set_fullscreen libdecor_frame_set_fullscreen_;+        PFN_libdecor_frame_unset_fullscreen libdecor_frame_unset_fullscreen_;+        PFN_libdecor_frame_map libdecor_frame_map_;+        PFN_libdecor_frame_commit libdecor_frame_commit_;+        PFN_libdecor_frame_set_min_content_size libdecor_frame_set_min_content_size_;+        PFN_libdecor_frame_set_max_content_size libdecor_frame_set_max_content_size_;+        PFN_libdecor_frame_set_maximized libdecor_frame_set_maximized_;+        PFN_libdecor_frame_unset_maximized libdecor_frame_unset_maximized_;+        PFN_libdecor_frame_set_capabilities libdecor_frame_set_capabilities_;+        PFN_libdecor_frame_unset_capabilities libdecor_frame_unset_capabilities_;+        PFN_libdecor_frame_set_visibility libdecor_frame_set_visibility_;+        PFN_libdecor_frame_get_xdg_toplevel libdecor_frame_get_xdg_toplevel_;+        PFN_libdecor_configuration_get_content_size libdecor_configuration_get_content_size_;+        PFN_libdecor_configuration_get_window_state libdecor_configuration_get_window_state_;+        PFN_libdecor_state_new libdecor_state_new_;+        PFN_libdecor_state_free libdecor_state_free_;+    } libdecor; } _GLFWlibraryWayland;  // Wayland-specific per-monitor data@@ -338,8 +507,7 @@      int                         x;     int                         y;-    int                         scale;-+    int                         contentScale; } _GLFWmonitorWayland;  // Wayland-specific per-cursor data@@ -354,6 +522,9 @@     int                         currentImage; } _GLFWcursorWayland; - void _glfwAddOutputWayland(uint32_t name, uint32_t version);+void _glfwUpdateContentScaleWayland(_GLFWwindow* window);++void _glfwAddSeatListenerWayland(struct wl_seat* seat);+void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device); 
glfw/src/wl_window.c view
@@ -33,1781 +33,2944 @@ #include <stdio.h> #include <stdlib.h> #include <errno.h>-#include <unistd.h>-#include <string.h>-#include <fcntl.h>-#include <sys/mman.h>-#include <sys/timerfd.h>-#include <poll.h>---static void shellSurfaceHandlePing(void* data,-                                   struct wl_shell_surface* shellSurface,-                                   uint32_t serial)-{-    wl_shell_surface_pong(shellSurface, serial);-}--static void shellSurfaceHandleConfigure(void* data,-                                        struct wl_shell_surface* shellSurface,-                                        uint32_t edges,-                                        int32_t width,-                                        int32_t height)-{-    _GLFWwindow* window = data;-    float aspectRatio;-    float targetRatio;--    if (!window->monitor)-    {-        if (_glfw.wl.viewporter && window->decorated)-        {-            width -= _GLFW_DECORATION_HORIZONTAL;-            height -= _GLFW_DECORATION_VERTICAL;-        }-        if (width < 1)-            width = 1;-        if (height < 1)-            height = 1;--        if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)-        {-            aspectRatio = (float)width / (float)height;-            targetRatio = (float)window->numer / (float)window->denom;-            if (aspectRatio < targetRatio)-                height = width / targetRatio;-            else if (aspectRatio > targetRatio)-                width = height * targetRatio;-        }--        if (window->minwidth != GLFW_DONT_CARE && width < window->minwidth)-            width = window->minwidth;-        else if (window->maxwidth != GLFW_DONT_CARE && width > window->maxwidth)-            width = window->maxwidth;--        if (window->minheight != GLFW_DONT_CARE && height < window->minheight)-            height = window->minheight;-        else if (window->maxheight != GLFW_DONT_CARE && height > window->maxheight)-            height = window->maxheight;-    }--    _glfwInputWindowSize(window, width, height);-    _glfwPlatformSetWindowSize(window, width, height);-    _glfwInputWindowDamage(window);-}--static void shellSurfaceHandlePopupDone(void* data,-                                        struct wl_shell_surface* shellSurface)-{-}--static const struct wl_shell_surface_listener shellSurfaceListener = {-    shellSurfaceHandlePing,-    shellSurfaceHandleConfigure,-    shellSurfaceHandlePopupDone-};--static int createTmpfileCloexec(char* tmpname)-{-    int fd;--    fd = mkostemp(tmpname, O_CLOEXEC);-    if (fd >= 0)-        unlink(tmpname);--    return fd;-}--/*- * Create a new, unique, anonymous file of the given size, and- * return the file descriptor for it. The file descriptor is set- * CLOEXEC. The file is immediately suitable for mmap()'ing- * the given size at offset zero.- *- * The file should not have a permanent backing store like a disk,- * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.- *- * The file name is deleted from the file system.- *- * The file is suitable for buffer sharing between processes by- * transmitting the file descriptor over Unix sockets using the- * SCM_RIGHTS methods.- *- * posix_fallocate() is used to guarantee that disk space is available- * for the file at the given size. If disk space is insufficient, errno- * is set to ENOSPC. If posix_fallocate() is not supported, program may- * receive SIGBUS on accessing mmap()'ed file contents instead.- */-static int createAnonymousFile(off_t size)-{-    static const char template[] = "/glfw-shared-XXXXXX";-    const char* path;-    char* name;-    int fd;-    int ret;--#ifdef HAVE_MEMFD_CREATE-    fd = memfd_create("glfw-shared", MFD_CLOEXEC | MFD_ALLOW_SEALING);-    if (fd >= 0)-    {-        // We can add this seal before calling posix_fallocate(), as the file-        // is currently zero-sized anyway.-        //-        // There is also no need to check for the return value, we couldn’t do-        // anything with it anyway.-        fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);-    }-    else-#elif defined(SHM_ANON)-    fd = shm_open(SHM_ANON, O_RDWR | O_CLOEXEC, 0600);-    if (fd < 0)-#endif-    {-        path = getenv("XDG_RUNTIME_DIR");-        if (!path)-        {-            errno = ENOENT;-            return -1;-        }--        name = calloc(strlen(path) + sizeof(template), 1);-        strcpy(name, path);-        strcat(name, template);--        fd = createTmpfileCloexec(name);-        free(name);-        if (fd < 0)-            return -1;-    }--#if defined(SHM_ANON)-    // posix_fallocate does not work on SHM descriptors-    ret = ftruncate(fd, size);-#else-    ret = posix_fallocate(fd, 0, size);-#endif-    if (ret != 0)-    {-        close(fd);-        errno = ret;-        return -1;-    }-    return fd;-}--static struct wl_buffer* createShmBuffer(const GLFWimage* image)-{-    struct wl_shm_pool* pool;-    struct wl_buffer* buffer;-    int stride = image->width * 4;-    int length = image->width * image->height * 4;-    void* data;-    int fd, i;--    fd = createAnonymousFile(length);-    if (fd < 0)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Creating a buffer file for %d B failed: %m",-                        length);-        return NULL;-    }--    data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);-    if (data == MAP_FAILED)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: mmap failed: %m");-        close(fd);-        return NULL;-    }--    pool = wl_shm_create_pool(_glfw.wl.shm, fd, length);--    close(fd);-    unsigned char* source = (unsigned char*) image->pixels;-    unsigned char* target = data;-    for (i = 0;  i < image->width * image->height;  i++, source += 4)-    {-        unsigned int alpha = source[3];--        *target++ = (unsigned char) ((source[2] * alpha) / 255);-        *target++ = (unsigned char) ((source[1] * alpha) / 255);-        *target++ = (unsigned char) ((source[0] * alpha) / 255);-        *target++ = (unsigned char) alpha;-    }--    buffer =-        wl_shm_pool_create_buffer(pool, 0,-                                  image->width,-                                  image->height,-                                  stride, WL_SHM_FORMAT_ARGB8888);-    munmap(data, length);-    wl_shm_pool_destroy(pool);--    return buffer;-}--static void createDecoration(_GLFWdecorationWayland* decoration,-                             struct wl_surface* parent,-                             struct wl_buffer* buffer, GLFWbool opaque,-                             int x, int y,-                             int width, int height)-{-    struct wl_region* region;--    decoration->surface = wl_compositor_create_surface(_glfw.wl.compositor);-    decoration->subsurface =-        wl_subcompositor_get_subsurface(_glfw.wl.subcompositor,-                                        decoration->surface, parent);-    wl_subsurface_set_position(decoration->subsurface, x, y);-    decoration->viewport = wp_viewporter_get_viewport(_glfw.wl.viewporter,-                                                      decoration->surface);-    wp_viewport_set_destination(decoration->viewport, width, height);-    wl_surface_attach(decoration->surface, buffer, 0, 0);--    if (opaque)-    {-        region = wl_compositor_create_region(_glfw.wl.compositor);-        wl_region_add(region, 0, 0, width, height);-        wl_surface_set_opaque_region(decoration->surface, region);-        wl_surface_commit(decoration->surface);-        wl_region_destroy(region);-    }-    else-        wl_surface_commit(decoration->surface);-}--static void createDecorations(_GLFWwindow* window)-{-    unsigned char data[] = { 224, 224, 224, 255 };-    const GLFWimage image = { 1, 1, data };-    GLFWbool opaque = (data[3] == 255);--    if (!_glfw.wl.viewporter || !window->decorated || window->wl.decorations.serverSide)-        return;--    if (!window->wl.decorations.buffer)-        window->wl.decorations.buffer = createShmBuffer(&image);-    if (!window->wl.decorations.buffer)-        return;--    createDecoration(&window->wl.decorations.top, window->wl.surface,-                     window->wl.decorations.buffer, opaque,-                     0, -_GLFW_DECORATION_TOP,-                     window->wl.width, _GLFW_DECORATION_TOP);-    createDecoration(&window->wl.decorations.left, window->wl.surface,-                     window->wl.decorations.buffer, opaque,-                     -_GLFW_DECORATION_WIDTH, -_GLFW_DECORATION_TOP,-                     _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);-    createDecoration(&window->wl.decorations.right, window->wl.surface,-                     window->wl.decorations.buffer, opaque,-                     window->wl.width, -_GLFW_DECORATION_TOP,-                     _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);-    createDecoration(&window->wl.decorations.bottom, window->wl.surface,-                     window->wl.decorations.buffer, opaque,-                     -_GLFW_DECORATION_WIDTH, window->wl.height,-                     window->wl.width + _GLFW_DECORATION_HORIZONTAL, _GLFW_DECORATION_WIDTH);-}--static void destroyDecoration(_GLFWdecorationWayland* decoration)-{-    if (decoration->surface)-        wl_surface_destroy(decoration->surface);-    if (decoration->subsurface)-        wl_subsurface_destroy(decoration->subsurface);-    if (decoration->viewport)-        wp_viewport_destroy(decoration->viewport);-    decoration->surface = NULL;-    decoration->subsurface = NULL;-    decoration->viewport = NULL;-}--static void destroyDecorations(_GLFWwindow* window)-{-    destroyDecoration(&window->wl.decorations.top);-    destroyDecoration(&window->wl.decorations.left);-    destroyDecoration(&window->wl.decorations.right);-    destroyDecoration(&window->wl.decorations.bottom);-}--static void xdgDecorationHandleConfigure(void* data,-                                         struct zxdg_toplevel_decoration_v1* decoration,-                                         uint32_t mode)-{-    _GLFWwindow* window = data;--    window->wl.decorations.serverSide = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);--    if (!window->wl.decorations.serverSide)-        createDecorations(window);-}--static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener = {-    xdgDecorationHandleConfigure,-};--// Makes the surface considered as XRGB instead of ARGB.-static void setOpaqueRegion(_GLFWwindow* window)-{-    struct wl_region* region;--    region = wl_compositor_create_region(_glfw.wl.compositor);-    if (!region)-        return;--    wl_region_add(region, 0, 0, window->wl.width, window->wl.height);-    wl_surface_set_opaque_region(window->wl.surface, region);-    wl_surface_commit(window->wl.surface);-    wl_region_destroy(region);-}---static void resizeWindow(_GLFWwindow* window)-{-    int scale = window->wl.scale;-    int scaledWidth = window->wl.width * scale;-    int scaledHeight = window->wl.height * scale;-    wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);-    if (!window->wl.transparent)-        setOpaqueRegion(window);-    _glfwInputFramebufferSize(window, scaledWidth, scaledHeight);-    _glfwInputWindowContentScale(window, scale, scale);--    if (!window->wl.decorations.top.surface)-        return;--    // Top decoration.-    wp_viewport_set_destination(window->wl.decorations.top.viewport,-                                window->wl.width, _GLFW_DECORATION_TOP);-    wl_surface_commit(window->wl.decorations.top.surface);--    // Left decoration.-    wp_viewport_set_destination(window->wl.decorations.left.viewport,-                                _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);-    wl_surface_commit(window->wl.decorations.left.surface);--    // Right decoration.-    wl_subsurface_set_position(window->wl.decorations.right.subsurface,-                               window->wl.width, -_GLFW_DECORATION_TOP);-    wp_viewport_set_destination(window->wl.decorations.right.viewport,-                                _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);-    wl_surface_commit(window->wl.decorations.right.surface);--    // Bottom decoration.-    wl_subsurface_set_position(window->wl.decorations.bottom.subsurface,-                               -_GLFW_DECORATION_WIDTH, window->wl.height);-    wp_viewport_set_destination(window->wl.decorations.bottom.viewport,-                                window->wl.width + _GLFW_DECORATION_HORIZONTAL, _GLFW_DECORATION_WIDTH);-    wl_surface_commit(window->wl.decorations.bottom.surface);-}--static void checkScaleChange(_GLFWwindow* window)-{-    int scale = 1;-    int i;-    int monitorScale;--    // Check if we will be able to set the buffer scale or not.-    if (_glfw.wl.compositorVersion < 3)-        return;--    // Get the scale factor from the highest scale monitor.-    for (i = 0; i < window->wl.monitorsCount; ++i)-    {-        monitorScale = window->wl.monitors[i]->wl.scale;-        if (scale < monitorScale)-            scale = monitorScale;-    }--    // Only change the framebuffer size if the scale changed.-    if (scale != window->wl.scale)-    {-        window->wl.scale = scale;-        wl_surface_set_buffer_scale(window->wl.surface, scale);-        resizeWindow(window);-    }-}--static void surfaceHandleEnter(void *data,-                               struct wl_surface *surface,-                               struct wl_output *output)-{-    _GLFWwindow* window = data;-    _GLFWmonitor* monitor = wl_output_get_user_data(output);--    if (window->wl.monitorsCount + 1 > window->wl.monitorsSize)-    {-        ++window->wl.monitorsSize;-        window->wl.monitors =-            realloc(window->wl.monitors,-                    window->wl.monitorsSize * sizeof(_GLFWmonitor*));-    }--    window->wl.monitors[window->wl.monitorsCount++] = monitor;--    checkScaleChange(window);-}--static void surfaceHandleLeave(void *data,-                               struct wl_surface *surface,-                               struct wl_output *output)-{-    _GLFWwindow* window = data;-    _GLFWmonitor* monitor = wl_output_get_user_data(output);-    GLFWbool found;-    int i;--    for (i = 0, found = GLFW_FALSE; i < window->wl.monitorsCount - 1; ++i)-    {-        if (monitor == window->wl.monitors[i])-            found = GLFW_TRUE;-        if (found)-            window->wl.monitors[i] = window->wl.monitors[i + 1];-    }-    window->wl.monitors[--window->wl.monitorsCount] = NULL;--    checkScaleChange(window);-}--static const struct wl_surface_listener surfaceListener = {-    surfaceHandleEnter,-    surfaceHandleLeave-};--static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)-{-    if (enable && !window->wl.idleInhibitor && _glfw.wl.idleInhibitManager)-    {-        window->wl.idleInhibitor =-            zwp_idle_inhibit_manager_v1_create_inhibitor(-                _glfw.wl.idleInhibitManager, window->wl.surface);-        if (!window->wl.idleInhibitor)-            _glfwInputError(GLFW_PLATFORM_ERROR,-                            "Wayland: Idle inhibitor creation failed");-    }-    else if (!enable && window->wl.idleInhibitor)-    {-        zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);-        window->wl.idleInhibitor = NULL;-    }-}--static GLFWbool createSurface(_GLFWwindow* window,-                              const _GLFWwndconfig* wndconfig)-{-    window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor);-    if (!window->wl.surface)-        return GLFW_FALSE;--    wl_surface_add_listener(window->wl.surface,-                            &surfaceListener,-                            window);--    wl_surface_set_user_data(window->wl.surface, window);--    window->wl.native = wl_egl_window_create(window->wl.surface,-                                             wndconfig->width,-                                             wndconfig->height);-    if (!window->wl.native)-        return GLFW_FALSE;--    window->wl.width = wndconfig->width;-    window->wl.height = wndconfig->height;-    window->wl.scale = 1;--    if (!window->wl.transparent)-        setOpaqueRegion(window);--    return GLFW_TRUE;-}--static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor,-                          int refreshRate)-{-    if (window->wl.xdg.toplevel)-    {-        xdg_toplevel_set_fullscreen(-            window->wl.xdg.toplevel,-            monitor->wl.output);-    }-    else if (window->wl.shellSurface)-    {-        wl_shell_surface_set_fullscreen(-            window->wl.shellSurface,-            WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,-            refreshRate * 1000, // Convert Hz to mHz.-            monitor->wl.output);-    }-    setIdleInhibitor(window, GLFW_TRUE);-    if (!window->wl.decorations.serverSide)-        destroyDecorations(window);-}--static GLFWbool createShellSurface(_GLFWwindow* window)-{-    if (!_glfw.wl.shell)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: wl_shell protocol not available");-        return GLFW_FALSE;-    }--    window->wl.shellSurface = wl_shell_get_shell_surface(_glfw.wl.shell,-                                                         window->wl.surface);-    if (!window->wl.shellSurface)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Shell surface creation failed");-        return GLFW_FALSE;-    }--    wl_shell_surface_add_listener(window->wl.shellSurface,-                                  &shellSurfaceListener,-                                  window);--    if (window->wl.title)-        wl_shell_surface_set_title(window->wl.shellSurface, window->wl.title);--    if (window->monitor)-    {-        setFullscreen(window, window->monitor, 0);-    }-    else if (window->wl.maximized)-    {-        wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);-        setIdleInhibitor(window, GLFW_FALSE);-        createDecorations(window);-    }-    else-    {-        wl_shell_surface_set_toplevel(window->wl.shellSurface);-        setIdleInhibitor(window, GLFW_FALSE);-        createDecorations(window);-    }--    wl_surface_commit(window->wl.surface);--    return GLFW_TRUE;-}--static void xdgToplevelHandleConfigure(void* data,-                                       struct xdg_toplevel* toplevel,-                                       int32_t width,-                                       int32_t height,-                                       struct wl_array* states)-{-    _GLFWwindow* window = data;-    float aspectRatio;-    float targetRatio;-    uint32_t* state;-    GLFWbool maximized = GLFW_FALSE;-    GLFWbool fullscreen = GLFW_FALSE;-    GLFWbool activated = GLFW_FALSE;--    wl_array_for_each(state, states)-    {-        switch (*state)-        {-            case XDG_TOPLEVEL_STATE_MAXIMIZED:-                maximized = GLFW_TRUE;-                break;-            case XDG_TOPLEVEL_STATE_FULLSCREEN:-                fullscreen = GLFW_TRUE;-                break;-            case XDG_TOPLEVEL_STATE_RESIZING:-                break;-            case XDG_TOPLEVEL_STATE_ACTIVATED:-                activated = GLFW_TRUE;-                break;-        }-    }--    if (width != 0 && height != 0)-    {-        if (!maximized && !fullscreen)-        {-            if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)-            {-                aspectRatio = (float)width / (float)height;-                targetRatio = (float)window->numer / (float)window->denom;-                if (aspectRatio < targetRatio)-                    height = width / targetRatio;-                else if (aspectRatio > targetRatio)-                    width = height * targetRatio;-            }-        }--        _glfwInputWindowSize(window, width, height);-        _glfwPlatformSetWindowSize(window, width, height);-        _glfwInputWindowDamage(window);-    }--    if (window->wl.wasFullscreen && window->autoIconify)-    {-        if (!activated || !fullscreen)-        {-            _glfwPlatformIconifyWindow(window);-            window->wl.wasFullscreen = GLFW_FALSE;-        }-    }-    if (fullscreen && activated)-        window->wl.wasFullscreen = GLFW_TRUE;-    _glfwInputWindowFocus(window, activated);-}--static void xdgToplevelHandleClose(void* data,-                                   struct xdg_toplevel* toplevel)-{-    _GLFWwindow* window = data;-    _glfwInputWindowCloseRequest(window);-}--static const struct xdg_toplevel_listener xdgToplevelListener = {-    xdgToplevelHandleConfigure,-    xdgToplevelHandleClose-};--static void xdgSurfaceHandleConfigure(void* data,-                                      struct xdg_surface* surface,-                                      uint32_t serial)-{-    xdg_surface_ack_configure(surface, serial);-}--static const struct xdg_surface_listener xdgSurfaceListener = {-    xdgSurfaceHandleConfigure-};--static void setXdgDecorations(_GLFWwindow* window)-{-    if (_glfw.wl.decorationManager)-    {-        window->wl.xdg.decoration =-            zxdg_decoration_manager_v1_get_toplevel_decoration(-                _glfw.wl.decorationManager, window->wl.xdg.toplevel);-        zxdg_toplevel_decoration_v1_add_listener(window->wl.xdg.decoration,-                                                 &xdgDecorationListener,-                                                 window);-        zxdg_toplevel_decoration_v1_set_mode(-            window->wl.xdg.decoration,-            ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);-    }-    else-    {-        window->wl.decorations.serverSide = GLFW_FALSE;-        createDecorations(window);-    }-}--static GLFWbool createXdgSurface(_GLFWwindow* window)-{-    window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,-                                                         window->wl.surface);-    if (!window->wl.xdg.surface)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: xdg-surface creation failed");-        return GLFW_FALSE;-    }--    xdg_surface_add_listener(window->wl.xdg.surface,-                             &xdgSurfaceListener,-                             window);--    window->wl.xdg.toplevel = xdg_surface_get_toplevel(window->wl.xdg.surface);-    if (!window->wl.xdg.toplevel)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: xdg-toplevel creation failed");-        return GLFW_FALSE;-    }--    xdg_toplevel_add_listener(window->wl.xdg.toplevel,-                              &xdgToplevelListener,-                              window);--    if (window->wl.title)-        xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title);--    if (window->minwidth != GLFW_DONT_CARE && window->minheight != GLFW_DONT_CARE)-        xdg_toplevel_set_min_size(window->wl.xdg.toplevel,-                                  window->minwidth, window->minheight);-    if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE)-        xdg_toplevel_set_max_size(window->wl.xdg.toplevel,-                                  window->maxwidth, window->maxheight);--    if (window->monitor)-    {-        xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel,-                                    window->monitor->wl.output);-        setIdleInhibitor(window, GLFW_TRUE);-    }-    else if (window->wl.maximized)-    {-        xdg_toplevel_set_maximized(window->wl.xdg.toplevel);-        setIdleInhibitor(window, GLFW_FALSE);-        setXdgDecorations(window);-    }-    else-    {-        setIdleInhibitor(window, GLFW_FALSE);-        setXdgDecorations(window);-    }--    wl_surface_commit(window->wl.surface);-    wl_display_roundtrip(_glfw.wl.display);--    return GLFW_TRUE;-}--static void setCursorImage(_GLFWwindow* window,-                           _GLFWcursorWayland* cursorWayland)-{-    struct itimerspec timer = {};-    struct wl_cursor* wlCursor = cursorWayland->cursor;-    struct wl_cursor_image* image;-    struct wl_buffer* buffer;-    struct wl_surface* surface = _glfw.wl.cursorSurface;-    int scale = 1;--    if (!wlCursor)-        buffer = cursorWayland->buffer;-    else-    {-        if (window->wl.scale > 1 && cursorWayland->cursorHiDPI)-        {-            wlCursor = cursorWayland->cursorHiDPI;-            scale = 2;-        }--        image = wlCursor->images[cursorWayland->currentImage];-        buffer = wl_cursor_image_get_buffer(image);-        if (!buffer)-            return;--        timer.it_value.tv_sec = image->delay / 1000;-        timer.it_value.tv_nsec = (image->delay % 1000) * 1000000;-        timerfd_settime(_glfw.wl.cursorTimerfd, 0, &timer, NULL);--        cursorWayland->width = image->width;-        cursorWayland->height = image->height;-        cursorWayland->xhot = image->hotspot_x;-        cursorWayland->yhot = image->hotspot_y;-    }--    wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,-                          surface,-                          cursorWayland->xhot / scale,-                          cursorWayland->yhot / scale);-    wl_surface_set_buffer_scale(surface, scale);-    wl_surface_attach(surface, buffer, 0, 0);-    wl_surface_damage(surface, 0, 0,-                      cursorWayland->width, cursorWayland->height);-    wl_surface_commit(surface);-}--static void incrementCursorImage(_GLFWwindow* window)-{-    _GLFWcursor* cursor;--    if (!window || window->wl.decorations.focus != mainWindow)-        return;--    cursor = window->wl.currentCursor;-    if (cursor && cursor->wl.cursor)-    {-        cursor->wl.currentImage += 1;-        cursor->wl.currentImage %= cursor->wl.cursor->image_count;-        setCursorImage(window, &cursor->wl);-    }-}--static void handleEvents(int timeout)-{-    struct wl_display* display = _glfw.wl.display;-    struct pollfd fds[] = {-        { wl_display_get_fd(display), POLLIN },-        { _glfw.wl.timerfd, POLLIN },-        { _glfw.wl.cursorTimerfd, POLLIN },-    };-    ssize_t read_ret;-    uint64_t repeats, i;--    while (wl_display_prepare_read(display) != 0)-        wl_display_dispatch_pending(display);--    // If an error different from EAGAIN happens, we have likely been-    // disconnected from the Wayland session, try to handle that the best we-    // can.-    if (wl_display_flush(display) < 0 && errno != EAGAIN)-    {-        _GLFWwindow* window = _glfw.windowListHead;-        while (window)-        {-            _glfwInputWindowCloseRequest(window);-            window = window->next;-        }-        wl_display_cancel_read(display);-        return;-    }--    if (poll(fds, 3, timeout) > 0)-    {-        if (fds[0].revents & POLLIN)-        {-            wl_display_read_events(display);-            wl_display_dispatch_pending(display);-        }-        else-        {-            wl_display_cancel_read(display);-        }--        if (fds[1].revents & POLLIN)-        {-            read_ret = read(_glfw.wl.timerfd, &repeats, sizeof(repeats));-            if (read_ret != 8)-                return;--            for (i = 0; i < repeats; ++i)-                _glfwInputKey(_glfw.wl.keyboardFocus, _glfw.wl.keyboardLastKey,-                              _glfw.wl.keyboardLastScancode, GLFW_REPEAT,-                              _glfw.wl.xkb.modifiers);-        }--        if (fds[2].revents & POLLIN)-        {-            read_ret = read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats));-            if (read_ret != 8)-                return;--            incrementCursorImage(_glfw.wl.pointerFocus);-        }-    }-    else-    {-        wl_display_cancel_read(display);-    }-}--// Translates a GLFW standard cursor to a theme cursor name-//-static char *translateCursorShape(int shape)-{-    switch (shape)-    {-        case GLFW_ARROW_CURSOR:-            return "left_ptr";-        case GLFW_IBEAM_CURSOR:-            return "xterm";-        case GLFW_CROSSHAIR_CURSOR:-            return "crosshair";-        case GLFW_HAND_CURSOR:-            return "hand2";-        case GLFW_HRESIZE_CURSOR:-            return "sb_h_double_arrow";-        case GLFW_VRESIZE_CURSOR:-            return "sb_v_double_arrow";-    }-    return NULL;-}--//////////////////////////////////////////////////////////////////////////-//////                       GLFW platform API                      //////-//////////////////////////////////////////////////////////////////////////--int _glfwPlatformCreateWindow(_GLFWwindow* window,-                              const _GLFWwndconfig* wndconfig,-                              const _GLFWctxconfig* ctxconfig,-                              const _GLFWfbconfig* fbconfig)-{-    window->wl.transparent = fbconfig->transparent;--    if (!createSurface(window, wndconfig))-        return GLFW_FALSE;--    if (ctxconfig->client != GLFW_NO_API)-    {-        if (ctxconfig->source == GLFW_EGL_CONTEXT_API ||-            ctxconfig->source == GLFW_NATIVE_CONTEXT_API)-        {-            if (!_glfwInitEGL())-                return GLFW_FALSE;-            if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))-                return GLFW_FALSE;-        }-        else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)-        {-            if (!_glfwInitOSMesa())-                return GLFW_FALSE;-            if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))-                return GLFW_FALSE;-        }-    }--    if (wndconfig->title)-        window->wl.title = _glfw_strdup(wndconfig->title);--    if (wndconfig->visible)-    {-        if (_glfw.wl.wmBase)-        {-            if (!createXdgSurface(window))-                return GLFW_FALSE;-        }-        else-        {-            if (!createShellSurface(window))-                return GLFW_FALSE;-        }--        window->wl.visible = GLFW_TRUE;-    }-    else-    {-        window->wl.xdg.surface = NULL;-        window->wl.xdg.toplevel = NULL;-        window->wl.shellSurface = NULL;-        window->wl.visible = GLFW_FALSE;-    }--    window->wl.currentCursor = NULL;--    window->wl.monitors = calloc(1, sizeof(_GLFWmonitor*));-    window->wl.monitorsCount = 0;-    window->wl.monitorsSize = 1;--    return GLFW_TRUE;-}--void _glfwPlatformDestroyWindow(_GLFWwindow* window)-{-    if (window == _glfw.wl.pointerFocus)-    {-        _glfw.wl.pointerFocus = NULL;-        _glfwInputCursorEnter(window, GLFW_FALSE);-    }-    if (window == _glfw.wl.keyboardFocus)-    {-        _glfw.wl.keyboardFocus = NULL;-        _glfwInputWindowFocus(window, GLFW_FALSE);-    }--    if (window->wl.idleInhibitor)-        zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);--    if (window->context.destroy)-        window->context.destroy(window);--    destroyDecorations(window);-    if (window->wl.xdg.decoration)-        zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);--    if (window->wl.decorations.buffer)-        wl_buffer_destroy(window->wl.decorations.buffer);--    if (window->wl.native)-        wl_egl_window_destroy(window->wl.native);--    if (window->wl.shellSurface)-        wl_shell_surface_destroy(window->wl.shellSurface);--    if (window->wl.xdg.toplevel)-        xdg_toplevel_destroy(window->wl.xdg.toplevel);--    if (window->wl.xdg.surface)-        xdg_surface_destroy(window->wl.xdg.surface);--    if (window->wl.surface)-        wl_surface_destroy(window->wl.surface);--    free(window->wl.title);-    free(window->wl.monitors);-}--void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)-{-    if (window->wl.title)-        free(window->wl.title);-    window->wl.title = _glfw_strdup(title);-    if (window->wl.xdg.toplevel)-        xdg_toplevel_set_title(window->wl.xdg.toplevel, title);-    else if (window->wl.shellSurface)-        wl_shell_surface_set_title(window->wl.shellSurface, title);-}--void _glfwPlatformSetWindowIcon(_GLFWwindow* window,-                                int count, const GLFWimage* images)-{-    _glfwInputError(GLFW_PLATFORM_ERROR,-                    "Wayland: Setting window icon not supported");-}--void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)-{-    // A Wayland client is not aware of its position, so just warn and leave it-    // as (0, 0)--    _glfwInputError(GLFW_PLATFORM_ERROR,-                    "Wayland: Window position retrieval not supported");-}--void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)-{-    // A Wayland client can not set its position, so just warn--    _glfwInputError(GLFW_PLATFORM_ERROR,-                    "Wayland: Window position setting not supported");-}--void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)-{-    if (width)-        *width = window->wl.width;-    if (height)-        *height = window->wl.height;-}--void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)-{-    window->wl.width = width;-    window->wl.height = height;-    resizeWindow(window);-}--void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,-                                      int minwidth, int minheight,-                                      int maxwidth, int maxheight)-{-    if (_glfw.wl.wmBase)-    {-        if (window->wl.xdg.toplevel)-        {-            if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)-                minwidth = minheight = 0;-            if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)-                maxwidth = maxheight = 0;-            xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight);-            xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight);-            wl_surface_commit(window->wl.surface);-        }-    }-    else-    {-        // TODO: find out how to trigger a resize.-        // The actual limits are checked in the wl_shell_surface::configure handler.-    }-}--void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window,-                                       int numer, int denom)-{-    // TODO: find out how to trigger a resize.-    // The actual limits are checked in the wl_shell_surface::configure handler.-}--void _glfwPlatformGetFramebufferSize(_GLFWwindow* window,-                                     int* width, int* height)-{-    _glfwPlatformGetWindowSize(window, width, height);-    *width *= window->wl.scale;-    *height *= window->wl.scale;-}--void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,-                                     int* left, int* top,-                                     int* right, int* bottom)-{-    if (window->decorated && !window->monitor && !window->wl.decorations.serverSide)-    {-        if (top)-            *top = _GLFW_DECORATION_TOP;-        if (left)-            *left = _GLFW_DECORATION_WIDTH;-        if (right)-            *right = _GLFW_DECORATION_WIDTH;-        if (bottom)-            *bottom = _GLFW_DECORATION_WIDTH;-    }-}--void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,-                                        float* xscale, float* yscale)-{-    if (xscale)-        *xscale = (float) window->wl.scale;-    if (yscale)-        *yscale = (float) window->wl.scale;-}--void _glfwPlatformIconifyWindow(_GLFWwindow* window)-{-    if (_glfw.wl.wmBase)-    {-        if (window->wl.xdg.toplevel)-            xdg_toplevel_set_minimized(window->wl.xdg.toplevel);-    }-    else-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Iconify window not supported on wl_shell");-    }-}--void _glfwPlatformRestoreWindow(_GLFWwindow* window)-{-    if (window->wl.xdg.toplevel)-    {-        if (window->monitor)-            xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);-        if (window->wl.maximized)-            xdg_toplevel_unset_maximized(window->wl.xdg.toplevel);-        // There is no way to unset minimized, or even to know if we are-        // minimized, so there is nothing to do here.-    }-    else if (window->wl.shellSurface)-    {-        if (window->monitor || window->wl.maximized)-            wl_shell_surface_set_toplevel(window->wl.shellSurface);-    }-    _glfwInputWindowMonitor(window, NULL);-    window->wl.maximized = GLFW_FALSE;-}--void _glfwPlatformMaximizeWindow(_GLFWwindow* window)-{-    if (window->wl.xdg.toplevel)-    {-        xdg_toplevel_set_maximized(window->wl.xdg.toplevel);-    }-    else if (window->wl.shellSurface)-    {-        // Let the compositor select the best output.-        wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);-    }-    window->wl.maximized = GLFW_TRUE;-}--void _glfwPlatformShowWindow(_GLFWwindow* window)-{-    if (!window->wl.visible)-    {-        if (_glfw.wl.wmBase)-            createXdgSurface(window);-        else if (!window->wl.shellSurface)-            createShellSurface(window);-        window->wl.visible = GLFW_TRUE;-    }-}--void _glfwPlatformHideWindow(_GLFWwindow* window)-{-    if (window->wl.xdg.toplevel)-    {-        xdg_toplevel_destroy(window->wl.xdg.toplevel);-        xdg_surface_destroy(window->wl.xdg.surface);-        window->wl.xdg.toplevel = NULL;-        window->wl.xdg.surface = NULL;-    }-    else if (window->wl.shellSurface)-    {-        wl_shell_surface_destroy(window->wl.shellSurface);-        window->wl.shellSurface = NULL;-    }-    window->wl.visible = GLFW_FALSE;-}--void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)-{-    // TODO-    _glfwInputError(GLFW_PLATFORM_ERROR,-                    "Wayland: Window attention request not implemented yet");-}--void _glfwPlatformFocusWindow(_GLFWwindow* window)-{-    _glfwInputError(GLFW_PLATFORM_ERROR,-                    "Wayland: Focusing a window requires user interaction");-}--void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,-                                   _GLFWmonitor* monitor,-                                   int xpos, int ypos,-                                   int width, int height,-                                   int refreshRate)-{-    if (monitor)-    {-        setFullscreen(window, monitor, refreshRate);-    }-    else-    {-        if (window->wl.xdg.toplevel)-            xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);-        else if (window->wl.shellSurface)-            wl_shell_surface_set_toplevel(window->wl.shellSurface);-        setIdleInhibitor(window, GLFW_FALSE);-        if (!_glfw.wl.decorationManager)-            createDecorations(window);-    }-    _glfwInputWindowMonitor(window, monitor);-}--int _glfwPlatformWindowFocused(_GLFWwindow* window)-{-    return _glfw.wl.keyboardFocus == window;-}--int _glfwPlatformWindowIconified(_GLFWwindow* window)-{-    // wl_shell doesn't have any iconified concept, and xdg-shell doesn’t give-    // any way to request whether a surface is iconified.-    return GLFW_FALSE;-}--int _glfwPlatformWindowVisible(_GLFWwindow* window)-{-    return window->wl.visible;-}--int _glfwPlatformWindowMaximized(_GLFWwindow* window)-{-    return window->wl.maximized;-}--int _glfwPlatformWindowHovered(_GLFWwindow* window)-{-    return window->wl.hovered;-}--int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)-{-    return window->wl.transparent;-}--void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)-{-    // TODO-    _glfwInputError(GLFW_PLATFORM_ERROR,-                    "Wayland: Window attribute setting not implemented yet");-}--void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)-{-    if (!window->monitor)-    {-        if (enabled)-            createDecorations(window);-        else-            destroyDecorations(window);-    }-}--void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)-{-    // TODO-    _glfwInputError(GLFW_PLATFORM_ERROR,-                    "Wayland: Window attribute setting not implemented yet");-}--float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)-{-    return 1.f;-}--void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)-{-}--void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)-{-    // This is handled in relativePointerHandleRelativeMotion-}--GLFWbool _glfwPlatformRawMouseMotionSupported(void)-{-    return GLFW_TRUE;-}--void _glfwPlatformPollEvents(void)-{-    handleEvents(0);-}--void _glfwPlatformWaitEvents(void)-{-    handleEvents(-1);-}--void _glfwPlatformWaitEventsTimeout(double timeout)-{-    handleEvents((int) (timeout * 1e3));-}--void _glfwPlatformPostEmptyEvent(void)-{-    wl_display_sync(_glfw.wl.display);-}--void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)-{-    if (xpos)-        *xpos = window->wl.cursorPosX;-    if (ypos)-        *ypos = window->wl.cursorPosY;-}--static GLFWbool isPointerLocked(_GLFWwindow* window);--void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)-{-    if (isPointerLocked(window))-    {-        zwp_locked_pointer_v1_set_cursor_position_hint(-            window->wl.pointerLock.lockedPointer,-            wl_fixed_from_double(x), wl_fixed_from_double(y));-        wl_surface_commit(window->wl.surface);-    }-}--void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)-{-    _glfwPlatformSetCursor(window, window->wl.currentCursor);-}--const char* _glfwPlatformGetScancodeName(int scancode)-{-    // TODO-    return NULL;-}--int _glfwPlatformGetKeyScancode(int key)-{-    return _glfw.wl.scancodes[key];-}--int _glfwPlatformCreateCursor(_GLFWcursor* cursor,-                              const GLFWimage* image,-                              int xhot, int yhot)-{-    cursor->wl.buffer = createShmBuffer(image);-    if (!cursor->wl.buffer)-        return GLFW_FALSE;--    cursor->wl.width = image->width;-    cursor->wl.height = image->height;-    cursor->wl.xhot = xhot;-    cursor->wl.yhot = yhot;-    return GLFW_TRUE;-}--int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)-{-    struct wl_cursor* standardCursor;--    standardCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,-                                                translateCursorShape(shape));-    if (!standardCursor)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Standard cursor \"%s\" not found",-                        translateCursorShape(shape));-        return GLFW_FALSE;-    }--    cursor->wl.cursor = standardCursor;-    cursor->wl.currentImage = 0;--    if (_glfw.wl.cursorThemeHiDPI)-    {-        standardCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI,-                                                    translateCursorShape(shape));-        cursor->wl.cursorHiDPI = standardCursor;-    }--    return GLFW_TRUE;-}--void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)-{-    // If it's a standard cursor we don't need to do anything here-    if (cursor->wl.cursor)-        return;--    if (cursor->wl.buffer)-        wl_buffer_destroy(cursor->wl.buffer);-}--static void relativePointerHandleRelativeMotion(void* data,-                                                struct zwp_relative_pointer_v1* pointer,-                                                uint32_t timeHi,-                                                uint32_t timeLo,-                                                wl_fixed_t dx,-                                                wl_fixed_t dy,-                                                wl_fixed_t dxUnaccel,-                                                wl_fixed_t dyUnaccel)-{-    _GLFWwindow* window = data;-    double xpos = window->virtualCursorPosX;-    double ypos = window->virtualCursorPosY;--    if (window->cursorMode != GLFW_CURSOR_DISABLED)-        return;--    if (window->rawMouseMotion)-    {-        xpos += wl_fixed_to_double(dxUnaccel);-        ypos += wl_fixed_to_double(dyUnaccel);-    }-    else-    {-        xpos += wl_fixed_to_double(dx);-        ypos += wl_fixed_to_double(dy);-    }--    _glfwInputCursorPos(window, xpos, ypos);-}--static const struct zwp_relative_pointer_v1_listener relativePointerListener = {-    relativePointerHandleRelativeMotion-};--static void lockedPointerHandleLocked(void* data,-                                      struct zwp_locked_pointer_v1* lockedPointer)-{-}--static void unlockPointer(_GLFWwindow* window)-{-    struct zwp_relative_pointer_v1* relativePointer =-        window->wl.pointerLock.relativePointer;-    struct zwp_locked_pointer_v1* lockedPointer =-        window->wl.pointerLock.lockedPointer;--    zwp_relative_pointer_v1_destroy(relativePointer);-    zwp_locked_pointer_v1_destroy(lockedPointer);--    window->wl.pointerLock.relativePointer = NULL;-    window->wl.pointerLock.lockedPointer = NULL;-}--static void lockPointer(_GLFWwindow* window);--static void lockedPointerHandleUnlocked(void* data,-                                        struct zwp_locked_pointer_v1* lockedPointer)-{-}--static const struct zwp_locked_pointer_v1_listener lockedPointerListener = {-    lockedPointerHandleLocked,-    lockedPointerHandleUnlocked-};--static void lockPointer(_GLFWwindow* window)-{-    struct zwp_relative_pointer_v1* relativePointer;-    struct zwp_locked_pointer_v1* lockedPointer;--    if (!_glfw.wl.relativePointerManager)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: no relative pointer manager");-        return;-    }--    relativePointer =-        zwp_relative_pointer_manager_v1_get_relative_pointer(-            _glfw.wl.relativePointerManager,-            _glfw.wl.pointer);-    zwp_relative_pointer_v1_add_listener(relativePointer,-                                         &relativePointerListener,-                                         window);--    lockedPointer =-        zwp_pointer_constraints_v1_lock_pointer(-            _glfw.wl.pointerConstraints,-            window->wl.surface,-            _glfw.wl.pointer,-            NULL,-            ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);-    zwp_locked_pointer_v1_add_listener(lockedPointer,-                                       &lockedPointerListener,-                                       window);--    window->wl.pointerLock.relativePointer = relativePointer;-    window->wl.pointerLock.lockedPointer = lockedPointer;--    wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,-                          NULL, 0, 0);-}--static GLFWbool isPointerLocked(_GLFWwindow* window)-{-    return window->wl.pointerLock.lockedPointer != NULL;-}--void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)-{-    struct wl_cursor* defaultCursor;-    struct wl_cursor* defaultCursorHiDPI = NULL;--    if (!_glfw.wl.pointer)-        return;--    window->wl.currentCursor = cursor;--    // If we're not in the correct window just save the cursor-    // the next time the pointer enters the window the cursor will change-    if (window != _glfw.wl.pointerFocus || window->wl.decorations.focus != mainWindow)-        return;--    // Unlock possible pointer lock if no longer disabled.-    if (window->cursorMode != GLFW_CURSOR_DISABLED && isPointerLocked(window))-        unlockPointer(window);--    if (window->cursorMode == GLFW_CURSOR_NORMAL)-    {-        if (cursor)-            setCursorImage(window, &cursor->wl);-        else-        {-            defaultCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,-                                                       "left_ptr");-            if (!defaultCursor)-            {-                _glfwInputError(GLFW_PLATFORM_ERROR,-                                "Wayland: Standard cursor not found");-                return;-            }-            if (_glfw.wl.cursorThemeHiDPI)-                defaultCursorHiDPI =-                    wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI,-                                               "left_ptr");-            _GLFWcursorWayland cursorWayland = {-                defaultCursor,-                defaultCursorHiDPI,-                NULL,-                0, 0,-                0, 0,-                0-            };-            setCursorImage(window, &cursorWayland);-        }-    }-    else if (window->cursorMode == GLFW_CURSOR_DISABLED)-    {-        if (!isPointerLocked(window))-            lockPointer(window);-    }-    else if (window->cursorMode == GLFW_CURSOR_HIDDEN)-    {-        wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial, NULL, 0, 0);-    }-}--static void dataSourceHandleTarget(void* data,-                                   struct wl_data_source* dataSource,-                                   const char* mimeType)-{-    if (_glfw.wl.dataSource != dataSource)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Unknown clipboard data source");-        return;-    }-}--static void dataSourceHandleSend(void* data,-                                 struct wl_data_source* dataSource,-                                 const char* mimeType,-                                 int fd)-{-    const char* string = _glfw.wl.clipboardSendString;-    size_t len = _glfw.wl.clipboardSendSize;-    int ret;--    if (_glfw.wl.dataSource != dataSource)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Unknown clipboard data source");-        return;-    }--    if (!string)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Copy requested from an invalid string");-        return;-    }--    if (strcmp(mimeType, "text/plain;charset=utf-8") != 0)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Wrong MIME type asked from clipboard");-        close(fd);-        return;-    }--    while (len > 0)-    {-        ret = write(fd, string, len);-        if (ret == -1 && errno == EINTR)-            continue;-        if (ret == -1)-        {-            // TODO: also report errno maybe.-            _glfwInputError(GLFW_PLATFORM_ERROR,-                            "Wayland: Error while writing the clipboard");-            close(fd);-            return;-        }-        len -= ret;-    }-    close(fd);-}--static void dataSourceHandleCancelled(void* data,-                                      struct wl_data_source* dataSource)-{-    wl_data_source_destroy(dataSource);--    if (_glfw.wl.dataSource != dataSource)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Unknown clipboard data source");-        return;-    }--    _glfw.wl.dataSource = NULL;-}--static const struct wl_data_source_listener dataSourceListener = {-    dataSourceHandleTarget,-    dataSourceHandleSend,-    dataSourceHandleCancelled,-};--void _glfwPlatformSetClipboardString(const char* string)-{-    if (_glfw.wl.dataSource)-    {-        wl_data_source_destroy(_glfw.wl.dataSource);-        _glfw.wl.dataSource = NULL;-    }--    if (_glfw.wl.clipboardSendString)-    {-        free(_glfw.wl.clipboardSendString);-        _glfw.wl.clipboardSendString = NULL;-    }--    _glfw.wl.clipboardSendString = strdup(string);-    if (!_glfw.wl.clipboardSendString)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Impossible to allocate clipboard string");-        return;-    }-    _glfw.wl.clipboardSendSize = strlen(string);-    _glfw.wl.dataSource =-        wl_data_device_manager_create_data_source(_glfw.wl.dataDeviceManager);-    if (!_glfw.wl.dataSource)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Impossible to create clipboard source");-        free(_glfw.wl.clipboardSendString);-        return;-    }-    wl_data_source_add_listener(_glfw.wl.dataSource,-                                &dataSourceListener,-                                NULL);-    wl_data_source_offer(_glfw.wl.dataSource, "text/plain;charset=utf-8");-    wl_data_device_set_selection(_glfw.wl.dataDevice,-                                 _glfw.wl.dataSource,-                                 _glfw.wl.serial);-}--static GLFWbool growClipboardString(void)-{-    char* clipboard = _glfw.wl.clipboardString;--    clipboard = realloc(clipboard, _glfw.wl.clipboardSize * 2);-    if (!clipboard)-    {-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Impossible to grow clipboard string");-        return GLFW_FALSE;-    }-    _glfw.wl.clipboardString = clipboard;-    _glfw.wl.clipboardSize = _glfw.wl.clipboardSize * 2;-    return GLFW_TRUE;-}--const char* _glfwPlatformGetClipboardString(void)-{-    int fds[2];-    int ret;-    size_t len = 0;--    if (!_glfw.wl.dataOffer)-    {-        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,-                        "No clipboard data has been sent yet");-        return NULL;-    }--    ret = pipe2(fds, O_CLOEXEC);-    if (ret < 0)-    {-        // TODO: also report errno maybe?-        _glfwInputError(GLFW_PLATFORM_ERROR,-                        "Wayland: Impossible to create clipboard pipe fds");-        return NULL;-    }--    wl_data_offer_receive(_glfw.wl.dataOffer, "text/plain;charset=utf-8", fds[1]);-    close(fds[1]);--    // XXX: this is a huge hack, this function shouldn’t be synchronous!-    handleEvents(-1);--    while (1)-    {-        // Grow the clipboard if we need to paste something bigger, there is no-        // shrink operation yet.-        if (len + 4096 > _glfw.wl.clipboardSize)-        {-            if (!growClipboardString())-            {-                close(fds[0]);-                return NULL;-            }-        }--        // Then read from the fd to the clipboard, handling all known errors.-        ret = read(fds[0], _glfw.wl.clipboardString + len, 4096);-        if (ret == 0)-            break;-        if (ret == -1 && errno == EINTR)-            continue;-        if (ret == -1)-        {-            // TODO: also report errno maybe.-            _glfwInputError(GLFW_PLATFORM_ERROR,-                            "Wayland: Impossible to read from clipboard fd");-            close(fds[0]);-            return NULL;-        }-        len += ret;-    }-    close(fds[0]);-    if (len + 1 > _glfw.wl.clipboardSize)-    {-        if (!growClipboardString())-            return NULL;-    }-    _glfw.wl.clipboardString[len] = '\0';+#include <assert.h>+#include <unistd.h>+#include <string.h>+#include <fcntl.h>+#include <sys/mman.h>+#include <sys/timerfd.h>+#include <poll.h>+#include <signal.h>+#include <time.h>++#define GLFW_BORDER_SIZE    4+#define GLFW_CAPTION_HEIGHT 24++static int createTmpfileCloexec(char* tmpname)+{+    int fd;++    fd = mkostemp(tmpname, O_CLOEXEC);+    if (fd >= 0)+        unlink(tmpname);++    return fd;+}++/*+ * Create a new, unique, anonymous file of the given size, and+ * return the file descriptor for it. The file descriptor is set+ * CLOEXEC. The file is immediately suitable for mmap()'ing+ * the given size at offset zero.+ *+ * The file should not have a permanent backing store like a disk,+ * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.+ *+ * The file name is deleted from the file system.+ *+ * The file is suitable for buffer sharing between processes by+ * transmitting the file descriptor over Unix sockets using the+ * SCM_RIGHTS methods.+ *+ * posix_fallocate() is used to guarantee that disk space is available+ * for the file at the given size. If disk space is insufficient, errno+ * is set to ENOSPC. If posix_fallocate() is not supported, program may+ * receive SIGBUS on accessing mmap()'ed file contents instead.+ */+static int createAnonymousFile(off_t size)+{+    static const char template[] = "/glfw-shared-XXXXXX";+    const char* path;+    char* name;+    int fd;+    int ret;++#ifdef HAVE_MEMFD_CREATE+    fd = memfd_create("glfw-shared", MFD_CLOEXEC | MFD_ALLOW_SEALING);+    if (fd >= 0)+    {+        // We can add this seal before calling posix_fallocate(), as the file+        // is currently zero-sized anyway.+        //+        // There is also no need to check for the return value, we couldn’t do+        // anything with it anyway.+        fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);+    }+    else+#elif defined(SHM_ANON)+    fd = shm_open(SHM_ANON, O_RDWR | O_CLOEXEC, 0600);+    if (fd < 0)+#endif+    {+        path = getenv("XDG_RUNTIME_DIR");+        if (!path)+        {+            errno = ENOENT;+            return -1;+        }++        name = calloc(strlen(path) + sizeof(template), 1);+        strcpy(name, path);+        strcat(name, template);++        fd = createTmpfileCloexec(name);+        free(name);+        if (fd < 0)+            return -1;+    }++#if defined(SHM_ANON)+    // posix_fallocate does not work on SHM descriptors+    ret = ftruncate(fd, size);+#else+    ret = posix_fallocate(fd, 0, size);+#endif+    if (ret != 0)+    {+        close(fd);+        errno = ret;+        return -1;+    }+    return fd;+}++static struct wl_buffer* createShmBuffer(const GLFWimage* image)+{+    const int stride = image->width * 4;+    const int length = image->width * image->height * 4;++    const int fd = createAnonymousFile(length);+    if (fd < 0)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to create buffer file of size %d: %s",+                        length, strerror(errno));+        return NULL;+    }++    void* data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);+    if (data == MAP_FAILED)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to map file: %s", strerror(errno));+        close(fd);+        return NULL;+    }++    struct wl_shm_pool* pool = wl_shm_create_pool(_glfw.wl.shm, fd, length);++    close(fd);++    unsigned char* source = (unsigned char*) image->pixels;+    unsigned char* target = data;+    for (int i = 0;  i < image->width * image->height;  i++, source += 4)+    {+        unsigned int alpha = source[3];++        *target++ = (unsigned char) ((source[2] * alpha) / 255);+        *target++ = (unsigned char) ((source[1] * alpha) / 255);+        *target++ = (unsigned char) ((source[0] * alpha) / 255);+        *target++ = (unsigned char) alpha;+    }++    struct wl_buffer* buffer =+        wl_shm_pool_create_buffer(pool, 0,+                                  image->width,+                                  image->height,+                                  stride, WL_SHM_FORMAT_ARGB8888);+    munmap(data, length);+    wl_shm_pool_destroy(pool);++    return buffer;+}++// Wait for data to arrive on any of the specified file descriptors+//+static GLFWbool waitForData(struct pollfd* fds, nfds_t count, double* timeout)+{+    for (;;)+    {+        if (timeout)+        {+            const uint64_t base = _glfwPlatformGetTimerValue();++#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__)+            const time_t seconds = (time_t) *timeout;+            const long nanoseconds = (long) ((*timeout - seconds) * 1e9);+            const struct timespec ts = { seconds, nanoseconds };+            const int result = ppoll(fds, count, &ts, NULL);+#elif defined(__NetBSD__)+            const time_t seconds = (time_t) *timeout;+            const long nanoseconds = (long) ((*timeout - seconds) * 1e9);+            const struct timespec ts = { seconds, nanoseconds };+            const int result = pollts(fds, count, &ts, NULL);+#else+            const int milliseconds = (int) (*timeout * 1e3);+            const int result = poll(fds, count, milliseconds);+#endif+            const int error = errno; // clock_gettime may overwrite our error++            *timeout -= (_glfwPlatformGetTimerValue() - base) /+                (double) _glfwPlatformGetTimerFrequency();++            if (result > 0)+                return GLFW_TRUE;+            else if (result == -1 && error != EINTR && error != EAGAIN)+                return GLFW_FALSE;+            else if (*timeout <= 0.0)+                return GLFW_FALSE;+        }+        else+        {+            const int result = poll(fds, count, -1);+            if (result > 0)+                return GLFW_TRUE;+            else if (result == -1 && errno != EINTR && errno != EAGAIN)+                return GLFW_FALSE;+        }+    }+}++static void createFallbackDecoration(_GLFWwindow* window,+                                     _GLFWdecorationWayland* decoration,+                                     struct wl_surface* parent,+                                     struct wl_buffer* buffer,+                                     int x, int y,+                                     int width, int height)+{+    decoration->surface = wl_compositor_create_surface(_glfw.wl.compositor);+    wl_surface_set_user_data(decoration->surface, window);+    wl_proxy_set_tag((struct wl_proxy*) decoration->surface, &_glfw.wl.tag);+    decoration->subsurface =+        wl_subcompositor_get_subsurface(_glfw.wl.subcompositor,+                                        decoration->surface, parent);+    wl_subsurface_set_position(decoration->subsurface, x, y);+    decoration->viewport = wp_viewporter_get_viewport(_glfw.wl.viewporter,+                                                      decoration->surface);+    wp_viewport_set_destination(decoration->viewport, width, height);+    wl_surface_attach(decoration->surface, buffer, 0, 0);++    struct wl_region* region = wl_compositor_create_region(_glfw.wl.compositor);+    wl_region_add(region, 0, 0, width, height);+    wl_surface_set_opaque_region(decoration->surface, region);+    wl_surface_commit(decoration->surface);+    wl_region_destroy(region);+}++static void createFallbackDecorations(_GLFWwindow* window)+{+    unsigned char data[] = { 224, 224, 224, 255 };+    const GLFWimage image = { 1, 1, data };++    if (!_glfw.wl.viewporter)+        return;++    if (!window->wl.decorations.buffer)+        window->wl.decorations.buffer = createShmBuffer(&image);+    if (!window->wl.decorations.buffer)+        return;++    createFallbackDecoration(window, &window->wl.decorations.top, window->wl.surface,+                             window->wl.decorations.buffer,+                             0, -GLFW_CAPTION_HEIGHT,+                             window->wl.width, GLFW_CAPTION_HEIGHT);+    createFallbackDecoration(window, &window->wl.decorations.left, window->wl.surface,+                             window->wl.decorations.buffer,+                             -GLFW_BORDER_SIZE, -GLFW_CAPTION_HEIGHT,+                             GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT);+    createFallbackDecoration(window, &window->wl.decorations.right, window->wl.surface,+                             window->wl.decorations.buffer,+                             window->wl.width, -GLFW_CAPTION_HEIGHT,+                             GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT);+    createFallbackDecoration(window, &window->wl.decorations.bottom, window->wl.surface,+                             window->wl.decorations.buffer,+                             -GLFW_BORDER_SIZE, window->wl.height,+                             window->wl.width + GLFW_BORDER_SIZE * 2, GLFW_BORDER_SIZE);+}++static void destroyFallbackDecoration(_GLFWdecorationWayland* decoration)+{+    if (decoration->subsurface)+        wl_subsurface_destroy(decoration->subsurface);+    if (decoration->surface)+        wl_surface_destroy(decoration->surface);+    if (decoration->viewport)+        wp_viewport_destroy(decoration->viewport);+    decoration->surface = NULL;+    decoration->subsurface = NULL;+    decoration->viewport = NULL;+}++static void destroyFallbackDecorations(_GLFWwindow* window)+{+    destroyFallbackDecoration(&window->wl.decorations.top);+    destroyFallbackDecoration(&window->wl.decorations.left);+    destroyFallbackDecoration(&window->wl.decorations.right);+    destroyFallbackDecoration(&window->wl.decorations.bottom);+}++static void xdgDecorationHandleConfigure(void* userData,+                                         struct zxdg_toplevel_decoration_v1* decoration,+                                         uint32_t mode)+{+    _GLFWwindow* window = userData;++    window->wl.xdg.decorationMode = mode;++    if (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE)+    {+        if (window->decorated && !window->monitor)+            createFallbackDecorations(window);+    }+    else+        destroyFallbackDecorations(window);+}++static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener =+{+    xdgDecorationHandleConfigure,+};++// Makes the surface considered as XRGB instead of ARGB.+static void setContentAreaOpaque(_GLFWwindow* window)+{+    struct wl_region* region;++    region = wl_compositor_create_region(_glfw.wl.compositor);+    if (!region)+        return;++    wl_region_add(region, 0, 0, window->wl.width, window->wl.height);+    wl_surface_set_opaque_region(window->wl.surface, region);+    wl_region_destroy(region);+}+++static void resizeWindow(_GLFWwindow* window)+{+    int scale = window->wl.contentScale;+    int scaledWidth = window->wl.width * scale;+    int scaledHeight = window->wl.height * scale;++    if (window->wl.egl.window)+        wl_egl_window_resize(window->wl.egl.window, scaledWidth, scaledHeight, 0, 0);+    if (!window->wl.transparent)+        setContentAreaOpaque(window);+    _glfwInputFramebufferSize(window, scaledWidth, scaledHeight);++    if (!window->wl.decorations.top.surface)+        return;++    wp_viewport_set_destination(window->wl.decorations.top.viewport,+                                window->wl.width, GLFW_CAPTION_HEIGHT);+    wl_surface_commit(window->wl.decorations.top.surface);++    wp_viewport_set_destination(window->wl.decorations.left.viewport,+                                GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT);+    wl_surface_commit(window->wl.decorations.left.surface);++    wl_subsurface_set_position(window->wl.decorations.right.subsurface,+                               window->wl.width, -GLFW_CAPTION_HEIGHT);+    wp_viewport_set_destination(window->wl.decorations.right.viewport,+                                GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT);+    wl_surface_commit(window->wl.decorations.right.surface);++    wl_subsurface_set_position(window->wl.decorations.bottom.subsurface,+                               -GLFW_BORDER_SIZE, window->wl.height);+    wp_viewport_set_destination(window->wl.decorations.bottom.viewport,+                                window->wl.width + GLFW_BORDER_SIZE * 2, GLFW_BORDER_SIZE);+    wl_surface_commit(window->wl.decorations.bottom.surface);+}++void _glfwUpdateContentScaleWayland(_GLFWwindow* window)+{+    if (wl_compositor_get_version(_glfw.wl.compositor) <+        WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION)+    {+        return;+    }++    // Get the scale factor from the highest scale monitor.+    int maxScale = 1;++    for (int i = 0; i < window->wl.scaleCount; i++)+        maxScale = _glfw_max(window->wl.scales[i].factor, maxScale);++    // Only change the framebuffer size if the scale changed.+    if (window->wl.contentScale != maxScale)+    {+        window->wl.contentScale = maxScale;+        wl_surface_set_buffer_scale(window->wl.surface, maxScale);+        _glfwInputWindowContentScale(window, maxScale, maxScale);+        resizeWindow(window);++        if (window->wl.visible)+            _glfwInputWindowDamage(window);+    }+}++static void surfaceHandleEnter(void* userData,+                               struct wl_surface* surface,+                               struct wl_output* output)+{+    if (wl_proxy_get_tag((struct wl_proxy*) output) != &_glfw.wl.tag)+        return;++    _GLFWwindow* window = userData;+    _GLFWmonitor* monitor = wl_output_get_user_data(output);+    if (!window || !monitor)+        return;++    if (window->wl.scaleCount + 1 > window->wl.scaleSize)+    {+        window->wl.scaleSize++;+        window->wl.scales =+            realloc(window->wl.scales,+                    window->wl.scaleSize * sizeof(_GLFWscaleWayland));+    }++    window->wl.scaleCount++;+    window->wl.scales[window->wl.scaleCount - 1].factor = monitor->wl.contentScale;+    window->wl.scales[window->wl.scaleCount - 1].output = output;++    _glfwUpdateContentScaleWayland(window);+}++static void surfaceHandleLeave(void* userData,+                               struct wl_surface* surface,+                               struct wl_output* output)+{+    if (wl_proxy_get_tag((struct wl_proxy*) output) != &_glfw.wl.tag)+        return;++    _GLFWwindow* window = userData;++    for (int i = 0; i < window->wl.scaleCount; i++)+    {+        if (window->wl.scales[i].output == output)+        {+            window->wl.scales[i] = window->wl.scales[window->wl.scaleCount - 1];+            window->wl.scaleCount--;+            break;+        }+    }++    _glfwUpdateContentScaleWayland(window);+}++static const struct wl_surface_listener surfaceListener =+{+    surfaceHandleEnter,+    surfaceHandleLeave+};++static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)+{+    if (enable && !window->wl.idleInhibitor && _glfw.wl.idleInhibitManager)+    {+        window->wl.idleInhibitor =+            zwp_idle_inhibit_manager_v1_create_inhibitor(+                _glfw.wl.idleInhibitManager, window->wl.surface);+        if (!window->wl.idleInhibitor)+            _glfwInputError(GLFW_PLATFORM_ERROR,+                            "Wayland: Failed to create idle inhibitor");+    }+    else if (!enable && window->wl.idleInhibitor)+    {+        zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);+        window->wl.idleInhibitor = NULL;+    }+}++// Make the specified window and its video mode active on its monitor+//+static void acquireMonitor(_GLFWwindow* window)+{+    if (window->wl.libdecor.frame)+    {+        libdecor_frame_set_fullscreen(window->wl.libdecor.frame,+                                      window->monitor->wl.output);+    }+    else if (window->wl.xdg.toplevel)+    {+        xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel,+                                    window->monitor->wl.output);+    }++    setIdleInhibitor(window, GLFW_TRUE);++    if (window->wl.decorations.top.surface)+        destroyFallbackDecorations(window);+}++// Remove the window and restore the original video mode+//+static void releaseMonitor(_GLFWwindow* window)+{+    if (window->wl.libdecor.frame)+        libdecor_frame_unset_fullscreen(window->wl.libdecor.frame);+    else if (window->wl.xdg.toplevel)+        xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);++    setIdleInhibitor(window, GLFW_FALSE);++    if (!window->wl.libdecor.frame &&+        window->wl.xdg.decorationMode != ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE)+    {+        if (window->decorated)+            createFallbackDecorations(window);+    }+}++static void xdgToplevelHandleConfigure(void* userData,+                                       struct xdg_toplevel* toplevel,+                                       int32_t width,+                                       int32_t height,+                                       struct wl_array* states)+{+    _GLFWwindow* window = userData;+    uint32_t* state;++    window->wl.pending.activated  = GLFW_FALSE;+    window->wl.pending.maximized  = GLFW_FALSE;+    window->wl.pending.fullscreen = GLFW_FALSE;++    wl_array_for_each(state, states)+    {+        switch (*state)+        {+            case XDG_TOPLEVEL_STATE_MAXIMIZED:+                window->wl.pending.maximized = GLFW_TRUE;+                break;+            case XDG_TOPLEVEL_STATE_FULLSCREEN:+                window->wl.pending.fullscreen = GLFW_TRUE;+                break;+            case XDG_TOPLEVEL_STATE_RESIZING:+                break;+            case XDG_TOPLEVEL_STATE_ACTIVATED:+                window->wl.pending.activated = GLFW_TRUE;+                break;+        }+    }++    if (width && height)+    {+        if (window->wl.decorations.top.surface)+        {+            window->wl.pending.width  = _glfw_max(0, width - GLFW_BORDER_SIZE * 2);+            window->wl.pending.height =+                _glfw_max(0, height - GLFW_BORDER_SIZE - GLFW_CAPTION_HEIGHT);+        }+        else+        {+            window->wl.pending.width  = width;+            window->wl.pending.height = height;+        }+    }+    else+    {+        window->wl.pending.width  = window->wl.width;+        window->wl.pending.height = window->wl.height;+    }+}++static void xdgToplevelHandleClose(void* userData,+                                   struct xdg_toplevel* toplevel)+{+    _GLFWwindow* window = userData;+    _glfwInputWindowCloseRequest(window);+}++static const struct xdg_toplevel_listener xdgToplevelListener =+{+    xdgToplevelHandleConfigure,+    xdgToplevelHandleClose+};++static void xdgSurfaceHandleConfigure(void* userData,+                                      struct xdg_surface* surface,+                                      uint32_t serial)+{+    _GLFWwindow* window = userData;++    xdg_surface_ack_configure(surface, serial);++    if (window->wl.activated != window->wl.pending.activated)+    {+        window->wl.activated = window->wl.pending.activated;+        if (!window->wl.activated)+        {+            if (window->monitor && window->autoIconify)+                xdg_toplevel_set_minimized(window->wl.xdg.toplevel);+        }+    }++    if (window->wl.maximized != window->wl.pending.maximized)+    {+        window->wl.maximized = window->wl.pending.maximized;+        _glfwInputWindowMaximize(window, window->wl.maximized);+    }++    window->wl.fullscreen = window->wl.pending.fullscreen;++    int width  = window->wl.pending.width;+    int height = window->wl.pending.height;++    if (!window->wl.maximized && !window->wl.fullscreen)+    {+        if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)+        {+            const float aspectRatio = (float) width / (float) height;+            const float targetRatio = (float) window->numer / (float) window->denom;+            if (aspectRatio < targetRatio)+                height = width / targetRatio;+            else if (aspectRatio > targetRatio)+                width = height * targetRatio;+        }+    }++    if (width != window->wl.width || height != window->wl.height)+    {+        window->wl.width = width;+        window->wl.height = height;+        resizeWindow(window);++        _glfwInputWindowSize(window, width, height);++        if (window->wl.visible)+            _glfwInputWindowDamage(window);+    }++    if (!window->wl.visible)+    {+        // Allow the window to be mapped only if it either has no XDG+        // decorations or they have already received a configure event+        if (!window->wl.xdg.decoration || window->wl.xdg.decorationMode)+        {+            window->wl.visible = GLFW_TRUE;+            _glfwInputWindowDamage(window);+        }+    }+}++static const struct xdg_surface_listener xdgSurfaceListener =+{+    xdgSurfaceHandleConfigure+};++void libdecorFrameHandleConfigure(struct libdecor_frame* frame,+                                  struct libdecor_configuration* config,+                                  void* userData)+{+    _GLFWwindow* window = userData;+    int width, height;++    enum libdecor_window_state windowState;+    GLFWbool fullscreen, activated, maximized;++    if (libdecor_configuration_get_window_state(config, &windowState))+    {+        fullscreen = (windowState & LIBDECOR_WINDOW_STATE_FULLSCREEN) != 0;+        activated = (windowState & LIBDECOR_WINDOW_STATE_ACTIVE) != 0;+        maximized = (windowState & LIBDECOR_WINDOW_STATE_MAXIMIZED) != 0;+    }+    else+    {+        fullscreen = window->wl.fullscreen;+        activated = window->wl.activated;+        maximized = window->wl.maximized;+    }++    if (!libdecor_configuration_get_content_size(config, frame, &width, &height))+    {+        width = window->wl.width;+        height = window->wl.height;+    }++    if (!maximized && !fullscreen)+    {+        if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)+        {+            const float aspectRatio = (float) width / (float) height;+            const float targetRatio = (float) window->numer / (float) window->denom;+            if (aspectRatio < targetRatio)+                height = width / targetRatio;+            else if (aspectRatio > targetRatio)+                width = height * targetRatio;+        }+    }++    struct libdecor_state* frameState = libdecor_state_new(width, height);+    libdecor_frame_commit(frame, frameState, config);+    libdecor_state_free(frameState);++    if (window->wl.activated != activated)+    {+        window->wl.activated = activated;+        if (!window->wl.activated)+        {+            if (window->monitor && window->autoIconify)+                libdecor_frame_set_minimized(window->wl.libdecor.frame);+        }+    }++    if (window->wl.maximized != maximized)+    {+        window->wl.maximized = maximized;+        _glfwInputWindowMaximize(window, window->wl.maximized);+    }++    window->wl.fullscreen = fullscreen;++    GLFWbool damaged = GLFW_FALSE;++    if (!window->wl.visible)+    {+        window->wl.visible = GLFW_TRUE;+        damaged = GLFW_TRUE;+    }++    if (width != window->wl.width || height != window->wl.height)+    {+        window->wl.width = width;+        window->wl.height = height;+        resizeWindow(window);++        _glfwInputWindowSize(window, width, height);+        damaged = GLFW_TRUE;+    }++    if (damaged)+        _glfwInputWindowDamage(window);+    else+        wl_surface_commit(window->wl.surface);+}++void libdecorFrameHandleClose(struct libdecor_frame* frame, void* userData)+{+    _GLFWwindow* window = userData;+    _glfwInputWindowCloseRequest(window);+}++void libdecorFrameHandleCommit(struct libdecor_frame* frame, void* userData)+{+    _GLFWwindow* window = userData;+    wl_surface_commit(window->wl.surface);+}++void libdecorFrameHandleDismissPopup(struct libdecor_frame* frame,+                                     const char* seatName,+                                     void* userData)+{+}++static const struct libdecor_frame_interface libdecorFrameInterface =+{+    libdecorFrameHandleConfigure,+    libdecorFrameHandleClose,+    libdecorFrameHandleCommit,+    libdecorFrameHandleDismissPopup+};++static GLFWbool createLibdecorFrame(_GLFWwindow* window)+{+    // Allow libdecor to finish initialization of itself and its plugin+    while (!_glfw.wl.libdecor.ready)+        _glfwPlatformWaitEvents();++    window->wl.libdecor.frame = libdecor_decorate(_glfw.wl.libdecor.context,+                                                  window->wl.surface,+                                                  &libdecorFrameInterface,+                                                  window);+    if (!window->wl.libdecor.frame)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to create libdecor frame");+        return GLFW_FALSE;+    }++    struct libdecor_state* frameState =+        libdecor_state_new(window->wl.width, window->wl.height);+    libdecor_frame_commit(window->wl.libdecor.frame, frameState, NULL);+    libdecor_state_free(frameState);++    if (strlen(window->wl.title))+        libdecor_frame_set_title(window->wl.libdecor.frame, window->wl.title);++    if (window->minwidth != GLFW_DONT_CARE &&+        window->minheight != GLFW_DONT_CARE)+    {+        libdecor_frame_set_min_content_size(window->wl.libdecor.frame,+                                            window->minwidth,+                                            window->minheight);+    }++    if (window->maxwidth != GLFW_DONT_CARE &&+        window->maxheight != GLFW_DONT_CARE)+    {+        libdecor_frame_set_max_content_size(window->wl.libdecor.frame,+                                            window->maxwidth,+                                            window->maxheight);+    }++    if (!window->resizable)+    {+        libdecor_frame_unset_capabilities(window->wl.libdecor.frame,+                                          LIBDECOR_ACTION_RESIZE);+    }++    if (window->monitor)+    {+        libdecor_frame_set_fullscreen(window->wl.libdecor.frame,+                                      window->monitor->wl.output);+        setIdleInhibitor(window, GLFW_TRUE);+    }+    else+    {+        if (window->wl.maximized)+            libdecor_frame_set_maximized(window->wl.libdecor.frame);++        if (!window->decorated)+            libdecor_frame_set_visibility(window->wl.libdecor.frame, false);++        setIdleInhibitor(window, GLFW_FALSE);+    }++    libdecor_frame_map(window->wl.libdecor.frame);+    wl_display_roundtrip(_glfw.wl.display);+    return GLFW_TRUE;+}++static GLFWbool createXdgShellObjects(_GLFWwindow* window)+{+    window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,+                                                         window->wl.surface);+    if (!window->wl.xdg.surface)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to create xdg-surface for window");+        return GLFW_FALSE;+    }++    xdg_surface_add_listener(window->wl.xdg.surface, &xdgSurfaceListener, window);++    window->wl.xdg.toplevel = xdg_surface_get_toplevel(window->wl.xdg.surface);+    if (!window->wl.xdg.toplevel)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to create xdg-toplevel for window");+        return GLFW_FALSE;+    }++    xdg_toplevel_add_listener(window->wl.xdg.toplevel, &xdgToplevelListener, window);++    if (window->wl.title)+        xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title);++    if (window->monitor)+    {+        xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel, window->monitor->wl.output);+        setIdleInhibitor(window, GLFW_TRUE);+    }+    else+    {+        if (window->wl.maximized)+            xdg_toplevel_set_maximized(window->wl.xdg.toplevel);++        setIdleInhibitor(window, GLFW_FALSE);+    }++    if (_glfw.wl.decorationManager)+    {+        window->wl.xdg.decoration =+            zxdg_decoration_manager_v1_get_toplevel_decoration(+                _glfw.wl.decorationManager, window->wl.xdg.toplevel);+        zxdg_toplevel_decoration_v1_add_listener(window->wl.xdg.decoration,+                                                 &xdgDecorationListener,+                                                 window);++        uint32_t mode;++        if (window->decorated)+            mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;+        else+            mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;++        zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, mode);+    }+    else+    {+        if (window->decorated && !window->monitor)+            createFallbackDecorations(window);+    }++    if (window->minwidth != GLFW_DONT_CARE && window->minheight != GLFW_DONT_CARE)+    {+        int minwidth  = window->minwidth;+        int minheight = window->minheight;++        if (window->wl.decorations.top.surface)+        {+            minwidth  += GLFW_BORDER_SIZE * 2;+            minheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE;+        }++        xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight);+    }++    if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE)+    {+        int maxwidth  = window->maxwidth;+        int maxheight = window->maxheight;++        if (window->wl.decorations.top.surface)+        {+            maxwidth  += GLFW_BORDER_SIZE * 2;+            maxheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE;+        }++        xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight);+    }++    wl_surface_commit(window->wl.surface);+    wl_display_roundtrip(_glfw.wl.display);+    return GLFW_TRUE;+}++static GLFWbool createShellObjects(_GLFWwindow* window)+{+    if (_glfw.wl.libdecor.context)+    {+        if (createLibdecorFrame(window))+            return GLFW_TRUE;+    }++    return createXdgShellObjects(window);+}++static void destroyShellObjects(_GLFWwindow* window)+{+    destroyFallbackDecorations(window);++    if (window->wl.libdecor.frame)+        libdecor_frame_unref(window->wl.libdecor.frame);++    if (window->wl.xdg.decoration)+        zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);++    if (window->wl.xdg.toplevel)+        xdg_toplevel_destroy(window->wl.xdg.toplevel);++    if (window->wl.xdg.surface)+        xdg_surface_destroy(window->wl.xdg.surface);++    window->wl.libdecor.frame = NULL;+    window->wl.xdg.decoration = NULL;+    window->wl.xdg.decorationMode = 0;+    window->wl.xdg.toplevel = NULL;+    window->wl.xdg.surface = NULL;+}++static GLFWbool createNativeSurface(_GLFWwindow* window,+                                    const _GLFWwndconfig* wndconfig,+                                    const _GLFWfbconfig* fbconfig)+{+    window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor);+    if (!window->wl.surface)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to create window surface");+        return GLFW_FALSE;+    }++    wl_proxy_set_tag((struct wl_proxy*) window->wl.surface, &_glfw.wl.tag);+    wl_surface_add_listener(window->wl.surface,+                            &surfaceListener,+                            window);++    window->wl.width = wndconfig->width;+    window->wl.height = wndconfig->height;+    window->wl.contentScale = 1;+    window->wl.title = _glfw_strdup(wndconfig->title);++    window->wl.maximized = wndconfig->maximized;++    window->wl.transparent = fbconfig->transparent;+    if (!window->wl.transparent)+        setContentAreaOpaque(window);++    return GLFW_TRUE;+}++static void setCursorImage(_GLFWwindow* window,+                           _GLFWcursorWayland* cursorWayland)+{+    struct itimerspec timer = {0};+    struct wl_cursor* wlCursor = cursorWayland->cursor;+    struct wl_cursor_image* image;+    struct wl_buffer* buffer;+    struct wl_surface* surface = _glfw.wl.cursorSurface;+    int scale = 1;++    if (!wlCursor)+        buffer = cursorWayland->buffer;+    else+    {+        if (window->wl.contentScale > 1 && cursorWayland->cursorHiDPI)+        {+            wlCursor = cursorWayland->cursorHiDPI;+            scale = 2;+        }++        image = wlCursor->images[cursorWayland->currentImage];+        buffer = wl_cursor_image_get_buffer(image);+        if (!buffer)+            return;++        timer.it_value.tv_sec = image->delay / 1000;+        timer.it_value.tv_nsec = (image->delay % 1000) * 1000000;+        timerfd_settime(_glfw.wl.cursorTimerfd, 0, &timer, NULL);++        cursorWayland->width = image->width;+        cursorWayland->height = image->height;+        cursorWayland->xhot = image->hotspot_x;+        cursorWayland->yhot = image->hotspot_y;+    }++    wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial,+                          surface,+                          cursorWayland->xhot / scale,+                          cursorWayland->yhot / scale);+    wl_surface_set_buffer_scale(surface, scale);+    wl_surface_attach(surface, buffer, 0, 0);+    wl_surface_damage(surface, 0, 0,+                      cursorWayland->width, cursorWayland->height);+    wl_surface_commit(surface);+}++static void incrementCursorImage(_GLFWwindow* window)+{+    _GLFWcursor* cursor;++    if (!window || window->wl.decorations.focus != GLFW_MAIN_WINDOW)+        return;++    cursor = window->wl.currentCursor;+    if (cursor && cursor->wl.cursor)+    {+        cursor->wl.currentImage += 1;+        cursor->wl.currentImage %= cursor->wl.cursor->image_count;+        setCursorImage(window, &cursor->wl);+    }+}++static GLFWbool flushDisplay(void)+{+    while (wl_display_flush(_glfw.wl.display) == -1)+    {+        if (errno != EAGAIN)+            return GLFW_FALSE;++        struct pollfd fd = { wl_display_get_fd(_glfw.wl.display), POLLOUT };++        while (poll(&fd, 1, -1) == -1)+        {+            if (errno != EINTR && errno != EAGAIN)+                return GLFW_FALSE;+        }+    }++    return GLFW_TRUE;+}++static int translateKey(uint32_t scancode)+{+    if (scancode < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))+        return _glfw.wl.keycodes[scancode];++    return GLFW_KEY_UNKNOWN;+}++static xkb_keysym_t composeSymbol(xkb_keysym_t sym)+{+    if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)+        return sym;+    if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym)+            != XKB_COMPOSE_FEED_ACCEPTED)+        return sym;+    switch (xkb_compose_state_get_status(_glfw.wl.xkb.composeState))+    {+        case XKB_COMPOSE_COMPOSED:+            return xkb_compose_state_get_one_sym(_glfw.wl.xkb.composeState);+        case XKB_COMPOSE_COMPOSING:+        case XKB_COMPOSE_CANCELLED:+            return XKB_KEY_NoSymbol;+        case XKB_COMPOSE_NOTHING:+        default:+            return sym;+    }+}++static void inputText(_GLFWwindow* window, uint32_t scancode)+{+    const xkb_keysym_t* keysyms;+    const xkb_keycode_t keycode = scancode + 8;++    if (xkb_state_key_get_syms(_glfw.wl.xkb.state, keycode, &keysyms) == 1)+    {+        const xkb_keysym_t keysym = composeSymbol(keysyms[0]);+        const uint32_t codepoint = _glfwKeySym2Unicode(keysym);+        if (codepoint != GLFW_INVALID_CODEPOINT)+        {+            const int mods = _glfw.wl.xkb.modifiers;+            const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));+            _glfwInputChar(window, codepoint, mods, plain);+        }+    }+}++static void handleEvents(double* timeout)+{+#if defined(__linux__)+    _glfwDetectJoystickConnectionLinux();+#endif++    GLFWbool event = GLFW_FALSE;+    struct pollfd fds[4] =+    {+        { wl_display_get_fd(_glfw.wl.display), POLLIN },+        { _glfw.wl.keyRepeatTimerfd, POLLIN },+        { _glfw.wl.cursorTimerfd, POLLIN },+        { -1, POLLIN }+    };++    if (_glfw.wl.libdecor.context)+        fds[3].fd = libdecor_get_fd(_glfw.wl.libdecor.context);++    while (!event)+    {+        while (wl_display_prepare_read(_glfw.wl.display) != 0)+        {+            if (wl_display_dispatch_pending(_glfw.wl.display) > 0)+                return;+        }++        // If an error other than EAGAIN happens, we have likely been disconnected+        // from the Wayland session; try to handle that the best we can.+        if (!flushDisplay())+        {+            wl_display_cancel_read(_glfw.wl.display);++            _GLFWwindow* window = _glfw.windowListHead;+            while (window)+            {+                _glfwInputWindowCloseRequest(window);+                window = window->next;+            }++            return;+        }++        if (!waitForData(fds, sizeof(fds) / sizeof(fds[0]), timeout))+        {+            wl_display_cancel_read(_glfw.wl.display);+            return;+        }++        if (fds[0].revents & POLLIN)+        {+            wl_display_read_events(_glfw.wl.display);+            if (wl_display_dispatch_pending(_glfw.wl.display) > 0)+                event = GLFW_TRUE;+        }+        else+            wl_display_cancel_read(_glfw.wl.display);++        if (fds[1].revents & POLLIN)+        {+            uint64_t repeats;++            if (read(_glfw.wl.keyRepeatTimerfd, &repeats, sizeof(repeats)) == 8)+            {+                for (uint64_t i = 0; i < repeats; i++)+                {+                    _glfwInputKey(_glfw.wl.keyboardFocus,+                                  translateKey(_glfw.wl.keyRepeatScancode),+                                  _glfw.wl.keyRepeatScancode,+                                  GLFW_PRESS,+                                  _glfw.wl.xkb.modifiers);+                    inputText(_glfw.wl.keyboardFocus, _glfw.wl.keyRepeatScancode);+                }++                event = GLFW_TRUE;+            }+        }++        if (fds[2].revents & POLLIN)+        {+            uint64_t repeats;++            if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8)+                incrementCursorImage(_glfw.wl.pointerFocus);+        }++        if (fds[3].revents & POLLIN)+        {+            if (libdecor_dispatch(_glfw.wl.libdecor.context, 0) > 0)+                event = GLFW_TRUE;+        }+    }+}++// Reads the specified data offer as the specified MIME type+//+static char* readDataOfferAsString(struct wl_data_offer* offer, const char* mimeType)+{+    int fds[2];++    if (pipe2(fds, O_CLOEXEC) == -1)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to create pipe for data offer: %s",+                        strerror(errno));+        return NULL;+    }++    wl_data_offer_receive(offer, mimeType, fds[1]);+    flushDisplay();+    close(fds[1]);++    char* string = NULL;+    size_t size = 0;+    size_t length = 0;++    for (;;)+    {+        const size_t readSize = 4096;+        const size_t requiredSize = length + readSize + 1;+        if (requiredSize > size)+        {+            char* longer = realloc(string, requiredSize);+            if (!longer)+            {+                _glfwInputError(GLFW_OUT_OF_MEMORY, NULL);+                close(fds[0]);+                return NULL;+            }++            string = longer;+            size = requiredSize;+        }++        const ssize_t result = read(fds[0], string + length, readSize);+        if (result == 0)+            break;+        else if (result == -1)+        {+            if (errno == EINTR)+                continue;++            _glfwInputError(GLFW_PLATFORM_ERROR,+                            "Wayland: Failed to read from data offer pipe: %s",+                            strerror(errno));+            close(fds[0]);+            return NULL;+        }++        length += result;+    }++    close(fds[0]);++    string[length] = '\0';+    return string;+}++static void pointerHandleEnter(void* userData,+                               struct wl_pointer* pointer,+                               uint32_t serial,+                               struct wl_surface* surface,+                               wl_fixed_t sx,+                               wl_fixed_t sy)+{+    // Happens in the case we just destroyed the surface.+    if (!surface)+        return;++    if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)+        return;++    _GLFWwindow* window = wl_surface_get_user_data(surface);++    if (surface == window->wl.decorations.top.surface)+        window->wl.decorations.focus = GLFW_TOP_DECORATION;+    else if (surface == window->wl.decorations.left.surface)+        window->wl.decorations.focus = GLFW_LEFT_DECORATION;+    else if (surface == window->wl.decorations.right.surface)+        window->wl.decorations.focus = GLFW_RIGHT_DECORATION;+    else if (surface == window->wl.decorations.bottom.surface)+        window->wl.decorations.focus = GLFW_BOTTOM_DECORATION;+    else+        window->wl.decorations.focus = GLFW_MAIN_WINDOW;++    _glfw.wl.serial = serial;+    _glfw.wl.pointerEnterSerial = serial;+    _glfw.wl.pointerFocus = window;++    window->wl.hovered = GLFW_TRUE;++    _glfwPlatformSetCursor(window, window->wl.currentCursor);+    _glfwInputCursorEnter(window, GLFW_TRUE);+}++static void pointerHandleLeave(void* userData,+                               struct wl_pointer* pointer,+                               uint32_t serial,+                               struct wl_surface* surface)+{+    if (!surface)+        return;++    if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)+        return;++    _GLFWwindow* window = _glfw.wl.pointerFocus;+    if (!window)+        return;++    window->wl.hovered = GLFW_FALSE;++    _glfw.wl.serial = serial;+    _glfw.wl.pointerFocus = NULL;+    _glfw.wl.cursorPreviousName = NULL;+    _glfwInputCursorEnter(window, GLFW_FALSE);+}++static void pointerHandleMotion(void* userData,+                                struct wl_pointer* pointer,+                                uint32_t time,+                                wl_fixed_t sx,+                                wl_fixed_t sy)+{+    _GLFWwindow* window = _glfw.wl.pointerFocus;+    if (!window)+        return;++    if (window->cursorMode == GLFW_CURSOR_DISABLED)+        return;++    const double xpos = wl_fixed_to_double(sx);+    const double ypos = wl_fixed_to_double(sy);+    window->wl.cursorPosX = xpos;+    window->wl.cursorPosY = ypos;++    const char* cursorName = NULL;++    switch (window->wl.decorations.focus)+    {+        case GLFW_MAIN_WINDOW:+            _glfw.wl.cursorPreviousName = NULL;+            _glfwInputCursorPos(window, xpos, ypos);+            return;+        case GLFW_TOP_DECORATION:+            if (ypos < GLFW_BORDER_SIZE)+                cursorName = "n-resize";+            else+                cursorName = "left_ptr";+            break;+        case GLFW_LEFT_DECORATION:+            if (ypos < GLFW_BORDER_SIZE)+                cursorName = "nw-resize";+            else+                cursorName = "w-resize";+            break;+        case GLFW_RIGHT_DECORATION:+            if (ypos < GLFW_BORDER_SIZE)+                cursorName = "ne-resize";+            else+                cursorName = "e-resize";+            break;+        case GLFW_BOTTOM_DECORATION:+            if (xpos < GLFW_BORDER_SIZE)+                cursorName = "sw-resize";+            else if (xpos > window->wl.width + GLFW_BORDER_SIZE)+                cursorName = "se-resize";+            else+                cursorName = "s-resize";+            break;+        default:+            assert(0);+    }++    if (_glfw.wl.cursorPreviousName != cursorName)+    {+        struct wl_surface* surface = _glfw.wl.cursorSurface;+        struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;+        int scale = 1;++        if (window->wl.contentScale > 1 && _glfw.wl.cursorThemeHiDPI)+        {+            // We only support up to scale=2 for now, since libwayland-cursor+            // requires us to load a different theme for each size.+            scale = 2;+            theme = _glfw.wl.cursorThemeHiDPI;+        }++        struct wl_cursor* cursor = wl_cursor_theme_get_cursor(theme, cursorName);+        if (!cursor)+            return;++        // TODO: handle animated cursors too.+        struct wl_cursor_image* image = cursor->images[0];+        if (!image)+            return;++        struct wl_buffer* buffer = wl_cursor_image_get_buffer(image);+        if (!buffer)+            return;++        wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial,+                              surface,+                              image->hotspot_x / scale,+                              image->hotspot_y / scale);+        wl_surface_set_buffer_scale(surface, scale);+        wl_surface_attach(surface, buffer, 0, 0);+        wl_surface_damage(surface, 0, 0, image->width, image->height);+        wl_surface_commit(surface);++        _glfw.wl.cursorPreviousName = cursorName;+    }+}++static void pointerHandleButton(void* userData,+                                struct wl_pointer* pointer,+                                uint32_t serial,+                                uint32_t time,+                                uint32_t button,+                                uint32_t state)+{+    _GLFWwindow* window = _glfw.wl.pointerFocus;+    int glfwButton;++    uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE;++    if (!window)+        return;+    if (button == BTN_LEFT)+    {+        switch (window->wl.decorations.focus)+        {+            case GLFW_MAIN_WINDOW:+                break;+            case GLFW_TOP_DECORATION:+                if (window->wl.cursorPosY < GLFW_BORDER_SIZE)+                    edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP;+                else+                {+                    xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);+                }+                break;+            case GLFW_LEFT_DECORATION:+                if (window->wl.cursorPosY < GLFW_BORDER_SIZE)+                    edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;+                else+                    edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;+                break;+            case GLFW_RIGHT_DECORATION:+                if (window->wl.cursorPosY < GLFW_BORDER_SIZE)+                    edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;+                else+                    edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;+                break;+            case GLFW_BOTTOM_DECORATION:+                if (window->wl.cursorPosX < GLFW_BORDER_SIZE)+                    edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;+                else if (window->wl.cursorPosX > window->wl.width + GLFW_BORDER_SIZE)+                    edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;+                else+                    edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;+                break;+            default:+                assert(0);+        }+        if (edges != XDG_TOPLEVEL_RESIZE_EDGE_NONE)+        {+            xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat,+                                serial, edges);+            return;+        }+    }+    else if (button == BTN_RIGHT)+    {+        if (window->wl.decorations.focus != GLFW_MAIN_WINDOW &&+            window->wl.xdg.toplevel)+        {+            xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,+                                          _glfw.wl.seat, serial,+                                          window->wl.cursorPosX,+                                          window->wl.cursorPosY);+            return;+        }+    }++    // Don’t pass the button to the user if it was related to a decoration.+    if (window->wl.decorations.focus != GLFW_MAIN_WINDOW)+        return;++    _glfw.wl.serial = serial;++    /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev+     * codes. */+    glfwButton = button - BTN_LEFT;++    _glfwInputMouseClick(window,+                         glfwButton,+                         state == WL_POINTER_BUTTON_STATE_PRESSED+                                ? GLFW_PRESS+                                : GLFW_RELEASE,+                         _glfw.wl.xkb.modifiers);+}++static void pointerHandleAxis(void* userData,+                              struct wl_pointer* pointer,+                              uint32_t time,+                              uint32_t axis,+                              wl_fixed_t value)+{+    _GLFWwindow* window = _glfw.wl.pointerFocus;+    double x = 0.0, y = 0.0;+    // Wayland scroll events are in pointer motion coordinate space (think two+    // finger scroll).  The factor 10 is commonly used to convert to "scroll+    // step means 1.0.+    const double scrollFactor = 1.0 / 10.0;++    if (!window)+        return;++    assert(axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL ||+           axis == WL_POINTER_AXIS_VERTICAL_SCROLL);++    if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)+        x = -wl_fixed_to_double(value) * scrollFactor;+    else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)+        y = -wl_fixed_to_double(value) * scrollFactor;++    _glfwInputScroll(window, x, y);+}++static const struct wl_pointer_listener pointerListener =+{+    pointerHandleEnter,+    pointerHandleLeave,+    pointerHandleMotion,+    pointerHandleButton,+    pointerHandleAxis,+};++static void keyboardHandleKeymap(void* userData,+                                 struct wl_keyboard* keyboard,+                                 uint32_t format,+                                 int fd,+                                 uint32_t size)+{+    struct xkb_keymap* keymap;+    struct xkb_state* state;+    struct xkb_compose_table* composeTable;+    struct xkb_compose_state* composeState;+    char* mapStr;+    const char* locale;++    if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)+    {+        close(fd);+        return;+    }++    mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);+    if (mapStr == MAP_FAILED) {+        close(fd);+        return;+    }++    keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context,+                                        mapStr,+                                        XKB_KEYMAP_FORMAT_TEXT_V1,+                                        0);+    munmap(mapStr, size);+    close(fd);++    if (!keymap)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to compile keymap");+        return;+    }++    state = xkb_state_new(keymap);+    if (!state)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to create XKB state");+        xkb_keymap_unref(keymap);+        return;+    }++    // Look up the preferred locale, falling back to "C" as default.+    locale = getenv("LC_ALL");+    if (!locale)+        locale = getenv("LC_CTYPE");+    if (!locale)+        locale = getenv("LANG");+    if (!locale)+        locale = "C";++    composeTable =+        xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,+                                          XKB_COMPOSE_COMPILE_NO_FLAGS);+    if (composeTable)+    {+        composeState =+            xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS);+        xkb_compose_table_unref(composeTable);+        if (composeState)+            _glfw.wl.xkb.composeState = composeState;+        else+            _glfwInputError(GLFW_PLATFORM_ERROR,+                            "Wayland: Failed to create XKB compose state");+    }+    else+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to create XKB compose table");+    }++    xkb_keymap_unref(_glfw.wl.xkb.keymap);+    xkb_state_unref(_glfw.wl.xkb.state);+    _glfw.wl.xkb.keymap = keymap;+    _glfw.wl.xkb.state = state;++    _glfw.wl.xkb.controlIndex  = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control");+    _glfw.wl.xkb.altIndex      = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");+    _glfw.wl.xkb.shiftIndex    = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift");+    _glfw.wl.xkb.superIndex    = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");+    _glfw.wl.xkb.capsLockIndex = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Lock");+    _glfw.wl.xkb.numLockIndex  = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod2");+}++static void keyboardHandleEnter(void* userData,+                                struct wl_keyboard* keyboard,+                                uint32_t serial,+                                struct wl_surface* surface,+                                struct wl_array* keys)+{+    // Happens in the case we just destroyed the surface.+    if (!surface)+        return;++    if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)+        return;++    _GLFWwindow* window = wl_surface_get_user_data(surface);+    if (surface != window->wl.surface)+        return;++    _glfw.wl.serial = serial;+    _glfw.wl.keyboardFocus = window;+    _glfwInputWindowFocus(window, GLFW_TRUE);+}++static void keyboardHandleLeave(void* userData,+                                struct wl_keyboard* keyboard,+                                uint32_t serial,+                                struct wl_surface* surface)+{+    _GLFWwindow* window = _glfw.wl.keyboardFocus;++    if (!window)+        return;++    struct itimerspec timer = {0};+    timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL);++    _glfw.wl.serial = serial;+    _glfw.wl.keyboardFocus = NULL;+    _glfwInputWindowFocus(window, GLFW_FALSE);+}++static void keyboardHandleKey(void* userData,+                              struct wl_keyboard* keyboard,+                              uint32_t serial,+                              uint32_t time,+                              uint32_t scancode,+                              uint32_t state)+{+    _GLFWwindow* window = _glfw.wl.keyboardFocus;+    if (!window)+        return;++    const int key = translateKey(scancode);+    const int action =+        state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;++    _glfw.wl.serial = serial;++    struct itimerspec timer = {0};++    if (action == GLFW_PRESS)+    {+        const xkb_keycode_t keycode = scancode + 8;++        if (xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, keycode) &&+            _glfw.wl.keyRepeatRate > 0)+        {+            _glfw.wl.keyRepeatScancode = scancode;+            if (_glfw.wl.keyRepeatRate > 1)+                timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyRepeatRate;+            else+                timer.it_interval.tv_sec = 1;++            timer.it_value.tv_sec = _glfw.wl.keyRepeatDelay / 1000;+            timer.it_value.tv_nsec = (_glfw.wl.keyRepeatDelay % 1000) * 1000000;+        }+    }++    timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL);++    _glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers);++    if (action == GLFW_PRESS)+        inputText(window, scancode);+}++static void keyboardHandleModifiers(void* userData,+                                    struct wl_keyboard* keyboard,+                                    uint32_t serial,+                                    uint32_t modsDepressed,+                                    uint32_t modsLatched,+                                    uint32_t modsLocked,+                                    uint32_t group)+{+    _glfw.wl.serial = serial;++    if (!_glfw.wl.xkb.keymap)+        return;++    xkb_state_update_mask(_glfw.wl.xkb.state,+                          modsDepressed,+                          modsLatched,+                          modsLocked,+                          0,+                          0,+                          group);++    _glfw.wl.xkb.modifiers = 0;++    struct+    {+        xkb_mod_index_t index;+        unsigned int bit;+    } modifiers[] =+    {+        { _glfw.wl.xkb.controlIndex,  GLFW_MOD_CONTROL },+        { _glfw.wl.xkb.altIndex,      GLFW_MOD_ALT },+        { _glfw.wl.xkb.shiftIndex,    GLFW_MOD_SHIFT },+        { _glfw.wl.xkb.superIndex,    GLFW_MOD_SUPER },+        { _glfw.wl.xkb.capsLockIndex, GLFW_MOD_CAPS_LOCK },+        { _glfw.wl.xkb.numLockIndex,  GLFW_MOD_NUM_LOCK }+    };++    for (size_t i = 0; i < sizeof(modifiers) / sizeof(modifiers[0]); i++)+    {+        if (xkb_state_mod_index_is_active(_glfw.wl.xkb.state,+                                          modifiers[i].index,+                                          XKB_STATE_MODS_EFFECTIVE) == 1)+        {+            _glfw.wl.xkb.modifiers |= modifiers[i].bit;+        }+    }+}++#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION+static void keyboardHandleRepeatInfo(void* userData,+                                     struct wl_keyboard* keyboard,+                                     int32_t rate,+                                     int32_t delay)+{+    if (keyboard != _glfw.wl.keyboard)+        return;++    _glfw.wl.keyRepeatRate = rate;+    _glfw.wl.keyRepeatDelay = delay;+}+#endif++static const struct wl_keyboard_listener keyboardListener =+{+    keyboardHandleKeymap,+    keyboardHandleEnter,+    keyboardHandleLeave,+    keyboardHandleKey,+    keyboardHandleModifiers,+#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION+    keyboardHandleRepeatInfo,+#endif+};++static void seatHandleCapabilities(void* userData,+                                   struct wl_seat* seat,+                                   enum wl_seat_capability caps)+{+    if ((caps & WL_SEAT_CAPABILITY_POINTER) && !_glfw.wl.pointer)+    {+        _glfw.wl.pointer = wl_seat_get_pointer(seat);+        wl_pointer_add_listener(_glfw.wl.pointer, &pointerListener, NULL);+    }+    else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && _glfw.wl.pointer)+    {+        wl_pointer_destroy(_glfw.wl.pointer);+        _glfw.wl.pointer = NULL;+    }++    if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !_glfw.wl.keyboard)+    {+        _glfw.wl.keyboard = wl_seat_get_keyboard(seat);+        wl_keyboard_add_listener(_glfw.wl.keyboard, &keyboardListener, NULL);+    }+    else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && _glfw.wl.keyboard)+    {+        wl_keyboard_destroy(_glfw.wl.keyboard);+        _glfw.wl.keyboard = NULL;+    }+}++static void seatHandleName(void* userData,+                           struct wl_seat* seat,+                           const char* name)+{+}++static const struct wl_seat_listener seatListener =+{+    seatHandleCapabilities,+    seatHandleName,+};++static void dataOfferHandleOffer(void* userData,+                                 struct wl_data_offer* offer,+                                 const char* mimeType)+{+    for (unsigned int i = 0; i < _glfw.wl.offerCount; i++)+    {+        if (_glfw.wl.offers[i].offer == offer)+        {+            if (strcmp(mimeType, "text/plain;charset=utf-8") == 0)+                _glfw.wl.offers[i].text_plain_utf8 = GLFW_TRUE;+            else if (strcmp(mimeType, "text/uri-list") == 0)+                _glfw.wl.offers[i].text_uri_list = GLFW_TRUE;++            break;+        }+    }+}++static const struct wl_data_offer_listener dataOfferListener =+{+    dataOfferHandleOffer+};++static void dataDeviceHandleDataOffer(void* userData,+                                      struct wl_data_device* device,+                                      struct wl_data_offer* offer)+{+    _GLFWofferWayland* offers =+        realloc(_glfw.wl.offers,+                sizeof(_GLFWofferWayland) * (_glfw.wl.offerCount + 1));+    if (!offers)+    {+        _glfwInputError(GLFW_OUT_OF_MEMORY, NULL);+        return;+    }++    _glfw.wl.offers = offers;+    _glfw.wl.offerCount++;++    _glfw.wl.offers[_glfw.wl.offerCount - 1] = (_GLFWofferWayland) { offer };+    wl_data_offer_add_listener(offer, &dataOfferListener, NULL);+}++static void dataDeviceHandleEnter(void* userData,+                                  struct wl_data_device* device,+                                  uint32_t serial,+                                  struct wl_surface* surface,+                                  wl_fixed_t x,+                                  wl_fixed_t y,+                                  struct wl_data_offer* offer)+{+    if (_glfw.wl.dragOffer)+    {+        wl_data_offer_destroy(_glfw.wl.dragOffer);+        _glfw.wl.dragOffer = NULL;+        _glfw.wl.dragFocus = NULL;+    }++    for (unsigned int i = 0; i < _glfw.wl.offerCount; i++)+    {+        if (_glfw.wl.offers[i].offer == offer)+        {+            _GLFWwindow* window = NULL;++            if (surface)+            {+                if (wl_proxy_get_tag((struct wl_proxy*) surface) == &_glfw.wl.tag)+                    window = wl_surface_get_user_data(surface);+            }++            if (surface == window->wl.surface && _glfw.wl.offers[i].text_uri_list)+            {+                _glfw.wl.dragOffer = offer;+                _glfw.wl.dragFocus = window;+                _glfw.wl.dragSerial = serial;+            }++            _glfw.wl.offers[i] = _glfw.wl.offers[_glfw.wl.offerCount - 1];+            _glfw.wl.offerCount--;+            break;+        }+    }++    if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)+        return;++    if (_glfw.wl.dragOffer)+        wl_data_offer_accept(offer, serial, "text/uri-list");+    else+    {+        wl_data_offer_accept(offer, serial, NULL);+        wl_data_offer_destroy(offer);+    }+}++static void dataDeviceHandleLeave(void* userData,+                                  struct wl_data_device* device)+{+    if (_glfw.wl.dragOffer)+    {+        wl_data_offer_destroy(_glfw.wl.dragOffer);+        _glfw.wl.dragOffer = NULL;+        _glfw.wl.dragFocus = NULL;+    }+}++static void dataDeviceHandleMotion(void* userData,+                                   struct wl_data_device* device,+                                   uint32_t time,+                                   wl_fixed_t x,+                                   wl_fixed_t y)+{+}++static void dataDeviceHandleDrop(void* userData,+                                 struct wl_data_device* device)+{+    if (!_glfw.wl.dragOffer)+        return;++    char* string = readDataOfferAsString(_glfw.wl.dragOffer, "text/uri-list");+    if (string)+    {+        int count;+        char** paths = _glfwParseUriList(string, &count);+        if (paths)+            _glfwInputDrop(_glfw.wl.dragFocus, count, (const char**) paths);++        for (int i = 0; i < count; i++)+            free(paths[i]);++        free(paths);+    }++    free(string);+}++static void dataDeviceHandleSelection(void* userData,+                                      struct wl_data_device* device,+                                      struct wl_data_offer* offer)+{+    if (_glfw.wl.selectionOffer)+    {+        wl_data_offer_destroy(_glfw.wl.selectionOffer);+        _glfw.wl.selectionOffer = NULL;+    }++    for (unsigned int i = 0; i < _glfw.wl.offerCount; i++)+    {+        if (_glfw.wl.offers[i].offer == offer)+        {+            if (_glfw.wl.offers[i].text_plain_utf8)+                _glfw.wl.selectionOffer = offer;+            else+                wl_data_offer_destroy(offer);++            _glfw.wl.offers[i] = _glfw.wl.offers[_glfw.wl.offerCount - 1];+            _glfw.wl.offerCount--;+            break;+        }+    }+}++const struct wl_data_device_listener dataDeviceListener =+{+    dataDeviceHandleDataOffer,+    dataDeviceHandleEnter,+    dataDeviceHandleLeave,+    dataDeviceHandleMotion,+    dataDeviceHandleDrop,+    dataDeviceHandleSelection,+};++// Translates a GLFW standard cursor to a theme cursor name+//+static char *translateCursorShape(int shape)+{+    switch (shape)+    {+        case GLFW_ARROW_CURSOR:+            return "left_ptr";+        case GLFW_IBEAM_CURSOR:+            return "xterm";+        case GLFW_CROSSHAIR_CURSOR:+            return "crosshair";+        case GLFW_HAND_CURSOR:+            return "hand2";+        case GLFW_HRESIZE_CURSOR:+            return "sb_h_double_arrow";+        case GLFW_VRESIZE_CURSOR:+            return "sb_v_double_arrow";+    }+    return NULL;+}++void _glfwAddSeatListenerWayland(struct wl_seat* seat)+{+    wl_seat_add_listener(seat, &seatListener, NULL);+}++void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device)+{+    wl_data_device_add_listener(device, &dataDeviceListener, NULL);+}+++//////////////////////////////////////////////////////////////////////////+//////                       GLFW platform API                      //////+//////////////////////////////////////////////////////////////////////////++int _glfwPlatformCreateWindow(_GLFWwindow* window,+                              const _GLFWwndconfig* wndconfig,+                              const _GLFWctxconfig* ctxconfig,+                              const _GLFWfbconfig* fbconfig)+{+    if (!createNativeSurface(window, wndconfig, fbconfig))+        return GLFW_FALSE;++    if (ctxconfig->client != GLFW_NO_API)+    {+        if (ctxconfig->source == GLFW_EGL_CONTEXT_API ||+            ctxconfig->source == GLFW_NATIVE_CONTEXT_API)+        {+            window->wl.egl.window = wl_egl_window_create(window->wl.surface,+                                                         wndconfig->width,+                                                         wndconfig->height);+            if (!window->wl.egl.window)+            {+                _glfwInputError(GLFW_PLATFORM_ERROR,+                                "Wayland: Failed to create EGL window");+                return GLFW_FALSE;+            }++            if (!_glfwInitEGL())+                return GLFW_FALSE;+            if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))+                return GLFW_FALSE;+        }+        else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)+        {+            if (!_glfwInitOSMesa())+                return GLFW_FALSE;+            if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))+                return GLFW_FALSE;+        }++        if (!_glfwRefreshContextAttribs(window, ctxconfig))+            return GLFW_FALSE;+    }++    if (window->monitor || wndconfig->visible)+    {+        if (!createShellObjects(window))+            return GLFW_FALSE;+    }++    return GLFW_TRUE;+}++void _glfwPlatformDestroyWindow(_GLFWwindow* window)+{+    if (window == _glfw.wl.pointerFocus)+        _glfw.wl.pointerFocus = NULL;++    if (window == _glfw.wl.keyboardFocus)+        _glfw.wl.keyboardFocus = NULL;++    if (window->wl.idleInhibitor)+        zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);++    if (window->wl.relativePointer)+        zwp_relative_pointer_v1_destroy(window->wl.relativePointer);++    if (window->wl.lockedPointer)+        zwp_locked_pointer_v1_destroy(window->wl.lockedPointer);++    if (window->context.destroy)+        window->context.destroy(window);++    destroyShellObjects(window);++    if (window->wl.decorations.buffer)+        wl_buffer_destroy(window->wl.decorations.buffer);++    if (window->wl.egl.window)+        wl_egl_window_destroy(window->wl.egl.window);++    if (window->wl.surface)+        wl_surface_destroy(window->wl.surface);++    free(window->wl.title);+    free(window->wl.scales);+}++void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)+{+    if (window->wl.title)+        free(window->wl.title);+    window->wl.title = _glfw_strdup(title);++    if (window->wl.libdecor.frame)+        libdecor_frame_set_title(window->wl.libdecor.frame, title);+    else if (window->wl.xdg.toplevel)+        xdg_toplevel_set_title(window->wl.xdg.toplevel, title);+}++void _glfwPlatformSetWindowIcon(_GLFWwindow* window,+                                int count, const GLFWimage* images)+{+    _glfwInputError(GLFW_PLATFORM_ERROR,+                    "Wayland: Setting window icon not supported");+}++void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)+{+    // A Wayland client is not aware of its position, so just warn and leave it+    // as (0, 0)++    _glfwInputError(GLFW_PLATFORM_ERROR,+                    "Wayland: Window position retrieval not supported");+}++void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)+{+    // A Wayland client can not set its position, so just warn++    _glfwInputError(GLFW_PLATFORM_ERROR,+                    "Wayland: Window position setting not supported");+}++void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)+{+    if (width)+        *width = window->wl.width;+    if (height)+        *height = window->wl.height;+}++void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)+{+    if (window->monitor)+    {+        // Video mode setting is not available on Wayland+    }+    else+    {+        window->wl.width = width;+        window->wl.height = height;+        resizeWindow(window);++        if (window->wl.libdecor.frame)+        {+            struct libdecor_state* frameState = libdecor_state_new(width, height);+            libdecor_frame_commit(window->wl.libdecor.frame, frameState, NULL);+            libdecor_state_free(frameState);+        }++        if (window->wl.visible)+            _glfwInputWindowDamage(window);+    }+}++void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,+                                      int minwidth, int minheight,+                                      int maxwidth, int maxheight)+{+    if (window->wl.libdecor.frame)+    {+        if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)+            minwidth = minheight = 0;++        if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)+            maxwidth = maxheight = 0;++        libdecor_frame_set_min_content_size(window->wl.libdecor.frame,+                                            minwidth, minheight);+        libdecor_frame_set_max_content_size(window->wl.libdecor.frame,+                                            maxwidth, maxheight);+    }+    else if (window->wl.xdg.toplevel)+    {+        if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)+            minwidth = minheight = 0;+        else+        {+            if (window->wl.decorations.top.surface)+            {+                minwidth  += GLFW_BORDER_SIZE * 2;+                minheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE;+            }+        }++        if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)+            maxwidth = maxheight = 0;+        else+        {+            if (window->wl.decorations.top.surface)+            {+                maxwidth  += GLFW_BORDER_SIZE * 2;+                maxheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE;+            }+        }++        xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight);+        xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight);+        wl_surface_commit(window->wl.surface);+    }+}++void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window,+                                       int numer, int denom)+{+    if (window->wl.maximized || window->wl.fullscreen)+        return;++    int width = window->wl.width, height = window->wl.height;++    if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE)+    {+        const float aspectRatio = (float) width / (float) height;+        const float targetRatio = (float) numer / (float) denom;+        if (aspectRatio < targetRatio)+            height /= targetRatio;+        else if (aspectRatio > targetRatio)+            width *= targetRatio;+    }++    if (width != window->wl.width || height != window->wl.height)+    {+        window->wl.width = width;+        window->wl.height = height;+        resizeWindow(window);++        if (window->wl.libdecor.frame)+        {+            struct libdecor_state* frameState = libdecor_state_new(width, height);+            libdecor_frame_commit(window->wl.libdecor.frame, frameState, NULL);+            libdecor_state_free(frameState);+        }++        _glfwInputWindowSize(window, width, height);++        if (window->wl.visible)+            _glfwInputWindowDamage(window);+    }+}++void _glfwPlatformGetFramebufferSize(_GLFWwindow* window,+                                     int* width, int* height)+{+    _glfwPlatformGetWindowSize(window, width, height);+    if (width)+        *width *= window->wl.contentScale;+    if (height)+        *height *= window->wl.contentScale;+}++void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,+                                     int* left, int* top,+                                     int* right, int* bottom)+{+    if (window->wl.decorations.top.surface)+    {+        if (top)+            *top = GLFW_CAPTION_HEIGHT;+        if (left)+            *left = GLFW_BORDER_SIZE;+        if (right)+            *right = GLFW_BORDER_SIZE;+        if (bottom)+            *bottom = GLFW_BORDER_SIZE;+    }+}++void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,+                                        float* xscale, float* yscale)+{+    if (xscale)+        *xscale = (float) window->wl.contentScale;+    if (yscale)+        *yscale = (float) window->wl.contentScale;+}++void _glfwPlatformIconifyWindow(_GLFWwindow* window)+{+    if (window->wl.libdecor.frame)+        libdecor_frame_set_minimized(window->wl.libdecor.frame);+    else if (window->wl.xdg.toplevel)+        xdg_toplevel_set_minimized(window->wl.xdg.toplevel);+}++void _glfwPlatformRestoreWindow(_GLFWwindow* window)+{+    if (window->monitor)+    {+        // There is no way to unset minimized, or even to know if we are+        // minimized, so there is nothing to do here.+    }+    else+    {+        // We assume we are not minimized and act only on maximization++        if (window->wl.maximized)+        {+            if (window->wl.libdecor.frame)+                libdecor_frame_unset_maximized(window->wl.libdecor.frame);+            else if (window->wl.xdg.toplevel)+                xdg_toplevel_unset_maximized(window->wl.xdg.toplevel);+            else+                window->wl.maximized = GLFW_FALSE;+        }+    }+}++void _glfwPlatformMaximizeWindow(_GLFWwindow* window)+{+    if (window->wl.libdecor.frame)+        libdecor_frame_set_maximized(window->wl.libdecor.frame);+    else if (window->wl.xdg.toplevel)+        xdg_toplevel_set_maximized(window->wl.xdg.toplevel);+    else+        window->wl.maximized = GLFW_TRUE;+}++void _glfwPlatformShowWindow(_GLFWwindow* window)+{+    if (!window->wl.libdecor.frame && !window->wl.xdg.toplevel)+    {+        // NOTE: The XDG/shell surface is created here so command-line applications+        //       with off-screen windows do not appear in for example the Unity dock+        createShellObjects(window);+    }+}++void _glfwPlatformHideWindow(_GLFWwindow* window)+{+    if (window->wl.visible)+    {+        window->wl.visible = GLFW_FALSE;+        destroyShellObjects(window);++        wl_surface_attach(window->wl.surface, NULL, 0, 0);+        wl_surface_commit(window->wl.surface);+    }+}++void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)+{+    // TODO+    _glfwInputError(GLFW_PLATFORM_ERROR,+                    "Wayland: Window attention request not implemented yet");+}++void _glfwPlatformFocusWindow(_GLFWwindow* window)+{+    _glfwInputError(GLFW_PLATFORM_ERROR,+                    "Wayland: Focusing a window requires user interaction");+}++void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,+                                   _GLFWmonitor* monitor,+                                   int xpos, int ypos,+                                   int width, int height,+                                   int refreshRate)+{+    if (window->monitor == monitor)+    {+        if (!monitor)+            _glfwPlatformSetWindowSize(window, width, height);++        return;+    }++    if (window->monitor)+        releaseMonitor(window);++    _glfwInputWindowMonitor(window, monitor);++    if (window->monitor)+        acquireMonitor(window);+    else+        _glfwPlatformSetWindowSize(window, width, height);+}++int _glfwPlatformWindowFocused(_GLFWwindow* window)+{+    return _glfw.wl.keyboardFocus == window;+}++int _glfwPlatformWindowIconified(_GLFWwindow* window)+{+    // xdg-shell doesn’t give any way to request whether a surface is iconified+    return GLFW_FALSE;+}++int _glfwPlatformWindowVisible(_GLFWwindow* window)+{+    return window->wl.visible;+}++int _glfwPlatformWindowMaximized(_GLFWwindow* window)+{+    return window->wl.maximized;+}++int _glfwPlatformWindowHovered(_GLFWwindow* window)+{+    return window->wl.hovered;+}++int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)+{+    return window->wl.transparent;+}++void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)+{+    if (window->wl.libdecor.frame)+    {+        if (enabled)+        {+            libdecor_frame_set_capabilities(window->wl.libdecor.frame,+                                            LIBDECOR_ACTION_RESIZE);+        }+        else+        {+            libdecor_frame_unset_capabilities(window->wl.libdecor.frame,+                                              LIBDECOR_ACTION_RESIZE);+        }+    }+    else+    {+        // TODO+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Window attribute setting not implemented yet");+    }+}++void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)+{+    if (window->wl.libdecor.frame)+    {+        libdecor_frame_set_visibility(window->wl.libdecor.frame, enabled);+    }+    else if (window->wl.xdg.decoration)+    {+        uint32_t mode;++        if (enabled)+            mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;+        else+            mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;++        zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, mode);+    }+    else if (window->wl.xdg.toplevel)+    {+        if (enabled)+            createFallbackDecorations(window);+        else+            destroyFallbackDecorations(window);+    }+}++void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)+{+    // TODO+    _glfwInputError(GLFW_PLATFORM_ERROR,+                    "Wayland: Window attribute setting not implemented yet");+}++float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)+{+    return 1.f;+}++void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)+{+}++void _glfwPlatformSetRawMouseMotion(_GLFWwindow* window, GLFWbool enabled)+{+    // This is handled in relativePointerHandleRelativeMotion+}++GLFWbool _glfwPlatformRawMouseMotionSupported(void)+{+    return GLFW_TRUE;+}++void _glfwPlatformPollEvents(void)+{+    double timeout = 0.0;+    handleEvents(&timeout);+}++void _glfwPlatformWaitEvents(void)+{+    handleEvents(NULL);+}++void _glfwPlatformWaitEventsTimeout(double timeout)+{+    handleEvents(&timeout);+}++void _glfwPlatformPostEmptyEvent(void)+{+    wl_display_sync(_glfw.wl.display);+    flushDisplay();+}++void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)+{+    if (xpos)+        *xpos = window->wl.cursorPosX;+    if (ypos)+        *ypos = window->wl.cursorPosY;+}++void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)+{+}++void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)+{+    _glfwPlatformSetCursor(window, window->wl.currentCursor);+}++const char* _glfwPlatformGetScancodeName(int scancode)+{+    if (scancode < 0 || scancode > 255 ||+        _glfw.wl.keycodes[scancode] == GLFW_KEY_UNKNOWN)+    {+        _glfwInputError(GLFW_INVALID_VALUE,+                        "Wayland: Invalid scancode %i",+                        scancode);+        return NULL;+    }++    const int key = _glfw.wl.keycodes[scancode];+    const xkb_keycode_t keycode = scancode + 8;+    const xkb_layout_index_t layout =+        xkb_state_key_get_layout(_glfw.wl.xkb.state, keycode);+    if (layout == XKB_LAYOUT_INVALID)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to retrieve layout for key name");+        return NULL;+    }++    const xkb_keysym_t* keysyms = NULL;+    xkb_keymap_key_get_syms_by_level(_glfw.wl.xkb.keymap,+                                     keycode,+                                     layout,+                                     0,+                                     &keysyms);+    if (keysyms == NULL)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to retrieve keysym for key name");+        return NULL;+    }++    const uint32_t codepoint = _glfwKeySym2Unicode(keysyms[0]);+    if (codepoint == GLFW_INVALID_CODEPOINT)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to retrieve codepoint for key name");+        return NULL;+    }++    const size_t count = _glfwEncodeUTF8(_glfw.wl.keynames[key],  codepoint);+    if (count == 0)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to encode codepoint for key name");+        return NULL;+    }++    _glfw.wl.keynames[key][count] = '\0';+    return _glfw.wl.keynames[key];+}++int _glfwPlatformGetKeyScancode(int key)+{+    return _glfw.wl.scancodes[key];+}++int _glfwPlatformCreateCursor(_GLFWcursor* cursor,+                              const GLFWimage* image,+                              int xhot, int yhot)+{+    cursor->wl.buffer = createShmBuffer(image);+    if (!cursor->wl.buffer)+        return GLFW_FALSE;++    cursor->wl.width = image->width;+    cursor->wl.height = image->height;+    cursor->wl.xhot = xhot;+    cursor->wl.yhot = yhot;+    return GLFW_TRUE;+}++int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)+{+    struct wl_cursor* standardCursor;++    standardCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,+                                                translateCursorShape(shape));+    if (!standardCursor)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Standard cursor \"%s\" not found",+                        translateCursorShape(shape));+        return GLFW_FALSE;+    }++    cursor->wl.cursor = standardCursor;+    cursor->wl.currentImage = 0;++    if (_glfw.wl.cursorThemeHiDPI)+    {+        standardCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI,+                                                    translateCursorShape(shape));+        cursor->wl.cursorHiDPI = standardCursor;+    }++    return GLFW_TRUE;+}++void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)+{+    // If it's a standard cursor we don't need to do anything here+    if (cursor->wl.cursor)+        return;++    if (cursor->wl.buffer)+        wl_buffer_destroy(cursor->wl.buffer);+}++static void relativePointerHandleRelativeMotion(void* userData,+                                                struct zwp_relative_pointer_v1* pointer,+                                                uint32_t timeHi,+                                                uint32_t timeLo,+                                                wl_fixed_t dx,+                                                wl_fixed_t dy,+                                                wl_fixed_t dxUnaccel,+                                                wl_fixed_t dyUnaccel)+{+    _GLFWwindow* window = userData;+    double xpos = window->virtualCursorPosX;+    double ypos = window->virtualCursorPosY;++    if (window->cursorMode != GLFW_CURSOR_DISABLED)+        return;++    if (window->rawMouseMotion)+    {+        xpos += wl_fixed_to_double(dxUnaccel);+        ypos += wl_fixed_to_double(dyUnaccel);+    }+    else+    {+        xpos += wl_fixed_to_double(dx);+        ypos += wl_fixed_to_double(dy);+    }++    _glfwInputCursorPos(window, xpos, ypos);+}++static const struct zwp_relative_pointer_v1_listener relativePointerListener =+{+    relativePointerHandleRelativeMotion+};++static void lockedPointerHandleLocked(void* userData,+                                      struct zwp_locked_pointer_v1* lockedPointer)+{+}++static void lockedPointerHandleUnlocked(void* userData,+                                        struct zwp_locked_pointer_v1* lockedPointer)+{+}++static const struct zwp_locked_pointer_v1_listener lockedPointerListener =+{+    lockedPointerHandleLocked,+    lockedPointerHandleUnlocked+};++static void lockPointer(_GLFWwindow* window)+{+    if (!_glfw.wl.relativePointerManager)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: no relative pointer manager");+        return;+    }++    window->wl.relativePointer =+        zwp_relative_pointer_manager_v1_get_relative_pointer(+            _glfw.wl.relativePointerManager,+            _glfw.wl.pointer);+    zwp_relative_pointer_v1_add_listener(window->wl.relativePointer,+                                         &relativePointerListener,+                                         window);++    window->wl.lockedPointer =+        zwp_pointer_constraints_v1_lock_pointer(+            _glfw.wl.pointerConstraints,+            window->wl.surface,+            _glfw.wl.pointer,+            NULL,+            ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);+    zwp_locked_pointer_v1_add_listener(window->wl.lockedPointer,+                                       &lockedPointerListener,+                                       window);+}++static void unlockPointer(_GLFWwindow* window)+{+    zwp_relative_pointer_v1_destroy(window->wl.relativePointer);+    window->wl.relativePointer = NULL;++    zwp_locked_pointer_v1_destroy(window->wl.lockedPointer);+    window->wl.lockedPointer = NULL;+}++void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)+{+    if (!_glfw.wl.pointer)+        return;++    window->wl.currentCursor = cursor;++    // If we're not in the correct window just save the cursor+    // the next time the pointer enters the window the cursor will change+    if (window != _glfw.wl.pointerFocus ||+        window->wl.decorations.focus != GLFW_MAIN_WINDOW)+    {+        return;+    }++    // Update pointer lock to match cursor mode+    if (window->cursorMode == GLFW_CURSOR_DISABLED)+    {+        if (!window->wl.lockedPointer)+            lockPointer(window);+    }+    else if (window->cursorMode == GLFW_CURSOR_NORMAL ||+             window->cursorMode == GLFW_CURSOR_HIDDEN)+    {+        if (window->wl.lockedPointer)+            unlockPointer(window);+    }++    if (window->cursorMode == GLFW_CURSOR_NORMAL)+    {+        if (cursor)+            setCursorImage(window, &cursor->wl);+        else+        {+            struct wl_cursor* defaultCursor =+                wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme, "left_ptr");+            if (!defaultCursor)+            {+                _glfwInputError(GLFW_PLATFORM_ERROR,+                                "Wayland: Standard cursor not found");+                return;+            }++            struct wl_cursor* defaultCursorHiDPI = NULL;+            if (_glfw.wl.cursorThemeHiDPI)+            {+                defaultCursorHiDPI =+                    wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI, "left_ptr");+            }++            _GLFWcursorWayland cursorWayland =+            {+                defaultCursor,+                defaultCursorHiDPI,+                NULL,+                0, 0,+                0, 0,+                0+            };++            setCursorImage(window, &cursorWayland);+        }+    }+    else if (window->cursorMode == GLFW_CURSOR_HIDDEN ||+             window->cursorMode == GLFW_CURSOR_DISABLED)+    {+        wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial, NULL, 0, 0);+    }+}++static void dataSourceHandleTarget(void* userData,+                                   struct wl_data_source* source,+                                   const char* mimeType)+{+    if (_glfw.wl.selectionSource != source)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Unknown clipboard data source");+        return;+    }+}++static void dataSourceHandleSend(void* userData,+                                 struct wl_data_source* source,+                                 const char* mimeType,+                                 int fd)+{+    // Ignore it if this is an outdated or invalid request+    if (_glfw.wl.selectionSource != source ||+        strcmp(mimeType, "text/plain;charset=utf-8") != 0)+    {+        close(fd);+        return;+    }++    char* string = _glfw.wl.clipboardString;+    size_t length = strlen(string);++    while (length > 0)+    {+        const ssize_t result = write(fd, string, length);+        if (result == -1)+        {+            if (errno == EINTR)+                continue;++            _glfwInputError(GLFW_PLATFORM_ERROR,+                            "Wayland: Error while writing the clipboard: %s",+                            strerror(errno));+            break;+        }++        length -= result;+        string += result;+    }++    close(fd);+}++static void dataSourceHandleCancelled(void* userData,+                                      struct wl_data_source* source)+{+    wl_data_source_destroy(source);++    if (_glfw.wl.selectionSource != source)+        return;++    _glfw.wl.selectionSource = NULL;+}++static const struct wl_data_source_listener dataSourceListener =+{+    dataSourceHandleTarget,+    dataSourceHandleSend,+    dataSourceHandleCancelled,+};++void _glfwPlatformSetClipboardString(const char* string)+{+    if (_glfw.wl.selectionSource)+    {+        wl_data_source_destroy(_glfw.wl.selectionSource);+        _glfw.wl.selectionSource = NULL;+    }++    char* copy = _glfw_strdup(string);+    if (!copy)+    {+        _glfwInputError(GLFW_OUT_OF_MEMORY, NULL);+        return;+    }++    free(_glfw.wl.clipboardString);+    _glfw.wl.clipboardString = copy;++    _glfw.wl.selectionSource =+        wl_data_device_manager_create_data_source(_glfw.wl.dataDeviceManager);+    if (!_glfw.wl.selectionSource)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "Wayland: Failed to create clipboard data source");+        return;+    }+    wl_data_source_add_listener(_glfw.wl.selectionSource,+                                &dataSourceListener,+                                NULL);+    wl_data_source_offer(_glfw.wl.selectionSource, "text/plain;charset=utf-8");+    wl_data_device_set_selection(_glfw.wl.dataDevice,+                                 _glfw.wl.selectionSource,+                                 _glfw.wl.serial);+}++const char* _glfwPlatformGetClipboardString(void)+{+    if (!_glfw.wl.selectionOffer)+    {+        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,+                        "Wayland: No clipboard data available");+        return NULL;+    }++    if (_glfw.wl.selectionSource)+        return _glfw.wl.clipboardString;++    free(_glfw.wl.clipboardString);+    _glfw.wl.clipboardString =+        readDataOfferAsString(_glfw.wl.selectionOffer, "text/plain;charset=utf-8");     return _glfw.wl.clipboardString; } 
glfw/src/x11_init.c view
@@ -36,26 +36,21 @@ #include <limits.h> #include <stdio.h> #include <locale.h>+#include <unistd.h>+#include <fcntl.h>+#include <errno.h>+#include <assert.h>  -// Translate an X11 key code to a GLFW key code.+// Translate the X11 KeySyms for a key to a GLFW key code+// NOTE: This is only used as a fallback, in case the XKB method fails+//       It is layout-dependent and will fail partially on most non-US layouts //-static int translateKeyCode(int scancode)+static int translateKeySyms(const KeySym* keysyms, int width) {-    int keySym;--    // Valid key code range is  [8,255], according to the Xlib manual-    if (scancode < 8 || scancode > 255)-        return GLFW_KEY_UNKNOWN;--    if (_glfw.x11.xkb.available)+    if (width > 1)     {-        // Try secondary keysym, for numeric keypad keys-        // Note: This way we always force "NumLock = ON", which is intentional-        // since the returned key code should correspond to a physical-        // location.-        keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, _glfw.x11.xkb.group, 1);-        switch (keySym)+        switch (keysyms[1])         {             case XK_KP_0:           return GLFW_KEY_KP_0;             case XK_KP_1:           return GLFW_KEY_KP_1;@@ -73,22 +68,9 @@             case XK_KP_Enter:       return GLFW_KEY_KP_ENTER;             default:                break;         }--        // Now try primary keysym for function keys (non-printable keys)-        // These should not depend on the current keyboard layout-        keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, _glfw.x11.xkb.group, 0);     }-    else-    {-        int dummy;-        KeySym* keySyms; -        keySyms = XGetKeyboardMapping(_glfw.x11.display, scancode, 1, &dummy);-        keySym = keySyms[0];-        XFree(keySyms);-    }--    switch (keySym)+    switch (keysyms[0])     {         case XK_Escape:         return GLFW_KEY_ESCAPE;         case XK_Tab:            return GLFW_KEY_TAB;@@ -232,7 +214,7 @@ // static void createKeyTables(void) {-    int scancode, key;+    int scancode, scancodeMin, scancodeMax;      memset(_glfw.x11.keycodes, -1, sizeof(_glfw.x11.keycodes));     memset(_glfw.x11.scancodes, -1, sizeof(_glfw.x11.scancodes));@@ -242,89 +224,217 @@         // Use XKB to determine physical key locations independently of the         // current keyboard layout -        char name[XkbKeyNameLength + 1];         XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd);-        XkbGetNames(_glfw.x11.display, XkbKeyNamesMask, desc);+        XkbGetNames(_glfw.x11.display, XkbKeyNamesMask | XkbKeyAliasesMask, desc); +        scancodeMin = desc->min_key_code;+        scancodeMax = desc->max_key_code;++        const struct+        {+            int key;+            char* name;+        } keymap[] =+        {+            { GLFW_KEY_GRAVE_ACCENT, "TLDE" },+            { GLFW_KEY_1, "AE01" },+            { GLFW_KEY_2, "AE02" },+            { GLFW_KEY_3, "AE03" },+            { GLFW_KEY_4, "AE04" },+            { GLFW_KEY_5, "AE05" },+            { GLFW_KEY_6, "AE06" },+            { GLFW_KEY_7, "AE07" },+            { GLFW_KEY_8, "AE08" },+            { GLFW_KEY_9, "AE09" },+            { GLFW_KEY_0, "AE10" },+            { GLFW_KEY_MINUS, "AE11" },+            { GLFW_KEY_EQUAL, "AE12" },+            { GLFW_KEY_Q, "AD01" },+            { GLFW_KEY_W, "AD02" },+            { GLFW_KEY_E, "AD03" },+            { GLFW_KEY_R, "AD04" },+            { GLFW_KEY_T, "AD05" },+            { GLFW_KEY_Y, "AD06" },+            { GLFW_KEY_U, "AD07" },+            { GLFW_KEY_I, "AD08" },+            { GLFW_KEY_O, "AD09" },+            { GLFW_KEY_P, "AD10" },+            { GLFW_KEY_LEFT_BRACKET, "AD11" },+            { GLFW_KEY_RIGHT_BRACKET, "AD12" },+            { GLFW_KEY_A, "AC01" },+            { GLFW_KEY_S, "AC02" },+            { GLFW_KEY_D, "AC03" },+            { GLFW_KEY_F, "AC04" },+            { GLFW_KEY_G, "AC05" },+            { GLFW_KEY_H, "AC06" },+            { GLFW_KEY_J, "AC07" },+            { GLFW_KEY_K, "AC08" },+            { GLFW_KEY_L, "AC09" },+            { GLFW_KEY_SEMICOLON, "AC10" },+            { GLFW_KEY_APOSTROPHE, "AC11" },+            { GLFW_KEY_Z, "AB01" },+            { GLFW_KEY_X, "AB02" },+            { GLFW_KEY_C, "AB03" },+            { GLFW_KEY_V, "AB04" },+            { GLFW_KEY_B, "AB05" },+            { GLFW_KEY_N, "AB06" },+            { GLFW_KEY_M, "AB07" },+            { GLFW_KEY_COMMA, "AB08" },+            { GLFW_KEY_PERIOD, "AB09" },+            { GLFW_KEY_SLASH, "AB10" },+            { GLFW_KEY_BACKSLASH, "BKSL" },+            { GLFW_KEY_WORLD_1, "LSGT" },+            { GLFW_KEY_SPACE, "SPCE" },+            { GLFW_KEY_ESCAPE, "ESC" },+            { GLFW_KEY_ENTER, "RTRN" },+            { GLFW_KEY_TAB, "TAB" },+            { GLFW_KEY_BACKSPACE, "BKSP" },+            { GLFW_KEY_INSERT, "INS" },+            { GLFW_KEY_DELETE, "DELE" },+            { GLFW_KEY_RIGHT, "RGHT" },+            { GLFW_KEY_LEFT, "LEFT" },+            { GLFW_KEY_DOWN, "DOWN" },+            { GLFW_KEY_UP, "UP" },+            { GLFW_KEY_PAGE_UP, "PGUP" },+            { GLFW_KEY_PAGE_DOWN, "PGDN" },+            { GLFW_KEY_HOME, "HOME" },+            { GLFW_KEY_END, "END" },+            { GLFW_KEY_CAPS_LOCK, "CAPS" },+            { GLFW_KEY_SCROLL_LOCK, "SCLK" },+            { GLFW_KEY_NUM_LOCK, "NMLK" },+            { GLFW_KEY_PRINT_SCREEN, "PRSC" },+            { GLFW_KEY_PAUSE, "PAUS" },+            { GLFW_KEY_F1, "FK01" },+            { GLFW_KEY_F2, "FK02" },+            { GLFW_KEY_F3, "FK03" },+            { GLFW_KEY_F4, "FK04" },+            { GLFW_KEY_F5, "FK05" },+            { GLFW_KEY_F6, "FK06" },+            { GLFW_KEY_F7, "FK07" },+            { GLFW_KEY_F8, "FK08" },+            { GLFW_KEY_F9, "FK09" },+            { GLFW_KEY_F10, "FK10" },+            { GLFW_KEY_F11, "FK11" },+            { GLFW_KEY_F12, "FK12" },+            { GLFW_KEY_F13, "FK13" },+            { GLFW_KEY_F14, "FK14" },+            { GLFW_KEY_F15, "FK15" },+            { GLFW_KEY_F16, "FK16" },+            { GLFW_KEY_F17, "FK17" },+            { GLFW_KEY_F18, "FK18" },+            { GLFW_KEY_F19, "FK19" },+            { GLFW_KEY_F20, "FK20" },+            { GLFW_KEY_F21, "FK21" },+            { GLFW_KEY_F22, "FK22" },+            { GLFW_KEY_F23, "FK23" },+            { GLFW_KEY_F24, "FK24" },+            { GLFW_KEY_F25, "FK25" },+            { GLFW_KEY_KP_0, "KP0" },+            { GLFW_KEY_KP_1, "KP1" },+            { GLFW_KEY_KP_2, "KP2" },+            { GLFW_KEY_KP_3, "KP3" },+            { GLFW_KEY_KP_4, "KP4" },+            { GLFW_KEY_KP_5, "KP5" },+            { GLFW_KEY_KP_6, "KP6" },+            { GLFW_KEY_KP_7, "KP7" },+            { GLFW_KEY_KP_8, "KP8" },+            { GLFW_KEY_KP_9, "KP9" },+            { GLFW_KEY_KP_DECIMAL, "KPDL" },+            { GLFW_KEY_KP_DIVIDE, "KPDV" },+            { GLFW_KEY_KP_MULTIPLY, "KPMU" },+            { GLFW_KEY_KP_SUBTRACT, "KPSU" },+            { GLFW_KEY_KP_ADD, "KPAD" },+            { GLFW_KEY_KP_ENTER, "KPEN" },+            { GLFW_KEY_KP_EQUAL, "KPEQ" },+            { GLFW_KEY_LEFT_SHIFT, "LFSH" },+            { GLFW_KEY_LEFT_CONTROL, "LCTL" },+            { GLFW_KEY_LEFT_ALT, "LALT" },+            { GLFW_KEY_LEFT_SUPER, "LWIN" },+            { GLFW_KEY_RIGHT_SHIFT, "RTSH" },+            { GLFW_KEY_RIGHT_CONTROL, "RCTL" },+            { GLFW_KEY_RIGHT_ALT, "RALT" },+            { GLFW_KEY_RIGHT_ALT, "LVL3" },+            { GLFW_KEY_RIGHT_ALT, "MDSW" },+            { GLFW_KEY_RIGHT_SUPER, "RWIN" },+            { GLFW_KEY_MENU, "MENU" }+        };+         // Find the X11 key code -> GLFW key code mapping-        for (scancode = desc->min_key_code;  scancode <= desc->max_key_code;  scancode++)+        for (scancode = scancodeMin;  scancode <= scancodeMax;  scancode++)         {-            memcpy(name, desc->names->keys[scancode].name, XkbKeyNameLength);-            name[XkbKeyNameLength] = '\0';+            int key = GLFW_KEY_UNKNOWN; -            // Map the key name to a GLFW key code. Note: We only map printable-            // keys here, and we use the US keyboard layout. The rest of the-            // keys (function keys) are mapped using traditional KeySym-            // translations.-            if (strcmp(name, "TLDE") == 0) key = GLFW_KEY_GRAVE_ACCENT;-            else if (strcmp(name, "AE01") == 0) key = GLFW_KEY_1;-            else if (strcmp(name, "AE02") == 0) key = GLFW_KEY_2;-            else if (strcmp(name, "AE03") == 0) key = GLFW_KEY_3;-            else if (strcmp(name, "AE04") == 0) key = GLFW_KEY_4;-            else if (strcmp(name, "AE05") == 0) key = GLFW_KEY_5;-            else if (strcmp(name, "AE06") == 0) key = GLFW_KEY_6;-            else if (strcmp(name, "AE07") == 0) key = GLFW_KEY_7;-            else if (strcmp(name, "AE08") == 0) key = GLFW_KEY_8;-            else if (strcmp(name, "AE09") == 0) key = GLFW_KEY_9;-            else if (strcmp(name, "AE10") == 0) key = GLFW_KEY_0;-            else if (strcmp(name, "AE11") == 0) key = GLFW_KEY_MINUS;-            else if (strcmp(name, "AE12") == 0) key = GLFW_KEY_EQUAL;-            else if (strcmp(name, "AD01") == 0) key = GLFW_KEY_Q;-            else if (strcmp(name, "AD02") == 0) key = GLFW_KEY_W;-            else if (strcmp(name, "AD03") == 0) key = GLFW_KEY_E;-            else if (strcmp(name, "AD04") == 0) key = GLFW_KEY_R;-            else if (strcmp(name, "AD05") == 0) key = GLFW_KEY_T;-            else if (strcmp(name, "AD06") == 0) key = GLFW_KEY_Y;-            else if (strcmp(name, "AD07") == 0) key = GLFW_KEY_U;-            else if (strcmp(name, "AD08") == 0) key = GLFW_KEY_I;-            else if (strcmp(name, "AD09") == 0) key = GLFW_KEY_O;-            else if (strcmp(name, "AD10") == 0) key = GLFW_KEY_P;-            else if (strcmp(name, "AD11") == 0) key = GLFW_KEY_LEFT_BRACKET;-            else if (strcmp(name, "AD12") == 0) key = GLFW_KEY_RIGHT_BRACKET;-            else if (strcmp(name, "AC01") == 0) key = GLFW_KEY_A;-            else if (strcmp(name, "AC02") == 0) key = GLFW_KEY_S;-            else if (strcmp(name, "AC03") == 0) key = GLFW_KEY_D;-            else if (strcmp(name, "AC04") == 0) key = GLFW_KEY_F;-            else if (strcmp(name, "AC05") == 0) key = GLFW_KEY_G;-            else if (strcmp(name, "AC06") == 0) key = GLFW_KEY_H;-            else if (strcmp(name, "AC07") == 0) key = GLFW_KEY_J;-            else if (strcmp(name, "AC08") == 0) key = GLFW_KEY_K;-            else if (strcmp(name, "AC09") == 0) key = GLFW_KEY_L;-            else if (strcmp(name, "AC10") == 0) key = GLFW_KEY_SEMICOLON;-            else if (strcmp(name, "AC11") == 0) key = GLFW_KEY_APOSTROPHE;-            else if (strcmp(name, "AB01") == 0) key = GLFW_KEY_Z;-            else if (strcmp(name, "AB02") == 0) key = GLFW_KEY_X;-            else if (strcmp(name, "AB03") == 0) key = GLFW_KEY_C;-            else if (strcmp(name, "AB04") == 0) key = GLFW_KEY_V;-            else if (strcmp(name, "AB05") == 0) key = GLFW_KEY_B;-            else if (strcmp(name, "AB06") == 0) key = GLFW_KEY_N;-            else if (strcmp(name, "AB07") == 0) key = GLFW_KEY_M;-            else if (strcmp(name, "AB08") == 0) key = GLFW_KEY_COMMA;-            else if (strcmp(name, "AB09") == 0) key = GLFW_KEY_PERIOD;-            else if (strcmp(name, "AB10") == 0) key = GLFW_KEY_SLASH;-            else if (strcmp(name, "BKSL") == 0) key = GLFW_KEY_BACKSLASH;-            else if (strcmp(name, "LSGT") == 0) key = GLFW_KEY_WORLD_1;-            else key = GLFW_KEY_UNKNOWN;+            // Map the key name to a GLFW key code. Note: We use the US+            // keyboard layout. Because function keys aren't mapped correctly+            // when using traditional KeySym translations, they are mapped+            // here instead.+            for (int i = 0;  i < sizeof(keymap) / sizeof(keymap[0]);  i++)+            {+                if (strncmp(desc->names->keys[scancode].name,+                            keymap[i].name,+                            XkbKeyNameLength) == 0)+                {+                    key = keymap[i].key;+                    break;+                }+            } -            if ((scancode >= 0) && (scancode < 256))-                _glfw.x11.keycodes[scancode] = key;+            // Fall back to key aliases in case the key name did not match+            for (int i = 0;  i < desc->names->num_key_aliases;  i++)+            {+                if (key != GLFW_KEY_UNKNOWN)+                    break;++                if (strncmp(desc->names->key_aliases[i].real,+                            desc->names->keys[scancode].name,+                            XkbKeyNameLength) != 0)+                {+                    continue;+                }++                for (int j = 0;  j < sizeof(keymap) / sizeof(keymap[0]);  j++)+                {+                    if (strncmp(desc->names->key_aliases[i].alias,+                                keymap[j].name,+                                XkbKeyNameLength) == 0)+                    {+                        key = keymap[j].key;+                        break;+                    }+                }+            }++            _glfw.x11.keycodes[scancode] = key;         }          XkbFreeNames(desc, XkbKeyNamesMask, True);         XkbFreeKeyboard(desc, 0, True);     }+    else+        XDisplayKeycodes(_glfw.x11.display, &scancodeMin, &scancodeMax); -    for (scancode = 0;  scancode < 256;  scancode++)+    int width;+    KeySym* keysyms = XGetKeyboardMapping(_glfw.x11.display,+                                          scancodeMin,+                                          scancodeMax - scancodeMin + 1,+                                          &width);++    for (scancode = scancodeMin;  scancode <= scancodeMax;  scancode++)     {         // Translate the un-translated key codes using traditional X11 KeySym         // lookups         if (_glfw.x11.keycodes[scancode] < 0)-            _glfw.x11.keycodes[scancode] = translateKeyCode(scancode);+        {+            const size_t base = (scancode - scancodeMin) * width;+            _glfw.x11.keycodes[scancode] = translateKeySyms(&keysyms[base], width);+        }          // Store the reverse translation for faster key name lookup         if (_glfw.x11.keycodes[scancode] > 0)             _glfw.x11.scancodes[_glfw.x11.keycodes[scancode]] = scancode;     }++    XFree(keysyms); }  // Check whether the IM has a usable style@@ -352,13 +462,13 @@  // Check whether the specified atom is supported //-static Atom getSupportedAtom(Atom* supportedAtoms,-                             unsigned long atomCount,-                             const char* atomName)+static Atom getAtomIfSupported(Atom* supportedAtoms,+                               unsigned long atomCount,+                               const char* atomName) {     const Atom atom = XInternAtom(_glfw.x11.display, atomName, False); -    for (unsigned int i = 0;  i < atomCount;  i++)+    for (unsigned long i = 0;  i < atomCount;  i++)     {         if (supportedAtoms[i] == atom)             return atom;@@ -426,33 +536,33 @@     // See which of the atoms we support that are supported by the WM      _glfw.x11.NET_WM_STATE =-        getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE");+        getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE");     _glfw.x11.NET_WM_STATE_ABOVE =-        getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_ABOVE");+        getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_ABOVE");     _glfw.x11.NET_WM_STATE_FULLSCREEN =-        getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN");+        getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN");     _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT =-        getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_VERT");+        getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_VERT");     _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ =-        getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_HORZ");+        getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_HORZ");     _glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION =-        getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_DEMANDS_ATTENTION");+        getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_DEMANDS_ATTENTION");     _glfw.x11.NET_WM_FULLSCREEN_MONITORS =-        getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS");+        getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS");     _glfw.x11.NET_WM_WINDOW_TYPE =-        getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE");+        getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE");     _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL =-        getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL");+        getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL");     _glfw.x11.NET_WORKAREA =-        getSupportedAtom(supportedAtoms, atomCount, "_NET_WORKAREA");+        getAtomIfSupported(supportedAtoms, atomCount, "_NET_WORKAREA");     _glfw.x11.NET_CURRENT_DESKTOP =-        getSupportedAtom(supportedAtoms, atomCount, "_NET_CURRENT_DESKTOP");+        getAtomIfSupported(supportedAtoms, atomCount, "_NET_CURRENT_DESKTOP");     _glfw.x11.NET_ACTIVE_WINDOW =-        getSupportedAtom(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW");+        getAtomIfSupported(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW");     _glfw.x11.NET_FRAME_EXTENTS =-        getSupportedAtom(supportedAtoms, atomCount, "_NET_FRAME_EXTENTS");+        getAtomIfSupported(supportedAtoms, atomCount, "_NET_FRAME_EXTENTS");     _glfw.x11.NET_REQUEST_FRAME_EXTENTS =-        getSupportedAtom(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");+        getAtomIfSupported(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");      if (supportedAtoms)         XFree(supportedAtoms);@@ -462,7 +572,11 @@ // static GLFWbool initExtensions(void) {+#if defined(__OpenBSD__) || defined(__NetBSD__)+    _glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so");+#else     _glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1");+#endif     if (_glfw.x11.vidmode.handle)     {         _glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension)@@ -482,6 +596,8 @@  #if defined(__CYGWIN__)     _glfw.x11.xi.handle = _glfw_dlopen("libXi-6.so");+#elif defined(__OpenBSD__) || defined(__NetBSD__)+    _glfw.x11.xi.handle = _glfw_dlopen("libXi.so"); #else     _glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6"); #endif@@ -512,6 +628,8 @@  #if defined(__CYGWIN__)     _glfw.x11.randr.handle = _glfw_dlopen("libXrandr-2.so");+#elif defined(__OpenBSD__) || defined(__NetBSD__)+    _glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so"); #else     _glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2"); #endif@@ -604,6 +722,8 @@  #if defined(__CYGWIN__)     _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor-1.so");+#elif defined(__OpenBSD__) || defined(__NetBSD__)+    _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so"); #else     _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1"); #endif@@ -619,6 +739,8 @@  #if defined(__CYGWIN__)     _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama-1.so");+#elif defined(__OpenBSD__) || defined(__NetBSD__)+    _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so"); #else     _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1"); #endif@@ -660,17 +782,18 @@                 _glfw.x11.xkb.detectable = GLFW_TRUE;         } -        _glfw.x11.xkb.group = 0;         XkbStateRec state;         if (XkbGetState(_glfw.x11.display, XkbUseCoreKbd, &state) == Success)-        {-            XkbSelectEventDetails(_glfw.x11.display, XkbUseCoreKbd, XkbStateNotify, XkbAllStateComponentsMask, XkbGroupStateMask);             _glfw.x11.xkb.group = (unsigned int)state.group;-        }++        XkbSelectEventDetails(_glfw.x11.display, XkbUseCoreKbd, XkbStateNotify,+                              XkbGroupStateMask, XkbGroupStateMask);     }  #if defined(__CYGWIN__)     _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb-1.so");+#elif defined(__OpenBSD__) || defined(__NetBSD__)+    _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so"); #else     _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1"); #endif@@ -682,6 +805,8 @@  #if defined(__CYGWIN__)     _glfw.x11.xrender.handle = _glfw_dlopen("libXrender-1.so");+#elif defined(__OpenBSD__) || defined(__NetBSD__)+    _glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so"); #else     _glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1"); #endif@@ -847,10 +972,44 @@                          CWEventMask, &wa); } +// Create the pipe for empty events without assumuing the OS has pipe2(2)+//+static GLFWbool createEmptyEventPipe(void)+{+    if (pipe(_glfw.x11.emptyEventPipe) != 0)+    {+        _glfwInputError(GLFW_PLATFORM_ERROR,+                        "X11: Failed to create empty event pipe: %s",+                        strerror(errno));+        return GLFW_FALSE;+    }++    for (int i = 0; i < 2; i++)+    {+        const int sf = fcntl(_glfw.x11.emptyEventPipe[i], F_GETFL, 0);+        const int df = fcntl(_glfw.x11.emptyEventPipe[i], F_GETFD, 0);++        if (sf == -1 || df == -1 ||+            fcntl(_glfw.x11.emptyEventPipe[i], F_SETFL, sf | O_NONBLOCK) == -1 ||+            fcntl(_glfw.x11.emptyEventPipe[i], F_SETFD, df | FD_CLOEXEC) == -1)+        {+            _glfwInputError(GLFW_PLATFORM_ERROR,+                            "X11: Failed to set flags for empty event pipe: %s",+                            strerror(errno));+            return GLFW_FALSE;+        }+    }++    return GLFW_TRUE;+}+ // X error handler // static int errorHandler(Display *display, XErrorEvent* event) {+    if (_glfw.x11.display != display)+        return 0;+     _glfw.x11.errorCode = event->error_code;     return 0; }@@ -864,8 +1023,9 @@ // void _glfwGrabErrorHandlerX11(void) {+    assert(_glfw.x11.errorHandler == NULL);     _glfw.x11.errorCode = Success;-    XSetErrorHandler(errorHandler);+    _glfw.x11.errorHandler = XSetErrorHandler(errorHandler); }  // Clears the X error handler callback@@ -874,7 +1034,8 @@ {     // Synchronize to make sure all commands are processed     XSync(_glfw.x11.display, False);-    XSetErrorHandler(NULL);+    XSetErrorHandler(_glfw.x11.errorHandler);+    _glfw.x11.errorHandler = NULL; }  // Reports the specified error, appending information about the last X error@@ -931,15 +1092,12 @@  int _glfwPlatformInit(void) {-#if !defined(X_HAVE_UTF8_STRING)-    // HACK: If the current locale is "C" and the Xlib UTF-8 functions are-    //       unavailable, apply the environment's locale in the hope that it's-    //       both available and not "C"-    //       This is done because the "C" locale breaks wide character input,-    //       which is what we fall back on when UTF-8 support is missing+    // HACK: If the application has left the locale as "C" then both wide+    //       character text input and explicit UTF-8 input via XIM will break+    //       This sets the CTYPE part of the current locale from the environment+    //       in the hope that it is set to something more sane than "C"     if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0)         setlocale(LC_CTYPE, "");-#endif      XInitThreads();     XrmInitialize();@@ -968,6 +1126,9 @@      getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY); +    if (!createEmptyEventPipe())+        return GLFW_FALSE;+     if (!initExtensions())         return GLFW_FALSE; @@ -1077,6 +1238,7 @@         _glfw.x11.xi.handle = NULL;     } +    _glfwTerminateOSMesa();     // NOTE: These need to be unloaded after XCloseDisplay, as they register     //       cleanup callbacks that get called by that function     _glfwTerminateEGL();@@ -1085,6 +1247,12 @@ #if defined(__linux__)     _glfwTerminateJoysticksLinux(); #endif++    if (_glfw.x11.emptyEventPipe[0] || _glfw.x11.emptyEventPipe[1])+    {+        close(_glfw.x11.emptyEventPipe[0]);+        close(_glfw.x11.emptyEventPipe[1]);+    } }  const char* _glfwPlatformGetVersionString(void)
glfw/src/x11_monitor.c view
@@ -164,7 +164,7 @@             if (widthMM <= 0 || heightMM <= 0)             {                 // HACK: If RandR does not provide a physical size, assume the-                //       X11 default 96 DPI and calcuate from the CRTC viewport+                //       X11 default 96 DPI and calculate from the CRTC viewport                 // NOTE: These members are affected by rotation, unlike the mode                 //       info and output info members                 widthMM  = (int) (ci->width * 25.4f / 96.f);
glfw/src/x11_platform.h view
@@ -199,9 +199,9 @@     // The last position the cursor was warped to by GLFW     int             warpCursorPosX, warpCursorPosY; -    // The time of the last KeyPress event-    Time            lastKeyTime;-+    // The time of the last KeyPress event per keycode, for discarding+    // duplicate key events generated for some keys by ibus+    Time            keyPressTimes[256]; } _GLFWwindowX11;  // X11-specific global data@@ -222,6 +222,8 @@     XContext        context;     // XIM input method     XIM             im;+    // The previous X error handler, to be restored later+    XErrorHandler   errorHandler;     // Most recent error code received by X error handler     int             errorCode;     // Primary selection string (while the primary selection is owned)@@ -238,6 +240,7 @@     double          restoreCursorPosX, restoreCursorPosY;     // The window whose disabled cursor mode is active     _GLFWwindow*    disabledCursorWindow;+    int             emptyEventPipe[2];      // Window manager atoms     Atom            NET_SUPPORTED;@@ -404,7 +407,6 @@         PFN_XRenderQueryVersion QueryVersion;         PFN_XRenderFindVisualFormat FindVisualFormat;     } xrender;- } _GLFWlibraryX11;  // X11-specific per-monitor data@@ -418,7 +420,6 @@     // Index of corresponding Xinerama screen,     // for EWMH full screen window placement     int             index;- } _GLFWmonitorX11;  // X11-specific per-cursor data@@ -426,7 +427,6 @@ typedef struct _GLFWcursorX11 {     Cursor handle;- } _GLFWcursorX11;  
glfw/src/x11_window.c view
@@ -27,12 +27,16 @@ // It is fine to use C99 in this file because it will not be built with VS //======================================================================== +#define _GNU_SOURCE+ #include "internal.h"  #include <X11/cursorfont.h> #include <X11/Xmd.h> -#include <sys/select.h>+#include <poll.h>+#include <signal.h>+#include <time.h>  #include <string.h> #include <stdio.h>@@ -56,53 +60,129 @@  #define _GLFW_XDND_VERSION 5 --// Wait for data to arrive using select-// This avoids blocking other threads via the per-display Xlib lock that also-// covers GLX functions+// Wait for data to arrive on any of the specified file descriptors //-static GLFWbool waitForEvent(double* timeout)+static GLFWbool waitForData(struct pollfd* fds, nfds_t count, double* timeout) {-    fd_set fds;-    const int fd = ConnectionNumber(_glfw.x11.display);-    int count = fd + 1;--#if defined(__linux__)-    if (_glfw.linjs.inotify > fd)-        count = _glfw.linjs.inotify + 1;-#endif     for (;;)     {-        FD_ZERO(&fds);-        FD_SET(fd, &fds);-#if defined(__linux__)-        if (_glfw.linjs.inotify > 0)-            FD_SET(_glfw.linjs.inotify, &fds);-#endif-         if (timeout)         {-            const long seconds = (long) *timeout;-            const long microseconds = (long) ((*timeout - seconds) * 1e6);-            struct timeval tv = { seconds, microseconds };             const uint64_t base = _glfwPlatformGetTimerValue(); -            const int result = select(count, &fds, NULL, NULL, &tv);-            const int error = errno;+#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__)+            const time_t seconds = (time_t) *timeout;+            const long nanoseconds = (long) ((*timeout - seconds) * 1e9);+            const struct timespec ts = { seconds, nanoseconds };+            const int result = ppoll(fds, count, &ts, NULL);+#elif defined(__NetBSD__)+            const time_t seconds = (time_t) *timeout;+            const long nanoseconds = (long) ((*timeout - seconds) * 1e9);+            const struct timespec ts = { seconds, nanoseconds };+            const int result = pollts(fds, count, &ts, NULL);+#else+            const int milliseconds = (int) (*timeout * 1e3);+            const int result = poll(fds, count, milliseconds);+#endif+            const int error = errno; // clock_gettime may overwrite our error              *timeout -= (_glfwPlatformGetTimerValue() - base) /                 (double) _glfwPlatformGetTimerFrequency();              if (result > 0)                 return GLFW_TRUE;-            if ((result == -1 && error == EINTR) || *timeout <= 0.0)+            else if (result == -1 && error != EINTR && error != EAGAIN)                 return GLFW_FALSE;+            else if (*timeout <= 0.0)+                return GLFW_FALSE;         }-        else if (select(count, &fds, NULL, NULL, NULL) != -1 || errno != EINTR)-            return GLFW_TRUE;+        else+        {+            const int result = poll(fds, count, -1);+            if (result > 0)+                return GLFW_TRUE;+            else if (result == -1 && errno != EINTR && errno != EAGAIN)+                return GLFW_FALSE;+        }     } } +// Wait for event data to arrive on the X11 display socket+// This avoids blocking other threads via the per-display Xlib lock that also+// covers GLX functions+//+static GLFWbool waitForX11Event(double* timeout)+{+    struct pollfd fd = { ConnectionNumber(_glfw.x11.display), POLLIN };++    while (!XPending(_glfw.x11.display))+    {+        if (!waitForData(&fd, 1, timeout))+            return GLFW_FALSE;+    }++    return GLFW_TRUE;+}++// Wait for event data to arrive on any event file descriptor+// This avoids blocking other threads via the per-display Xlib lock that also+// covers GLX functions+//+static GLFWbool waitForAnyEvent(double* timeout)+{+    nfds_t count = 2;+    struct pollfd fds[3] =+    {+        { ConnectionNumber(_glfw.x11.display), POLLIN },+        { _glfw.x11.emptyEventPipe[0], POLLIN }+    };++#if defined(__linux__)+    if (_glfw.linjs.inotify > 0)+        fds[count++] = (struct pollfd) { _glfw.linjs.inotify, POLLIN };+#endif++    while (!XPending(_glfw.x11.display))+    {+        if (!waitForData(fds, count, timeout))+            return GLFW_FALSE;++        for (int i = 1; i < count; i++)+        {+            if (fds[i].revents & POLLIN)+                return GLFW_TRUE;+        }+    }++    return GLFW_TRUE;+}++// Writes a byte to the empty event pipe+//+static void writeEmptyEvent(void)+{+    for (;;)+    {+        const char byte = 0;+        const ssize_t result = write(_glfw.x11.emptyEventPipe[1], &byte, 1);+        if (result == 1 || (result == -1 && errno != EINTR))+            break;+    }+}++// Drains available data from the empty event pipe+//+static void drainEmptyEvents(void)+{+    for (;;)+    {+        char dummy[64];+        const ssize_t result = read(_glfw.x11.emptyEventPipe[0], dummy, sizeof(dummy));+        if (result == -1 && errno != EINTR)+            break;+    }+}+ // Waits until a VisibilityNotify event arrives for the specified window or the // timeout period elapses (ICCCM section 4.2.2) //@@ -116,7 +196,7 @@                                    VisibilityNotify,                                    &dummy))     {-        if (!waitForEvent(&timeout))+        if (!waitForX11Event(&timeout))             return GLFW_FALSE;     } @@ -241,6 +321,11 @@ {     XSizeHints* hints = XAllocSizeHints(); +    long supplied;+    XGetWMNormalHints(_glfw.x11.display, window->x11.handle, hints, &supplied);++    hints->flags &= ~(PMinSize | PMaxSize | PAspect);+     if (!window->monitor)     {         if (window->resizable)@@ -277,9 +362,6 @@         }     } -    hints->flags |= PWinGravity;-    hints->win_gravity = StaticGravity;-     XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);     XFree(hints); }@@ -378,96 +460,14 @@     } } -// Splits and translates a text/uri-list into separate file paths-// NOTE: This function destroys the provided string-//-static char** parseUriList(char* text, int* count)-{-    const char* prefix = "file://";-    char** paths = NULL;-    char* line;--    *count = 0;--    while ((line = strtok(text, "\r\n")))-    {-        text = NULL;--        if (line[0] == '#')-            continue;--        if (strncmp(line, prefix, strlen(prefix)) == 0)-        {-            line += strlen(prefix);-            // TODO: Validate hostname-            while (*line != '/')-                line++;-        }--        (*count)++;--        char* path = calloc(strlen(line) + 1, 1);-        paths = realloc(paths, *count * sizeof(char*));-        paths[*count - 1] = path;--        while (*line)-        {-            if (line[0] == '%' && line[1] && line[2])-            {-                const char digits[3] = { line[1], line[2], '\0' };-                *path = strtol(digits, NULL, 16);-                line += 2;-            }-            else-                *path = *line;--            path++;-            line++;-        }-    }--    return paths;-}--// Encode a Unicode code point to a UTF-8 stream-// Based on cutef8 by Jeff Bezanson (Public Domain)-//-static size_t encodeUTF8(char* s, unsigned int ch)-{-    size_t count = 0;--    if (ch < 0x80)-        s[count++] = (char) ch;-    else if (ch < 0x800)-    {-        s[count++] = (ch >> 6) | 0xc0;-        s[count++] = (ch & 0x3f) | 0x80;-    }-    else if (ch < 0x10000)-    {-        s[count++] = (ch >> 12) | 0xe0;-        s[count++] = ((ch >> 6) & 0x3f) | 0x80;-        s[count++] = (ch & 0x3f) | 0x80;-    }-    else if (ch < 0x110000)-    {-        s[count++] = (ch >> 18) | 0xf0;-        s[count++] = ((ch >> 12) & 0x3f) | 0x80;-        s[count++] = ((ch >> 6) & 0x3f) | 0x80;-        s[count++] = (ch & 0x3f) | 0x80;-    }--    return count;-}- // Decode a Unicode code point from a UTF-8 stream // Based on cutef8 by Jeff Bezanson (Public Domain) // #if defined(X_HAVE_UTF8_STRING)-static unsigned int decodeUTF8(const char** s)+static uint32_t decodeUTF8(const char** s) {-    unsigned int ch = 0, count = 0;-    static const unsigned int offsets[] =+    uint32_t codepoint = 0, count = 0;+    static const uint32_t offsets[] =     {         0x00000000u, 0x00003080u, 0x000e2080u,         0x03c82080u, 0xfa082080u, 0x82082080u@@ -475,13 +475,13 @@      do     {-        ch = (ch << 6) + (unsigned char) **s;+        codepoint = (codepoint << 6) + (unsigned char) **s;         (*s)++;         count++;     } while ((**s & 0xc0) == 0x80);      assert(count <= 6);-    return ch - offsets[count - 1];+    return codepoint - offsets[count - 1]; } #endif /*X_HAVE_UTF8_STRING*/ @@ -499,7 +499,7 @@     char* tp = target;      for (sp = source;  *sp;  sp++)-        tp += encodeUTF8(tp, *sp);+        tp += _glfwEncodeUTF8(tp, *sp);      return target; }@@ -525,6 +525,25 @@     } } +// Grabs the cursor and confines it to the window+//+static void captureCursor(_GLFWwindow* window)+{+    XGrabPointer(_glfw.x11.display, window->x11.handle, True,+                 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,+                 GrabModeAsync, GrabModeAsync,+                 window->x11.handle,+                 None,+                 CurrentTime);+}++// Ungrabs the cursor+//+static void releaseCursor(void)+{+    XUngrabPointer(_glfw.x11.display, CurrentTime);+}+ // Enable XI2 raw mouse motion events // static void enableRawMouseMotion(_GLFWwindow* window)@@ -567,12 +586,7 @@                               &_glfw.x11.restoreCursorPosY);     updateCursorImage(window);     _glfwCenterCursorInContentArea(window);-    XGrabPointer(_glfw.x11.display, window->x11.handle, True,-                 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,-                 GrabModeAsync, GrabModeAsync,-                 window->x11.handle,-                 _glfw.x11.hiddenCursorHandle,-                 CurrentTime);+    captureCursor(window); }  // Exit disabled cursor mode for the specified window@@ -583,7 +597,7 @@         disableRawMouseMotion(window);      _glfw.x11.disabledCursorWindow = NULL;-    XUngrabPointer(_glfw.x11.display, CurrentTime);+    releaseCursor();     _glfwPlatformSetCursorPos(window,                               _glfw.x11.restoreCursorPosX,                               _glfw.x11.restoreCursorPosY);@@ -728,8 +742,29 @@         XFree(hints);     } -    updateNormalHints(window, width, height);+    // Set ICCCM WM_NORMAL_HINTS property+    {+        XSizeHints* hints = XAllocSizeHints();+        if (!hints)+        {+            _glfwInputError(GLFW_OUT_OF_MEMORY, "X11: Failed to allocate size hints");+            return GLFW_FALSE;+        } +        if (!wndconfig->resizable)+        {+            hints->flags |= (PMinSize | PMaxSize);+            hints->min_width  = hints->max_width  = width;+            hints->min_height = hints->max_height = height;+        }++        hints->flags |= PWinGravity;+        hints->win_gravity = StaticGravity;++        XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);+        XFree(hints);+    }+     // Set ICCCM WM_CLASS property     {         XClassHint* hint = XAllocClassHint();@@ -931,20 +966,6 @@     return None; } -static void handleSelectionClear(XEvent* event)-{-    if (event->xselectionclear.selection == _glfw.x11.PRIMARY)-    {-        free(_glfw.x11.primarySelectionString);-        _glfw.x11.primarySelectionString = NULL;-    }-    else-    {-        free(_glfw.x11.clipboardString);-        _glfw.x11.clipboardString = NULL;-    }-}- static void handleSelectionRequest(XEvent* event) {     const XSelectionRequestEvent* request = &event->xselectionrequest;@@ -1002,7 +1023,7 @@                                        SelectionNotify,                                        &notification))         {-            waitForEvent(NULL);+            waitForX11Event(NULL);         }          if (notification.xselection.property == None)@@ -1038,7 +1059,7 @@                                       isSelPropNewValueNotify,                                       (XPointer) &notification))                 {-                    waitForEvent(NULL);+                    waitForX11Event(NULL);                 }                  XFree(data);@@ -1065,13 +1086,16 @@                  if (!itemCount)                 {-                    if (targets[i] == XA_STRING)+                    if (string)                     {-                        *selectionString = convertLatin1toUTF8(string);-                        free(string);+                        if (targets[i] == XA_STRING)+                        {+                            *selectionString = convertLatin1toUTF8(string);+                            free(string);+                        }+                        else+                            *selectionString = string;                     }-                    else-                        *selectionString = string;                      break;                 }@@ -1195,6 +1219,8 @@             {                 _glfw.x11.xkb.group = ((XkbEvent*) event)->state.group;             }++            return;         }     } @@ -1236,12 +1262,7 @@         return;     } -    if (event->type == SelectionClear)-    {-        handleSelectionClear(event);-        return;-    }-    else if (event->type == SelectionRequest)+    if (event->type == SelectionRequest)     {         handleSelectionRequest(event);         return;@@ -1273,16 +1294,20 @@              if (window->x11.ic)             {-                // HACK: Ignore duplicate key press events generated by ibus-                //       These have the same timestamp as the original event-                //       Corresponding release events are filtered out-                //       implicitly by the GLFW key repeat logic-                if (window->x11.lastKeyTime < event->xkey.time)+                // HACK: Do not report the key press events duplicated by XIM+                //       Duplicate key releases are filtered out implicitly by+                //       the GLFW key repeat logic in _glfwInputKey+                //       A timestamp per key is used to handle simultaneous keys+                // NOTE: Always allow the first event for each key through+                //       (the server never sends a timestamp of zero)+                // NOTE: Timestamp difference is compared to handle wrap-around+                Time diff = event->xkey.time - window->x11.keyPressTimes[keycode];+                if (diff == event->xkey.time || (diff > 0 && diff < ((Time)1 << 31)))                 {                     if (keycode)                         _glfwInputKey(window, key, keycode, GLFW_PRESS, mods); -                    window->x11.lastKeyTime = event->xkey.time;+                    window->x11.keyPressTimes[keycode] = event->xkey.time;                 }                  if (!filtered)@@ -1353,9 +1378,9 @@                  _glfwInputKey(window, key, keycode, GLFW_PRESS, mods); -                const long character = _glfwKeySym2Unicode(keysym);-                if (character != -1)-                    _glfwInputChar(window, character, mods, plain);+                const uint32_t codepoint = _glfwKeySym2Unicode(keysym);+                if (codepoint != GLFW_INVALID_CODEPOINT)+                    _glfwInputChar(window, codepoint, mods, plain);             }              return;@@ -1557,6 +1582,8 @@             //       the position into root (screen) coordinates             if (!event->xany.send_event && window->x11.parent != _glfw.x11.root)             {+                _glfwGrabErrorHandlerX11();+                 Window dummy;                 XTranslateCoordinates(_glfw.x11.display,                                       window->x11.parent,@@ -1564,6 +1591,10 @@                                       xpos, ypos,                                       &xpos, &ypos,                                       &dummy);++                _glfwReleaseErrorHandlerX11();+                if (_glfw.x11.errorCode == BadWindow)+                    return;             }              if (xpos != window->x11.xpos || ypos != window->x11.ypos)@@ -1747,7 +1778,7 @@                 if (result)                 {                     int i, count;-                    char** paths = parseUriList(data, &count);+                    char** paths = _glfwParseUriList(data, &count);                      _glfwInputDrop(window, count, (const char**) paths); @@ -1936,10 +1967,6 @@                     handleSelectionRequest(&event);                     break; -                case SelectionClear:-                    handleSelectionClear(&event);-                    break;-                 case SelectionNotify:                 {                     if (event.xselection.target == _glfw.x11.SAVE_TARGETS)@@ -1957,7 +1984,7 @@             }         } -        waitForEvent(NULL);+        waitForX11Event(NULL);     } } @@ -1971,7 +1998,7 @@                               const _GLFWctxconfig* ctxconfig,                               const _GLFWfbconfig* fbconfig) {-    Visual* visual;+    Visual* visual = NULL;     int depth;      if (ctxconfig->client != GLFW_NO_API)@@ -1997,8 +2024,7 @@         }     } -    if (ctxconfig->client == GLFW_NO_API ||-        ctxconfig->source == GLFW_OSMESA_CONTEXT_API)+    if (!visual)     {         visual = DefaultVisual(_glfw.x11.display, _glfw.x11.screen);         depth = DefaultDepth(_glfw.x11.display, _glfw.x11.screen);@@ -2024,6 +2050,9 @@             if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))                 return GLFW_FALSE;         }++        if (!_glfwRefreshContextAttribs(window, ctxconfig))+            return GLFW_FALSE;     }      if (window->monitor)@@ -2031,7 +2060,19 @@         _glfwPlatformShowWindow(window);         updateWindowMode(window);         acquireMonitor(window);++        if (wndconfig->centerCursor)+            _glfwCenterCursorInContentArea(window);     }+    else+    {+        if (wndconfig->visible)+        {+            _glfwPlatformShowWindow(window);+            if (wndconfig->focused)+                _glfwPlatformFocusWindow(window);+        }+    }      XFlush(_glfw.x11.display);     return GLFW_TRUE;@@ -2040,7 +2081,7 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) {     if (_glfw.x11.disabledCursorWindow == window)-        _glfw.x11.disabledCursorWindow = NULL;+        enableCursor(window);      if (window->monitor)         releaseMonitor(window);@@ -2112,8 +2153,8 @@         for (i = 0;  i < count;  i++)             longCount += 2 + images[i].width * images[i].height; -        long* icon = calloc(longCount, sizeof(long));-        long* target = icon;+        unsigned long* icon = calloc(longCount, sizeof(unsigned long));+        unsigned long* target = icon;          for (i = 0;  i < count;  i++)         {@@ -2122,13 +2163,19 @@              for (j = 0;  j < images[i].width * images[i].height;  j++)             {-                *target++ = (images[i].pixels[j * 4 + 0] << 16) |-                            (images[i].pixels[j * 4 + 1] <<  8) |-                            (images[i].pixels[j * 4 + 2] <<  0) |-                            (images[i].pixels[j * 4 + 3] << 24);+                *target++ = (((unsigned long) images[i].pixels[j * 4 + 0]) << 16) |+                            (((unsigned long) images[i].pixels[j * 4 + 1]) <<  8) |+                            (((unsigned long) images[i].pixels[j * 4 + 2]) <<  0) |+                            (((unsigned long) images[i].pixels[j * 4 + 3]) << 24);             }         } +        // NOTE: XChangeProperty expects 32-bit values like the image data above to be+        //       placed in the 32 least significant bits of individual longs.  This is+        //       true even if long is 64-bit and a WM protocol calls for "packed" data.+        //       This is because of a historical mistake that then became part of the Xlib+        //       ABI.  Xlib will pack these values into a regular array of 32-bit values+        //       before sending it over the wire.         XChangeProperty(_glfw.x11.display, window->x11.handle,                         _glfw.x11.NET_WM_ICON,                         XA_CARDINAL, 32,@@ -2270,7 +2317,7 @@                               isFrameExtentsEvent,                               (XPointer) window))         {-            if (!waitForEvent(&timeout))+            if (!waitForX11Event(&timeout))             {                 _glfwInputError(GLFW_PLATFORM_ERROR,                                 "X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue");@@ -2489,7 +2536,11 @@     }      if (window->monitor)+    {+        _glfwPlatformSetWindowDecorated(window, window->decorated);+        _glfwPlatformSetWindowFloating(window, window->floating);         releaseMonitor(window);+    }      _glfwInputWindowMonitor(window, monitor);     updateNormalHints(window, width, height);@@ -2580,13 +2631,19 @@         int rootX, rootY, childX, childY;         unsigned int mask; -        if (!XQueryPointer(_glfw.x11.display, w,-                           &root, &w, &rootX, &rootY, &childX, &childY, &mask))-        {-            return GLFW_FALSE;-        }+        _glfwGrabErrorHandlerX11(); -        if (w == window->x11.handle)+        const Bool result = XQueryPointer(_glfw.x11.display, w,+                                          &root, &w, &rootX, &rootY,+                                          &childX, &childY, &mask);++        _glfwReleaseErrorHandlerX11();++        if (_glfw.x11.errorCode == BadWindow)+            w = _glfw.x11.root;+        else if (!result)+            return GLFW_FALSE;+        else if (w == window->x11.handle)             return GLFW_TRUE;     } @@ -2665,14 +2722,14 @@                     break;             } -            if (i < count)-                return;--            XChangeProperty(_glfw.x11.display, window->x11.handle,-                            _glfw.x11.NET_WM_STATE, XA_ATOM, 32,-                            PropModeAppend,-                            (unsigned char*) &_glfw.x11.NET_WM_STATE_ABOVE,-                            1);+            if (i == count)+            {+                XChangeProperty(_glfw.x11.display, window->x11.handle,+                                _glfw.x11.NET_WM_STATE, XA_ATOM, 32,+                                PropModeAppend,+                                (unsigned char*) &_glfw.x11.NET_WM_STATE_ABOVE,+                                1);+            }         }         else if (states)         {@@ -2682,15 +2739,15 @@                     break;             } -            if (i == count)-                return;--            states[i] = states[count - 1];-            count--;+            if (i < count)+            {+                states[i] = states[count - 1];+                count--; -            XChangeProperty(_glfw.x11.display, window->x11.handle,-                            _glfw.x11.NET_WM_STATE, XA_ATOM, 32,-                            PropModeReplace, (unsigned char*) states, count);+                XChangeProperty(_glfw.x11.display, window->x11.handle,+                                _glfw.x11.NET_WM_STATE, XA_ATOM, 32,+                                PropModeReplace, (unsigned char*) states, count);+            }         }          if (states)@@ -2752,7 +2809,7 @@  void _glfwPlatformPollEvents(void) {-    _GLFWwindow* window;+    drainEmptyEvents();  #if defined(__linux__)     _glfwDetectJoystickConnectionLinux();@@ -2766,7 +2823,7 @@         processEvent(&event);     } -    window = _glfw.x11.disabledCursorWindow;+    _GLFWwindow* window = _glfw.x11.disabledCursorWindow;     if (window)     {         int width, height;@@ -2786,32 +2843,19 @@  void _glfwPlatformWaitEvents(void) {-    while (!XPending(_glfw.x11.display))-        waitForEvent(NULL);-+    waitForAnyEvent(NULL);     _glfwPlatformPollEvents(); }  void _glfwPlatformWaitEventsTimeout(double timeout) {-    while (!XPending(_glfw.x11.display))-    {-        if (!waitForEvent(&timeout))-            break;-    }-+    waitForAnyEvent(&timeout);     _glfwPlatformPollEvents(); }  void _glfwPlatformPostEmptyEvent(void) {-    XEvent event = { ClientMessage };-    event.xclient.window = _glfw.x11.helperWindowHandle;-    event.xclient.format = 32; // Data is 32-bit longs-    event.xclient.message_type = _glfw.x11.NULL_;--    XSendEvent(_glfw.x11.display, _glfw.x11.helperWindowHandle, False, 0, &event);-    XFlush(_glfw.x11.display);+    writeEmptyEvent(); }  void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)@@ -2844,16 +2888,40 @@  void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) {-    if (mode == GLFW_CURSOR_DISABLED)+    if (_glfwPlatformWindowFocused(window))     {-        if (_glfwPlatformWindowFocused(window))-            disableCursor(window);+        if (mode == GLFW_CURSOR_DISABLED)+        {+            _glfwPlatformGetCursorPos(window,+                                      &_glfw.x11.restoreCursorPosX,+                                      &_glfw.x11.restoreCursorPosY);+            _glfwCenterCursorInContentArea(window);+            if (window->rawMouseMotion)+                enableRawMouseMotion(window);+        }+        else if (_glfw.x11.disabledCursorWindow == window)+        {+            if (window->rawMouseMotion)+                disableRawMouseMotion(window);+        }++        if (mode == GLFW_CURSOR_DISABLED)+            captureCursor(window);+        else+            releaseCursor();++        if (mode == GLFW_CURSOR_DISABLED)+            _glfw.x11.disabledCursorWindow = window;+        else if (_glfw.x11.disabledCursorWindow == window)+        {+            _glfw.x11.disabledCursorWindow = NULL;+            _glfwPlatformSetCursorPos(window,+                                      _glfw.x11.restoreCursorPosX,+                                      _glfw.x11.restoreCursorPosY);+        }     }-    else if (_glfw.x11.disabledCursorWindow == window)-        enableCursor(window);-    else-        updateCursorImage(window); +    updateCursorImage(window);     XFlush(_glfw.x11.display); } @@ -2865,7 +2933,7 @@     if (scancode < 0 || scancode > 0xff ||         _glfw.x11.keycodes[scancode] == GLFW_KEY_UNKNOWN)     {-        _glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode");+        _glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode %i", scancode);         return NULL;     } @@ -2875,11 +2943,11 @@     if (keysym == NoSymbol)         return NULL; -    const long ch = _glfwKeySym2Unicode(keysym);-    if (ch == -1)+    const uint32_t codepoint = _glfwKeySym2Unicode(keysym);+    if (codepoint == GLFW_INVALID_CODEPOINT)         return NULL; -    const size_t count = encodeUTF8(_glfw.x11.keynames[key], (unsigned int) ch);+    const size_t count = _glfwEncodeUTF8(_glfw.x11.keynames[key], codepoint);     if (count == 0)         return NULL; @@ -2950,8 +3018,9 @@  void _glfwPlatformSetClipboardString(const char* string) {+    char* copy = _glfw_strdup(string);     free(_glfw.x11.clipboardString);-    _glfw.x11.clipboardString = _glfw_strdup(string);+    _glfw.x11.clipboardString = copy;      XSetSelectionOwner(_glfw.x11.display,                        _glfw.x11.CLIPBOARD,
glfw/src/xkb_unicode.c view
@@ -907,7 +907,7 @@  // Convert XKB KeySym to Unicode //-long _glfwKeySym2Unicode(unsigned int keysym)+uint32_t _glfwKeySym2Unicode(unsigned int keysym) {     int min = 0;     int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;@@ -937,6 +937,6 @@     }      // No matching Unicode value found-    return -1;+    return GLFW_INVALID_CODEPOINT; }