Updated GLFW library to latest version

This commit is contained in:
raysan5 2018-03-03 15:58:44 +01:00
parent fd2adbe62d
commit 3b4a64f2d6
39 changed files with 7656 additions and 1254 deletions

View file

@ -1,4 +1,4 @@
Copyright (c) 2002-2006 Marcus Geelnard Copyright (c) 2002-2006 Marcus Geelnard
Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied

View file

@ -12,7 +12,7 @@ creating windows, contexts and surfaces, reading input, handling events, etc.
GLFW natively supports Windows, macOS and Linux and other Unix-like systems. GLFW natively supports Windows, macOS and Linux and other Unix-like systems.
Experimental implementations for the Wayland protocol and the Mir display server Experimental implementations for the Wayland protocol and the Mir display server
are available but not yet officially supported. are available but not yet officially supported.
GLFW is licensed under the [zlib/libpng GLFW is licensed under the [zlib/libpng
license](http://www.glfw.org/license.html). license](http://www.glfw.org/license.html).
@ -106,9 +106,9 @@ located in the `deps/` directory.
- [stb\_image\_write](https://github.com/nothings/stb) for writing images to disk - [stb\_image\_write](https://github.com/nothings/stb) for writing images to disk
- [Vulkan headers](https://www.khronos.org/registry/vulkan/) for Vulkan tests - [Vulkan headers](https://www.khronos.org/registry/vulkan/) for Vulkan tests
The Vulkan example additionally requires the Vulkan SDK to be installed, or it The Vulkan example additionally requires the LunarG Vulkan SDK to be installed,
will not be included in the build. On macOS you need to provide the path to the or it will not be included in the build. On macOS you need to provide the path
MoltenVK SDK manually as it has no standard installation location. to the SDK manually as it has no standard installation location.
The documentation is generated with [Doxygen](http://doxygen.org/) if CMake can The documentation is generated with [Doxygen](http://doxygen.org/) if CMake can
find that tool. find that tool.
@ -136,8 +136,9 @@ information on what to include when reporting a bug.
gamepad mapping (#900) gamepad mapping (#900)
- Added `glfwGetGamepadState` function, `GLFW_GAMEPAD_*` and `GLFWgamepadstate` - Added `glfwGetGamepadState` function, `GLFW_GAMEPAD_*` and `GLFWgamepadstate`
for retrieving gamepad input state (#900) for retrieving gamepad input state (#900)
- Added `glfwGetWindowContentScale` and `glfwGetMonitorContentScale` for - Added `glfwGetWindowContentScale`, `glfwGetMonitorContentScale` and
DPI-aware rendering (#235,#439,#677,#845,#898) `glfwSetWindowContentScaleCallback` for DPI-aware rendering
(#235,#439,#677,#845,#898)
- Added `glfwRequestWindowAttention` function for requesting attention from the - Added `glfwRequestWindowAttention` function for requesting attention from the
user (#732,#988) user (#732,#988)
- Added `glfwGetKeyScancode` function that allows retrieving platform dependent - Added `glfwGetKeyScancode` function that allows retrieving platform dependent
@ -147,30 +148,38 @@ information on what to include when reporting a bug.
- Added `glfwSetWindowAttrib` function for changing window attributes (#537) - Added `glfwSetWindowAttrib` function for changing window attributes (#537)
- Added `glfwGetJoystickHats` function for querying joystick hats - Added `glfwGetJoystickHats` function for querying joystick hats
(#889,#906,#934) (#889,#906,#934)
- Added `glfwInitHint` and `glfwInitHintString` for setting initialization hints - Added `glfwInitHint` for setting initialization hints
- Added `glfwWindowHintString` for setting string type window hints (#893,#1139)
- Added `glfwGetWindowOpacity` and `glfwSetWindowOpacity` for controlling whole - Added `glfwGetWindowOpacity` and `glfwSetWindowOpacity` for controlling whole
window transparency (#1089) window transparency (#1089)
- Added `glfwSetMonitorUserPointer` and `glfwGetMonitorUserPointer` for
per-monitor user pointers
- Added `glfwSetJoystickUserPointer` and `glfwGetJoystickUserPointer` for
per-joystick user pointers
- Added `glfwGetX11SelectionString` and `glfwSetX11SelectionString` - Added `glfwGetX11SelectionString` and `glfwSetX11SelectionString`
functions for accessing X11 primary selection (#894,#1056) functions for accessing X11 primary selection (#894,#1056)
- Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#850) - Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#850)
- Added definition of `GLAPIENTRY` to public header - Added definition of `GLAPIENTRY` to public header
- Added `GLFW_TRANSPARENT_FRAMEBUFFER` window hint and attribute for controlling - Added `GLFW_TRANSPARENT_FRAMEBUFFER` window hint and attribute for controlling
per-pixel framebuffer transparency (#197,#663,#715,#723,#1078) per-pixel framebuffer transparency (#197,#663,#715,#723,#1078)
- Added `GLFW_HOVERED` window attribute for polling cursor hover state (#1166)
- Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering - Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering
(#749,#842) (#749,#842)
- Added `GLFW_JOYSTICK_HAT_BUTTONS` init hint (#889) - Added `GLFW_JOYSTICK_HAT_BUTTONS` init hint (#889)
- Added `GLFW_LOCK_KEY_MODS` input mode and `GLFW_MOD_*_LOCK` mod bits (#946) - Added `GLFW_LOCK_KEY_MODS` input mode and `GLFW_MOD_*_LOCK` mod bits (#946)
- Added macOS specific `GLFW_COCOA_RETINA_FRAMEBUFFER` window hint - Added macOS specific `GLFW_COCOA_RETINA_FRAMEBUFFER` window hint
- Added macOS specific `GLFW_COCOA_FRAME_AUTOSAVE` window hint (#195) - Added macOS specific `GLFW_COCOA_FRAME_NAME` window hint (#195)
- Added macOS specific `GLFW_COCOA_GRAPHICS_SWITCHING` window hint (#377,#935) - Added macOS specific `GLFW_COCOA_GRAPHICS_SWITCHING` window hint (#377,#935)
- Added macOS specific `GLFW_COCOA_CHDIR_RESOURCES` init hint - Added macOS specific `GLFW_COCOA_CHDIR_RESOURCES` init hint
- Added macOS specific `GLFW_COCOA_MENUBAR` init hint - Added macOS specific `GLFW_COCOA_MENUBAR` init hint
- Added X11 specific `GLFW_X11_WM_CLASS_NAME` and `GLFW_X11_WM_CLASS_CLASS` init - Added X11 specific `GLFW_X11_CLASS_NAME` and `GLFW_X11_INSTANCE_NAME` window
hints (#893) hints (#893,#1139)
- Added `GLFW_INCLUDE_ES32` for including the OpenGL ES 3.2 header - Added `GLFW_INCLUDE_ES32` for including the OpenGL ES 3.2 header
- Added `GLFW_OSMESA_CONTEXT_API` for creating OpenGL contexts with - Added `GLFW_OSMESA_CONTEXT_API` for creating OpenGL contexts with
[OSMesa](https://www.mesa3d.org/osmesa.html) (#281) [OSMesa](https://www.mesa3d.org/osmesa.html) (#281)
- Added `GenerateMappings.cmake` script for updating gamepad mappings - Added `GenerateMappings.cmake` script for updating gamepad mappings
- Made `glfwCreateWindowSurface` emit an error when the window has a context
(#1194,#1205)
- Deprecated window parameter of clipboard string functions - Deprecated window parameter of clipboard string functions
- Deprecated charmods callback - Deprecated charmods callback
- Removed `GLFW_USE_RETINA` compile-time option - Removed `GLFW_USE_RETINA` compile-time option
@ -207,6 +216,9 @@ information on what to include when reporting a bug.
- [Win32] Bugfix: Returned key names did not match other platforms (#943) - [Win32] Bugfix: Returned key names did not match other platforms (#943)
- [Win32] Bugfix: Undecorated windows did not maximize to workarea (#899) - [Win32] Bugfix: Undecorated windows did not maximize to workarea (#899)
- [Win32] Bugfix: Window was resized twice when entering full screen (#1085) - [Win32] Bugfix: Window was resized twice when entering full screen (#1085)
- [Win32] Bugfix: The HID device notification was not unregistered (#1170)
- [Win32] Bugfix: `glfwCreateWindow` activated window even with `GLFW_FOCUSED`
hint set to false (#1179,#1180)
- [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125) - [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125)
- [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading - [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading
- [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X - [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X
@ -221,6 +233,8 @@ information on what to include when reporting a bug.
- [X11] Bugfix: Selection I/O reported but did not support `COMPOUND_TEXT` - [X11] Bugfix: Selection I/O reported but did not support `COMPOUND_TEXT`
- [X11] Bugfix: Latin-1 text read from selections was not converted to UTF-8 - [X11] Bugfix: Latin-1 text read from selections was not converted to UTF-8
- [X11] Bugfix: NVidia EGL would segfault if unloaded before closing the display - [X11] Bugfix: NVidia EGL would segfault if unloaded before closing the display
- [Linux] Added workaround for missing `SYN_DROPPED` in pre-2.6.39 kernel
headers (#1196)
- [Linux] Moved to evdev for joystick input (#906,#1005) - [Linux] Moved to evdev for joystick input (#906,#1005)
- [Linux] Bugfix: Event processing did not detect joystick disconnection (#932) - [Linux] Bugfix: Event processing did not detect joystick disconnection (#932)
- [Linux] Bugfix: The joystick device path could be truncated (#1025) - [Linux] Bugfix: The joystick device path could be truncated (#1025)
@ -250,6 +264,7 @@ information on what to include when reporting a bug.
- [Cocoa] Bugfix: Window title was lost when full screen or undecorated (#1082) - [Cocoa] Bugfix: Window title was lost when full screen or undecorated (#1082)
- [Cocoa] Bugfix: Window was resized twice when entering full screen (#1085) - [Cocoa] Bugfix: Window was resized twice when entering full screen (#1085)
- [Cocoa] Bugfix: Duplicate size events were not filtered (#1085) - [Cocoa] Bugfix: Duplicate size events were not filtered (#1085)
- [Cocoa] Bugfix: Event polling did not initialize AppKit if necessary (#1218)
- [WGL] Added support for `WGL_EXT_colorspace` for OpenGL ES contexts - [WGL] Added support for `WGL_EXT_colorspace` for OpenGL ES contexts
- [WGL] Added support for `WGL_ARB_create_context_no_error` - [WGL] Added support for `WGL_ARB_create_context_no_error`
- [GLX] Added support for `GLX_ARB_create_context_no_error` - [GLX] Added support for `GLX_ARB_create_context_no_error`
@ -325,6 +340,8 @@ skills.
- Mário Freitas - Mário Freitas
- GeO4d - GeO4d
- Marcus Geelnard - Marcus Geelnard
- Stephen Gowen
- Kovid Goyal
- Eloi Marín Gratacós - Eloi Marín Gratacós
- Stefan Gustavson - Stefan Gustavson
- Jonathan Hale - Jonathan Hale
@ -390,6 +407,7 @@ skills.
- Keith Pitt - Keith Pitt
- Stanislav Podgorskiy - Stanislav Podgorskiy
- Alexandre Pretyman - Alexandre Pretyman
- przemekmirek
- Philip Rideout - Philip Rideout
- Eddie Ringle - Eddie Ringle
- Jorge Rodriguez - Jorge Rodriguez
@ -429,6 +447,7 @@ skills.
- Ricardo Vieira - Ricardo Vieira
- Nicholas Vitovitch - Nicholas Vitovitch
- Simon Voordouw - Simon Voordouw
- Corentin Wallez
- Torsten Walluhn - Torsten Walluhn
- Patrick Walton - Patrick Walton
- Xo Wang - Xo Wang

282
src/external/glfw/deps/KHR/khrplatform.h vendored Normal file
View file

@ -0,0 +1,282 @@
#ifndef __khrplatform_h_
#define __khrplatform_h_
/*
** Copyright (c) 2008-2009 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
/* Khronos platform-specific types and definitions.
*
* $Revision: 23298 $ on $Date: 2013-09-30 17:07:13 -0700 (Mon, 30 Sep 2013) $
*
* Adopters may modify this file to suit their platform. Adopters are
* encouraged to submit platform specific modifications to the Khronos
* group so that they can be included in future versions of this file.
* Please submit changes by sending them to the public Khronos Bugzilla
* (http://khronos.org/bugzilla) by filing a bug against product
* "Khronos (general)" component "Registry".
*
* A predefined template which fills in some of the bug fields can be
* reached using http://tinyurl.com/khrplatform-h-bugreport, but you
* must create a Bugzilla login first.
*
*
* See the Implementer's Guidelines for information about where this file
* should be located on your system and for more details of its use:
* http://www.khronos.org/registry/implementers_guide.pdf
*
* This file should be included as
* #include <KHR/khrplatform.h>
* by Khronos client API header files that use its types and defines.
*
* The types in khrplatform.h should only be used to define API-specific types.
*
* Types defined in khrplatform.h:
* khronos_int8_t signed 8 bit
* khronos_uint8_t unsigned 8 bit
* khronos_int16_t signed 16 bit
* khronos_uint16_t unsigned 16 bit
* khronos_int32_t signed 32 bit
* khronos_uint32_t unsigned 32 bit
* khronos_int64_t signed 64 bit
* khronos_uint64_t unsigned 64 bit
* khronos_intptr_t signed same number of bits as a pointer
* khronos_uintptr_t unsigned same number of bits as a pointer
* khronos_ssize_t signed size
* khronos_usize_t unsigned size
* khronos_float_t signed 32 bit floating point
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
* nanoseconds
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
* khronos_boolean_enum_t enumerated boolean type. This should
* only be used as a base type when a client API's boolean type is
* an enum. Client APIs which use an integer or other type for
* booleans cannot use this as the base type for their boolean.
*
* Tokens defined in khrplatform.h:
*
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
*
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
*
* Calling convention macros defined in this file:
* KHRONOS_APICALL
* KHRONOS_APIENTRY
* KHRONOS_APIATTRIBUTES
*
* These may be used in function prototypes as:
*
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
* int arg1,
* int arg2) KHRONOS_APIATTRIBUTES;
*/
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APICALL
*-------------------------------------------------------------------------
* This precedes the return type of the function in the function prototype.
*/
#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
# define KHRONOS_APICALL __declspec(dllimport)
#elif defined (__SYMBIAN32__)
# define KHRONOS_APICALL IMPORT_C
#else
# define KHRONOS_APICALL
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIENTRY
*-------------------------------------------------------------------------
* This follows the return type of the function and precedes the function
* name in the function prototype.
*/
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
/* Win32 but not WinCE */
# define KHRONOS_APIENTRY __stdcall
#else
# define KHRONOS_APIENTRY
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIATTRIBUTES
*-------------------------------------------------------------------------
* This follows the closing parenthesis of the function prototype arguments.
*/
#if defined (__ARMCC_2__)
#define KHRONOS_APIATTRIBUTES __softfp
#else
#define KHRONOS_APIATTRIBUTES
#endif
/*-------------------------------------------------------------------------
* basic type definitions
*-----------------------------------------------------------------------*/
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
/*
* Using <stdint.h>
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(__VMS ) || defined(__sgi)
/*
* Using <inttypes.h>
*/
#include <inttypes.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
/*
* Win32
*/
typedef __int32 khronos_int32_t;
typedef unsigned __int32 khronos_uint32_t;
typedef __int64 khronos_int64_t;
typedef unsigned __int64 khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(__sun__) || defined(__digital__)
/*
* Sun or Digital
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#if defined(__arch64__) || defined(_LP64)
typedef long int khronos_int64_t;
typedef unsigned long int khronos_uint64_t;
#else
typedef long long int khronos_int64_t;
typedef unsigned long long int khronos_uint64_t;
#endif /* __arch64__ */
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif 0
/*
* Hypothetical platform with no float or int64 support
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#define KHRONOS_SUPPORT_INT64 0
#define KHRONOS_SUPPORT_FLOAT 0
#else
/*
* Generic fallback
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#endif
/*
* Types that are (so far) the same on all platforms
*/
typedef signed char khronos_int8_t;
typedef unsigned char khronos_uint8_t;
typedef signed short int khronos_int16_t;
typedef unsigned short int khronos_uint16_t;
/*
* Types that differ between LLP64 and LP64 architectures - in LLP64,
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
* to be the only LLP64 architecture in current use.
*/
#ifdef _WIN64
typedef signed long long int khronos_intptr_t;
typedef unsigned long long int khronos_uintptr_t;
typedef signed long long int khronos_ssize_t;
typedef unsigned long long int khronos_usize_t;
#else
typedef signed long int khronos_intptr_t;
typedef unsigned long int khronos_uintptr_t;
typedef signed long int khronos_ssize_t;
typedef unsigned long int khronos_usize_t;
#endif
#if KHRONOS_SUPPORT_FLOAT
/*
* Float type
*/
typedef float khronos_float_t;
#endif
#if KHRONOS_SUPPORT_INT64
/* Time types
*
* These types can be used to represent a time interval in nanoseconds or
* an absolute Unadjusted System Time. Unadjusted System Time is the number
* of nanoseconds since some arbitrary system event (e.g. since the last
* time the system booted). The Unadjusted System Time is an unsigned
* 64 bit value that wraps back to 0 every 584 years. Time intervals
* may be either signed or unsigned.
*/
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
typedef khronos_int64_t khronos_stime_nanoseconds_t;
#endif
/*
* Dummy value used to pad enum types to 32 bits.
*/
#ifndef KHRONOS_MAX_ENUM
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
#endif
/*
* Enumerated boolean type
*
* Values other than zero should be considered to be true. Therefore
* comparisons should not be made against KHRONOS_TRUE.
*/
typedef enum {
KHRONOS_FALSE = 0,
KHRONOS_TRUE = 1,
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
} khronos_boolean_enum_t;
#endif /* __khrplatform_h_ */

View file

@ -0,0 +1,120 @@
//
// File: vk_platform.h
//
/*
** Copyright (c) 2014-2015 The Khronos Group Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#ifndef VK_PLATFORM_H_
#define VK_PLATFORM_H_
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
/*
***************************************************************************************************
* Platform-specific directives and type declarations
***************************************************************************************************
*/
/* Platform-specific calling convention macros.
*
* Platforms should define these so that Vulkan clients call Vulkan commands
* with the same calling conventions that the Vulkan implementation expects.
*
* VKAPI_ATTR - Placed before the return type in function declarations.
* Useful for C++11 and GCC/Clang-style function attribute syntax.
* VKAPI_CALL - Placed after the return type in function declarations.
* Useful for MSVC-style calling convention syntax.
* VKAPI_PTR - Placed between the '(' and '*' in function pointer types.
*
* Function declaration: VKAPI_ATTR void VKAPI_CALL vkCommand(void);
* Function pointer type: typedef void (VKAPI_PTR *PFN_vkCommand)(void);
*/
#if defined(_WIN32)
// On Windows, Vulkan commands use the stdcall convention
#define VKAPI_ATTR
#define VKAPI_CALL __stdcall
#define VKAPI_PTR VKAPI_CALL
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
#error "Vulkan isn't supported for the 'armeabi' NDK ABI"
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
// On Android 32-bit ARM targets, Vulkan functions use the "hardfloat"
// calling convention, i.e. float parameters are passed in registers. This
// is true even if the rest of the application passes floats on the stack,
// as it does by default when compiling for the armeabi-v7a NDK ABI.
#define VKAPI_ATTR __attribute__((pcs("aapcs-vfp")))
#define VKAPI_CALL
#define VKAPI_PTR VKAPI_ATTR
#else
// On other platforms, use the default calling convention
#define VKAPI_ATTR
#define VKAPI_CALL
#define VKAPI_PTR
#endif
#include <stddef.h>
#if !defined(VK_NO_STDINT_H)
#if defined(_MSC_VER) && (_MSC_VER < 1600)
typedef signed __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef signed __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef signed __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>
#endif
#endif // !defined(VK_NO_STDINT_H)
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
// Platform-specific headers required by platform window system extensions.
// These are enabled prior to #including "vulkan.h". The same enable then
// controls inclusion of the extension interfaces in vulkan.h.
#ifdef VK_USE_PLATFORM_ANDROID_KHR
#include <android/native_window.h>
#endif
#ifdef VK_USE_PLATFORM_MIR_KHR
#include <mir_toolkit/client_types.h>
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
#include <wayland-client.h>
#endif
#ifdef VK_USE_PLATFORM_WIN32_KHR
#include <windows.h>
#endif
#ifdef VK_USE_PLATFORM_XLIB_KHR
#include <X11/Xlib.h>
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
#include <xcb/xcb.h>
#endif
#endif

4763
src/external/glfw/deps/vulkan/vulkan.h vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -814,6 +814,11 @@ extern "C" {
* [window attribute](@ref GLFW_TRANSPARENT_FRAMEBUFFER_attrib). * [window attribute](@ref GLFW_TRANSPARENT_FRAMEBUFFER_attrib).
*/ */
#define GLFW_TRANSPARENT_FRAMEBUFFER 0x0002000A #define GLFW_TRANSPARENT_FRAMEBUFFER 0x0002000A
/*! @brief Mouse cursor hover window attribute.
*
* Mouse cursor hover [window attribute](@ref GLFW_HOVERED_attrib).
*/
#define GLFW_HOVERED 0x0002000B
/*! @brief Framebuffer bit depth hint. /*! @brief Framebuffer bit depth hint.
* *
@ -964,8 +969,11 @@ extern "C" {
#define GLFW_CONTEXT_CREATION_API 0x0002200B #define GLFW_CONTEXT_CREATION_API 0x0002200B
#define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001 #define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001
#define GLFW_COCOA_FRAME_AUTOSAVE 0x00023002 #define GLFW_COCOA_FRAME_NAME 0x00023002
#define GLFW_COCOA_GRAPHICS_SWITCHING 0x00023003 #define GLFW_COCOA_GRAPHICS_SWITCHING 0x00023003
#define GLFW_X11_CLASS_NAME 0x00024001
#define GLFW_X11_INSTANCE_NAME 0x00024002
/*! @} */ /*! @} */
#define GLFW_NO_API 0 #define GLFW_NO_API 0
@ -1046,9 +1054,6 @@ extern "C" {
#define GLFW_COCOA_CHDIR_RESOURCES 0x00051001 #define GLFW_COCOA_CHDIR_RESOURCES 0x00051001
#define GLFW_COCOA_MENUBAR 0x00051002 #define GLFW_COCOA_MENUBAR 0x00051002
#define GLFW_X11_WM_CLASS_NAME 0x00052001
#define GLFW_X11_WM_CLASS_CLASS 0x00052002
/*! @} */ /*! @} */
#define GLFW_DONT_CARE -1 #define GLFW_DONT_CARE -1
@ -1067,7 +1072,7 @@ extern "C" {
* @sa @ref glfwGetProcAddress * @sa @ref glfwGetProcAddress
* *
* @since Added in version 3.0. * @since Added in version 3.0.
*
* @ingroup context * @ingroup context
*/ */
typedef void (*GLFWglproc)(void); typedef void (*GLFWglproc)(void);
@ -1278,6 +1283,24 @@ typedef void (* GLFWwindowmaximizefun)(GLFWwindow*,int);
*/ */
typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int);
/*! @brief The function signature for window content scale callbacks.
*
* This is the function signature for window content scale callback
* functions.
*
* @param[in] window The window whose content scale changed.
* @param[in] xscale The new x-axis content scale of the window.
* @param[in] yscale The new y-axis content scale of the window.
*
* @sa @ref window_scale
* @sa @ref glfwSetWindowContentScaleCallback
*
* @since Added in version 3.3.
*
* @ingroup window
*/
typedef void (* GLFWwindowcontentscalefun)(GLFWwindow*,float,float);
/*! @brief The function signature for mouse button callbacks. /*! @brief The function signature for mouse button callbacks.
* *
* This is the function signature for mouse button callback functions. * This is the function signature for mouse button callback functions.
@ -1435,7 +1458,8 @@ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**);
* This is the function signature for monitor configuration callback functions. * This is the function signature for monitor configuration callback functions.
* *
* @param[in] monitor The monitor that was connected or disconnected. * @param[in] monitor The monitor that was connected or disconnected.
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. Remaining
* values reserved for future use.
* *
* @sa @ref monitor_event * @sa @ref monitor_event
* @sa @ref glfwSetMonitorCallback * @sa @ref glfwSetMonitorCallback
@ -1452,7 +1476,8 @@ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int);
* functions. * functions.
* *
* @param[in] jid The joystick that was connected or disconnected. * @param[in] jid The joystick that was connected or disconnected.
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. Remaining
* values reserved for future use.
* *
* @sa @ref joystick_event * @sa @ref joystick_event
* @sa @ref glfwSetJoystickCallback * @sa @ref glfwSetJoystickCallback
@ -1644,8 +1669,7 @@ GLFWAPI void glfwTerminate(void);
/*! @brief Sets the specified init hint to the desired value. /*! @brief Sets the specified init hint to the desired value.
* *
* This function sets hints for the next initialization of GLFW. Only integer * This function sets hints for the next initialization of GLFW.
* type hints can be set with this function.
* *
* The values you set hints to are never reset by GLFW, but they only take * The values you set hints to are never reset by GLFW, but they only take
* effect during initialization. Once GLFW has been initialized, any values * effect during initialization. Once GLFW has been initialized, any values
@ -1654,7 +1678,7 @@ GLFWAPI void glfwTerminate(void);
* *
* Some hints are platform specific. These may be set on any platform but they * Some hints are platform specific. These may be set on any platform but they
* will only affect their specific platform. Other platforms will ignore them. * will only affect their specific platform. Other platforms will ignore them.
* Setting these hints requires no platform specific headers or functions. * Setting these hints requires no platform specific headers or functions.
* *
* @param[in] hint The [init hint](@ref init_hints) to set. * @param[in] hint The [init hint](@ref init_hints) to set.
* @param[in] value The new value of the init hint. * @param[in] value The new value of the init hint.
@ -1668,7 +1692,6 @@ GLFWAPI void glfwTerminate(void);
* *
* @sa init_hints * @sa init_hints
* @sa glfwInit * @sa glfwInit
* @sa glfwInitHintString
* *
* @since Added in version 3.3. * @since Added in version 3.3.
* *
@ -1676,40 +1699,6 @@ GLFWAPI void glfwTerminate(void);
*/ */
GLFWAPI void glfwInitHint(int hint, int value); GLFWAPI void glfwInitHint(int hint, int value);
/*! @brief Sets the specified init hint to the desired value.
*
* This function sets hints for the next initialization of GLFW. Only string
* type hints can be set with this function.
*
* The values you set hints to are never reset by GLFW, but they only take
* effect during initialization. Once GLFW has been initialized, any values
* you set will be ignored until the library is terminated and initialized
* again.
*
* Some hints are platform specific. These may be set on any platform but they
* will only affect their specific platform. Other platforms will ignore them.
* Setting these hints requires no platform specific headers or functions.
*
* @param[in] hint The [init hint](@ref init_hints) to set.
* @param[in] value The new value of the init hint.
*
* @errors Possible errors include @ref GLFW_INVALID_ENUM and @ref
* GLFW_INVALID_VALUE.
*
* @remarks This function may be called before @ref glfwInit.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa init_hints
* @sa glfwInit
* @sa glfwInitHint
*
* @since Added in version 3.3.
*
* @ingroup init
*/
GLFWAPI void glfwInitHintString(int hint, const char* value);
/*! @brief Retrieves the version of the GLFW library. /*! @brief Retrieves the version of the GLFW library.
* *
* This function retrieves the major, minor and revision numbers of the GLFW * This function retrieves the major, minor and revision numbers of the GLFW
@ -2006,6 +1995,56 @@ GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* monitor, float* xscale, flo
*/ */
GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* monitor); GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* monitor);
/*! @brief Sets the user pointer of the specified monitor.
*
* This function sets the user-defined pointer of the specified monitor. The
* current value is retained until the monitor is disconnected. The initial
* value is `NULL`.
*
* This function may be called from the monitor callback, even for a monitor
* that is being disconnected.
*
* @param[in] monitor The monitor whose pointer to set.
* @param[in] pointer The new value.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @sa @ref monitor_userptr
* @sa @ref glfwGetMonitorUserPointer
*
* @since Added in version 3.3.
*
* @ingroup monitor
*/
GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* monitor, void* pointer);
/*! @brief Returns the user pointer of the specified monitor.
*
* This function returns the current value of the user-defined pointer of the
* specified monitor. The initial value is `NULL`.
*
* This function may be called from the monitor callback, even for a monitor
* that is being disconnected.
*
* @param[in] monitor The monitor whose pointer to return.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @sa @ref monitor_userptr
* @sa @ref glfwSetMonitorUserPointer
*
* @since Added in version 3.3.
*
* @ingroup monitor
*/
GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* monitor);
/*! @brief Sets the monitor configuration callback. /*! @brief Sets the monitor configuration callback.
* *
* This function sets the monitor configuration callback, or removes the * This function sets the monitor configuration callback, or removes the
@ -2205,6 +2244,7 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* monitor, const GLFWgammaramp* ramp);
* *
* @sa @ref window_hints * @sa @ref window_hints
* @sa @ref glfwWindowHint * @sa @ref glfwWindowHint
* @sa @ref glfwWindowHintString
* *
* @since Added in version 3.0. * @since Added in version 3.0.
* *
@ -2215,14 +2255,20 @@ GLFWAPI void glfwDefaultWindowHints(void);
/*! @brief Sets the specified window hint to the desired value. /*! @brief Sets the specified window hint to the desired value.
* *
* This function sets hints for the next call to @ref glfwCreateWindow. The * This function sets hints for the next call to @ref glfwCreateWindow. The
* hints, once set, retain their values until changed by a call to @ref * hints, once set, retain their values until changed by a call to this
* glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * function or @ref glfwDefaultWindowHints, or until the library is terminated.
* terminated. *
* Only integer value hints can be set with this function. String value hints
* are set with @ref glfwWindowHintString.
* *
* This function does not check whether the specified hint values are valid. * This function does not check whether the specified hint values are valid.
* If you set hints to invalid values this will instead be reported by the next * If you set hints to invalid values this will instead be reported by the next
* call to @ref glfwCreateWindow. * call to @ref glfwCreateWindow.
* *
* Some hints are platform specific. These may be set on any platform but they
* will only affect their specific platform. Other platforms will ignore them.
* Setting these hints requires no platform specific headers or functions.
*
* @param[in] hint The [window hint](@ref window_hints) to set. * @param[in] hint The [window hint](@ref window_hints) to set.
* @param[in] value The new value of the window hint. * @param[in] value The new value of the window hint.
* *
@ -2232,6 +2278,7 @@ GLFWAPI void glfwDefaultWindowHints(void);
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
* @sa @ref window_hints * @sa @ref window_hints
* @sa @ref glfwWindowHintString
* @sa @ref glfwDefaultWindowHints * @sa @ref glfwDefaultWindowHints
* *
* @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * @since Added in version 3.0. Replaces `glfwOpenWindowHint`.
@ -2240,6 +2287,44 @@ GLFWAPI void glfwDefaultWindowHints(void);
*/ */
GLFWAPI void glfwWindowHint(int hint, int value); GLFWAPI void glfwWindowHint(int hint, int value);
/*! @brief Sets the specified window hint to the desired value.
*
* This function sets hints for the next call to @ref glfwCreateWindow. The
* hints, once set, retain their values until changed by a call to this
* function or @ref glfwDefaultWindowHints, or until the library is terminated.
*
* Only string type hints can be set with this function. Integer value hints
* are set with @ref glfwWindowHint.
*
* This function does not check whether the specified hint values are valid.
* If you set hints to invalid values this will instead be reported by the next
* call to @ref glfwCreateWindow.
*
* Some hints are platform specific. These may be set on any platform but they
* will only affect their specific platform. Other platforms will ignore them.
* Setting these hints requires no platform specific headers or functions.
*
* @param[in] hint The [window hint](@ref window_hints) to set.
* @param[in] value The new value of the window hint.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_INVALID_ENUM.
*
* @pointer_lifetime The specified string is copied before this function
* returns.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_hints
* @sa @ref glfwWindowHint
* @sa @ref glfwDefaultWindowHints
*
* @since Added in version 3.3.
*
* @ingroup window
*/
GLFWAPI void glfwWindowHintString(int hint, const char* value);
/*! @brief Creates a window and its associated context. /*! @brief Creates a window and its associated context.
* *
* This function creates a window and its associated OpenGL or OpenGL ES * This function creates a window and its associated OpenGL or OpenGL ES
@ -2350,9 +2435,8 @@ GLFWAPI void glfwWindowHint(int hint, int value);
* `CMake/MacOSXBundleInfo.plist.in` in the source tree. * `CMake/MacOSXBundleInfo.plist.in` in the source tree.
* *
* @remark @macos When activating frame autosaving with * @remark @macos When activating frame autosaving with
* [GLFW_COCOA_FRAME_AUTOSAVE](@ref GLFW_COCOA_FRAME_AUTOSAVE_hint), the * [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified
* specified window size may be overriden by a previously saved size and * window size and position may be overriden by previously saved values.
* position.
* *
* @remark @x11 Some window managers will not respect the placement of * @remark @x11 Some window managers will not respect the placement of
* initially hidden windows. * initially hidden windows.
@ -2362,23 +2446,22 @@ GLFWAPI void glfwWindowHint(int hint, int value);
* query the final size, position or other attributes directly after window * query the final size, position or other attributes directly after window
* creation. * creation.
* *
* @remark @x11 The name and class of the `WM_CLASS` window property will by * @remark @x11 The class part of the `WM_CLASS` window property will by
* default be set to the window title passed to this function. Set the @ref * default be set to the window title passed to this function. The instance
* GLFW_X11_WM_CLASS_NAME and @ref GLFW_X11_WM_CLASS_CLASS init hints before * part will use the contents of the `RESOURCE_NAME` environment variable, if
* initialization to override this. * present and not empty, or fall back to the window title. Set the @ref
* GLFW_X11_CLASS_NAME and @ref GLFW_X11_INSTANCE_NAME window hints to override
* this.
* *
* @remark @wayland The window frame is currently unimplemented, as if * @remark @wayland The window frame is currently very simple, only allowing
* [GLFW_DECORATED](@ref GLFW_DECORATED_hint) was always set to `GLFW_FALSE`. * window resize or move. A compositor can still emit close, maximize or
* A compositor can still emit close, resize or maximize events, using for * fullscreen events, using for example a keybind mechanism. Additionally,
* example a keybind mechanism. * the wp_viewporter protocol is required for this feature, otherwise the
* window will not be decorated.
* *
* @remark @wayland A full screen window will not attempt to change the mode, * @remark @wayland A full screen window will not attempt to change the mode,
* no matter what the requested size or refresh rate. * no matter what the requested size or refresh rate.
* *
* @remark @wayland The wl_shell protocol does not support window
* icons, the window will inherit the one defined in the application's
* desktop file, so this function emits @ref GLFW_PLATFORM_ERROR.
*
* @remark @wayland Screensaver inhibition requires the idle-inhibit protocol * @remark @wayland Screensaver inhibition requires the idle-inhibit protocol
* to be implemented in the user's compositor. * to be implemented in the user's compositor.
* *
@ -2522,9 +2605,9 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
* [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
* in the Mac Developer Library. * in the Mac Developer Library.
* *
* @remark @wayland The wl_shell protocol does not support icons, the window * @remark @wayland There is no existing protocol to change an icon, the
* will inherit the one defined in the application's desktop file, so this * window will thus inherit the one defined in the application's desktop file.
* function emits @ref GLFW_PLATFORM_ERROR. * This function always emits @ref GLFW_PLATFORM_ERROR.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
@ -2816,10 +2899,6 @@ GLFWAPI void glfwGetFramebufferSize(GLFWwindow* window, int* width, int* height)
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @wayland The window frame is currently unimplemented, as if
* [GLFW_DECORATED](@ref GLFW_DECORATED_hint) was always set to `GLFW_FALSE`,
* so the returned values will always be zero.
*
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
* @sa @ref window_size * @sa @ref window_size
@ -2852,6 +2931,7 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
* @sa @ref window_scale * @sa @ref window_scale
* @sa @ref glfwSetWindowContentScaleCallback
* @sa @ref glfwGetMonitorContentScale * @sa @ref glfwGetMonitorContentScale
* *
* @since Added in version 3.3. * @since Added in version 3.3.
@ -2931,7 +3011,8 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity);
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @wayland There is no concept of iconification in wl_shell, this * @remark @wayland There is no concept of iconification in wl_shell, this
* function will always emit @ref GLFW_PLATFORM_ERROR. * function will emit @ref GLFW_PLATFORM_ERROR when using this deprecated
* protocol.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
@ -3226,7 +3307,7 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
* The supported attributes are [GLFW_DECORATED](@ref GLFW_DECORATED_attrib), * The supported attributes are [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
* [GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib), * [GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib),
* [GLFW_FLOATING](@ref GLFW_FLOATING_attrib) and * [GLFW_FLOATING](@ref GLFW_FLOATING_attrib) and
* [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib). * [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib).
* *
* Some of these attributes are ignored for full screen windows. The new * Some of these attributes are ignored for full screen windows. The new
* value will take effect if the window is later made windowed. * value will take effect if the window is later made windowed.
@ -3456,7 +3537,7 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwi
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
* *
* @remark @wayland The wl_shell protocol has no concept of iconification, * @remark @wayland The wl_shell protocol has no concept of iconification,
* this callback will never be called. * this callback will never be called when using this deprecated protocol.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
@ -3514,6 +3595,30 @@ GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* window,
*/ */
GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun cbfun); GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun cbfun);
/*! @brief Sets the window content scale callback for the specified window.
*
* This function sets the window content scale callback of the specified window,
* which is called when the content scale of the specified window changes.
*
* @param[in] window The window whose callback to set.
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
* callback.
* @return The previously set callback, or `NULL` if no callback was set or the
* library had not been [initialized](@ref intro_init).
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_scale
* @sa @ref glfwGetWindowContentScale
*
* @since Added in version 3.3.
*
* @ingroup window
*/
GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* window, GLFWwindowcontentscalefun cbfun);
/*! @brief Processes all pending events. /*! @brief Processes all pending events.
* *
* This function processes only those events that are already in the event * This function processes only those events that are already in the event
@ -4476,10 +4581,10 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count);
* it with the corresponding direction. * it with the corresponding direction.
* *
* @code * @code
* if (hats[2] & GLFW_HAT_RIGHT) * if (hats[2] & GLFW_HAT_RIGHT)
* { * {
* // State of hat 2 could be right-up, right or right-down * // State of hat 2 could be right-up, right or right-down
* } * }
* @endcode * @endcode
* *
* If the specified joystick is not present this function will return `NULL` * If the specified joystick is not present this function will return `NULL`
@ -4583,6 +4688,56 @@ GLFWAPI const char* glfwGetJoystickName(int jid);
*/ */
GLFWAPI const char* glfwGetJoystickGUID(int jid); GLFWAPI const char* glfwGetJoystickGUID(int jid);
/*! @brief Sets the user pointer of the specified joystick.
*
* This function sets the user-defined pointer of the specified joystick. The
* current value is retained until the joystick is disconnected. The initial
* value is `NULL`.
*
* This function may be called from the joystick callback, even for a joystick
* that is being disconnected.
*
* @param[in] joystick The joystick whose pointer to set.
* @param[in] pointer The new value.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @sa @ref joystick_userptr
* @sa @ref glfwGetJoystickUserPointer
*
* @since Added in version 3.3.
*
* @ingroup input
*/
GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer);
/*! @brief Returns the user pointer of the specified joystick.
*
* This function returns the current value of the user-defined pointer of the
* specified joystick. The initial value is `NULL`.
*
* This function may be called from the joystick callback, even for a joystick
* that is being disconnected.
*
* @param[in] joystick The joystick whose pointer to return.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @sa @ref joystick_userptr
* @sa @ref glfwSetJoystickUserPointer
*
* @since Added in version 3.3.
*
* @ingroup input
*/
GLFWAPI void* glfwGetJoystickUserPointer(int jid);
/*! @brief Returns whether the specified joystick has a gamepad mapping. /*! @brief Returns whether the specified joystick has a gamepad mapping.
* *
* This function returns whether the specified joystick is both present and has * This function returns whether the specified joystick is both present and has
@ -4859,7 +5014,7 @@ GLFWAPI void glfwSetTime(double time);
* 1&nbsp;/&nbsp;frequency seconds. To get the frequency, call @ref * 1&nbsp;/&nbsp;frequency seconds. To get the frequency, call @ref
* glfwGetTimerFrequency. * glfwGetTimerFrequency.
* *
* @return The value of the timer, or zero if an * @return The value of the timer, or zero if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
@ -5285,6 +5440,11 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhys
* glfwGetRequiredInstanceExtensions to check what instance extensions are * glfwGetRequiredInstanceExtensions to check what instance extensions are
* required. * required.
* *
* The window surface cannot be shared with another API so the window must
* have been created with the [client api hint](@ref GLFW_CLIENT_API_attrib)
* set to `GLFW_NO_API` otherwise it generates a @ref GLFW_INVALID_VALUE error
* and returns `VK_ERROR_NATIVE_WINDOW_IN_USE_KHR`.
*
* The window surface must be destroyed before the specified Vulkan instance. * The window surface must be destroyed before the specified Vulkan instance.
* It is the responsibility of the caller to destroy the window surface. GLFW * It is the responsibility of the caller to destroy the window surface. GLFW
* does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the
@ -5300,7 +5460,7 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhys
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. * GLFW_API_UNAVAILABLE, @ref GLFW_PLATFORM_ERROR and @ref GLFW_INVALID_VALUE
* *
* @remark If an error occurs before the creation call is made, GLFW returns * @remark If an error occurs before the creation call is made, GLFW returns
* the Vulkan error code most appropriate for the error. Appropriate use of * the Vulkan error code most appropriate for the error. Appropriate use of

View file

@ -39,6 +39,14 @@ elseif (_GLFW_WAYLAND)
linux_joystick.c posix_time.c posix_thread.c xkb_unicode.c linux_joystick.c posix_time.c posix_thread.c xkb_unicode.c
egl_context.c osmesa_context.c) egl_context.c osmesa_context.c)
ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/xdg-shell/xdg-shell.xml"
BASENAME xdg-shell)
ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/viewporter/viewporter.xml"
BASENAME viewporter)
ecm_add_wayland_client_protocol(glfw_SOURCES ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml" "${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml"
@ -49,7 +57,7 @@ elseif (_GLFW_WAYLAND)
BASENAME pointer-constraints-unstable-v1) BASENAME pointer-constraints-unstable-v1)
ecm_add_wayland_client_protocol(glfw_SOURCES ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL PROTOCOL
${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml "${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml"
BASENAME idle-inhibit-unstable-v1) BASENAME idle-inhibit-unstable-v1)
elseif (_GLFW_MIR) elseif (_GLFW_MIR)
set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
@ -90,9 +98,7 @@ set_target_properties(glfw PROPERTIES
POSITION_INDEPENDENT_CODE ON POSITION_INDEPENDENT_CODE ON
FOLDER "GLFW3") FOLDER "GLFW3")
target_compile_definitions(glfw PRIVATE target_compile_definitions(glfw PRIVATE _GLFW_USE_CONFIG_H)
_GLFW_USE_CONFIG_H
$<$<BOOL:${UNIX}>:_XOPEN_SOURCE=600>)
target_include_directories(glfw PUBLIC target_include_directories(glfw PUBLIC
"$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>" "$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>") "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>")

View file

@ -264,7 +264,7 @@ void _glfwPollMonitorsNS(void)
const CGSize size = CGDisplayScreenSize(displays[i]); const CGSize size = CGDisplayScreenSize(displays[i]);
char* name = getDisplayName(displays[i]); char* name = getDisplayName(displays[i]);
if (!name) if (!name)
name = strdup("Unknown"); name = _glfw_strdup("Unknown");
monitor = _glfwAllocMonitor(name, size.width, size.height); monitor = _glfwAllocMonitor(name, size.width, size.height);
monitor->ns.displayID = displays[i]; monitor->ns.displayID = displays[i];
@ -287,7 +287,7 @@ void _glfwPollMonitorsNS(void)
// Change the current video mode // Change the current video mode
// //
GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired) void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
{ {
CFArrayRef modes; CFArrayRef modes;
CFIndex count, i; CFIndex count, i;
@ -299,7 +299,7 @@ GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
best = _glfwChooseVideoMode(monitor, desired); best = _glfwChooseVideoMode(monitor, desired);
_glfwPlatformGetVideoMode(monitor, &current); _glfwPlatformGetVideoMode(monitor, &current);
if (_glfwCompareVideoModes(&current, best) == 0) if (_glfwCompareVideoModes(&current, best) == 0)
return GLFW_TRUE; return;
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link); CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
@ -332,15 +332,6 @@ GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
CFRelease(modes); CFRelease(modes);
CVDisplayLinkRelease(link); CVDisplayLinkRelease(link);
if (!native)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Cocoa: Monitor mode list changed");
return GLFW_FALSE;
}
return GLFW_TRUE;
} }
// Restore the previously saved (original) video mode // Restore the previously saved (original) video mode
@ -364,6 +355,10 @@ void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
{
}
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{ {
const CGRect bounds = CGDisplayBounds(monitor->ns.displayID); const CGRect bounds = CGDisplayBounds(monitor->ns.displayID);

View file

@ -88,9 +88,10 @@ typedef struct _GLFWwindowNS
GLFWbool maximized; GLFWbool maximized;
// Cached window and framebuffer sizes used to filter out duplicate events // Cached window properties to filter out duplicate events
int width, height; int width, height;
int fbWidth, fbHeight; int fbWidth, fbHeight;
float xscale, yscale;
// The total sum of the distances the cursor has been warped // The total sum of the distances the cursor has been warped
// since the last cursor motion event was processed // since the last cursor motion event was processed
@ -163,6 +164,6 @@ typedef struct _GLFWtimerNS
void _glfwInitTimerNS(void); void _glfwInitTimerNS(void);
void _glfwPollMonitorsNS(void); void _glfwPollMonitorsNS(void);
GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired); void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor); void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);

View file

@ -138,9 +138,9 @@ static float transformY(float y)
// Make the specified window and its video mode active on its monitor // Make the specified window and its video mode active on its monitor
// //
static GLFWbool acquireMonitor(_GLFWwindow* window) static void acquireMonitor(_GLFWwindow* window)
{ {
const GLFWbool status = _glfwSetVideoModeNS(window->monitor, &window->videoMode); _glfwSetVideoModeNS(window->monitor, &window->videoMode);
const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID); const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID);
const NSRect frame = NSMakeRect(bounds.origin.x, const NSRect frame = NSMakeRect(bounds.origin.x,
transformY(bounds.origin.y + bounds.size.height), transformY(bounds.origin.y + bounds.size.height),
@ -150,7 +150,6 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
[window->ns.object setFrame:frame display:YES]; [window->ns.object setFrame:frame display:YES];
_glfwInputMonitorWindow(window->monitor, window); _glfwInputMonitorWindow(window->monitor, window);
return status;
} }
// Remove the window and restore the original video mode // Remove the window and restore the original video mode
@ -574,6 +573,16 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
window->ns.fbHeight = fbRect.size.height; window->ns.fbHeight = fbRect.size.height;
_glfwInputFramebufferSize(window, fbRect.size.width, 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)
{
window->ns.xscale = xscale;
window->ns.yscale = yscale;
_glfwInputWindowContentScale(window, xscale, yscale);
}
} }
- (void)drawRect:(NSRect)rect - (void)drawRect:(NSRect)rect
@ -697,7 +706,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
NSUInteger i; NSUInteger i;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
paths[i] = strdup([[e nextObject] UTF8String]); paths[i] = _glfw_strdup([[e nextObject] UTF8String]);
_glfwInputDrop(window, (int) count, (const char**) paths); _glfwInputDrop(window, (int) count, (const char**) paths);
@ -1096,8 +1105,8 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
[window->ns.object zoom:nil]; [window->ns.object zoom:nil];
} }
if (wndconfig->ns.frame) if (strlen(wndconfig->ns.frameName))
[window->ns.object setFrameAutosaveName:[NSString stringWithUTF8String:wndconfig->title]]; [window->ns.object setFrameAutosaveName:[NSString stringWithUTF8String:wndconfig->ns.frameName]];
window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window]; window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
@ -1168,11 +1177,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
{ {
_glfwPlatformShowWindow(window); _glfwPlatformShowWindow(window);
_glfwPlatformFocusWindow(window); _glfwPlatformFocusWindow(window);
if (!acquireMonitor(window)) acquireMonitor(window);
return GLFW_FALSE;
if (wndconfig->centerCursor)
centerCursor(window);
} }
return GLFW_TRUE; return GLFW_TRUE;
@ -1408,6 +1413,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
const NSUInteger styleMask = getStyleMask(window); const NSUInteger styleMask = getStyleMask(window);
[window->ns.object setStyleMask:styleMask]; [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]; [window->ns.object makeFirstResponder:window->ns.view];
if (monitor) if (monitor)
@ -1478,6 +1484,20 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return [window->ns.object isZoomed]; return [window->ns.object isZoomed];
} }
int _glfwPlatformWindowHovered(_GLFWwindow* window)
{
const NSPoint point = [NSEvent mouseLocation];
if ([NSWindow windowNumberAtPoint:point belowWindowWithWindowNumber:0] !=
[window->ns.object windowNumber])
{
return GLFW_FALSE;
}
return NSPointInRect(point,
[window->ns.object convertRectToScreen:[window->ns.view bounds]]);
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{ {
return ![window->ns.object isOpaque] && ![window->ns.view isOpaque]; return ![window->ns.object isOpaque] && ![window->ns.view isOpaque];
@ -1514,6 +1534,9 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
if (!initializeAppKit())
return;
for (;;) for (;;)
{ {
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
@ -1789,7 +1812,7 @@ const char* _glfwPlatformGetClipboardString(void)
} }
free(_glfw.ns.clipboardString); free(_glfw.ns.clipboardString);
_glfw.ns.clipboardString = strdup([object UTF8String]); _glfw.ns.clipboardString = _glfw_strdup([object UTF8String]);
return _glfw.ns.clipboardString; return _glfw.ns.clipboardString;
} }

View file

@ -38,8 +38,24 @@
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Checks whether the desired context attributes are valid
//
// This function checks things like whether the specified client API version
// exists and whether all relevant options have supported and non-conflicting
// values
//
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) 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 && if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
ctxconfig->source != GLFW_EGL_CONTEXT_API && ctxconfig->source != GLFW_EGL_CONTEXT_API &&
ctxconfig->source != GLFW_OSMESA_CONTEXT_API) ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
@ -155,6 +171,8 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
return GLFW_TRUE; return GLFW_TRUE;
} }
// Chooses the framebuffer config that best matches the desired one
//
const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired, const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
const _GLFWfbconfig* alternatives, const _GLFWfbconfig* alternatives,
unsigned int count) unsigned int count)
@ -321,10 +339,13 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
return closest; return closest;
} }
GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig) // Retrieves the attributes of the current context
//
GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig)
{ {
int i; int i;
_GLFWwindow* window; _GLFWwindow* previous;
const char* version; const char* version;
const char* prefixes[] = const char* prefixes[] =
{ {
@ -334,11 +355,12 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
NULL NULL
}; };
window = _glfwPlatformGetTls(&_glfw.contextSlot);
window->context.source = ctxconfig->source; window->context.source = ctxconfig->source;
window->context.client = GLFW_OPENGL_API; window->context.client = GLFW_OPENGL_API;
previous = _glfwPlatformGetTls(&_glfw.contextSlot);;
glfwMakeContextCurrent((GLFWwindow*) window);
window->context.GetIntegerv = (PFNGLGETINTEGERVPROC) window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
window->context.getProcAddress("glGetIntegerv"); window->context.getProcAddress("glGetIntegerv");
window->context.GetString = (PFNGLGETSTRINGPROC) window->context.GetString = (PFNGLGETSTRINGPROC)
@ -346,6 +368,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
if (!window->context.GetIntegerv || !window->context.GetString) if (!window->context.GetIntegerv || !window->context.GetString)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken"); _glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -363,6 +386,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
"OpenGL ES version string retrieval is broken"); "OpenGL ES version string retrieval is broken");
} }
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -394,6 +418,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
"No version found in OpenGL ES version string"); "No version found in OpenGL ES version string");
} }
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -423,6 +448,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
window->context.major, window->context.minor); window->context.major, window->context.minor);
} }
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -438,6 +464,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Entry point retrieval is broken"); "Entry point retrieval is broken");
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_FALSE; return GLFW_FALSE;
} }
} }
@ -544,9 +571,12 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
window->context.swapBuffers(window); window->context.swapBuffers(window);
} }
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_TRUE; return GLFW_TRUE;
} }
// Searches an extension string for the specified extension
//
GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions) GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions)
{ {
const char* start = extensions; const char* start = extensions;
@ -587,7 +617,8 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
if (window && window->context.client == GLFW_NO_API) if (window && window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT,
"Cannot make current with a window that has no OpenGL or OpenGL ES context");
return; return;
} }
@ -616,7 +647,8 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
if (window->context.client == GLFW_NO_API) if (window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT,
"Cannot swap buffers of a window that has no OpenGL or OpenGL ES context");
return; return;
} }
@ -632,7 +664,8 @@ GLFWAPI void glfwSwapInterval(int interval)
window = _glfwPlatformGetTls(&_glfw.contextSlot); window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (!window) if (!window)
{ {
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL); _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
"Cannot set swap interval without a current OpenGL or OpenGL ES context");
return; return;
} }
@ -649,13 +682,14 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
window = _glfwPlatformGetTls(&_glfw.contextSlot); window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (!window) if (!window)
{ {
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL); _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
"Cannot query extension without a current OpenGL or OpenGL ES context");
return GLFW_FALSE; return GLFW_FALSE;
} }
if (*extension == '\0') if (*extension == '\0')
{ {
_glfwInputError(GLFW_INVALID_VALUE, "Extension name is empty string"); _glfwInputError(GLFW_INVALID_VALUE, "Extension name cannot be an empty string");
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -714,7 +748,8 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
window = _glfwPlatformGetTls(&_glfw.contextSlot); window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (!window) if (!window)
{ {
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL); _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
"Cannot query entry point without a current OpenGL or OpenGL ES context");
return NULL; return NULL;
} }

View file

@ -223,7 +223,7 @@ static GLFWglproc getProcAddressGLX(const char* procname)
else if (_glfw.glx.GetProcAddressARB) else if (_glfw.glx.GetProcAddressARB)
return _glfw.glx.GetProcAddressARB((const GLubyte*) procname); return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
else else
return dlsym(_glfw.glx.handle, procname); return _glfw_dlsym(_glfw.glx.handle, procname);
} }
// Destroy the OpenGL context // Destroy the OpenGL context
@ -271,7 +271,7 @@ GLFWbool _glfwInitGLX(void)
for (i = 0; sonames[i]; i++) for (i = 0; sonames[i]; i++)
{ {
_glfw.glx.handle = dlopen(sonames[i], RTLD_LAZY | RTLD_GLOBAL); _glfw.glx.handle = _glfw_dlopen(sonames[i]);
if (_glfw.glx.handle) if (_glfw.glx.handle)
break; break;
} }
@ -283,35 +283,35 @@ GLFWbool _glfwInitGLX(void)
} }
_glfw.glx.GetFBConfigs = _glfw.glx.GetFBConfigs =
dlsym(_glfw.glx.handle, "glXGetFBConfigs"); _glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigs");
_glfw.glx.GetFBConfigAttrib = _glfw.glx.GetFBConfigAttrib =
dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib"); _glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib");
_glfw.glx.GetClientString = _glfw.glx.GetClientString =
dlsym(_glfw.glx.handle, "glXGetClientString"); _glfw_dlsym(_glfw.glx.handle, "glXGetClientString");
_glfw.glx.QueryExtension = _glfw.glx.QueryExtension =
dlsym(_glfw.glx.handle, "glXQueryExtension"); _glfw_dlsym(_glfw.glx.handle, "glXQueryExtension");
_glfw.glx.QueryVersion = _glfw.glx.QueryVersion =
dlsym(_glfw.glx.handle, "glXQueryVersion"); _glfw_dlsym(_glfw.glx.handle, "glXQueryVersion");
_glfw.glx.DestroyContext = _glfw.glx.DestroyContext =
dlsym(_glfw.glx.handle, "glXDestroyContext"); _glfw_dlsym(_glfw.glx.handle, "glXDestroyContext");
_glfw.glx.MakeCurrent = _glfw.glx.MakeCurrent =
dlsym(_glfw.glx.handle, "glXMakeCurrent"); _glfw_dlsym(_glfw.glx.handle, "glXMakeCurrent");
_glfw.glx.SwapBuffers = _glfw.glx.SwapBuffers =
dlsym(_glfw.glx.handle, "glXSwapBuffers"); _glfw_dlsym(_glfw.glx.handle, "glXSwapBuffers");
_glfw.glx.QueryExtensionsString = _glfw.glx.QueryExtensionsString =
dlsym(_glfw.glx.handle, "glXQueryExtensionsString"); _glfw_dlsym(_glfw.glx.handle, "glXQueryExtensionsString");
_glfw.glx.CreateNewContext = _glfw.glx.CreateNewContext =
dlsym(_glfw.glx.handle, "glXCreateNewContext"); _glfw_dlsym(_glfw.glx.handle, "glXCreateNewContext");
_glfw.glx.CreateWindow = _glfw.glx.CreateWindow =
dlsym(_glfw.glx.handle, "glXCreateWindow"); _glfw_dlsym(_glfw.glx.handle, "glXCreateWindow");
_glfw.glx.DestroyWindow = _glfw.glx.DestroyWindow =
dlsym(_glfw.glx.handle, "glXDestroyWindow"); _glfw_dlsym(_glfw.glx.handle, "glXDestroyWindow");
_glfw.glx.GetProcAddress = _glfw.glx.GetProcAddress =
dlsym(_glfw.glx.handle, "glXGetProcAddress"); _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddress");
_glfw.glx.GetProcAddressARB = _glfw.glx.GetProcAddressARB =
dlsym(_glfw.glx.handle, "glXGetProcAddressARB"); _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
_glfw.glx.GetVisualFromFBConfig = _glfw.glx.GetVisualFromFBConfig =
dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig"); _glfw_dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
if (!_glfw.glx.GetFBConfigs || if (!_glfw.glx.GetFBConfigs ||
!_glfw.glx.GetFBConfigAttrib || !_glfw.glx.GetFBConfigAttrib ||
@ -428,7 +428,7 @@ void _glfwTerminateGLX(void)
if (_glfw.glx.handle) if (_glfw.glx.handle)
{ {
dlclose(_glfw.glx.handle); _glfw_dlclose(_glfw.glx.handle);
_glfw.glx.handle = NULL; _glfw.glx.handle = NULL;
} }
} }

View file

@ -35,8 +35,9 @@
#include <assert.h> #include <assert.h>
// The global variables below comprise all global data in GLFW. // The global variables below comprise all mutable global data in GLFW
// Any other global variable is a bug. //
// Any other global variable is a bug
// Global state shared between compilation units of GLFW // Global state shared between compilation units of GLFW
// //
@ -53,10 +54,6 @@ static _GLFWinitconfig _glfwInitHints =
{ {
GLFW_TRUE, // macOS menu bar GLFW_TRUE, // macOS menu bar
GLFW_TRUE // macOS bundle chdir GLFW_TRUE // macOS bundle chdir
},
{
"", // X11 WM_CLASS name
"" // X11 WM_CLASS class
} }
}; };
@ -141,10 +138,25 @@ static void terminate(void)
} }
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
char* _glfw_strdup(const char* source)
{
const size_t length = strlen(source);
char* result = calloc(length + 1, 1);
strcpy(result, source);
return result;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW event API ////// ////// GLFW event API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Notifies shared code of an error
//
void _glfwInputError(int code, const char* format, ...) void _glfwInputError(int code, const char* format, ...)
{ {
_GLFWerror* error; _GLFWerror* error;
@ -260,27 +272,7 @@ GLFWAPI void glfwInitHint(int hint, int value)
} }
_glfwInputError(GLFW_INVALID_ENUM, _glfwInputError(GLFW_INVALID_ENUM,
"Invalid integer type init hint 0x%08X", hint); "Invalid init hint 0x%08X", hint);
}
GLFWAPI void glfwInitHintString(int hint, const char* value)
{
assert(value != NULL);
switch (hint)
{
case GLFW_X11_WM_CLASS_NAME:
strncpy(_glfwInitHints.x11.className, value,
sizeof(_glfwInitHints.x11.className) - 1);
return;
case GLFW_X11_WM_CLASS_CLASS:
strncpy(_glfwInitHints.x11.classClass, value,
sizeof(_glfwInitHints.x11.classClass) - 1);
return;
}
_glfwInputError(GLFW_INVALID_ENUM,
"Invalid string type init hint 0x%08X", hint);
} }
GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev) GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)

View file

@ -62,11 +62,11 @@ static _GLFWmapping* findMapping(const char* guid)
static GLFWbool isValidElementForJoystick(const _GLFWmapelement* e, static GLFWbool isValidElementForJoystick(const _GLFWmapelement* e,
const _GLFWjoystick* js) const _GLFWjoystick* js)
{ {
if (e->type == _GLFW_JOYSTICK_HATBIT && (e->value >> 4) >= js->hatCount) if (e->type == _GLFW_JOYSTICK_HATBIT && (e->index >> 4) >= js->hatCount)
return GLFW_FALSE; return GLFW_FALSE;
else if (e->type == _GLFW_JOYSTICK_BUTTON && e->value >= js->buttonCount) else if (e->type == _GLFW_JOYSTICK_BUTTON && e->index >= js->buttonCount)
return GLFW_FALSE; return GLFW_FALSE;
else if (e->type == _GLFW_JOYSTICK_AXIS && e->value >= js->axisCount) else if (e->type == _GLFW_JOYSTICK_AXIS && e->index >= js->axisCount)
return GLFW_FALSE; return GLFW_FALSE;
return GLFW_TRUE; return GLFW_TRUE;
@ -167,6 +167,10 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
while (*c) while (*c)
{ {
// TODO: Implement output modifiers
if (*c == '+' || *c == '-')
return GLFW_FALSE;
for (i = 0; i < sizeof(fields) / sizeof(fields[0]); i++) for (i = 0; i < sizeof(fields) / sizeof(fields[0]); i++)
{ {
length = strlen(fields[i].name); length = strlen(fields[i].name);
@ -177,23 +181,50 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
if (fields[i].element) if (fields[i].element)
{ {
_GLFWmapelement* e = fields[i].element;
int8_t minimum = -1;
int8_t maximum = 1;
if (*c == '+')
{
minimum = 0;
c += 1;
}
else if (*c == '-')
{
maximum = 0;
c += 1;
}
if (*c == 'a') if (*c == 'a')
fields[i].element->type = _GLFW_JOYSTICK_AXIS; e->type = _GLFW_JOYSTICK_AXIS;
else if (*c == 'b') else if (*c == 'b')
fields[i].element->type = _GLFW_JOYSTICK_BUTTON; e->type = _GLFW_JOYSTICK_BUTTON;
else if (*c == 'h') else if (*c == 'h')
fields[i].element->type = _GLFW_JOYSTICK_HATBIT; e->type = _GLFW_JOYSTICK_HATBIT;
else else
break; break;
if (fields[i].element->type == _GLFW_JOYSTICK_HATBIT) if (e->type == _GLFW_JOYSTICK_HATBIT)
{ {
const unsigned long hat = strtoul(c + 1, (char**) &c, 10); const unsigned long hat = strtoul(c + 1, (char**) &c, 10);
const unsigned long bit = strtoul(c + 1, (char**) &c, 10); const unsigned long bit = strtoul(c + 1, (char**) &c, 10);
fields[i].element->value = (uint8_t) ((hat << 4) | bit); e->index = (uint8_t) ((hat << 4) | bit);
} }
else else
fields[i].element->value = (uint8_t) strtoul(c + 1, (char**) &c, 10); e->index = (uint8_t) strtoul(c + 1, (char**) &c, 10);
if (e->type == _GLFW_JOYSTICK_AXIS)
{
e->axisScale = 2 / (maximum - minimum);
e->axisOffset = -(maximum + minimum);
if (*c == '~')
{
e->axisScale = -e->axisScale;
e->axisOffset = -e->axisOffset;
}
}
} }
else else
{ {
@ -224,6 +255,8 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
////// GLFW event API ////// ////// GLFW event API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Notifies shared code of a physical key event
//
void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods) void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods)
{ {
if (key >= 0 && key <= GLFW_KEY_LAST) if (key >= 0 && key <= GLFW_KEY_LAST)
@ -252,6 +285,9 @@ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int m
window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods); window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods);
} }
// 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, unsigned int codepoint, int mods, GLFWbool plain)
{ {
if (codepoint < 32 || (codepoint > 126 && codepoint < 160)) if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
@ -270,12 +306,16 @@ void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWb
} }
} }
// Notifies shared code of a scroll event
//
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset) void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
{ {
if (window->callbacks.scroll) if (window->callbacks.scroll)
window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset); window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
} }
// Notifies shared code of a mouse button click event
//
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods) void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
{ {
if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST) if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
@ -293,6 +333,9 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods); window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods);
} }
// Notifies shared code of a cursor motion event
// The position is specified in client-area relative screen coordinates
//
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos) void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
{ {
if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos) if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)
@ -305,18 +348,24 @@ void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos); window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos);
} }
// Notifies shared code of a cursor enter/leave event
//
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered) void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
{ {
if (window->callbacks.cursorEnter) if (window->callbacks.cursorEnter)
window->callbacks.cursorEnter((GLFWwindow*) window, entered); window->callbacks.cursorEnter((GLFWwindow*) window, entered);
} }
// Notifies shared code of files or directories dropped on a window
//
void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths) void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
{ {
if (window->callbacks.drop) if (window->callbacks.drop)
window->callbacks.drop((GLFWwindow*) window, count, paths); window->callbacks.drop((GLFWwindow*) window, count, paths);
} }
// Notifies shared code of a joystick connection or disconnection
//
void _glfwInputJoystick(_GLFWjoystick* js, int event) void _glfwInputJoystick(_GLFWjoystick* js, int event)
{ {
const int jid = (int) (js - _glfw.joysticks); const int jid = (int) (js - _glfw.joysticks);
@ -325,16 +374,22 @@ void _glfwInputJoystick(_GLFWjoystick* js, int event)
_glfw.callbacks.joystick(jid, event); _glfw.callbacks.joystick(jid, event);
} }
// Notifies shared code of the new value of a joystick axis
//
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value) void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value)
{ {
js->axes[axis] = value; js->axes[axis] = value;
} }
// Notifies shared code of the new value of a joystick button
//
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value) void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value)
{ {
js->buttons[button] = value; js->buttons[button] = value;
} }
// Notifies shared code of the new value of a joystick hat
//
void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value) void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
{ {
const int base = js->buttonCount + hat * 4; const int base = js->buttonCount + hat * 4;
@ -352,6 +407,8 @@ void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Returns an available joystick object with arrays and name allocated
//
_GLFWjoystick* _glfwAllocJoystick(const char* name, _GLFWjoystick* _glfwAllocJoystick(const char* name,
const char* guid, const char* guid,
int axisCount, int axisCount,
@ -372,7 +429,7 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
js->present = GLFW_TRUE; js->present = GLFW_TRUE;
js->name = strdup(name); js->name = _glfw_strdup(name);
js->axes = calloc(axisCount, sizeof(float)); js->axes = calloc(axisCount, sizeof(float));
js->buttons = calloc(buttonCount + hatCount * 4, 1); js->buttons = calloc(buttonCount + hatCount * 4, 1);
js->hats = calloc(hatCount, 1); js->hats = calloc(hatCount, 1);
@ -386,6 +443,8 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
return js; return js;
} }
// Frees arrays and name and flags the joystick object as unused
//
void _glfwFreeJoystick(_GLFWjoystick* js) void _glfwFreeJoystick(_GLFWjoystick* js)
{ {
free(js->name); free(js->name);
@ -979,6 +1038,38 @@ GLFWAPI const char* glfwGetJoystickGUID(int jid)
return js->guid; return js->guid;
} }
GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer)
{
_GLFWjoystick* js;
assert(jid >= GLFW_JOYSTICK_1);
assert(jid <= GLFW_JOYSTICK_LAST);
_GLFW_REQUIRE_INIT();
js = _glfw.joysticks + jid;
if (!js->present)
return;
js->userPointer = pointer;
}
GLFWAPI void* glfwGetJoystickUserPointer(int jid)
{
_GLFWjoystick* js;
assert(jid >= GLFW_JOYSTICK_1);
assert(jid <= GLFW_JOYSTICK_LAST);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
js = _glfw.joysticks + jid;
if (!js->present)
return NULL;
return js->userPointer;
}
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun) GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
@ -1128,35 +1219,41 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++) for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++)
{ {
if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_AXIS) const _GLFWmapelement* e = js->mapping->buttons + i;
if (e->type == _GLFW_JOYSTICK_AXIS)
{ {
if (fabs(js->axes[js->mapping->buttons[i].value]) > 0.5) const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
if (value > 0.f)
state->buttons[i] = GLFW_PRESS; state->buttons[i] = GLFW_PRESS;
} }
else if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_HATBIT) else if (e->type == _GLFW_JOYSTICK_HATBIT)
{ {
const unsigned int hat = js->mapping->buttons[i].value >> 4; const unsigned int hat = e->index >> 4;
const unsigned int bit = js->mapping->buttons[i].value & 0xf; const unsigned int bit = e->index & 0xf;
if (js->hats[hat] & bit) if (js->hats[hat] & bit)
state->buttons[i] = GLFW_PRESS; state->buttons[i] = GLFW_PRESS;
} }
else if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_BUTTON) else if (e->type == _GLFW_JOYSTICK_BUTTON)
state->buttons[i] = js->buttons[js->mapping->buttons[i].value]; state->buttons[i] = js->buttons[e->index];
} }
for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++) for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++)
{ {
if (js->mapping->axes[i].type == _GLFW_JOYSTICK_AXIS) const _GLFWmapelement* e = js->mapping->axes + i;
state->axes[i] = js->axes[js->mapping->axes[i].value]; if (e->type == _GLFW_JOYSTICK_AXIS)
else if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_HATBIT)
{ {
const unsigned int hat = js->mapping->axes[i].value >> 4; const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
const unsigned int bit = js->mapping->axes[i].value & 0xf; state->axes[i] = fminf(fmaxf(value, -1.f), 1.f);
}
else if (e->type == _GLFW_JOYSTICK_HATBIT)
{
const unsigned int hat = e->index >> 4;
const unsigned int bit = e->index & 0xf;
if (js->hats[hat] & bit) if (js->hats[hat] & bit)
state->axes[i] = 1.f; state->axes[i] = 1.f;
} }
else if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_BUTTON) else if (e->type == _GLFW_JOYSTICK_BUTTON)
state->axes[i] = (float) js->buttons[js->mapping->axes[i].value]; state->axes[i] = (float) js->buttons[e->index];
} }
return GLFW_TRUE; return GLFW_TRUE;

View file

@ -196,38 +196,6 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
#error "No supported window creation API selected" #error "No supported window creation API selected"
#endif #endif
//========================================================================
// Doxygen group definitions
//========================================================================
/*! @defgroup platform Platform interface
* @brief The interface implemented by the platform-specific code.
*
* The platform API is the interface exposed by the platform-specific code for
* each platform and is called by the shared code of the public API It mirrors
* the public API except it uses objects instead of handles.
*/
/*! @defgroup event Event interface
* @brief The interface used by the platform-specific code to report events.
*
* The event API is used by the platform-specific code to notify the shared
* code of events that can be translated into state changes and/or callback
* calls.
*/
/*! @defgroup utility Utility functions
* @brief Various utility functions for internal use.
*
* These functions are shared code and may be used by any part of GLFW
* Each platform may add its own utility functions, but those must only be
* called by the platform-specific code
*/
//========================================================================
// Helper macros
//========================================================================
// Constructs a version number string from the public header macros // Constructs a version number string from the public header macros
#define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r #define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r
#define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r) #define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r)
@ -258,11 +226,8 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
y = t; \ y = t; \
} }
// Per-thread error structure
//======================================================================== //
// Platform-independent structures
//========================================================================
struct _GLFWerror struct _GLFWerror
{ {
_GLFWerror* next; _GLFWerror* next;
@ -270,10 +235,10 @@ struct _GLFWerror
char description[_GLFW_MESSAGE_SIZE]; char description[_GLFW_MESSAGE_SIZE];
}; };
/*! @brief Initialization configuration. // Initialization configuration
* //
* Parameters relating to the initialization of the library. // Parameters relating to the initialization of the library
*/ //
struct _GLFWinitconfig struct _GLFWinitconfig
{ {
GLFWbool hatButtons; GLFWbool hatButtons;
@ -281,18 +246,14 @@ struct _GLFWinitconfig
GLFWbool menubar; GLFWbool menubar;
GLFWbool chdir; GLFWbool chdir;
} ns; } ns;
struct {
char className[256];
char classClass[256];
} x11;
}; };
/*! @brief Window configuration. // Window configuration
* //
* Parameters relating to the creation of the window but not directly related // Parameters relating to the creation of the window but not directly related
* to the framebuffer. This is used to pass window creation parameters from // to the framebuffer. This is used to pass window creation parameters from
* shared code to the platform API. // shared code to the platform API.
*/ //
struct _GLFWwndconfig struct _GLFWwndconfig
{ {
int width; int width;
@ -308,16 +269,20 @@ struct _GLFWwndconfig
GLFWbool centerCursor; GLFWbool centerCursor;
struct { struct {
GLFWbool retina; GLFWbool retina;
GLFWbool frame; char frameName[256];
} ns; } ns;
struct {
char className[256];
char instanceName[256];
} x11;
}; };
/*! @brief Context configuration. // Context configuration
* //
* Parameters relating to the creation of the context but not directly related // Parameters relating to the creation of the context but not directly related
* to the framebuffer. This is used to pass context creation parameters from // to the framebuffer. This is used to pass context creation parameters from
* shared code to the platform API. // shared code to the platform API.
*/ //
struct _GLFWctxconfig struct _GLFWctxconfig
{ {
int client; int client;
@ -336,14 +301,14 @@ struct _GLFWctxconfig
} nsgl; } nsgl;
}; };
/*! @brief Framebuffer configuration. // Framebuffer configuration
* //
* This describes buffers and their sizes. It also contains // This describes buffers and their sizes. It also contains
* a platform-specific ID used to map back to the backend API object. // a platform-specific ID used to map back to the backend API object.
* //
* It is used to pass framebuffer parameters from shared code to the platform // It is used to pass framebuffer parameters from shared code to the platform
* API and also to enumerate and select available framebuffer configs. // API and also to enumerate and select available framebuffer configs.
*/ //
struct _GLFWfbconfig struct _GLFWfbconfig
{ {
int redBits; int redBits;
@ -365,8 +330,8 @@ struct _GLFWfbconfig
uintptr_t handle; uintptr_t handle;
}; };
/*! @brief Context structure. // Context structure
*/ //
struct _GLFWcontext struct _GLFWcontext
{ {
int client; int client;
@ -396,8 +361,8 @@ struct _GLFWcontext
_GLFW_OSMESA_CONTEXT_STATE; _GLFW_OSMESA_CONTEXT_STATE;
}; };
/*! @brief Window and context structure. // Window and context structure
*/ //
struct _GLFWwindow struct _GLFWwindow
{ {
struct _GLFWwindow* next; struct _GLFWwindow* next;
@ -437,6 +402,7 @@ struct _GLFWwindow
GLFWwindowiconifyfun iconify; GLFWwindowiconifyfun iconify;
GLFWwindowmaximizefun maximize; GLFWwindowmaximizefun maximize;
GLFWframebuffersizefun fbsize; GLFWframebuffersizefun fbsize;
GLFWwindowcontentscalefun scale;
GLFWmousebuttonfun mouseButton; GLFWmousebuttonfun mouseButton;
GLFWcursorposfun cursorPos; GLFWcursorposfun cursorPos;
GLFWcursorenterfun cursorEnter; GLFWcursorenterfun cursorEnter;
@ -451,11 +417,12 @@ struct _GLFWwindow
_GLFW_PLATFORM_WINDOW_STATE; _GLFW_PLATFORM_WINDOW_STATE;
}; };
/*! @brief Monitor structure. // Monitor structure
*/ //
struct _GLFWmonitor struct _GLFWmonitor
{ {
char* name; char* name;
void* userPointer;
// Physical dimensions in millimeters. // Physical dimensions in millimeters.
int widthMM, heightMM; int widthMM, heightMM;
@ -474,8 +441,8 @@ struct _GLFWmonitor
_GLFW_PLATFORM_MONITOR_STATE; _GLFW_PLATFORM_MONITOR_STATE;
}; };
/*! @brief Cursor structure // Cursor structure
*/ //
struct _GLFWcursor struct _GLFWcursor
{ {
_GLFWcursor* next; _GLFWcursor* next;
@ -484,16 +451,18 @@ struct _GLFWcursor
_GLFW_PLATFORM_CURSOR_STATE; _GLFW_PLATFORM_CURSOR_STATE;
}; };
/*! @brief Gamepad mapping element structure // Gamepad mapping element structure
*/ //
struct _GLFWmapelement struct _GLFWmapelement
{ {
uint8_t type; uint8_t type;
uint8_t value; uint8_t index;
int8_t axisScale;
int8_t axisOffset;
}; };
/*! @brief Gamepad mapping structure // Gamepad mapping structure
*/ //
struct _GLFWmapping struct _GLFWmapping
{ {
char name[128]; char name[128];
@ -502,8 +471,8 @@ struct _GLFWmapping
_GLFWmapelement axes[6]; _GLFWmapelement axes[6];
}; };
/*! @brief Joystick structure // Joystick structure
*/ //
struct _GLFWjoystick struct _GLFWjoystick
{ {
GLFWbool present; GLFWbool present;
@ -514,6 +483,7 @@ struct _GLFWjoystick
unsigned char* hats; unsigned char* hats;
int hatCount; int hatCount;
char* name; char* name;
void* userPointer;
char guid[33]; char guid[33];
_GLFWmapping* mapping; _GLFWmapping* mapping;
@ -521,24 +491,24 @@ struct _GLFWjoystick
_GLFW_PLATFORM_JOYSTICK_STATE; _GLFW_PLATFORM_JOYSTICK_STATE;
}; };
/*! @brief Thread local storage structure. // Thread local storage structure
*/ //
struct _GLFWtls struct _GLFWtls
{ {
// This is defined in the platform's thread.h // This is defined in the platform's thread.h
_GLFW_PLATFORM_TLS_STATE; _GLFW_PLATFORM_TLS_STATE;
}; };
/*! @brief Mutex structure. // Mutex structure
*/ //
struct _GLFWmutex struct _GLFWmutex
{ {
// This is defined in the platform's thread.h // This is defined in the platform's thread.h
_GLFW_PLATFORM_MUTEX_STATE; _GLFW_PLATFORM_MUTEX_STATE;
}; };
/*! @brief Library global data. // Library global data
*/ //
struct _GLFWlibrary struct _GLFWlibrary
{ {
GLFWbool initialized; GLFWbool initialized;
@ -612,21 +582,14 @@ struct _GLFWlibrary
_GLFW_OSMESA_LIBRARY_CONTEXT_STATE; _GLFW_OSMESA_LIBRARY_CONTEXT_STATE;
}; };
//========================================================================
// Global state shared between compilation units of GLFW // Global state shared between compilation units of GLFW
//======================================================================== //
/*! @brief All global data shared between compilation units.
*/
extern _GLFWlibrary _glfw; extern _GLFWlibrary _glfw;
//======================================================================== //////////////////////////////////////////////////////////////////////////
// Platform API functions ////// GLFW platform API //////
//======================================================================== //////////////////////////////////////////////////////////////////////////
/*! @addtogroup platform @{ */
int _glfwPlatformInit(void); int _glfwPlatformInit(void);
void _glfwPlatformTerminate(void); void _glfwPlatformTerminate(void);
@ -635,7 +598,8 @@ const char* _glfwPlatformGetVersionString(void);
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos); void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos);
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos); void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos);
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode); void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
int _glfwPlatformCreateCursor(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot); int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
const GLFWimage* image, int xhot, int yhot);
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape); int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape);
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor); void _glfwPlatformDestroyCursor(_GLFWcursor* cursor);
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor); void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
@ -643,8 +607,10 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
const char* _glfwPlatformGetScancodeName(int scancode); const char* _glfwPlatformGetScancodeName(int scancode);
int _glfwPlatformGetKeyScancode(int key); int _glfwPlatformGetKeyScancode(int key);
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor);
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos); void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, float* xscale, float* yscale); void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
float* xscale, float* yscale);
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count); GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode); void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp); void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
@ -665,16 +631,22 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
const _GLFWfbconfig* fbconfig); const _GLFWfbconfig* fbconfig);
void _glfwPlatformDestroyWindow(_GLFWwindow* window); void _glfwPlatformDestroyWindow(_GLFWwindow* window);
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title); void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title);
void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count, const GLFWimage* images); void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
int count, const GLFWimage* images);
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos); void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos);
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos); void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos);
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height); void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height);
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height); void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height);
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
int minwidth, int minheight,
int maxwidth, int maxheight);
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom); void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height); void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, int* left, int* top, int* right, int* bottom); void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, float* xscale, float* yscale); int* left, int* top,
int* right, int* bottom);
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
float* xscale, float* yscale);
void _glfwPlatformIconifyWindow(_GLFWwindow* window); void _glfwPlatformIconifyWindow(_GLFWwindow* window);
void _glfwPlatformRestoreWindow(_GLFWwindow* window); void _glfwPlatformRestoreWindow(_GLFWwindow* window);
void _glfwPlatformMaximizeWindow(_GLFWwindow* window); void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
@ -682,11 +654,14 @@ void _glfwPlatformShowWindow(_GLFWwindow* window);
void _glfwPlatformHideWindow(_GLFWwindow* window); void _glfwPlatformHideWindow(_GLFWwindow* window);
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window); void _glfwPlatformRequestWindowAttention(_GLFWwindow* window);
void _glfwPlatformFocusWindow(_GLFWwindow* window); void _glfwPlatformFocusWindow(_GLFWwindow* window);
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor,
int xpos, int ypos, int width, int height,
int refreshRate);
int _glfwPlatformWindowFocused(_GLFWwindow* window); int _glfwPlatformWindowFocused(_GLFWwindow* window);
int _glfwPlatformWindowIconified(_GLFWwindow* window); int _glfwPlatformWindowIconified(_GLFWwindow* window);
int _glfwPlatformWindowVisible(_GLFWwindow* window); int _glfwPlatformWindowVisible(_GLFWwindow* window);
int _glfwPlatformWindowMaximized(_GLFWwindow* window); int _glfwPlatformWindowMaximized(_GLFWwindow* window);
int _glfwPlatformWindowHovered(_GLFWwindow* window);
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window); int _glfwPlatformFramebufferTransparent(_GLFWwindow* window);
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window); float _glfwPlatformGetWindowOpacity(_GLFWwindow* window);
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
@ -700,8 +675,13 @@ void _glfwPlatformWaitEventsTimeout(double timeout);
void _glfwPlatformPostEmptyEvent(void); void _glfwPlatformPostEmptyEvent(void);
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions); void _glfwPlatformGetRequiredInstanceExtensions(char** extensions);
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); VkPhysicalDevice device,
uint32_t queuefamily);
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
_GLFWwindow* window,
const VkAllocationCallbacks* allocator,
VkSurfaceKHR* surface);
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls); GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls);
void _glfwPlatformDestroyTls(_GLFWtls* tls); void _glfwPlatformDestroyTls(_GLFWtls* tls);
@ -713,307 +693,79 @@ void _glfwPlatformDestroyMutex(_GLFWmutex* mutex);
void _glfwPlatformLockMutex(_GLFWmutex* mutex); void _glfwPlatformLockMutex(_GLFWmutex* mutex);
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex); void _glfwPlatformUnlockMutex(_GLFWmutex* mutex);
/*! @} */
//////////////////////////////////////////////////////////////////////////
////// GLFW event API //////
//////////////////////////////////////////////////////////////////////////
//========================================================================
// Event API functions
//========================================================================
/*! @brief Notifies shared code that a window has lost or received input focus.
* @param[in] window The window that received the event.
* @param[in] focused `GLFW_TRUE` if the window received focus, or `GLFW_FALSE`
* if it lost focus.
* @ingroup event
*/
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused); void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused);
/*! @brief Notifies shared code that a window has moved.
* @param[in] window The window that received the event.
* @param[in] xpos The new x-coordinate of the client area of the window.
* @param[in] ypos The new y-coordinate of the client area of the window.
* @ingroup event
*/
void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos); void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos);
/*! @brief Notifies shared code that a window has been resized.
* @param[in] window The window that received the event.
* @param[in] width The new width of the client area of the window.
* @param[in] height The new height of the client area of the window.
* @ingroup event
*/
void _glfwInputWindowSize(_GLFWwindow* window, int width, int height); void _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
/*! @brief Notifies shared code that a window framebuffer has been resized.
* @param[in] window The window that received the event.
* @param[in] width The new width, in pixels, of the framebuffer.
* @param[in] height The new height, in pixels, of the framebuffer.
* @ingroup event
*/
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height); void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
void _glfwInputWindowContentScale(_GLFWwindow* window,
/*! @brief Notifies shared code that a window has been iconified or restored. float xscale, float yscale);
* @param[in] window The window that received the event.
* @param[in] iconified `GLFW_TRUE` if the window was iconified, or
* `GLFW_FALSE` if it was restored.
* @ingroup event
*/
void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified); void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified);
/*! @brief Notifies shared code that a window has been maximized or restored.
* @param[in] window The window that received the event.
* @param[in] maximized `GLFW_TRUE` if the window was maximized, or
* `GLFW_FALSE` if it was restored.
* @ingroup event
*/
void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized); void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized);
/*! @brief Notifies shared code that a window's contents needs updating.
* @param[in] window The window that received the event.
*/
void _glfwInputWindowDamage(_GLFWwindow* window); void _glfwInputWindowDamage(_GLFWwindow* window);
/*! @brief Notifies shared code that the user wishes to close a window.
* @param[in] window The window that received the event.
* @ingroup event
*/
void _glfwInputWindowCloseRequest(_GLFWwindow* window); void _glfwInputWindowCloseRequest(_GLFWwindow* window);
/*! @brief Notifies shared code that a window has changed its desired monitor.
* @param[in] window The window that received the event.
* @param[in] monitor The new desired monitor, or `NULL`.
* @ingroup event
*/
void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor); void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
/*! @brief Notifies shared code of a physical key event. void _glfwInputKey(_GLFWwindow* window,
* @param[in] window The window that received the event. int key, int scancode, int action, int mods);
* @param[in] key The key that was pressed or released. void _glfwInputChar(_GLFWwindow* window,
* @param[in] scancode The system-specific scan code of the key. unsigned int codepoint, int mods, GLFWbool plain);
* @param[in] action @ref GLFW_PRESS or @ref GLFW_RELEASE.
* @param[in] mods The modifiers pressed when the event was generated.
* @ingroup event
*/
void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods);
/*! @brief Notifies shared code of a Unicode character input event.
* @param[in] window The window that received the event.
* @param[in] codepoint The Unicode code point of the input character.
* @param[in] mods Bit field describing which modifier keys were held down.
* @param[in] plain `GLFW_TRUE` if the character is regular text input, or
* `GLFW_FALSE` otherwise.
* @ingroup event
*/
void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain);
/*! @brief Notifies shared code of a scroll event.
* @param[in] window The window that received the event.
* @param[in] xoffset The scroll offset along the x-axis.
* @param[in] yoffset The scroll offset along the y-axis.
* @ingroup event
*/
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset); void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset);
/*! @brief Notifies shared code of a mouse button click event.
* @param[in] window The window that received the event.
* @param[in] button The button that was pressed or released.
* @param[in] action @ref GLFW_PRESS or @ref GLFW_RELEASE.
* @param[in] mods The modifiers pressed when the event was generated.
* @ingroup event
*/
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods); void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
/*! @brief Notifies shared code of a cursor motion event.
* @param[in] window The window that received the event.
* @param[in] xpos The new x-coordinate of the cursor, relative to the left
* edge of the client area of the window.
* @param[in] ypos The new y-coordinate of the cursor, relative to the top edge
* of the client area of the window.
* @ingroup event
*/
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos); void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
/*! @brief Notifies shared code of a cursor enter/leave event.
* @param[in] window The window that received the event.
* @param[in] entered `GLFW_TRUE` if the cursor entered the client area of the
* window, or `GLFW_FALSE` if it left it.
* @ingroup event
*/
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered); void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered);
void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
void _glfwInputJoystick(_GLFWjoystick* js, int event);
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value);
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value);
void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value);
/*! @brief Notifies shared code of a monitor connection or disconnection.
* @param[in] monitor The monitor that was connected or disconnected.
* @param[in] action One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
* @param[in] placement `_GLFW_INSERT_FIRST` or `_GLFW_INSERT_LAST`.
* @ingroup event
*/
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement); void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement);
/*! @brief Notifies shared code that a full screen window has acquired or
* released a monitor.
* @param[in] monitor The monitor that was acquired or released.
* @param[in] window The window that acquired the monitor, or `NULL`.
* @ingroup event
*/
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window); void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window);
/*! @brief Notifies shared code of an error.
* @param[in] code The error code most suitable for the error.
* @param[in] format The `printf` style format string of the error
* description.
* @ingroup event
*/
#if defined(__GNUC__) #if defined(__GNUC__)
void _glfwInputError(int code, const char* format, ...) __attribute__((format(printf, 2, 3))); void _glfwInputError(int code, const char* format, ...)
__attribute__((format(printf, 2, 3)));
#else #else
void _glfwInputError(int code, const char* format, ...); void _glfwInputError(int code, const char* format, ...);
#endif #endif
/*! @brief Notifies shared code of files or directories dropped on a window.
* @param[in] window The window that received the event.
* @param[in] count The number of dropped objects.
* @param[in] names The names of the dropped objects.
* @ingroup event
*/
void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
/*! @brief Notifies shared code of a joystick connection or disconnection. //////////////////////////////////////////////////////////////////////////
* @param[in] js The joystick that was connected or disconnected. ////// GLFW internal API //////
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. //////////////////////////////////////////////////////////////////////////
* @ingroup event
*/
void _glfwInputJoystick(_GLFWjoystick* js, int event);
/*! @brief Notifies shared code of the new value of a joystick axis.
* @param[in] js The joystick whose axis to update.
* @param[in] axis The index of the axis to update.
* @param[in] value The new value of the axis.
*/
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value);
/*! @brief Notifies shared code of the new value of a joystick button.
* @param[in] js The joystick whose button to update.
* @param[in] button The index of the button to update.
* @param[in] value The new value of the button.
*/
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value);
/*! @brief Notifies shared code of the new value of a joystick hat.
* @param[in] js The joystick whose hat to update.
* @param[in] button The index of the hat to update.
* @param[in] value The new value of the hat.
*/
void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value);
//========================================================================
// Utility functions
//========================================================================
/*! @brief Chooses the video mode most closely matching the desired one.
* @ingroup utility
*/
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
const GLFWvidmode* desired);
/*! @brief Performs lexical comparison between two @ref GLFWvidmode structures.
* @ingroup utility
*/
int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second);
/*! @brief Splits a color depth into red, green and blue bit depths.
* @ingroup utility
*/
void _glfwSplitBPP(int bpp, int* red, int* green, int* blue);
/*! @brief Searches an extension string for the specified extension.
* @param[in] string The extension string to search.
* @param[in] extensions The extension to search for.
* @return `GLFW_TRUE` if the extension was found, or `GLFW_FALSE` otherwise.
* @ingroup utility
*/
GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions); GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions);
/*! @brief Chooses the framebuffer config that best matches the desired one.
* @param[in] desired The desired framebuffer config.
* @param[in] alternatives The framebuffer configs supported by the system.
* @param[in] count The number of entries in the alternatives array.
* @return The framebuffer config most closely matching the desired one, or @c
* NULL if none fulfilled the hard constraints of the desired values.
* @ingroup utility
*/
const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired, const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
const _GLFWfbconfig* alternatives, const _GLFWfbconfig* alternatives,
unsigned int count); unsigned int count);
GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
/*! @brief Retrieves the attributes of the current context. const _GLFWctxconfig* ctxconfig);
* @param[in] ctxconfig The desired context attributes.
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if the context is
* unusable.
* @ingroup utility
*/
GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig);
/*! @brief Checks whether the desired context attributes are valid.
* @param[in] ctxconfig The context attributes to check.
* @return `GLFW_TRUE` if the context attributes are valid, or `GLFW_FALSE`
* otherwise.
* @ingroup utility
*
* This function checks things like whether the specified client API version
* exists and whether all relevant options have supported and non-conflicting
* values.
*/
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig); GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig);
/*! @brief Allocates red, green and blue value arrays of the specified size. const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
* @ingroup utility const GLFWvidmode* desired);
*/ int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second);
void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size);
/*! @brief Frees the red, green and blue value arrays and clears the struct.
* @ingroup utility
*/
void _glfwFreeGammaArrays(GLFWgammaramp* ramp);
/*! @brief Allocates and returns a monitor object with the specified name
* and dimensions.
* @param[in] name The name of the monitor.
* @param[in] widthMM The width, in mm, of the monitor's display area.
* @param[in] heightMM The height, in mm, of the monitor's display area.
* @return The newly created object.
* @ingroup utility
*/
_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM); _GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM);
/*! @brief Frees a monitor object and any data associated with it.
* @ingroup utility
*/
void _glfwFreeMonitor(_GLFWmonitor* monitor); void _glfwFreeMonitor(_GLFWmonitor* monitor);
void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size);
void _glfwFreeGammaArrays(GLFWgammaramp* ramp);
void _glfwSplitBPP(int bpp, int* red, int* green, int* blue);
/*! @brief Returns an available joystick object with arrays and name allocated.
* @ingroup utility
*/
_GLFWjoystick* _glfwAllocJoystick(const char* name, _GLFWjoystick* _glfwAllocJoystick(const char* name,
const char* guid, const char* guid,
int axisCount, int axisCount,
int buttonCount, int buttonCount,
int hatCount); int hatCount);
/*! @brief Frees arrays and name and flags the joystick object as unused.
* @ingroup utility
*/
void _glfwFreeJoystick(_GLFWjoystick* js); void _glfwFreeJoystick(_GLFWjoystick* js);
/*! @ingroup utility
*/
GLFWbool _glfwInitVulkan(int mode); GLFWbool _glfwInitVulkan(int mode);
/*! @ingroup utility
*/
void _glfwTerminateVulkan(void); void _glfwTerminateVulkan(void);
/*! @ingroup utility
*/
const char* _glfwGetVulkanResultString(VkResult result); const char* _glfwGetVulkanResultString(VkResult result);
char* _glfw_strdup(const char* source);

View file

@ -38,7 +38,8 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#ifndef SYN_DROPPED // < 2.6.39 kernel headers #ifndef SYN_DROPPED // < v2.6.39 kernel headers
// Workaround for CentOS-6, which is supported till 2020-11-30, but still on v2.6.32
#define SYN_DROPPED 3 #define SYN_DROPPED 3
#endif #endif

View file

@ -51,7 +51,7 @@
// 1. The origin of this software must not be misrepresented; you must not // 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software // claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would // in a product, an acknowledgment in the product documentation would
// be appreciated but is not required. // be appreciated but is not required.
// //
// 2. Altered source versions must be plainly marked as such, and must not be // 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software. // misrepresented as being the original software.
@ -60,243 +60,411 @@
const char* _glfwDefaultMappings[] = const char* _glfwDefaultMappings[] =
{ {
"02200090000000000000504944564944,8Bitdo NES30 PRO USB,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,",
"20380900000000000000504944564944,8Bitdo NES30 PRO Wireless,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "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,",
"10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,y:b3,x:b4,start:b11,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,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,",
"8f0e1200000000000000504944564944,Acme,platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", "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,",
"341a3608000000000000504944564944,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,", "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,",
"c0111352000000000000504944564944,Battalife Joystick,platform:Windows,x:b4,a:b6,b:b7,y:b5,back:b2,start:b3,leftshoulder:b0,rightshoulder:b1,leftx:a0,lefty:a1,", "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,",
"d81d0b00000000000000504944564944,BUFFALO BSGP1601 Series ,platform:Windows,x:b4,a:b5,b:b3,y:b2,back:b12,start:b13,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b6,rightshoulder:b9,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "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,",
"5e048e02000000000000504944564944,Controller (XBOX 360 For Windows),platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,righttrigger:a2,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"4f0423b3000000000000504944564944,Dual Trigger 3-in-1,a:b1,b:b2,x:b0,y:b3,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:a5,lefttrigger:b6,righttrigger:b7,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,",
"341a0108000000000000504944564944,EXEQ RF USB Gamepad 8206,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,leftstick:b8,rightstick:b7,back:b8,start:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,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,",
"0d0f8500000000000000504944564944,Fighting Commander 2016 PS3,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,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,",
"0d0f5f00000000000000504944564944,Fighting Commander 4,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,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,",
"0d0f5e00000000000000504944564944,Fighting Commander 4,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b5,rightshoulder:b4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a4,righttrigger:a3,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,",
"0d0f8400000000000000504944564944,Fighting Commander 5,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:a5,lefttrigger:b6,righttrigger:b7,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,",
"0d0f8700000000000000504944564944,Fighting Stick mini 4,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,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,",
"0d0f8800000000000000504944564944,Fighting Stick mini 4,a:b1,b:b2,x:b0,y:b3,back:b9,guide:b12,start:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,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,",
"0d0f2700000000000000504944564944,FIGHTING STICK V3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,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,",
"79000600000000000000504944564944,G-Shark GS-GP702,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:a4,lefttrigger:b6,righttrigger:b7,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,",
"28040140000000000000504944564944,GamePad Pro USB,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,", "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,",
"ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,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,", "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,",
"6d0416c2000000000000504944564944,Generic DirectInput 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: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,",
"45130010000000000000504944564944,Generic USB Joystick,a:b0,b:b1,x:b2,y:b3,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: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,",
"0d0f4900000000000000504944564944,Hatsune Miku Sho Controller,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,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,",
"d8140862000000000000504944564944,HitBox Edition Cthulhu+,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b5,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b4,righttrigger:b6,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,",
"0d0f4000000000000000504944564944,Hori Fighting Stick Mini 3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b5,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b4,righttrigger:b6,platform:Windows,", "03000000790000000600000000000000,G-Shark GS-GP702,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,",
"0d0f6e00000000000000504944564944,HORIPAD 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,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,",
"0d0f4d00000000000000504944564944,HORIPAD3 A,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,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,",
"25090017000000000000504944564944,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b5,rightshoulder:b7,leftx:a0,lefty:a1,lefttrigger:b4,righttrigger:b6,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,",
"d81d0f00000000000000504944564944,iBUFFALO BSGP1204 Series,platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "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,",
"d81d1000000000000000504944564944,iBUFFALO BSGP1204P Series,platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "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,",
"83056020000000000000504944564944,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,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,",
"6f0e2401000000000000504944564944,INJUSTICE FightStick for PS3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,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,",
"49190204000000000000504944564944,Ipega PG-9023,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,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,",
"6d0419c2000000000000504944564944,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,", "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,",
"6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "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,",
"38075032000000000000504944564944,Mad Catz FightPad PRO PS3,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "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,",
"38075082000000000000504944564944,Mad Catz FightPad PRO PS4,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b13,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,", "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,",
"38078433000000000000504944564944,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,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,",
"38078483000000000000504944564944,Mad Catz FightStick TE S+ PS4,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:a5,lefttrigger:a3,righttrigger:b6,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,",
"38078134000000000000504944564944,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b7,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:b4,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,",
"38078184000000000000504944564944,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b5,rightshoulder:b4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a4,righttrigger:b7,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,",
"38078034000000000000504944564944,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,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: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,",
"38078084000000000000504944564944,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,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,",
"38078532000000000000504944564944,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,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: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,",
"38073888000000000000504944564944,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,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: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,",
"38071888000000000000504944564944,MadCatz SFIV FightStick PS3,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b5,rightshoulder:b4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b7,righttrigger:b6,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,",
"03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,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,",
"25090128000000000000504944564944,Mayflash Arcade Stick,a:b1,b:b2,x:b5,y:b6,back:b8,start:b9,leftshoulder:b0,rightshoulder:b3,leftx:a0,lefty:a1,rightx:h0.4,righty:h0.0,lefttrigger:b4,righttrigger:b7,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,",
"79004318000000000000504944564944,Mayflash GameCube Controller Adapter,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b0,start:b9,guide:b0,leftshoulder:b4,rightshoulder:b7,leftstick:b0,rightstick:b0,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,", "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,",
"8f0e1030000000000000504944564944,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,x:b3,y:b4,start:b9,leftshoulder:b6,rightshoulder:b2,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b5,righttrigger:b7,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,",
"2509e803000000000000504944564944,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,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,",
"79000018000000000000504944564944,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,x:b0,y:b3,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: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,",
"8f0e0d31000000000000504944564944,Multilaser JS071 USB,platform:Windows,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", "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,",
"100801e5000000000000504944564944,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,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,",
"bd1215d0000000000000504944564944,Nintendo Retrolink USB Super SNES Classic Controller,y:b0,b:b1,a:b2,x:b3,leftshoulder:b4,rightshoulder:b5,start:b9,back:b8,leftx:a0,lefty:a1,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,",
"4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftstick:a0,rightstick:a2,leftshoulder:a3,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:h0.6,lefty:h0.12,rightx:h0.9,righty:h0.4,lefttrigger:b6,righttrigger:b7,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,",
"36280100000000000000504944564944,OUYA Controller,platform:Windows,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13,", "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,",
"120cf60e000000000000504944564944,P4 Wired Gamepad,a:b1,b:b2,x:b0,y:b3,back:b12,guide:b8,start:b9,leftshoulder:b5,rightshoulder:b4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:h0.0,lefttrigger:b7,righttrigger:b6,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,",
"8f0e0300000000000000504944564944,Piranha xtreme,platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", "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,",
"d6206dca000000000000504944564944,PowerA Pro Ex,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.0,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,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,",
"10080100000000000000504944564944,PS1 USB,platform:Windows,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,", "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,",
"10080300000000000000504944564944,PS2 USB,platform:Windows,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5,", "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,",
"88880803000000000000504944564944,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,", "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,",
"4c056802000000000000504944564944,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,", "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,",
"25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,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,", "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,",
"10008200000000000000504944564944,PS360+ v1.66,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:h0.4,lefttrigger:b6,righttrigger:b7,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,",
"4c05c405000000000000504944564944,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,", "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,",
"300f0011000000000000504944564944,QanBa Arcade JoyStick 1008,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,start:b10,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,", "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,",
"300f1611000000000000504944564944,QanBa Arcade JoyStick 4018,a:b1,b:b2,x:b0,y:b3,back:b10,guide:b9,start:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,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,",
"222c0020000000000000504944564944,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:a3,righttrigger:a4,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,",
"300f1210000000000000504944564944,QanBa Joystick Plus,a:b0,b:b1,x:b2,y:b3,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,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,",
"341a0104000000000000504944564944,QanBa Joystick Q4RAF,a:b5,b:b6,x:b1,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b0,rightshoulder:b3,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,lefttrigger:b4,righttrigger:b7,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,",
"222c0223000000000000504944564944,Qanba Obsidian Arcade Joystick PS3 Mode,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,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,",
"222c0023000000000000504944564944,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,x:b0,y:b3,back:b13,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:a5,lefttrigger:a3,righttrigger:a4,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,",
"0d0f1100000000000000504944564944,REAL ARCADE PRO.3,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,lefttrigger:b6,righttrigger:b7,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,",
"0d0f8b00000000000000504944564944,Real Arcade Pro.4,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "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,",
"0d0f8a00000000000000504944564944,Real Arcade Pro.4,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,", "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,",
"0d0f6b00000000000000504944564944,Real Arcade Pro.4,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "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,",
"0d0f6a00000000000000504944564944,Real Arcade Pro.4,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,", "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,",
"0d0f7000000000000000504944564944,REAL ARCADE PRO.4 VLX,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,lefttrigger:b6,righttrigger:b7,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,",
"0d0f2200000000000000504944564944,REAL ARCADE Pro.V3,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "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,",
"00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,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,",
"00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,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,",
"6f0e1e01000000000000504944564944,Rock Candy Gamepad for PS3,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,", "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,",
"300f1201000000000000504944564944,Saitek Dual Analog Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,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,",
"a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,y:b1,x:b0,start:b4,guide:b10,back:b5,leftstick:b8,rightstick:b9,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,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,",
"300f1001000000000000504944564944,Saitek P480 Rumble Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,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,",
"9b280500000000000000504944564944,Saturn_Adapter_2.0,a:b1,b:b2,x:b0,y:b3,start:b9,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,lefttrigger:b4,righttrigger:b5,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,",
"79001100000000000000504944564944,Sega Saturn Gamepad,a:b1,b:b2,x:b4,y:b5,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a4,lefttrigger:b3,righttrigger:b0,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,",
"4c05cc09000000000000504944564944,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,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,",
"4c05a00b000000000000504944564944,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,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,",
"ff113133000000000000504944564944,SVEN X-PAD,platform:Windows,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9,", "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,",
"4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,platform:Windows,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "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,",
"4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Windows,", "03000000300f00001210000000000000,QanBa Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,",
"66660488000000000000504944564944,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:b12,dpdown:b14,dpleft:b15,dpright:b13,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,platform:Windows,", "03000000341a00000104000000000000,QanBa Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows,",
"38076652000000000000504944564944,UnKnown,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"63252305000000000000504944564944,USB Vibration Joystick (BM),platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "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,",
"79001b18000000000000504944564944,Venom Arcade Joystick,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,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,",
"10280000000000000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,", "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,",
"79000000000000000600000000000000,G-Shark GP-702,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:a3,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,", "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,",
"AD1B00000000000001F9000000000000,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,", "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,",
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,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,", "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,",
"0d0f0000000000004d00000000000000,HORI Gem Pad 3,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", "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,",
"0d0f0000000000006600000000000000,HORIPAD FPS PLUS 4,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:a4,", "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,",
"83050000000000006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X,", "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,",
"6d0400000000000016c2000000000000,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,", "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,",
"6d0400000000000018c2000000000000,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,", "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,",
"6d040000000000001fc2000000000000,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,", "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,",
"6d0400000000000019c2000000000000,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,", "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,",
"2509000000000000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,", "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,",
"79000000000000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,x:b0,y:b12,back:b32,start:b36,leftstick:b40,rightstick:b44,leftshoulder:b16,rightshoulder:b20,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a4,rightx:a8,righty:a12,lefttrigger:b24,righttrigger:b28,platform:Mac OS X,", "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,",
"d814000000000000cecf000000000000,MC Cthulhu,platform:Mac OS X,leftx:,lefty:,rightx:,righty:,lefttrigger:b6,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,righttrigger:b7,", "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,",
"8f0e0000000000000300000000000000,Piranha xtreme,platform:Mac OS X,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", "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,",
"4c050000000000006802000000000000,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,", "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,",
"4c05000000000000c405000000000000,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,", "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,",
"891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Mac OS X,", "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,",
"79000000000000001100000000000000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a3,lefty:a4,platform:Mac OS X,", "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,",
"81170000000000007e05000000000000,Sega Saturn,x:b0,a:b2,b:b4,y:b6,start:b13,dpleft:b15,dpdown:b16,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,lefttrigger:b10,rightshoulder:b9,righttrigger:a4,righttrigger:b11,leftx:a0,lefty:a2,platform:Mac OS X,", "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,",
"b4040000000000000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,x:b3,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,", "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,",
"351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,", "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,",
"4c05000000000000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X,", "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,",
"4c05000000000000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X,", "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,",
"4f0400000000000015b3000000000000,Thrustmaster Dual Analog 3.2,platform:Mac OS X,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "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,",
"4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Mac OS X,", "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,",
"bd1200000000000015d0000000000000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X,", "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,",
"10080000000000000100000000000000,Twin USB Joystick,a:b4,b:b2,x:b6,y:b0,back:b16,start:b18,leftstick:b20,rightstick:b22,leftshoulder:b12,rightshoulder:b14,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a2,rightx:a6,righty:a4,lefttrigger:b8,righttrigger:b10,platform:Mac OS X,", "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,",
"050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,y:b9,x:b10,start:b6,guide:b8,back:b7,dpup:b2,dpleft:b0,dpdown:b3,dpright:b1,leftx:a0,lefty:a1,lefttrigger:b12,righttrigger:,leftshoulder:b11,platform:Mac OS X,", "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,",
"050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,x:b18,y:b17,back:b7,guide:b8,start:b6,leftstick:b23,rightstick:b24,leftshoulder:b19,rightshoulder:b20,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b21,righttrigger:b22,platform:Mac OS X,", "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,",
"5e040000000000008e02000000000000,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,", "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,",
"5e04000000000000dd02000000000000,Xbox One Wired Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"5e04000000000000ea02000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"5e04000000000000e002000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b10,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"05000000102800000900000000010000,8Bitdo SFC30 GamePad,platform:Linux,x:b4,a:b1,b:b0,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", "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,",
"05000000a00500003232000001000000,8Bitdo Zero GamePad,platform:Linux,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", "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,",
"030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux,", "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,",
"03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"030000006f0e00003001000001010000,EA Sports PS3 Controller,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", "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,",
"03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,y:b3,x:b0,start:b9,guide:,back:,leftstick:,rightstick:,leftshoulder:,dpleft:b15,dpdown:b14,dpright:b13,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,rightshoulder:b7,dpup:b12,platform:Linux,", "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,",
"03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Linux,", "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,",
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,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,", "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,",
"030000006f0e00001f01000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"030000006f0e00001304000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:a0,rightstick:a3,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "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,",
"03000000280400000140000000010000,Gravis GamePad Pro USB ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,", "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,",
"030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", "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,",
"030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", "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,",
"03000000ff1100004133000010010000,GreenAsia Inc.USB Joystick,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", "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,",
"06000000adde0000efbe000002010000,Hidromancer Game Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "03000000790000000600000000000000,G-Shark GP-702,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:Mac OS X,",
"03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,leftx:a0,lefty:a1,", "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,",
"03000000c9110000f055000011010000,HJC Game GAMEPAD,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:h0.8,lefttrigger:b6,x:b2,dpup:h0.1,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:h0.2,righttrigger:b7,b:b1,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:Mac OS X,",
"030000000d0f00000d00000000010000,hori,platform:Linux,a:b0,b:b6,y:b2,x:b1,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,start:b9,guide:b10,back:b8,leftshoulder:b3,rightshoulder:b7,leftx:b4,lefty:b5,", "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,",
"030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7", "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,",
"030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,", "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,",
"03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,", "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,",
"03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux,", "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,",
"03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),platform:Linux,a:b3,b:b4,y:b1,x:b0,start:b7,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,", "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,",
"030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,platform:Linux,x:b0,a:b2,b:b3,y:b1,back:b10,guide:b12,start:b11,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "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,",
"03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,platform:Linux,x:b0,a:b2,b:b3,y:b1,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", "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,",
"03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,", "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,",
"030000006f0e00000103000000020000,Logic3 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,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,", "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,",
"030000006d04000016c2000011010000,Logitech F310 Gamepad (DInput),x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux,", "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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,", "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,",
"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,", "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,", "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,", "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,",
"030000006d04000016c2000010010000,Logitech Logitech Dual Action,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "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,",
"030000006d04000018c2000010010000,Logitech Logitech RumblePad 2 USB,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "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,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,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,",
"05000000380700006652000025010000,Mad Catz C.T.R.L.R ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "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,",
"03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,lefttrigger:a2,righttrigger:a5,", "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,",
"03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,", "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,",
"03000000780000000600000010010000,Microntek USB Joystick,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftx:a0,lefty:a1,", "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,",
"030000005e0400008e02000004010000,Microsoft X-Box 360 pad,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,", "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,",
"030000005e0400008e02000062230000,Microsoft X-Box 360 pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"030000005e040000d102000001010000,Microsoft X-Box One pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"030000005e040000dd02000003020000,Microsoft X-Box One pad v2,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,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,",
"030000005e0400008502000000010000,Microsoft X-Box pad (Japan),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"05000000d6200000ad0d000001000000,Moga Pro,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,", "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,",
"030000001008000001e5000010010000,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,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,",
"050000007e0500003003000001000000,Nintendo Wii U Pro Controller,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b8,start:b9,guide:b10,leftshoulder:b4,rightshoulder:b5,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:b13,dpleft:b15,dpdown:b14,dpright:b16,", "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,",
"05000000010000000100000003000000,Nintendo Wiimote,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b9,guide:b10,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", "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,",
"03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,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,",
"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,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,", "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,",
"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,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,", "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,",
"03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,", "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,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,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,",
"050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,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,",
"05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,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,",
"030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,platform:Linux,x:b1,a:b0,b:b4,y:b5,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", "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,",
"030000008916000001fd000024010000,Razer Onza Classic Edition,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,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,",
"03000000790000001100000010010000,RetroLink Saturn Classic Controller,platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", "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,",
"0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,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,",
"0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,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,",
"030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,", "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,",
"030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,platform:Linux,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,guide:b8,leftstick:b9,rightstick:b10,lefttrigger:a2,righttrigger:a5,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,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,",
"03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,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,",
"03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,y:b1,x:b0,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b6,righttrigger:b7,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,",
"03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,platform:Linux,a:b12,b:b10,x:b13,y:b11,back:b4,start:b5,leftstick:b14,rightstick:b15,leftshoulder:b9,rightshoulder:b8,dpup:b0,dpdown:b2,dpleft:b3,dpright:b1,leftx:a1,lefty:a0,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", "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,",
"030000004c050000c405000011810000,Sony DualShock 4,a:b0,b:b1,y:b2,x:b3,start:b9,guide:b10,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,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,",
"030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,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,",
"050000004c050000cc09000000810000,Sony DualShock 4 (CUH-ZCT2U) (Bluetooth),platform:Linux,a:b0,b:b1,y:b2,x:b3,leftshoulder:b4,rightshoulder:b5,back:b8,start:b9,guide:b10,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,lefttrigger:a2,rightx:a3,righty:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "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,",
"030000004c050000cc09000011810000,Sony DualShock 4 (CUH-ZCT2U) (USB),platform:Linux,a:b0,b:b1,y:b2,x:b3,leftshoulder:b4,rightshoulder:b5,back:b8,start:b9,guide:b10,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,lefttrigger:a2,rightx:a3,righty:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "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,",
"050000004c050000c405000000010000,Sony DualShock 4 BT,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: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,",
"030000004c050000cc09000011010000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,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,",
"050000004c050000cc09000000010000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,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,",
"030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,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,",
"03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,platform:Linux,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,", "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,",
"030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "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,",
"03000000666600000488000000010000,Super Joy Box 5 Pro,platform:Linux,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13,", "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,",
"030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,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,",
"030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,platform:Linux,a:b0,b:b2,x:b1,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,", "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,",
"030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,", "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,",
"030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,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,",
"030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,", "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,",
"030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", "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,",
"03000000bd12000015d0000010010000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,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,",
"03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,platform:Linux,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,", "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,",
"03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,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,",
"03000000100800000300000010010000,USB Gamepad,platform:Linux,a:b2,b:b1,x:b3,y:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,", "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,",
"03000000de280000ff11000001000000,Valve Streaming 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,", "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,",
"05000000ac0500003232000001000000,VR-BOX,platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,", "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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"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,",
"03000000790000001100000000010000,USB Gamepad1,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,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,", "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,",
"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,", "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,",
"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,", "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,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,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,",
"030000005e040000a102000000010000,X360 Wireless Controller,platform:Linux,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,", "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,",
"0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b7,back:b6,guide:b8,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,lefttrigger:a5,righttrigger:a4,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "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,",
"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,",
"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,",
"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,", "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,",
"03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,platform:Linux,y:b0,x:b1,b:b3,a:b4,leftshoulder:b2,rightshoulder:b5,back:b6,start:b7,guide:b9,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftx:a0,lefty:a1,", "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,",
"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,",
"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,", "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,", "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,",

View file

@ -51,7 +51,7 @@
// 1. The origin of this software must not be misrepresented; you must not // 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software // claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would // in a product, an acknowledgment in the product documentation would
// be appreciated but is not required. // be appreciated but is not required.
// //
// 2. Altered source versions must be plainly marked as such, and must not be // 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software. // misrepresented as being the original software.

View file

@ -80,6 +80,10 @@ void _glfwPollMonitorsMir(void)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
{
}
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{ {
if (xpos) if (xpos)

View file

@ -627,6 +627,13 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return mir_window_get_state(window->mir.window) == mir_window_state_maximized; return mir_window_get_state(window->mir.window) == mir_window_state_maximized;
} }
int _glfwPlatformWindowHovered(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return GLFW_FALSE;
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,

View file

@ -86,6 +86,8 @@ static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
////// GLFW event API ////// ////// GLFW event API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Notifies shared code of a monitor connection or disconnection
//
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement) void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
{ {
if (action == GLFW_CONNECTED) if (action == GLFW_CONNECTED)
@ -141,6 +143,9 @@ void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
_glfwFreeMonitor(monitor); _glfwFreeMonitor(monitor);
} }
// Notifies shared code that a full screen window has acquired or released
// a monitor
//
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window) void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
{ {
monitor->window = window; monitor->window = window;
@ -151,6 +156,8 @@ void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Allocates and returns a monitor object with the specified name and dimensions
//
_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM) _GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
{ {
_GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor)); _GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor));
@ -158,16 +165,20 @@ _GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
monitor->heightMM = heightMM; monitor->heightMM = heightMM;
if (name) if (name)
monitor->name = strdup(name); monitor->name = _glfw_strdup(name);
return monitor; return monitor;
} }
// Frees a monitor object and any data associated with it
//
void _glfwFreeMonitor(_GLFWmonitor* monitor) void _glfwFreeMonitor(_GLFWmonitor* monitor)
{ {
if (monitor == NULL) if (monitor == NULL)
return; return;
_glfwPlatformFreeMonitor(monitor);
_glfwFreeGammaArrays(&monitor->originalRamp); _glfwFreeGammaArrays(&monitor->originalRamp);
_glfwFreeGammaArrays(&monitor->currentRamp); _glfwFreeGammaArrays(&monitor->currentRamp);
@ -176,6 +187,8 @@ void _glfwFreeMonitor(_GLFWmonitor* monitor)
free(monitor); free(monitor);
} }
// Allocates red, green and blue value arrays of the specified size
//
void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size) void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size)
{ {
ramp->red = calloc(size, sizeof(unsigned short)); ramp->red = calloc(size, sizeof(unsigned short));
@ -184,6 +197,8 @@ void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size)
ramp->size = size; ramp->size = size;
} }
// Frees the red, green and blue value arrays and clears the struct
//
void _glfwFreeGammaArrays(GLFWgammaramp* ramp) void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
{ {
free(ramp->red); free(ramp->red);
@ -193,6 +208,8 @@ void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
memset(ramp, 0, sizeof(GLFWgammaramp)); memset(ramp, 0, sizeof(GLFWgammaramp));
} }
// Chooses the video mode most closely matching the desired one
//
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
const GLFWvidmode* desired) const GLFWvidmode* desired)
{ {
@ -243,11 +260,15 @@ const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
return closest; return closest;
} }
// Performs lexical comparison between two @ref GLFWvidmode structures
//
int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm) int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm)
{ {
return compareVideoModes(fm, sm); return compareVideoModes(fm, sm);
} }
// Splits a color depth into red, green and blue bit depths
//
void _glfwSplitBPP(int bpp, int* red, int* green, int* blue) void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
{ {
int delta; int delta;
@ -351,6 +372,24 @@ GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
return monitor->name; return monitor->name;
} }
GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* handle, void* pointer)
{
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
_GLFW_REQUIRE_INIT();
monitor->userPointer = pointer;
}
GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* handle)
{
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return monitor->userPointer;
}
GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun) GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
@ -406,16 +445,16 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
double value; float value;
// Calculate intensity // Calculate intensity
value = i / 255.0; value = i / 255.f;
// Apply gamma curve // Apply gamma curve
value = pow(value, 1.0 / gamma) * 65535.0 + 0.5; value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
// Clamp to value range // Clamp to value range
if (value > 65535.0) if (value > 65535.f)
value = 65535.0; value = 65535.f;
values[i] = (unsigned short) value; values[i] = (unsigned short) value;
} }

View file

@ -32,6 +32,10 @@
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
{
}
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{ {
} }

View file

@ -165,6 +165,11 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return GLFW_FALSE; return GLFW_FALSE;
} }
int _glfwPlatformWindowHovered(_GLFWwindow* window)
{
return GLFW_FALSE;
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{ {
return GLFW_FALSE; return GLFW_FALSE;

View file

@ -54,7 +54,7 @@ GLFWbool _glfwInitVulkan(int mode)
#elif defined(_GLFW_WIN32) #elif defined(_GLFW_WIN32)
_glfw.vk.handle = _glfw_dlopen("vulkan-1.dll"); _glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
#elif defined(_GLFW_COCOA) #elif defined(_GLFW_COCOA)
_glfw.vk.handle = _glfw_dlopen("libMoltenVK.dylib"); _glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
#else #else
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1"); _glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
#endif #endif
@ -317,6 +317,13 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
return VK_ERROR_EXTENSION_NOT_PRESENT; return VK_ERROR_EXTENSION_NOT_PRESENT;
} }
if (window->context.client != GLFW_NO_API)
{
_glfwInputError(GLFW_INVALID_VALUE,
"Vulkan: Window surface creation requires the window to have the client API set to GLFW_NO_API");
return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
}
return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface); return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface);
} }

View file

@ -329,21 +329,52 @@ static void destroyContextWGL(_GLFWwindow* window)
} }
} }
// Initialize WGL-specific extensions
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Initialize WGL
// //
static void loadWGLExtensions(void) GLFWbool _glfwInitWGL(void)
{ {
PIXELFORMATDESCRIPTOR pfd; PIXELFORMATDESCRIPTOR pfd;
HGLRC rc; HGLRC prc, rc;
HDC dc = GetDC(_glfw.win32.helperWindowHandle);; HDC pdc, dc;
_glfw.wgl.extensionsLoaded = GLFW_TRUE; if (_glfw.wgl.instance)
return GLFW_TRUE;
_glfw.wgl.instance = LoadLibraryA("opengl32.dll");
if (!_glfw.wgl.instance)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to load opengl32.dll");
return GLFW_FALSE;
}
_glfw.wgl.CreateContext = (PFN_wglCreateContext)
GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
_glfw.wgl.DeleteContext = (PFN_wglDeleteContext)
GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
_glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress)
GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
_glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC)
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
_glfw.wgl.GetCurrentContext = (PFN_wglGetCurrentContext)
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentContext");
_glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent)
GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
_glfw.wgl.ShareLists = (PFN_wglShareLists)
GetProcAddress(_glfw.wgl.instance, "wglShareLists");
// NOTE: A dummy context has to be created for opengl32.dll to load the // NOTE: A dummy context has to be created for opengl32.dll to load the
// OpenGL ICD, from which we can then query WGL extensions // OpenGL ICD, from which we can then query WGL extensions
// NOTE: This code will accept the Microsoft GDI ICD; accelerated context // NOTE: This code will accept the Microsoft GDI ICD; accelerated context
// creation failure occurs during manual pixel format enumeration // creation failure occurs during manual pixel format enumeration
dc = GetDC(_glfw.win32.helperWindowHandle);;
ZeroMemory(&pfd, sizeof(pfd)); ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd); pfd.nSize = sizeof(pfd);
pfd.nVersion = 1; pfd.nVersion = 1;
@ -355,7 +386,7 @@ static void loadWGLExtensions(void)
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to set pixel format for dummy context"); "WGL: Failed to set pixel format for dummy context");
return; return GLFW_FALSE;
} }
rc = wglCreateContext(dc); rc = wglCreateContext(dc);
@ -363,15 +394,19 @@ static void loadWGLExtensions(void)
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to create dummy context"); "WGL: Failed to create dummy context");
return; return GLFW_FALSE;
} }
pdc = wglGetCurrentDC();
prc = wglGetCurrentContext();
if (!wglMakeCurrent(dc, rc)) if (!wglMakeCurrent(dc, rc))
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to make dummy context current"); "WGL: Failed to make dummy context current");
wglMakeCurrent(pdc, prc);
wglDeleteContext(rc); wglDeleteContext(rc);
return; return GLFW_FALSE;
} }
// NOTE: Functions must be loaded first as they're needed to retrieve the // NOTE: Functions must be loaded first as they're needed to retrieve the
@ -414,43 +449,8 @@ static void loadWGLExtensions(void)
_glfw.wgl.ARB_context_flush_control = _glfw.wgl.ARB_context_flush_control =
extensionSupportedWGL("WGL_ARB_context_flush_control"); extensionSupportedWGL("WGL_ARB_context_flush_control");
wglMakeCurrent(dc, NULL); wglMakeCurrent(pdc, prc);
wglDeleteContext(rc); wglDeleteContext(rc);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Initialize WGL
//
GLFWbool _glfwInitWGL(void)
{
if (_glfw.wgl.instance)
return GLFW_TRUE;
_glfw.wgl.instance = LoadLibraryA("opengl32.dll");
if (!_glfw.wgl.instance)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to load opengl32.dll");
return GLFW_FALSE;
}
_glfw.wgl.CreateContext = (PFN_wglCreateContext)
GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
_glfw.wgl.DeleteContext = (PFN_wglDeleteContext)
GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
_glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress)
GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
_glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC)
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
_glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent)
GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
_glfw.wgl.ShareLists = (PFN_wglShareLists)
GetProcAddress(_glfw.wgl.instance, "wglShareLists");
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -480,9 +480,6 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
PIXELFORMATDESCRIPTOR pfd; PIXELFORMATDESCRIPTOR pfd;
HGLRC share = NULL; HGLRC share = NULL;
if (!_glfw.wgl.extensionsLoaded)
loadWGLExtensions();
if (ctxconfig->share) if (ctxconfig->share)
share = ctxconfig->share->context.wgl.handle; share = ctxconfig->share->context.wgl.handle;

View file

@ -86,6 +86,7 @@ typedef HGLRC (WINAPI * PFN_wglCreateContext)(HDC);
typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC); typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC);
typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR); typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR);
typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void); typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void);
typedef HGLRC (WINAPI * PFN_wglGetCurrentContext)(void);
typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC); typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC);
typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC); typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
@ -94,6 +95,7 @@ typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
#define wglDeleteContext _glfw.wgl.DeleteContext #define wglDeleteContext _glfw.wgl.DeleteContext
#define wglGetProcAddress _glfw.wgl.GetProcAddress #define wglGetProcAddress _glfw.wgl.GetProcAddress
#define wglGetCurrentDC _glfw.wgl.GetCurrentDC #define wglGetCurrentDC _glfw.wgl.GetCurrentDC
#define wglGetCurrentContext _glfw.wgl.GetCurrentContext
#define wglMakeCurrent _glfw.wgl.MakeCurrent #define wglMakeCurrent _glfw.wgl.MakeCurrent
#define wglShareLists _glfw.wgl.ShareLists #define wglShareLists _glfw.wgl.ShareLists
@ -124,11 +126,10 @@ typedef struct _GLFWlibraryWGL
PFN_wglDeleteContext DeleteContext; PFN_wglDeleteContext DeleteContext;
PFN_wglGetProcAddress GetProcAddress; PFN_wglGetProcAddress GetProcAddress;
PFN_wglGetCurrentDC GetCurrentDC; PFN_wglGetCurrentDC GetCurrentDC;
PFN_wglGetCurrentContext GetCurrentContext;
PFN_wglMakeCurrent MakeCurrent; PFN_wglMakeCurrent MakeCurrent;
PFN_wglShareLists ShareLists; PFN_wglShareLists ShareLists;
GLFWbool extensionsLoaded;
PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT; PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;
PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB; PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB;
PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT; PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;

View file

@ -351,9 +351,10 @@ static HWND createHelperWindow(void)
dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
dbi.dbcc_classguid = GUID_DEVINTERFACE_HID; dbi.dbcc_classguid = GUID_DEVINTERFACE_HID;
RegisterDeviceNotificationW(window, _glfw.win32.deviceNotificationHandle =
(DEV_BROADCAST_HDR*) &dbi, RegisterDeviceNotificationW(window,
DEVICE_NOTIFY_WINDOW_HANDLE); (DEV_BROADCAST_HDR*) &dbi,
DEVICE_NOTIFY_WINDOW_HANDLE);
} }
while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE)) while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE))
@ -543,6 +544,9 @@ int _glfwPlatformInit(void)
void _glfwPlatformTerminate(void) void _glfwPlatformTerminate(void)
{ {
if (_glfw.win32.deviceNotificationHandle)
UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
if (_glfw.win32.helperWindowHandle) if (_glfw.win32.helperWindowHandle)
DestroyWindow(_glfw.win32.helperWindowHandle); DestroyWindow(_glfw.win32.helperWindowHandle);

View file

@ -241,7 +241,7 @@ void _glfwPollMonitorsWin32(void)
// Change the current video mode // Change the current video mode
// //
GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired) void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired)
{ {
GLFWvidmode current; GLFWvidmode current;
const GLFWvidmode* best; const GLFWvidmode* best;
@ -251,7 +251,7 @@ GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desire
best = _glfwChooseVideoMode(monitor, desired); best = _glfwChooseVideoMode(monitor, desired);
_glfwPlatformGetVideoMode(monitor, &current); _glfwPlatformGetVideoMode(monitor, &current);
if (_glfwCompareVideoModes(&current, best) == 0) if (_glfwCompareVideoModes(&current, best) == 0)
return GLFW_TRUE; return;
ZeroMemory(&dm, sizeof(dm)); ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(dm); dm.dmSize = sizeof(dm);
@ -270,7 +270,9 @@ GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desire
NULL, NULL,
CDS_FULLSCREEN, CDS_FULLSCREEN,
NULL); NULL);
if (result != DISP_CHANGE_SUCCESSFUL) if (result == DISP_CHANGE_SUCCESSFUL)
monitor->win32.modeChanged = GLFW_TRUE;
else
{ {
const char* description = "Unknown error"; const char* description = "Unknown error";
@ -292,12 +294,7 @@ GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desire
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to set video mode: %s", "Win32: Failed to set video mode: %s",
description); description);
return GLFW_FALSE;
} }
monitor->win32.modeChanged = GLFW_TRUE;
return GLFW_TRUE;
} }
// Restore the previously saved (original) video mode // Restore the previously saved (original) video mode
@ -337,6 +334,10 @@ void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* ysc
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
{
}
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{ {
DEVMODEW dm; DEVMODEW dm;

View file

@ -67,11 +67,6 @@
#include <xinput.h> #include <xinput.h>
#include <dbt.h> #include <dbt.h>
#if defined(_MSC_VER)
#include <malloc.h>
#define strdup _strdup
#endif
// HACK: Define macros that some windows.h variants don't // HACK: Define macros that some windows.h variants don't
#ifndef WM_MOUSEHWHEEL #ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x020E #define WM_MOUSEHWHEEL 0x020E
@ -288,6 +283,7 @@ typedef struct _GLFWwindowWin32
typedef struct _GLFWlibraryWin32 typedef struct _GLFWlibraryWin32
{ {
HWND helperWindowHandle; HWND helperWindowHandle;
HDEVNOTIFY deviceNotificationHandle;
DWORD foregroundLockTimeout; DWORD foregroundLockTimeout;
int acquiredMonitorCount; int acquiredMonitorCount;
char* clipboardString; char* clipboardString;
@ -402,7 +398,7 @@ void _glfwUpdateKeyNamesWin32(void);
void _glfwInitTimerWin32(void); void _glfwInitTimerWin32(void);
void _glfwPollMonitorsWin32(void); void _glfwPollMonitorsWin32(void);
GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired); void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor); void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale); void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale);

View file

@ -471,30 +471,29 @@ static int translateKey(WPARAM wParam, LPARAM lParam)
return _glfw.win32.keycodes[HIWORD(lParam) & 0x1FF]; return _glfw.win32.keycodes[HIWORD(lParam) & 0x1FF];
} }
static void fitToMonitor(_GLFWwindow* window)
{
MONITORINFO mi = { sizeof(mi) };
GetMonitorInfo(window->monitor->win32.handle, &mi);
SetWindowPos(window->win32.handle, HWND_TOPMOST,
mi.rcMonitor.left,
mi.rcMonitor.top,
mi.rcMonitor.right - mi.rcMonitor.left,
mi.rcMonitor.bottom - mi.rcMonitor.top,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS);
}
// Make the specified window and its video mode active on its monitor // Make the specified window and its video mode active on its monitor
// //
static GLFWbool acquireMonitor(_GLFWwindow* window) static void acquireMonitor(_GLFWwindow* window)
{ {
GLFWvidmode mode;
GLFWbool status;
int xpos, ypos;
if (!_glfw.win32.acquiredMonitorCount) if (!_glfw.win32.acquiredMonitorCount)
SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED); SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
if (!window->monitor->window) if (!window->monitor->window)
_glfw.win32.acquiredMonitorCount++; _glfw.win32.acquiredMonitorCount++;
status = _glfwSetVideoModeWin32(window->monitor, &window->videoMode); _glfwSetVideoModeWin32(window->monitor, &window->videoMode);
_glfwPlatformGetVideoMode(window->monitor, &mode);
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
SetWindowPos(window->win32.handle, HWND_TOPMOST,
xpos, ypos, mode.width, mode.height,
SWP_NOACTIVATE | SWP_NOCOPYBITS);
_glfwInputMonitorWindow(window->monitor, window); _glfwInputMonitorWindow(window->monitor, window);
return status;
} }
// Remove the window and restore the original video mode // Remove the window and restore the original video mode
@ -901,7 +900,10 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (iconified) if (iconified)
releaseMonitor(window); releaseMonitor(window);
else else
{
acquireMonitor(window); acquireMonitor(window);
fitToMonitor(window);
}
} }
window->win32.iconified = iconified; window->win32.iconified = iconified;
@ -996,6 +998,14 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
return 0; return 0;
} }
case WM_DPICHANGED:
{
const float xscale = HIWORD(wParam) / 96.f;
const float yscale = LOWORD(wParam) / 96.f;
_glfwInputWindowContentScale(window, xscale, yscale);
break;
}
case WM_SETCURSOR: case WM_SETCURSOR:
{ {
if (LOWORD(lParam) == HTCLIENT) if (LOWORD(lParam) == HTCLIENT)
@ -1232,11 +1242,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
{ {
_glfwPlatformShowWindow(window); _glfwPlatformShowWindow(window);
_glfwPlatformFocusWindow(window); _glfwPlatformFocusWindow(window);
if (!acquireMonitor(window)) acquireMonitor(window);
return GLFW_FALSE; fitToMonitor(window);
if (wndconfig->centerCursor)
centerCursor(window);
} }
return GLFW_TRUE; return GLFW_TRUE;
@ -1352,7 +1359,10 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
if (window->monitor) if (window->monitor)
{ {
if (window->monitor->window == window) if (window->monitor->window == window)
{
acquireMonitor(window); acquireMonitor(window);
fitToMonitor(window);
}
} }
else else
{ {
@ -1451,7 +1461,7 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
void _glfwPlatformShowWindow(_GLFWwindow* window) void _glfwPlatformShowWindow(_GLFWwindow* window)
{ {
ShowWindow(window->win32.handle, SW_SHOW); ShowWindow(window->win32.handle, SW_SHOWNA);
} }
void _glfwPlatformHideWindow(_GLFWwindow* window) void _glfwPlatformHideWindow(_GLFWwindow* window)
@ -1482,7 +1492,10 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
if (monitor) if (monitor)
{ {
if (monitor->window == window) if (monitor->window == window)
{
acquireMonitor(window); acquireMonitor(window);
fitToMonitor(window);
}
} }
else else
{ {
@ -1505,20 +1518,27 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
if (monitor) if (monitor)
{ {
MONITORINFO mi = { sizeof(mi) };
UINT flags = SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOCOPYBITS;
if (window->decorated) if (window->decorated)
{ {
DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE); DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
UINT flags = SWP_FRAMECHANGED | SWP_SHOWWINDOW |
SWP_NOACTIVATE | SWP_NOCOPYBITS |
SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE;
style &= ~WS_OVERLAPPEDWINDOW; style &= ~WS_OVERLAPPEDWINDOW;
style |= getWindowStyle(window); style |= getWindowStyle(window);
SetWindowLongW(window->win32.handle, GWL_STYLE, style); SetWindowLongW(window->win32.handle, GWL_STYLE, style);
SetWindowPos(window->win32.handle, HWND_TOPMOST, 0, 0, 0, 0, flags); flags |= SWP_FRAMECHANGED;
} }
acquireMonitor(window); acquireMonitor(window);
GetMonitorInfo(window->monitor->win32.handle, &mi);
SetWindowPos(window->win32.handle, HWND_TOPMOST,
mi.rcMonitor.left,
mi.rcMonitor.top,
mi.rcMonitor.right - mi.rcMonitor.left,
mi.rcMonitor.bottom - mi.rcMonitor.top,
flags);
} }
else else
{ {
@ -1570,6 +1590,11 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return IsZoomed(window->win32.handle); return IsZoomed(window->win32.handle);
} }
int _glfwPlatformWindowHovered(_GLFWwindow* window)
{
return cursorInClientArea(window);
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{ {
return window->win32.transparent && _glfwIsCompositionEnabledWin32(); return window->win32.transparent && _glfwIsCompositionEnabledWin32();

View file

@ -38,6 +38,8 @@
////// GLFW event API ////// ////// GLFW event API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Notifies shared code that a window has lost or received input focus
//
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
{ {
if (window->callbacks.focus) if (window->callbacks.focus)
@ -64,42 +66,68 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
} }
} }
// Notifies shared code that a window has moved
// The position is specified in client-area relative screen coordinates
//
void _glfwInputWindowPos(_GLFWwindow* window, int x, int y) void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
{ {
if (window->callbacks.pos) if (window->callbacks.pos)
window->callbacks.pos((GLFWwindow*) window, x, y); window->callbacks.pos((GLFWwindow*) window, x, y);
} }
// Notifies shared code that a window has been resized
// The size is specified in screen coordinates
//
void _glfwInputWindowSize(_GLFWwindow* window, int width, int height) void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
{ {
if (window->callbacks.size) if (window->callbacks.size)
window->callbacks.size((GLFWwindow*) window, width, height); window->callbacks.size((GLFWwindow*) window, width, height);
} }
// Notifies shared code that a window has been iconified or restored
//
void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified) void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
{ {
if (window->callbacks.iconify) if (window->callbacks.iconify)
window->callbacks.iconify((GLFWwindow*) window, iconified); window->callbacks.iconify((GLFWwindow*) window, iconified);
} }
// Notifies shared code that a window has been maximized or restored
//
void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized) void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)
{ {
if (window->callbacks.maximize) if (window->callbacks.maximize)
window->callbacks.maximize((GLFWwindow*) window, maximized); window->callbacks.maximize((GLFWwindow*) window, maximized);
} }
// Notifies shared code that a window framebuffer has been resized
// The size is specified in pixels
//
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height) void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
{ {
if (window->callbacks.fbsize) if (window->callbacks.fbsize)
window->callbacks.fbsize((GLFWwindow*) window, width, height); window->callbacks.fbsize((GLFWwindow*) window, width, height);
} }
// Notifies shared code that a window content scale has changed
// The scale is specified as the ratio between the current and default DPI
//
void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale)
{
if (window->callbacks.scale)
window->callbacks.scale((GLFWwindow*) window, xscale, yscale);
}
// Notifies shared code that the window contents needs updating
//
void _glfwInputWindowDamage(_GLFWwindow* window) void _glfwInputWindowDamage(_GLFWwindow* window)
{ {
if (window->callbacks.refresh) if (window->callbacks.refresh)
window->callbacks.refresh((GLFWwindow*) window); window->callbacks.refresh((GLFWwindow*) window);
} }
// Notifies shared code that the user wishes to close a window
//
void _glfwInputWindowCloseRequest(_GLFWwindow* window) void _glfwInputWindowCloseRequest(_GLFWwindow* window)
{ {
window->shouldClose = GLFW_TRUE; window->shouldClose = GLFW_TRUE;
@ -108,6 +136,8 @@ void _glfwInputWindowCloseRequest(_GLFWwindow* window)
window->callbacks.close((GLFWwindow*) window); window->callbacks.close((GLFWwindow*) window);
} }
// Notifies shared code that a window has changed its desired monitor
//
void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor) void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor)
{ {
window->monitor = monitor; window->monitor = monitor;
@ -127,7 +157,6 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
_GLFWctxconfig ctxconfig; _GLFWctxconfig ctxconfig;
_GLFWwndconfig wndconfig; _GLFWwndconfig wndconfig;
_GLFWwindow* window; _GLFWwindow* window;
_GLFWwindow* previous;
assert(title != NULL); assert(title != NULL);
assert(width >= 0); assert(width >= 0);
@ -153,16 +182,6 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
wndconfig.title = title; wndconfig.title = title;
ctxconfig.share = (_GLFWwindow*) share; ctxconfig.share = (_GLFWwindow*) share;
if (ctxconfig.share)
{
if (ctxconfig.client == GLFW_NO_API ||
ctxconfig.share->context.client == GLFW_NO_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL;
}
}
if (!_glfwIsValidContextConfig(&ctxconfig)) if (!_glfwIsValidContextConfig(&ctxconfig))
return NULL; return NULL;
@ -191,36 +210,32 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
window->numer = GLFW_DONT_CARE; window->numer = GLFW_DONT_CARE;
window->denom = GLFW_DONT_CARE; window->denom = GLFW_DONT_CARE;
// Save the currently current context so it can be restored later
previous = _glfwPlatformGetTls(&_glfw.contextSlot);
if (ctxconfig.client != GLFW_NO_API)
glfwMakeContextCurrent(NULL);
// Open the actual window and create its context // Open the actual window and create its context
if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig)) if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig))
{ {
glfwMakeContextCurrent((GLFWwindow*) previous);
glfwDestroyWindow((GLFWwindow*) window); glfwDestroyWindow((GLFWwindow*) window);
return NULL; return NULL;
} }
if (ctxconfig.client != GLFW_NO_API) if (ctxconfig.client != GLFW_NO_API)
{ {
window->context.makeCurrent(window); if (!_glfwRefreshContextAttribs(window, &ctxconfig))
// Retrieve the actual (as opposed to requested) context attributes
if (!_glfwRefreshContextAttribs(&ctxconfig))
{ {
glfwMakeContextCurrent((GLFWwindow*) previous);
glfwDestroyWindow((GLFWwindow*) window); glfwDestroyWindow((GLFWwindow*) window);
return NULL; return NULL;
} }
// Restore the previously current context (or NULL)
glfwMakeContextCurrent((GLFWwindow*) previous);
} }
if (!window->monitor) if (window->monitor)
{
if (wndconfig.centerCursor)
{
int width, height;
_glfwPlatformGetWindowSize(window, &width, &height);
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
}
}
else
{ {
if (wndconfig.visible) if (wndconfig.visible)
{ {
@ -349,9 +364,6 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_COCOA_RETINA_FRAMEBUFFER: case GLFW_COCOA_RETINA_FRAMEBUFFER:
_glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
return; return;
case GLFW_COCOA_FRAME_AUTOSAVE:
_glfw.hints.window.ns.frame = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_COCOA_GRAPHICS_SWITCHING: case GLFW_COCOA_GRAPHICS_SWITCHING:
_glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
return; return;
@ -396,6 +408,31 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint); _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);
} }
GLFWAPI void glfwWindowHintString(int hint, const char* value)
{
assert(value != NULL);
_GLFW_REQUIRE_INIT();
switch (hint)
{
case GLFW_COCOA_FRAME_NAME:
strncpy(_glfw.hints.window.ns.frameName, value,
sizeof(_glfw.hints.window.ns.frameName) - 1);
return;
case GLFW_X11_CLASS_NAME:
strncpy(_glfw.hints.window.x11.className, value,
sizeof(_glfw.hints.window.x11.className) - 1);
return;
case GLFW_X11_INSTANCE_NAME:
strncpy(_glfw.hints.window.x11.instanceName, value,
sizeof(_glfw.hints.window.x11.instanceName) - 1);
return;
}
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint string 0x%08X", hint);
}
GLFWAPI void glfwDestroyWindow(GLFWwindow* handle) GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
@ -771,6 +808,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
return _glfwPlatformWindowVisible(window); return _glfwPlatformWindowVisible(window);
case GLFW_MAXIMIZED: case GLFW_MAXIMIZED:
return _glfwPlatformWindowMaximized(window); return _glfwPlatformWindowMaximized(window);
case GLFW_HOVERED:
return _glfwPlatformWindowHovered(window);
case GLFW_TRANSPARENT_FRAMEBUFFER: case GLFW_TRANSPARENT_FRAMEBUFFER:
return _glfwPlatformFramebufferTransparent(window); return _glfwPlatformFramebufferTransparent(window);
case GLFW_RESIZABLE: case GLFW_RESIZABLE:
@ -1005,6 +1044,17 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle
return cbfun; return cbfun;
} }
GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* handle,
GLFWwindowcontentscalefun cbfun)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.scale, cbfun);
return cbfun;
}
GLFWAPI void glfwPollEvents(void) GLFWAPI void glfwPollEvents(void)
{ {
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();

View file

@ -32,9 +32,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/timerfd.h>
#include <unistd.h> #include <unistd.h>
#include <wayland-client.h> #include <wayland-client.h>
#include <wayland-cursor.h>
static inline int min(int n1, int n2) static inline int min(int n1, int n2)
@ -42,6 +42,39 @@ static inline int min(int n1, int n2)
return n1 < n2 ? n1 : 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, static void pointerHandleEnter(void* data,
struct wl_pointer* pointer, struct wl_pointer* pointer,
uint32_t serial, uint32_t serial,
@ -49,11 +82,25 @@ static void pointerHandleEnter(void* data,
wl_fixed_t sx, wl_fixed_t sx,
wl_fixed_t sy) wl_fixed_t sy)
{ {
_GLFWwindow* window = wl_surface_get_user_data(surface); // 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.pointerSerial = serial; _glfw.wl.pointerSerial = serial;
_glfw.wl.pointerFocus = window; _glfw.wl.pointerFocus = window;
window->wl.hovered = GLFW_TRUE;
_glfwPlatformSetCursor(window, window->wl.currentCursor); _glfwPlatformSetCursor(window, window->wl.currentCursor);
_glfwInputCursorEnter(window, GLFW_TRUE); _glfwInputCursorEnter(window, GLFW_TRUE);
} }
@ -68,11 +115,46 @@ static void pointerHandleLeave(void* data,
if (!window) if (!window)
return; return;
window->wl.hovered = GLFW_FALSE;
_glfw.wl.pointerSerial = serial; _glfw.wl.pointerSerial = serial;
_glfw.wl.pointerFocus = NULL; _glfw.wl.pointerFocus = NULL;
_glfwInputCursorEnter(window, GLFW_FALSE); _glfwInputCursorEnter(window, GLFW_FALSE);
} }
static void setCursor(const char* name)
{
struct wl_buffer* buffer;
struct wl_cursor* cursor;
struct wl_cursor_image* image;
struct wl_surface* surface = _glfw.wl.cursorSurface;
cursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,
name);
if (!cursor)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Standard cursor not found");
return;
}
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.pointerSerial,
surface,
image->hotspot_x,
image->hotspot_y);
wl_surface_attach(surface, buffer, 0, 0);
wl_surface_damage(surface, 0, 0,
image->width, image->height);
wl_surface_commit(surface);
}
static void pointerHandleMotion(void* data, static void pointerHandleMotion(void* data,
struct wl_pointer* pointer, struct wl_pointer* pointer,
uint32_t time, uint32_t time,
@ -80,6 +162,7 @@ static void pointerHandleMotion(void* data,
wl_fixed_t sy) wl_fixed_t sy)
{ {
_GLFWwindow* window = _glfw.wl.pointerFocus; _GLFWwindow* window = _glfw.wl.pointerFocus;
const char* cursorName;
if (!window) if (!window)
return; return;
@ -92,13 +175,47 @@ static void pointerHandleMotion(void* data,
window->wl.cursorPosY = wl_fixed_to_double(sy); window->wl.cursorPosY = wl_fixed_to_double(sy);
} }
_glfwInputCursorPos(window, switch (window->wl.decorations.focus)
wl_fixed_to_double(sx), {
wl_fixed_to_double(sy)); case mainWindow:
_glfwInputCursorPos(window,
wl_fixed_to_double(sx),
wl_fixed_to_double(sy));
return;
case topDecoration:
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
cursorName = "n-resize";
else
cursorName = "left_ptr";
break;
case leftDecoration:
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
cursorName = "nw-resize";
else
cursorName = "w-resize";
break;
case rightDecoration:
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
cursorName = "ne-resize";
else
cursorName = "e-resize";
break;
case bottomDecoration:
if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH)
cursorName = "sw-resize";
else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH)
cursorName = "se-resize";
else
cursorName = "s-resize";
break;
default:
assert(0);
}
setCursor(cursorName);
} }
static void pointerHandleButton(void* data, static void pointerHandleButton(void* data,
struct wl_pointer* wl_pointer, struct wl_pointer* pointer,
uint32_t serial, uint32_t serial,
uint32_t time, uint32_t time,
uint32_t button, uint32_t button,
@ -107,8 +224,76 @@ static void pointerHandleButton(void* data,
_GLFWwindow* window = _glfw.wl.pointerFocus; _GLFWwindow* window = _glfw.wl.pointerFocus;
int glfwButton; int glfwButton;
// Both xdg-shell and wl_shell use the same values.
uint32_t edges = WL_SHELL_SURFACE_RESIZE_NONE;
if (!window) if (!window)
return; 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;
}
}
// Dont pass the button to the user if it was related to a decoration.
if (window->wl.decorations.focus != mainWindow)
return;
_glfw.wl.pointerSerial = serial; _glfw.wl.pointerSerial = serial;
@ -125,37 +310,28 @@ static void pointerHandleButton(void* data,
} }
static void pointerHandleAxis(void* data, static void pointerHandleAxis(void* data,
struct wl_pointer* wl_pointer, struct wl_pointer* pointer,
uint32_t time, uint32_t time,
uint32_t axis, uint32_t axis,
wl_fixed_t value) wl_fixed_t value)
{ {
_GLFWwindow* window = _glfw.wl.pointerFocus; _GLFWwindow* window = _glfw.wl.pointerFocus;
double scrollFactor; double x = 0.0, y = 0.0;
double x, y; // 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) if (!window)
return; return;
/* Wayland scroll events are in pointer motion coordinate space (think assert(axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL ||
* two finger scroll). The factor 10 is commonly used to convert to axis == WL_POINTER_AXIS_VERTICAL_SCROLL);
* "scroll step means 1.0. */
scrollFactor = 1.0/10.0;
switch (axis) if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
{ x = wl_fixed_to_double(value) * scrollFactor;
case WL_POINTER_AXIS_HORIZONTAL_SCROLL: else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
x = wl_fixed_to_double(value) * scrollFactor; y = wl_fixed_to_double(value) * scrollFactor;
y = 0.0;
break;
case WL_POINTER_AXIS_VERTICAL_SCROLL:
x = 0.0;
y = wl_fixed_to_double(value) * scrollFactor;
break;
default:
assert(GLFW_FALSE);
break;
}
_glfwInputScroll(window, x, y); _glfwInputScroll(window, x, y);
} }
@ -276,7 +452,17 @@ static void keyboardHandleEnter(void* data,
struct wl_surface* surface, struct wl_surface* surface,
struct wl_array* keys) struct wl_array* keys)
{ {
// Happens in the case we just destroyed the surface.
if (!surface)
return;
_GLFWwindow* window = wl_surface_get_user_data(surface); _GLFWwindow* window = wl_surface_get_user_data(surface);
if (!window)
{
window = findWindowFromDecorationSurface(surface, NULL);
if (!window)
return;
}
_glfw.wl.keyboardFocus = window; _glfw.wl.keyboardFocus = window;
_glfwInputWindowFocus(window, GLFW_TRUE); _glfwInputWindowFocus(window, GLFW_TRUE);
@ -326,7 +512,7 @@ static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
} }
#endif #endif
static void inputChar(_GLFWwindow* window, uint32_t key) static GLFWbool inputChar(_GLFWwindow* window, uint32_t key)
{ {
uint32_t code, numSyms; uint32_t code, numSyms;
long cp; long cp;
@ -351,6 +537,8 @@ static void inputChar(_GLFWwindow* window, uint32_t key)
_glfwInputChar(window, cp, mods, plain); _glfwInputChar(window, cp, mods, plain);
} }
} }
return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, syms[0]);
} }
static void keyboardHandleKey(void* data, static void keyboardHandleKey(void* data,
@ -363,6 +551,8 @@ static void keyboardHandleKey(void* data,
int keyCode; int keyCode;
int action; int action;
_GLFWwindow* window = _glfw.wl.keyboardFocus; _GLFWwindow* window = _glfw.wl.keyboardFocus;
GLFWbool shouldRepeat;
struct itimerspec timer = {};
if (!window) if (!window)
return; return;
@ -375,7 +565,20 @@ static void keyboardHandleKey(void* data,
_glfw.wl.xkb.modifiers); _glfw.wl.xkb.modifiers);
if (action == GLFW_PRESS) if (action == GLFW_PRESS)
inputChar(window, key); {
shouldRepeat = inputChar(window, key);
if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0)
{
_glfw.wl.keyboardLastKey = keyCode;
_glfw.wl.keyboardLastScancode = key;
timer.it_interval.tv_sec = _glfw.wl.keyboardRepeatRate / 1000;
timer.it_interval.tv_nsec = (_glfw.wl.keyboardRepeatRate % 1000) * 1000000;
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, static void keyboardHandleModifiers(void* data,
@ -420,12 +623,29 @@ static void keyboardHandleModifiers(void* data,
_glfw.wl.xkb.modifiers = modifiers; _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 = { static const struct wl_keyboard_listener keyboardListener = {
keyboardHandleKeymap, keyboardHandleKeymap,
keyboardHandleEnter, keyboardHandleEnter,
keyboardHandleLeave, keyboardHandleLeave,
keyboardHandleKey, keyboardHandleKey,
keyboardHandleModifiers, keyboardHandleModifiers,
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
keyboardHandleRepeatInfo,
#endif
}; };
static void seatHandleCapabilities(void* data, static void seatHandleCapabilities(void* data,
@ -455,8 +675,26 @@ static void seatHandleCapabilities(void* data,
} }
} }
static void seatHandleName(void* data,
struct wl_seat* seat,
const char* name)
{
}
static const struct wl_seat_listener seatListener = { static const struct wl_seat_listener seatListener = {
seatHandleCapabilities seatHandleCapabilities,
seatHandleName,
};
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, static void registryHandleGlobal(void* data,
@ -472,6 +710,11 @@ static void registryHandleGlobal(void* data,
wl_registry_bind(registry, name, &wl_compositor_interface, wl_registry_bind(registry, name, &wl_compositor_interface,
_glfw.wl.compositorVersion); _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) else if (strcmp(interface, "wl_shm") == 0)
{ {
_glfw.wl.shm = _glfw.wl.shm =
@ -490,11 +733,24 @@ static void registryHandleGlobal(void* data,
{ {
if (!_glfw.wl.seat) if (!_glfw.wl.seat)
{ {
_glfw.wl.seatVersion = min(4, version);
_glfw.wl.seat = _glfw.wl.seat =
wl_registry_bind(registry, name, &wl_seat_interface, 1); wl_registry_bind(registry, name, &wl_seat_interface,
_glfw.wl.seatVersion);
wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL); wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL);
} }
} }
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, "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) else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0)
{ {
_glfw.wl.relativePointerManager = _glfw.wl.relativePointerManager =
@ -522,6 +778,18 @@ static void registryHandleGlobalRemove(void *data,
struct wl_registry *registry, struct wl_registry *registry,
uint32_t name) 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;
}
}
} }
@ -671,50 +939,84 @@ static void createKeyTables(void)
int _glfwPlatformInit(void) int _glfwPlatformInit(void)
{ {
_glfw.wl.xkb.handle = dlopen("libxkbcommon.so.0", RTLD_LAZY | RTLD_GLOBAL); _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) if (!_glfw.wl.xkb.handle)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to open libxkbcommon."); "Wayland: Failed to open libxkbcommon");
return GLFW_FALSE; return GLFW_FALSE;
} }
_glfw.wl.xkb.context_new = (PFN_xkb_context_new) _glfw.wl.xkb.context_new = (PFN_xkb_context_new)
dlsym(_glfw.wl.xkb.handle, "xkb_context_new"); _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_new");
_glfw.wl.xkb.context_unref = (PFN_xkb_context_unref) _glfw.wl.xkb.context_unref = (PFN_xkb_context_unref)
dlsym(_glfw.wl.xkb.handle, "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.wl.xkb.keymap_new_from_string = (PFN_xkb_keymap_new_from_string)
dlsym(_glfw.wl.xkb.handle, "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.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref)
dlsym(_glfw.wl.xkb.handle, "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.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index)
dlsym(_glfw.wl.xkb.handle, "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.wl.xkb.state_new = (PFN_xkb_state_new)
dlsym(_glfw.wl.xkb.handle, "xkb_state_new"); _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new");
_glfw.wl.xkb.state_unref = (PFN_xkb_state_unref) _glfw.wl.xkb.state_unref = (PFN_xkb_state_unref)
dlsym(_glfw.wl.xkb.handle, "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.wl.xkb.state_key_get_syms = (PFN_xkb_state_key_get_syms)
dlsym(_glfw.wl.xkb.handle, "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.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask)
dlsym(_glfw.wl.xkb.handle, "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.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods)
dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods"); _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods");
#ifdef HAVE_XKBCOMMON_COMPOSE_H #ifdef HAVE_XKBCOMMON_COMPOSE_H
_glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale) _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)
dlsym(_glfw.wl.xkb.handle, "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.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref)
dlsym(_glfw.wl.xkb.handle, "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.wl.xkb.compose_state_new = (PFN_xkb_compose_state_new)
dlsym(_glfw.wl.xkb.handle, "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.wl.xkb.compose_state_unref = (PFN_xkb_compose_state_unref)
dlsym(_glfw.wl.xkb.handle, "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.wl.xkb.compose_state_feed = (PFN_xkb_compose_state_feed)
dlsym(_glfw.wl.xkb.handle, "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.wl.xkb.compose_state_get_status = (PFN_xkb_compose_state_get_status)
dlsym(_glfw.wl.xkb.handle, "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.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)
dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym"); _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");
#endif #endif
_glfw.wl.display = wl_display_connect(NULL); _glfw.wl.display = wl_display_connect(NULL);
@ -749,13 +1051,17 @@ int _glfwPlatformInit(void)
_glfwInitTimerPOSIX(); _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) if (_glfw.wl.pointer && _glfw.wl.shm)
{ {
_glfw.wl.cursorTheme = wl_cursor_theme_load(NULL, 32, _glfw.wl.shm); _glfw.wl.cursorTheme = wl_cursor_theme_load(NULL, 32, _glfw.wl.shm);
if (!_glfw.wl.cursorTheme) if (!_glfw.wl.cursorTheme)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Unable to load default cursor theme\n"); "Wayland: Unable to load default cursor theme");
return GLFW_FALSE; return GLFW_FALSE;
} }
_glfw.wl.cursorSurface = _glfw.wl.cursorSurface =
@ -767,30 +1073,52 @@ int _glfwPlatformInit(void)
void _glfwPlatformTerminate(void) void _glfwPlatformTerminate(void)
{ {
_glfwTerminateEGL();
_glfwTerminateJoysticksLinux(); _glfwTerminateJoysticksLinux();
_glfwTerminateEGL();
if (_glfw.wl.egl.handle)
{
_glfw_dlclose(_glfw.wl.egl.handle);
_glfw.wl.egl.handle = NULL;
}
#ifdef HAVE_XKBCOMMON_COMPOSE_H #ifdef HAVE_XKBCOMMON_COMPOSE_H
xkb_compose_state_unref(_glfw.wl.xkb.composeState); if (_glfw.wl.xkb.composeState)
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
#endif #endif
if (_glfw.wl.xkb.keymap)
xkb_keymap_unref(_glfw.wl.xkb.keymap); xkb_keymap_unref(_glfw.wl.xkb.keymap);
xkb_state_unref(_glfw.wl.xkb.state); if (_glfw.wl.xkb.state)
xkb_context_unref(_glfw.wl.xkb.context); xkb_state_unref(_glfw.wl.xkb.state);
if (_glfw.wl.xkb.context)
dlclose(_glfw.wl.xkb.handle); xkb_context_unref(_glfw.wl.xkb.context);
_glfw.wl.xkb.handle = NULL; if (_glfw.wl.xkb.handle)
{
_glfw_dlclose(_glfw.wl.xkb.handle);
_glfw.wl.xkb.handle = NULL;
}
if (_glfw.wl.cursorTheme) if (_glfw.wl.cursorTheme)
wl_cursor_theme_destroy(_glfw.wl.cursorTheme); wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
if (_glfw.wl.cursor.handle)
{
_glfw_dlclose(_glfw.wl.cursor.handle);
_glfw.wl.cursor.handle = NULL;
}
if (_glfw.wl.cursorSurface) if (_glfw.wl.cursorSurface)
wl_surface_destroy(_glfw.wl.cursorSurface); wl_surface_destroy(_glfw.wl.cursorSurface);
if (_glfw.wl.subcompositor)
wl_subcompositor_destroy(_glfw.wl.subcompositor);
if (_glfw.wl.compositor) if (_glfw.wl.compositor)
wl_compositor_destroy(_glfw.wl.compositor); wl_compositor_destroy(_glfw.wl.compositor);
if (_glfw.wl.shm) if (_glfw.wl.shm)
wl_shm_destroy(_glfw.wl.shm); wl_shm_destroy(_glfw.wl.shm);
if (_glfw.wl.shell) if (_glfw.wl.shell)
wl_shell_destroy(_glfw.wl.shell); wl_shell_destroy(_glfw.wl.shell);
if (_glfw.wl.viewporter)
wp_viewporter_destroy(_glfw.wl.viewporter);
if (_glfw.wl.wmBase)
xdg_wm_base_destroy(_glfw.wl.wmBase);
if (_glfw.wl.pointer) if (_glfw.wl.pointer)
wl_pointer_destroy(_glfw.wl.pointer); wl_pointer_destroy(_glfw.wl.pointer);
if (_glfw.wl.keyboard) if (_glfw.wl.keyboard)

View file

@ -52,7 +52,7 @@ static void geometry(void* data,
monitor->heightMM = physicalHeight; monitor->heightMM = physicalHeight;
snprintf(name, sizeof(name), "%s %s", make, model); snprintf(name, sizeof(name), "%s %s", make, model);
monitor->name = strdup(name); monitor->name = _glfw_strdup(name);
} }
static void mode(void* data, static void mode(void* data,
@ -136,6 +136,7 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
monitor->wl.scale = 1; monitor->wl.scale = 1;
monitor->wl.output = output; monitor->wl.output = output;
monitor->wl.name = name;
wl_output_add_listener(output, &outputListener, monitor); wl_output_add_listener(output, &outputListener, monitor);
} }
@ -145,6 +146,12 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
{
if (monitor->wl.output)
wl_output_destroy(monitor->wl.output);
}
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{ {
if (xpos) if (xpos)

View file

@ -52,6 +52,8 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
#include "egl_context.h" #include "egl_context.h"
#include "osmesa_context.h" #include "osmesa_context.h"
#include "wayland-xdg-shell-client-protocol.h"
#include "wayland-viewporter-client-protocol.h"
#include "wayland-relative-pointer-unstable-v1-client-protocol.h" #include "wayland-relative-pointer-unstable-v1-client-protocol.h"
#include "wayland-pointer-constraints-unstable-v1-client-protocol.h" #include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
#include "wayland-idle-inhibit-unstable-v1-client-protocol.h" #include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
@ -71,11 +73,40 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
#define _GLFW_PLATFORM_CONTEXT_STATE #define _GLFW_PLATFORM_CONTEXT_STATE
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE #define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
struct wl_cursor_image {
uint32_t width;
uint32_t height;
uint32_t hotspot_x;
uint32_t hotspot_y;
uint32_t delay;
};
struct wl_cursor {
unsigned int image_count;
struct wl_cursor_image** images;
char* name;
};
typedef struct wl_cursor_theme* (* PFN_wl_cursor_theme_load)(const char*, int, struct wl_shm*);
typedef void (* PFN_wl_cursor_theme_destroy)(struct wl_cursor_theme*);
typedef struct wl_cursor* (* PFN_wl_cursor_theme_get_cursor)(struct wl_cursor_theme*, const char*);
typedef struct wl_buffer* (* PFN_wl_cursor_image_get_buffer)(struct wl_cursor_image*);
#define wl_cursor_theme_load _glfw.wl.cursor.theme_load
#define wl_cursor_theme_destroy _glfw.wl.cursor.theme_destroy
#define wl_cursor_theme_get_cursor _glfw.wl.cursor.theme_get_cursor
#define wl_cursor_image_get_buffer _glfw.wl.cursor.image_get_buffer
typedef struct wl_egl_window* (* PFN_wl_egl_window_create)(struct wl_surface*, int, int);
typedef void (* PFN_wl_egl_window_destroy)(struct wl_egl_window*);
typedef void (* PFN_wl_egl_window_resize)(struct wl_egl_window*, int, int, int, int);
#define wl_egl_window_create _glfw.wl.egl.window_create
#define wl_egl_window_destroy _glfw.wl.egl.window_destroy
#define wl_egl_window_resize _glfw.wl.egl.window_resize
typedef struct xkb_context* (* PFN_xkb_context_new)(enum xkb_context_flags); typedef struct xkb_context* (* PFN_xkb_context_new)(enum xkb_context_flags);
typedef void (* PFN_xkb_context_unref)(struct xkb_context*); typedef void (* PFN_xkb_context_unref)(struct xkb_context*);
typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context*, const char*, enum xkb_keymap_format, enum xkb_keymap_compile_flags); typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context*, const char*, enum xkb_keymap_format, enum xkb_keymap_compile_flags);
typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*); 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 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 struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*); typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
typedef void (* PFN_xkb_state_unref)(struct xkb_state*); 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 int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
@ -86,6 +117,7 @@ typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum
#define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string #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_unref _glfw.wl.xkb.keymap_unref
#define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index #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_state_new _glfw.wl.xkb.state_new #define xkb_state_new _glfw.wl.xkb.state_new
#define xkb_state_unref _glfw.wl.xkb.state_unref #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_key_get_syms _glfw.wl.xkb.state_key_get_syms
@ -109,6 +141,28 @@ typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_st
#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym #define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
#endif #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)
typedef enum _GLFWdecorationSideWayland
{
mainWindow,
topDecoration,
leftDecoration,
rightDecoration,
bottomDecoration,
} _GLFWdecorationSideWayland;
typedef struct _GLFWdecorationWayland
{
struct wl_surface* surface;
struct wl_subsurface* subsurface;
struct wp_viewport* viewport;
} _GLFWdecorationWayland;
// Wayland-specific per-window data // Wayland-specific per-window data
// //
@ -117,12 +171,18 @@ typedef struct _GLFWwindowWayland
int width, height; int width, height;
GLFWbool visible; GLFWbool visible;
GLFWbool maximized; GLFWbool maximized;
GLFWbool hovered;
GLFWbool transparent; GLFWbool transparent;
struct wl_surface* surface; struct wl_surface* surface;
struct wl_egl_window* native; struct wl_egl_window* native;
struct wl_shell_surface* shellSurface; struct wl_shell_surface* shellSurface;
struct wl_callback* callback; struct wl_callback* callback;
struct {
struct xdg_surface* surface;
struct xdg_toplevel* toplevel;
} xdg;
_GLFWcursor* currentCursor; _GLFWcursor* currentCursor;
double cursorPosX, cursorPosY; double cursorPosX, cursorPosY;
@ -142,6 +202,15 @@ typedef struct _GLFWwindowWayland
struct zwp_idle_inhibitor_v1* idleInhibitor; struct zwp_idle_inhibitor_v1* idleInhibitor;
// This is a hack to prevent auto-iconification on creation.
GLFWbool justCreated;
struct {
struct wl_buffer* buffer;
_GLFWdecorationWayland top, left, right, bottom;
int focus;
} decorations;
} _GLFWwindowWayland; } _GLFWwindowWayland;
// Wayland-specific global data // Wayland-specific global data
@ -151,21 +220,30 @@ typedef struct _GLFWlibraryWayland
struct wl_display* display; struct wl_display* display;
struct wl_registry* registry; struct wl_registry* registry;
struct wl_compositor* compositor; struct wl_compositor* compositor;
struct wl_subcompositor* subcompositor;
struct wl_shell* shell; struct wl_shell* shell;
struct wl_shm* shm; struct wl_shm* shm;
struct wl_seat* seat; struct wl_seat* seat;
struct wl_pointer* pointer; struct wl_pointer* pointer;
struct wl_keyboard* keyboard; struct wl_keyboard* keyboard;
struct xdg_wm_base* wmBase;
struct wp_viewporter* viewporter;
struct zwp_relative_pointer_manager_v1* relativePointerManager; struct zwp_relative_pointer_manager_v1* relativePointerManager;
struct zwp_pointer_constraints_v1* pointerConstraints; struct zwp_pointer_constraints_v1* pointerConstraints;
struct zwp_idle_inhibit_manager_v1* idleInhibitManager; struct zwp_idle_inhibit_manager_v1* idleInhibitManager;
int compositorVersion; int compositorVersion;
int seatVersion;
struct wl_cursor_theme* cursorTheme; struct wl_cursor_theme* cursorTheme;
struct wl_surface* cursorSurface; struct wl_surface* cursorSurface;
uint32_t pointerSerial; uint32_t pointerSerial;
int32_t keyboardRepeatRate;
int32_t keyboardRepeatDelay;
int keyboardLastKey;
int keyboardLastScancode;
int timerfd;
short int keycodes[256]; short int keycodes[256];
short int scancodes[GLFW_KEY_LAST + 1]; short int scancodes[GLFW_KEY_LAST + 1];
@ -192,6 +270,7 @@ typedef struct _GLFWlibraryWayland
PFN_xkb_keymap_new_from_string keymap_new_from_string; PFN_xkb_keymap_new_from_string keymap_new_from_string;
PFN_xkb_keymap_unref keymap_unref; PFN_xkb_keymap_unref keymap_unref;
PFN_xkb_keymap_mod_get_index keymap_mod_get_index; PFN_xkb_keymap_mod_get_index keymap_mod_get_index;
PFN_xkb_keymap_key_repeats keymap_key_repeats;
PFN_xkb_state_new state_new; PFN_xkb_state_new state_new;
PFN_xkb_state_unref state_unref; PFN_xkb_state_unref state_unref;
PFN_xkb_state_key_get_syms state_key_get_syms; PFN_xkb_state_key_get_syms state_key_get_syms;
@ -212,6 +291,23 @@ typedef struct _GLFWlibraryWayland
_GLFWwindow* pointerFocus; _GLFWwindow* pointerFocus;
_GLFWwindow* keyboardFocus; _GLFWwindow* keyboardFocus;
struct {
void* handle;
PFN_wl_cursor_theme_load theme_load;
PFN_wl_cursor_theme_destroy theme_destroy;
PFN_wl_cursor_theme_get_cursor theme_get_cursor;
PFN_wl_cursor_image_get_buffer image_get_buffer;
} cursor;
struct {
void* handle;
PFN_wl_egl_window_create window_create;
PFN_wl_egl_window_destroy window_destroy;
PFN_wl_egl_window_resize window_resize;
} egl;
} _GLFWlibraryWayland; } _GLFWlibraryWayland;
// Wayland-specific per-monitor data // Wayland-specific per-monitor data
@ -219,6 +315,7 @@ typedef struct _GLFWlibraryWayland
typedef struct _GLFWmonitorWayland typedef struct _GLFWmonitorWayland
{ {
struct wl_output* output; struct wl_output* output;
int name;
int currentMode; int currentMode;
int x; int x;

View file

@ -35,11 +35,9 @@
#include <string.h> #include <string.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/timerfd.h>
#include <poll.h> #include <poll.h>
#include <wayland-egl.h>
#include <wayland-cursor.h>
static void handlePing(void* data, static void handlePing(void* data,
struct wl_shell_surface* shellSurface, struct wl_shell_surface* shellSurface,
@ -60,6 +58,16 @@ static void handleConfigure(void* data,
if (!window->monitor) 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) if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)
{ {
aspectRatio = (float)width / (float)height; aspectRatio = (float)width / (float)height;
@ -97,9 +105,265 @@ static const struct wl_shell_surface_listener shellSurfaceListener = {
handlePopupDone handlePopupDone
}; };
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 insufficent, 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;
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;
ret = posix_fallocate(fd, 0, size);
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 GLFW_FALSE;
}
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 GLFW_FALSE;
}
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)
return;
if (!window->wl.decorations.buffer)
window->wl.decorations.buffer = createShmBuffer(&image);
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);
}
// 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) static void checkScaleChange(_GLFWwindow* window)
{ {
int scaledWidth, scaledHeight;
int scale = 1; int scale = 1;
int i; int i;
int monitorScale; int monitorScale;
@ -120,11 +384,8 @@ static void checkScaleChange(_GLFWwindow* window)
if (scale != window->wl.scale) if (scale != window->wl.scale)
{ {
window->wl.scale = scale; window->wl.scale = scale;
scaledWidth = window->wl.width * scale;
scaledHeight = window->wl.height * scale;
wl_surface_set_buffer_scale(window->wl.surface, scale); wl_surface_set_buffer_scale(window->wl.surface, scale);
wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0); resizeWindow(window);
_glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
} }
} }
@ -174,21 +435,6 @@ static const struct wl_surface_listener surfaceListener = {
handleLeave handleLeave
}; };
// 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 setIdleInhibitor(_GLFWwindow* window, GLFWbool enable) static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)
{ {
if (enable && !window->wl.idleInhibitor && _glfw.wl.idleInhibitManager) if (enable && !window->wl.idleInhibitor && _glfw.wl.idleInhibitManager)
@ -233,15 +479,49 @@ static GLFWbool createSurface(_GLFWwindow* window,
if (!window->wl.transparent) if (!window->wl.transparent)
setOpaqueRegion(window); setOpaqueRegion(window);
if (window->decorated && !window->monitor)
createDecorations(window);
return GLFW_TRUE; 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);
destroyDecorations(window);
}
static GLFWbool createShellSurface(_GLFWwindow* 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.shellSurface = wl_shell_get_shell_surface(_glfw.wl.shell,
window->wl.surface); window->wl.surface);
if (!window->wl.shellSurface) if (!window->wl.shellSurface)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Shell surface creation failed");
return GLFW_FALSE; return GLFW_FALSE;
}
wl_shell_surface_add_listener(window->wl.shellSurface, wl_shell_surface_add_listener(window->wl.shellSurface,
&shellSurfaceListener, &shellSurfaceListener,
@ -252,12 +532,7 @@ static GLFWbool createShellSurface(_GLFWwindow* window)
if (window->monitor) if (window->monitor)
{ {
wl_shell_surface_set_fullscreen( setFullscreen(window, window->monitor, 0);
window->wl.shellSurface,
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
0,
window->monitor->wl.output);
setIdleInhibitor(window, GLFW_TRUE);
} }
else if (window->wl.maximized) else if (window->wl.maximized)
{ {
@ -275,16 +550,144 @@ static GLFWbool createShellSurface(_GLFWwindow* window)
return GLFW_TRUE; return GLFW_TRUE;
} }
static int static void xdgToplevelHandleConfigure(void* data,
createTmpfileCloexec(char* tmpname) struct xdg_toplevel* toplevel,
int32_t width,
int32_t height,
struct wl_array* states)
{ {
int fd; _GLFWwindow* window = data;
float aspectRatio;
float targetRatio;
uint32_t* state;
GLFWbool maximized = GLFW_FALSE;
GLFWbool fullscreen = GLFW_FALSE;
GLFWbool activated = GLFW_FALSE;
fd = mkostemp(tmpname, O_CLOEXEC); wl_array_for_each(state, states)
if (fd >= 0) {
unlink(tmpname); 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;
}
}
return fd; 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.justCreated && !activated && window->autoIconify)
_glfwPlatformIconifyWindow(window);
_glfwInputWindowFocus(window, activated);
window->wl.justCreated = GLFW_FALSE;
}
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 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);
}
else
{
setIdleInhibitor(window, GLFW_FALSE);
}
wl_surface_commit(window->wl.surface);
wl_display_roundtrip(_glfw.wl.display);
return GLFW_TRUE;
} }
static void static void
@ -293,7 +696,10 @@ handleEvents(int timeout)
struct wl_display* display = _glfw.wl.display; struct wl_display* display = _glfw.wl.display;
struct pollfd fds[] = { struct pollfd fds[] = {
{ wl_display_get_fd(display), POLLIN }, { wl_display_get_fd(display), POLLIN },
{ _glfw.wl.timerfd, POLLIN },
}; };
ssize_t read_ret;
uint64_t repeats, i;
while (wl_display_prepare_read(display) != 0) while (wl_display_prepare_read(display) != 0)
wl_display_dispatch_pending(display); wl_display_dispatch_pending(display);
@ -313,10 +719,29 @@ handleEvents(int timeout)
return; return;
} }
if (poll(fds, 1, timeout) > 0) if (poll(fds, 2, timeout) > 0)
{ {
wl_display_read_events(display); if (fds[0].revents & POLLIN)
wl_display_dispatch_pending(display); {
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);
}
} }
else else
{ {
@ -324,62 +749,6 @@ handleEvents(int timeout)
} }
} }
/*
* 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 insufficent, errno
* is set to ENOSPC. If posix_fallocate() is not supported, program may
* receive SIGBUS on accessing mmap()'ed file contents instead.
*/
int
createAnonymousFile(off_t size)
{
static const char template[] = "/glfw-shared-XXXXXX";
const char* path;
char* name;
int fd;
int ret;
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;
ret = posix_fallocate(fd, 0, size);
if (ret != 0)
{
close(fd);
errno = ret;
return -1;
}
return fd;
}
// Translates a GLFW standard cursor to a theme cursor name // Translates a GLFW standard cursor to a theme cursor name
// //
static char *translateCursorShape(int shape) static char *translateCursorShape(int shape)
@ -411,6 +780,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) const _GLFWfbconfig* fbconfig)
{ {
window->wl.justCreated = GLFW_TRUE;
window->wl.transparent = fbconfig->transparent; window->wl.transparent = fbconfig->transparent;
if (!createSurface(window, wndconfig)) if (!createSurface(window, wndconfig))
@ -436,17 +806,27 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
} }
if (wndconfig->title) if (wndconfig->title)
window->wl.title = strdup(wndconfig->title); window->wl.title = _glfw_strdup(wndconfig->title);
if (wndconfig->visible) if (wndconfig->visible)
{ {
if (!createShellSurface(window)) if (_glfw.wl.wmBase)
return GLFW_FALSE; {
if (!createXdgSurface(window))
return GLFW_FALSE;
}
else
{
if (!createShellSurface(window))
return GLFW_FALSE;
}
window->wl.visible = GLFW_TRUE; window->wl.visible = GLFW_TRUE;
} }
else else
{ {
window->wl.xdg.surface = NULL;
window->wl.xdg.toplevel = NULL;
window->wl.shellSurface = NULL; window->wl.shellSurface = NULL;
window->wl.visible = GLFW_FALSE; window->wl.visible = GLFW_FALSE;
} }
@ -479,12 +859,22 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
if (window->context.destroy) if (window->context.destroy)
window->context.destroy(window); window->context.destroy(window);
destroyDecorations(window);
if (window->wl.decorations.buffer)
wl_buffer_destroy(window->wl.decorations.buffer);
if (window->wl.native) if (window->wl.native)
wl_egl_window_destroy(window->wl.native); wl_egl_window_destroy(window->wl.native);
if (window->wl.shellSurface) if (window->wl.shellSurface)
wl_shell_surface_destroy(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) if (window->wl.surface)
wl_surface_destroy(window->wl.surface); wl_surface_destroy(window->wl.surface);
@ -496,8 +886,10 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
{ {
if (window->wl.title) if (window->wl.title)
free(window->wl.title); free(window->wl.title);
window->wl.title = strdup(title); window->wl.title = _glfw_strdup(title);
if (window->wl.shellSurface) 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); wl_shell_surface_set_title(window->wl.shellSurface, title);
} }
@ -535,22 +927,33 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{ {
int scaledWidth = width * window->wl.scale;
int scaledHeight = height * window->wl.scale;
window->wl.width = width; window->wl.width = width;
window->wl.height = height; window->wl.height = height;
wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0); resizeWindow(window);
if (!window->wl.transparent)
setOpaqueRegion(window);
_glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
} }
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
int minwidth, int minheight, int minwidth, int minheight,
int maxwidth, int maxheight) int maxwidth, int maxheight)
{ {
// TODO: find out how to trigger a resize. if (_glfw.wl.wmBase)
// The actual limits are checked in the wl_shell_surface::configure handler. {
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) void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
@ -570,8 +973,17 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
int* left, int* top, int* left, int* top,
int* right, int* bottom) int* right, int* bottom)
{ {
// TODO: will need a proper implementation once decorations are if (window->decorated && !window->monitor)
// implemented, but for now just leave everything as 0. {
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, void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
@ -585,41 +997,59 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
void _glfwPlatformIconifyWindow(_GLFWwindow* window) void _glfwPlatformIconifyWindow(_GLFWwindow* window)
{ {
// TODO: move to xdg_shell instead of wl_shell. if (_glfw.wl.wmBase)
_glfwInputError(GLFW_PLATFORM_ERROR, {
"Wayland: Iconify window not supported"); 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) void _glfwPlatformRestoreWindow(_GLFWwindow* window)
{ {
// TODO: also do the same for iconified. if (window->wl.xdg.toplevel)
if (window->monitor || window->wl.maximized)
{ {
if (window->wl.shellSurface) if (window->monitor)
wl_shell_surface_set_toplevel(window->wl.shellSurface); xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
if (window->wl.maximized)
window->wl.maximized = GLFW_FALSE; 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) void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
{ {
if (!window->monitor && !window->wl.maximized) if (window->wl.xdg.toplevel)
{ {
if (window->wl.shellSurface) xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
{
// Let the compositor select the best output.
wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
}
window->wl.maximized = GLFW_TRUE;
} }
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) void _glfwPlatformShowWindow(_GLFWwindow* window)
{ {
if (!window->monitor) if (!window->wl.visible)
{ {
if (!window->wl.shellSurface) if (_glfw.wl.wmBase)
createXdgSurface(window);
else if (!window->wl.shellSurface)
createShellSurface(window); createShellSurface(window);
window->wl.visible = GLFW_TRUE; window->wl.visible = GLFW_TRUE;
} }
@ -627,12 +1057,19 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
void _glfwPlatformHideWindow(_GLFWwindow* window) void _glfwPlatformHideWindow(_GLFWwindow* window)
{ {
if (!window->monitor) if (window->wl.xdg.toplevel)
{ {
if (window->wl.shellSurface) xdg_toplevel_destroy(window->wl.xdg.toplevel);
wl_shell_surface_destroy(window->wl.shellSurface); xdg_surface_destroy(window->wl.xdg.surface);
window->wl.visible = GLFW_FALSE; 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) void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
@ -656,17 +1093,17 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
{ {
if (monitor) if (monitor)
{ {
wl_shell_surface_set_fullscreen( setFullscreen(window, monitor, refreshRate);
window->wl.shellSurface,
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
refreshRate * 1000, // Convert Hz to mHz.
monitor->wl.output);
setIdleInhibitor(window, GLFW_TRUE);
} }
else else
{ {
wl_shell_surface_set_toplevel(window->wl.shellSurface); 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); setIdleInhibitor(window, GLFW_FALSE);
if (window->decorated)
createDecorations(window);
} }
_glfwInputWindowMonitor(window, monitor); _glfwInputWindowMonitor(window, monitor);
} }
@ -678,7 +1115,8 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window)
int _glfwPlatformWindowIconified(_GLFWwindow* window) int _glfwPlatformWindowIconified(_GLFWwindow* window)
{ {
// TODO: move to xdg_shell, wl_shell doesn't have any iconified concept. // wl_shell doesn't have any iconified concept, and xdg-shell doesnt give
// any way to request whether a surface is iconified.
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -692,6 +1130,11 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return window->wl.maximized; return window->wl.maximized;
} }
int _glfwPlatformWindowHovered(_GLFWwindow* window)
{
return window->wl.hovered;
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{ {
return window->wl.transparent; return window->wl.transparent;
@ -706,9 +1149,13 @@ void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled) void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
{ {
// TODO if (!window->monitor)
_glfwInputError(GLFW_PLATFORM_ERROR, {
"Wayland: Window attribute setting not implemented yet"); if (enabled)
createDecorations(window);
else
destroyDecorations(window);
}
} }
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
@ -788,53 +1235,7 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
const GLFWimage* image, const GLFWimage* image,
int xhot, int yhot) int xhot, int yhot)
{ {
struct wl_shm_pool* pool; cursor->wl.buffer = createShmBuffer(image);
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 GLFW_FALSE;
}
data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (data == MAP_FAILED)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Cursor mmap failed: %m");
close(fd);
return GLFW_FALSE;
}
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;
}
cursor->wl.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);
cursor->wl.width = image->width; cursor->wl.width = image->width;
cursor->wl.height = image->height; cursor->wl.height = image->height;
cursor->wl.xhot = xhot; cursor->wl.xhot = xhot;

View file

@ -461,17 +461,17 @@ static void detectEWMH(void)
// //
static GLFWbool initExtensions(void) static GLFWbool initExtensions(void)
{ {
_glfw.x11.vidmode.handle = dlopen("libXxf86vm.so.1", RTLD_LAZY | RTLD_GLOBAL); _glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1");
if (_glfw.x11.vidmode.handle) if (_glfw.x11.vidmode.handle)
{ {
_glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension) _glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension)
dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension"); _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension");
_glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp) _glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp)
dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp"); _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp");
_glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp) _glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp)
dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp"); _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp");
_glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize) _glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize)
dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize"); _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize");
_glfw.x11.vidmode.available = _glfw.x11.vidmode.available =
XF86VidModeQueryExtension(_glfw.x11.display, XF86VidModeQueryExtension(_glfw.x11.display,
@ -479,13 +479,13 @@ static GLFWbool initExtensions(void)
&_glfw.x11.vidmode.errorBase); &_glfw.x11.vidmode.errorBase);
} }
_glfw.x11.xi.handle = dlopen("libXi.so.6", RTLD_LAZY | RTLD_GLOBAL); _glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6");
if (_glfw.x11.xi.handle) if (_glfw.x11.xi.handle)
{ {
_glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion) _glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion)
dlsym(_glfw.x11.xi.handle, "XIQueryVersion"); _glfw_dlsym(_glfw.x11.xi.handle, "XIQueryVersion");
_glfw.x11.xi.SelectEvents = (PFN_XISelectEvents) _glfw.x11.xi.SelectEvents = (PFN_XISelectEvents)
dlsym(_glfw.x11.xi.handle, "XISelectEvents"); _glfw_dlsym(_glfw.x11.xi.handle, "XISelectEvents");
if (XQueryExtension(_glfw.x11.display, if (XQueryExtension(_glfw.x11.display,
"XInputExtension", "XInputExtension",
@ -505,45 +505,45 @@ static GLFWbool initExtensions(void)
} }
} }
_glfw.x11.randr.handle = dlopen("libXrandr.so.2", RTLD_LAZY | RTLD_GLOBAL); _glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2");
if (_glfw.x11.randr.handle) if (_glfw.x11.randr.handle)
{ {
_glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma) _glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma)
dlsym(_glfw.x11.randr.handle, "XRRAllocGamma"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRAllocGamma");
_glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma) _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma)
dlsym(_glfw.x11.randr.handle, "XRRFreeGamma"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
_glfw.x11.randr.FreeCrtcInfo = (PFN_XRRFreeCrtcInfo) _glfw.x11.randr.FreeCrtcInfo = (PFN_XRRFreeCrtcInfo)
dlsym(_glfw.x11.randr.handle, "XRRFreeCrtcInfo"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeCrtcInfo");
_glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma) _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma)
dlsym(_glfw.x11.randr.handle, "XRRFreeGamma"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
_glfw.x11.randr.FreeOutputInfo = (PFN_XRRFreeOutputInfo) _glfw.x11.randr.FreeOutputInfo = (PFN_XRRFreeOutputInfo)
dlsym(_glfw.x11.randr.handle, "XRRFreeOutputInfo"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeOutputInfo");
_glfw.x11.randr.FreeScreenResources = (PFN_XRRFreeScreenResources) _glfw.x11.randr.FreeScreenResources = (PFN_XRRFreeScreenResources)
dlsym(_glfw.x11.randr.handle, "XRRFreeScreenResources"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeScreenResources");
_glfw.x11.randr.GetCrtcGamma = (PFN_XRRGetCrtcGamma) _glfw.x11.randr.GetCrtcGamma = (PFN_XRRGetCrtcGamma)
dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGamma"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGamma");
_glfw.x11.randr.GetCrtcGammaSize = (PFN_XRRGetCrtcGammaSize) _glfw.x11.randr.GetCrtcGammaSize = (PFN_XRRGetCrtcGammaSize)
dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize");
_glfw.x11.randr.GetCrtcInfo = (PFN_XRRGetCrtcInfo) _glfw.x11.randr.GetCrtcInfo = (PFN_XRRGetCrtcInfo)
dlsym(_glfw.x11.randr.handle, "XRRGetCrtcInfo"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcInfo");
_glfw.x11.randr.GetOutputInfo = (PFN_XRRGetOutputInfo) _glfw.x11.randr.GetOutputInfo = (PFN_XRRGetOutputInfo)
dlsym(_glfw.x11.randr.handle, "XRRGetOutputInfo"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputInfo");
_glfw.x11.randr.GetOutputPrimary = (PFN_XRRGetOutputPrimary) _glfw.x11.randr.GetOutputPrimary = (PFN_XRRGetOutputPrimary)
dlsym(_glfw.x11.randr.handle, "XRRGetOutputPrimary"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputPrimary");
_glfw.x11.randr.GetScreenResourcesCurrent = (PFN_XRRGetScreenResourcesCurrent) _glfw.x11.randr.GetScreenResourcesCurrent = (PFN_XRRGetScreenResourcesCurrent)
dlsym(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent");
_glfw.x11.randr.QueryExtension = (PFN_XRRQueryExtension) _glfw.x11.randr.QueryExtension = (PFN_XRRQueryExtension)
dlsym(_glfw.x11.randr.handle, "XRRQueryExtension"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryExtension");
_glfw.x11.randr.QueryVersion = (PFN_XRRQueryVersion) _glfw.x11.randr.QueryVersion = (PFN_XRRQueryVersion)
dlsym(_glfw.x11.randr.handle, "XRRQueryVersion"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryVersion");
_glfw.x11.randr.SelectInput = (PFN_XRRSelectInput) _glfw.x11.randr.SelectInput = (PFN_XRRSelectInput)
dlsym(_glfw.x11.randr.handle, "XRRSelectInput"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRSelectInput");
_glfw.x11.randr.SetCrtcConfig = (PFN_XRRSetCrtcConfig) _glfw.x11.randr.SetCrtcConfig = (PFN_XRRSetCrtcConfig)
dlsym(_glfw.x11.randr.handle, "XRRSetCrtcConfig"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcConfig");
_glfw.x11.randr.SetCrtcGamma = (PFN_XRRSetCrtcGamma) _glfw.x11.randr.SetCrtcGamma = (PFN_XRRSetCrtcGamma)
dlsym(_glfw.x11.randr.handle, "XRRSetCrtcGamma"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcGamma");
_glfw.x11.randr.UpdateConfiguration = (PFN_XRRUpdateConfiguration) _glfw.x11.randr.UpdateConfiguration = (PFN_XRRUpdateConfiguration)
dlsym(_glfw.x11.randr.handle, "XRRUpdateConfiguration"); _glfw_dlsym(_glfw.x11.randr.handle, "XRRUpdateConfiguration");
if (XRRQueryExtension(_glfw.x11.display, if (XRRQueryExtension(_glfw.x11.display,
&_glfw.x11.randr.eventBase, &_glfw.x11.randr.eventBase,
@ -593,26 +593,26 @@ static GLFWbool initExtensions(void)
RROutputChangeNotifyMask); RROutputChangeNotifyMask);
} }
_glfw.x11.xcursor.handle = dlopen("libXcursor.so.1", RTLD_LAZY | RTLD_GLOBAL); _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1");
if (_glfw.x11.xcursor.handle) if (_glfw.x11.xcursor.handle)
{ {
_glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate) _glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate)
dlsym(_glfw.x11.xcursor.handle, "XcursorImageCreate"); _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageCreate");
_glfw.x11.xcursor.ImageDestroy = (PFN_XcursorImageDestroy) _glfw.x11.xcursor.ImageDestroy = (PFN_XcursorImageDestroy)
dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy"); _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy");
_glfw.x11.xcursor.ImageLoadCursor = (PFN_XcursorImageLoadCursor) _glfw.x11.xcursor.ImageLoadCursor = (PFN_XcursorImageLoadCursor)
dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor"); _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor");
} }
_glfw.x11.xinerama.handle = dlopen("libXinerama.so.1", RTLD_LAZY | RTLD_GLOBAL); _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1");
if (_glfw.x11.xinerama.handle) if (_glfw.x11.xinerama.handle)
{ {
_glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive) _glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive)
dlsym(_glfw.x11.xinerama.handle, "XineramaIsActive"); _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaIsActive");
_glfw.x11.xinerama.QueryExtension = (PFN_XineramaQueryExtension) _glfw.x11.xinerama.QueryExtension = (PFN_XineramaQueryExtension)
dlsym(_glfw.x11.xinerama.handle, "XineramaQueryExtension"); _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryExtension");
_glfw.x11.xinerama.QueryScreens = (PFN_XineramaQueryScreens) _glfw.x11.xinerama.QueryScreens = (PFN_XineramaQueryScreens)
dlsym(_glfw.x11.xinerama.handle, "XineramaQueryScreens"); _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryScreens");
if (XineramaQueryExtension(_glfw.x11.display, if (XineramaQueryExtension(_glfw.x11.display,
&_glfw.x11.xinerama.major, &_glfw.x11.xinerama.major,
@ -644,22 +644,22 @@ static GLFWbool initExtensions(void)
} }
} }
_glfw.x11.x11xcb.handle = dlopen("libX11-xcb.so.1", RTLD_LAZY | RTLD_GLOBAL); _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1");
if (_glfw.x11.x11xcb.handle) if (_glfw.x11.x11xcb.handle)
{ {
_glfw.x11.x11xcb.GetXCBConnection = (PFN_XGetXCBConnection) _glfw.x11.x11xcb.GetXCBConnection = (PFN_XGetXCBConnection)
dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection"); _glfw_dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection");
} }
_glfw.x11.xrender.handle = dlopen("libXrender.so.1", RTLD_LAZY | RTLD_GLOBAL); _glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1");
if (_glfw.x11.xrender.handle) if (_glfw.x11.xrender.handle)
{ {
_glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension) _glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension)
dlsym(_glfw.x11.xrender.handle, "XRenderQueryExtension"); _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryExtension");
_glfw.x11.xrender.QueryVersion = (PFN_XRenderQueryVersion) _glfw.x11.xrender.QueryVersion = (PFN_XRenderQueryVersion)
dlsym(_glfw.x11.xrender.handle, "XRenderQueryVersion"); _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryVersion");
_glfw.x11.xrender.FindVisualFormat = (PFN_XRenderFindVisualFormat) _glfw.x11.xrender.FindVisualFormat = (PFN_XRenderFindVisualFormat)
dlsym(_glfw.x11.xrender.handle, "XRenderFindVisualFormat"); _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderFindVisualFormat");
if (XRenderQueryExtension(_glfw.x11.display, if (XRenderQueryExtension(_glfw.x11.display,
&_glfw.x11.xrender.errorBase, &_glfw.x11.xrender.errorBase,
@ -1002,25 +1002,25 @@ void _glfwPlatformTerminate(void)
if (_glfw.x11.x11xcb.handle) if (_glfw.x11.x11xcb.handle)
{ {
dlclose(_glfw.x11.x11xcb.handle); _glfw_dlclose(_glfw.x11.x11xcb.handle);
_glfw.x11.x11xcb.handle = NULL; _glfw.x11.x11xcb.handle = NULL;
} }
if (_glfw.x11.xcursor.handle) if (_glfw.x11.xcursor.handle)
{ {
dlclose(_glfw.x11.xcursor.handle); _glfw_dlclose(_glfw.x11.xcursor.handle);
_glfw.x11.xcursor.handle = NULL; _glfw.x11.xcursor.handle = NULL;
} }
if (_glfw.x11.randr.handle) if (_glfw.x11.randr.handle)
{ {
dlclose(_glfw.x11.randr.handle); _glfw_dlclose(_glfw.x11.randr.handle);
_glfw.x11.randr.handle = NULL; _glfw.x11.randr.handle = NULL;
} }
if (_glfw.x11.xinerama.handle) if (_glfw.x11.xinerama.handle)
{ {
dlclose(_glfw.x11.xinerama.handle); _glfw_dlclose(_glfw.x11.xinerama.handle);
_glfw.x11.xinerama.handle = NULL; _glfw.x11.xinerama.handle = NULL;
} }

View file

@ -216,7 +216,7 @@ void _glfwPollMonitorsX11(void)
// Set the current video mode for the specified monitor // Set the current video mode for the specified monitor
// //
GLFWbool _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired) void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired)
{ {
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
{ {
@ -231,7 +231,7 @@ GLFWbool _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired)
best = _glfwChooseVideoMode(monitor, desired); best = _glfwChooseVideoMode(monitor, desired);
_glfwPlatformGetVideoMode(monitor, &current); _glfwPlatformGetVideoMode(monitor, &current);
if (_glfwCompareVideoModes(&current, best) == 0) if (_glfwCompareVideoModes(&current, best) == 0)
return GLFW_TRUE; return;
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
@ -269,16 +269,7 @@ GLFWbool _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired)
XRRFreeOutputInfo(oi); XRRFreeOutputInfo(oi);
XRRFreeCrtcInfo(ci); XRRFreeCrtcInfo(ci);
XRRFreeScreenResources(sr); XRRFreeScreenResources(sr);
if (!native)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"X11: Monitor mode list changed");
return GLFW_FALSE;
}
} }
return GLFW_TRUE;
} }
// Restore the saved (original) video mode for the specified monitor // Restore the saved (original) video mode for the specified monitor
@ -317,6 +308,10 @@ void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
{
}
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{ {
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)

View file

@ -425,7 +425,7 @@ typedef struct _GLFWcursorX11
void _glfwPollMonitorsX11(void); void _glfwPollMonitorsX11(void);
GLFWbool _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired); void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor); void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor);
Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot); Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot);

View file

@ -711,21 +711,26 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
{ {
XClassHint* hint = XAllocClassHint(); XClassHint* hint = XAllocClassHint();
if (strlen(_glfw.hints.init.x11.className) && if (strlen(wndconfig->x11.instanceName) &&
strlen(_glfw.hints.init.x11.classClass)) strlen(wndconfig->x11.className))
{ {
hint->res_name = (char*) _glfw.hints.init.x11.className; hint->res_name = (char*) wndconfig->x11.instanceName;
hint->res_class = (char*) _glfw.hints.init.x11.classClass; hint->res_class = (char*) wndconfig->x11.className;
}
else if (strlen(wndconfig->title))
{
hint->res_name = (char*) wndconfig->title;
hint->res_class = (char*) wndconfig->title;
} }
else else
{ {
hint->res_name = (char*) "glfw-application"; const char* resourceName = getenv("RESOURCE_NAME");
hint->res_class = (char*) "GLFW-Application"; if (resourceName && strlen(resourceName))
hint->res_name = (char*) resourceName;
else if (strlen(wndconfig->title))
hint->res_name = (char*) wndconfig->title;
else
hint->res_name = (char*) "glfw-application";
if (strlen(wndconfig->title))
hint->res_class = (char*) wndconfig->title;
else
hint->res_class = (char*) "GLFW-Application";
} }
XSetClassHint(_glfw.x11.display, window->x11.handle, hint); XSetClassHint(_glfw.x11.display, window->x11.handle, hint);
@ -1051,7 +1056,7 @@ static const char* getSelectionString(Atom selection)
if (targets[i] == XA_STRING) if (targets[i] == XA_STRING)
*selectionString = convertLatin1toUTF8(data); *selectionString = convertLatin1toUTF8(data);
else else
*selectionString = strdup(data); *selectionString = _glfw_strdup(data);
} }
XFree(data); XFree(data);
@ -1071,10 +1076,8 @@ static const char* getSelectionString(Atom selection)
// Make the specified window and its video mode active on its monitor // Make the specified window and its video mode active on its monitor
// //
static GLFWbool acquireMonitor(_GLFWwindow* window) static void acquireMonitor(_GLFWwindow* window)
{ {
GLFWbool status;
if (_glfw.x11.saver.count == 0) if (_glfw.x11.saver.count == 0)
{ {
// Remember old screen saver settings // Remember old screen saver settings
@ -1092,7 +1095,7 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
if (!window->monitor->window) if (!window->monitor->window)
_glfw.x11.saver.count++; _glfw.x11.saver.count++;
status = _glfwSetVideoModeX11(window->monitor, &window->videoMode); _glfwSetVideoModeX11(window->monitor, &window->videoMode);
if (window->x11.overrideRedirect) if (window->x11.overrideRedirect)
{ {
@ -1108,7 +1111,6 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
} }
_glfwInputMonitorWindow(window->monitor, window); _glfwInputMonitorWindow(window->monitor, window);
return status;
} }
// Remove the window and restore the original video mode // Remove the window and restore the original video mode
@ -1972,11 +1974,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
{ {
_glfwPlatformShowWindow(window); _glfwPlatformShowWindow(window);
updateWindowMode(window); updateWindowMode(window);
if (!acquireMonitor(window)) acquireMonitor(window);
return GLFW_FALSE;
if (wndconfig->centerCursor)
centerCursor(window);
} }
XFlush(_glfw.x11.display); XFlush(_glfw.x11.display);
@ -2448,6 +2446,28 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return maximized; return maximized;
} }
int _glfwPlatformWindowHovered(_GLFWwindow* window)
{
Window w = _glfw.x11.root;
while (w)
{
Window root;
int rootX, rootY, childX, childY;
unsigned int mask;
if (!XQueryPointer(_glfw.x11.display, w,
&root, &w, &rootX, &rootY, &childX, &childY, &mask))
{
return GLFW_FALSE;
}
if (w == window->x11.handle)
return GLFW_TRUE;
}
return GLFW_FALSE;
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{ {
if (!window->x11.transparent) if (!window->x11.transparent)
@ -2807,7 +2827,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
void _glfwPlatformSetClipboardString(const char* string) void _glfwPlatformSetClipboardString(const char* string)
{ {
free(_glfw.x11.clipboardString); free(_glfw.x11.clipboardString);
_glfw.x11.clipboardString = strdup(string); _glfw.x11.clipboardString = _glfw_strdup(string);
XSetSelectionOwner(_glfw.x11.display, XSetSelectionOwner(_glfw.x11.display,
_glfw.x11.CLIPBOARD, _glfw.x11.CLIPBOARD,
@ -2999,7 +3019,7 @@ GLFWAPI void glfwSetX11SelectionString(const char* string)
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
free(_glfw.x11.primarySelectionString); free(_glfw.x11.primarySelectionString);
_glfw.x11.primarySelectionString = strdup(string); _glfw.x11.primarySelectionString = _glfw_strdup(string);
XSetSelectionOwner(_glfw.x11.display, XSetSelectionOwner(_glfw.x11.display,
_glfw.x11.PRIMARY, _glfw.x11.PRIMARY,