glfw: Update to GLFW 3.3

Fixes #1000
This commit is contained in:
Hajime Hoshi 2019-11-25 23:13:44 +09:00
parent 5f33d47711
commit a040aae83b
51 changed files with 7666 additions and 3044 deletions

View File

@ -30,7 +30,7 @@ import (
"strings" "strings"
"text/template" "text/template"
"github.com/go-gl/glfw/v3.2/glfw" "github.com/go-gl/glfw/v3.3/glfw"
) )
var ( var (

2
go.mod
View File

@ -3,7 +3,7 @@ module github.com/hajimehoshi/ebiten
go 1.12 go 1.12
require ( require (
github.com/go-gl/glfw v0.0.0-20191124195120-e5ec43523f6f github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191124195120-e5ec43523f6f
github.com/gofrs/flock v0.7.1 github.com/gofrs/flock v0.7.1
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/hajimehoshi/bitmapfont v1.2.0 github.com/hajimehoshi/bitmapfont v1.2.0

5
go.sum
View File

@ -1,6 +1,6 @@
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/go-gl/glfw v0.0.0-20191124195120-e5ec43523f6f h1:+cueGTBwFJV9cVfrdCbsS3TXS0WpxZjQC6HsUW4WM8Q= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191124195120-e5ec43523f6f h1:U8O0rPsWxcSd7V3h3WhA0IscOFf7JzufOHx+fEZpotw=
github.com/go-gl/glfw v0.0.0-20191124195120-e5ec43523f6f/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191124195120-e5ec43523f6f/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/gofrs/flock v0.7.1 h1:DP+LD/t0njgoPBvT5MJLeliUIVQR03hiKR6vezdwHlc= github.com/gofrs/flock v0.7.1 h1:DP+LD/t0njgoPBvT5MJLeliUIVQR03hiKR6vezdwHlc=
github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
@ -42,6 +42,7 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -15,6 +15,8 @@
package driver package driver
import ( import (
"unsafe"
"github.com/hajimehoshi/ebiten/internal/affine" "github.com/hajimehoshi/ebiten/internal/affine"
"github.com/hajimehoshi/ebiten/internal/thread" "github.com/hajimehoshi/ebiten/internal/thread"
) )
@ -23,7 +25,7 @@ type Graphics interface {
SetThread(thread *thread.Thread) SetThread(thread *thread.Thread)
Begin() Begin()
End() End()
SetWindow(window uintptr) SetWindow(window unsafe.Pointer)
SetVertices(vertices []float32, indices []uint16) SetVertices(vertices []float32, indices []uint16)
Flush() Flush()
NewImage(width, height int) (Image, error) NewImage(width, height int) (Image, error)

View File

@ -19,15 +19,15 @@ import (
) )
type ( type (
Action int Action int
ErrorCode int ErrorCode int
Hint int Hint int
InputMode int InputMode int
Joystick int Joystick int
Key int Key int
ModifierKey int ModifierKey int
MouseButton int MouseButton int
MonitorEvent int PeripheralEvent int
) )
const ( const (

View File

@ -0,0 +1,3 @@
These files are basically copy of github.com/v3.3/glfw/glfw.
There is one change from the original files: `GLFWscrollfun` takes pointers instead of values since all arguments of C functions have to be 32bit on 32bit Windows machine.

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,9 @@
/************************************************************************* /*************************************************************************
* GLFW 3.2 - www.glfw.org * GLFW 3.3 - www.glfw.org
* A library for OpenGL, window and input * A library for OpenGL, window and input
*------------------------------------------------------------------------ *------------------------------------------------------------------------
* Copyright (c) 2002-2006 Marcus Geelnard * Copyright (c) 2002-2006 Marcus Geelnard
* Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> * Copyright (c) 2006-2018 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
* warranty. In no event will the authors be held liable for any damages * warranty. In no event will the authors be held liable for any damages
@ -45,12 +45,13 @@ extern "C" {
* more information. * more information.
*/ */
/*! @defgroup native Native access /*! @defgroup native Native access
* @brief Functions related to accessing native handles.
* *
* **By using the native access functions you assert that you know what you're * **By using the native access functions you assert that you know what you're
* doing and how to fix problems caused by using them. If you don't, you * doing and how to fix problems caused by using them. If you don't, you
* shouldn't be using them.** * shouldn't be using them.**
* *
* Before the inclusion of @ref glfw3native.h, you may define exactly one * Before the inclusion of @ref glfw3native.h, you may define zero or more
* window system API macro and zero or more context creation API macros. * window system API macro and zero or more context creation API macros.
* *
* The chosen backends must match those the library was compiled for. Failure * The chosen backends must match those the library was compiled for. Failure
@ -61,13 +62,13 @@ extern "C" {
* * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_COCOA`
* * `GLFW_EXPOSE_NATIVE_X11` * * `GLFW_EXPOSE_NATIVE_X11`
* * `GLFW_EXPOSE_NATIVE_WAYLAND` * * `GLFW_EXPOSE_NATIVE_WAYLAND`
* * `GLFW_EXPOSE_NATIVE_MIR`
* *
* The available context API macros are: * The available context API macros are:
* * `GLFW_EXPOSE_NATIVE_WGL` * * `GLFW_EXPOSE_NATIVE_WGL`
* * `GLFW_EXPOSE_NATIVE_NSGL` * * `GLFW_EXPOSE_NATIVE_NSGL`
* * `GLFW_EXPOSE_NATIVE_GLX` * * `GLFW_EXPOSE_NATIVE_GLX`
* * `GLFW_EXPOSE_NATIVE_EGL` * * `GLFW_EXPOSE_NATIVE_EGL`
* * `GLFW_EXPOSE_NATIVE_OSMESA`
* *
* These macros select which of the native access functions that are declared * These macros select which of the native access functions that are declared
* and which platform-specific headers to include. It is then up your (by * and which platform-specific headers to include. It is then up your (by
@ -80,26 +81,27 @@ extern "C" {
* System headers and types * System headers and types
*************************************************************************/ *************************************************************************/
#if defined(GLFW_EXPOSE_NATIVE_WIN32) #if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL)
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for // This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
// example to allow applications to correctly declare a GL_ARB_debug_output // example to allow applications to correctly declare a GL_ARB_debug_output
// callback) but windows.h assumes no one will define APIENTRY before it does // callback) but windows.h assumes no one will define APIENTRY before it does
#undef APIENTRY #if defined(GLFW_APIENTRY_DEFINED)
#undef APIENTRY
#undef GLFW_APIENTRY_DEFINED
#endif
#include <windows.h> #include <windows.h>
#elif defined(GLFW_EXPOSE_NATIVE_COCOA) #elif defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL)
#include <ApplicationServices/ApplicationServices.h>
#if defined(__OBJC__) #if defined(__OBJC__)
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#else #else
#include <ApplicationServices/ApplicationServices.h>
typedef void* id; typedef void* id;
#endif #endif
#elif defined(GLFW_EXPOSE_NATIVE_X11) #elif defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h> #include <X11/extensions/Xrandr.h>
#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) #elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
#include <wayland-client.h> #include <wayland-client.h>
#elif defined(GLFW_EXPOSE_NATIVE_MIR)
#include <mir_toolkit/mir_client_library.h>
#endif #endif
#if defined(GLFW_EXPOSE_NATIVE_WGL) #if defined(GLFW_EXPOSE_NATIVE_WGL)
@ -114,6 +116,9 @@ extern "C" {
#if defined(GLFW_EXPOSE_NATIVE_EGL) #if defined(GLFW_EXPOSE_NATIVE_EGL)
#include <EGL/egl.h> #include <EGL/egl.h>
#endif #endif
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
#include <GL/osmesa.h>
#endif
/************************************************************************* /*************************************************************************
@ -284,6 +289,56 @@ GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
* @ingroup native * @ingroup native
*/ */
GLFWAPI Window glfwGetX11Window(GLFWwindow* window); GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
/*! @brief Sets the current primary selection to the specified string.
*
* @param[in] string A UTF-8 encoded string.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @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 clipboard
* @sa glfwGetX11SelectionString
* @sa glfwSetClipboardString
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI void glfwSetX11SelectionString(const char* string);
/*! @brief Returns the contents of the current primary selection as a string.
*
* If the selection is empty or if its contents cannot be converted, `NULL`
* is returned and a @ref GLFW_FORMAT_UNAVAILABLE error is generated.
*
* @return The contents of the selection as a UTF-8 encoded string, or `NULL`
* if an [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @pointer_lifetime The returned string is allocated and freed by GLFW. You
* should not free it yourself. It is valid until the next call to @ref
* glfwGetX11SelectionString or @ref glfwSetX11SelectionString, or until the
* library is terminated.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref clipboard
* @sa glfwSetX11SelectionString
* @sa glfwGetClipboardString
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI const char* glfwGetX11SelectionString(void);
#endif #endif
#if defined(GLFW_EXPOSE_NATIVE_GLX) #if defined(GLFW_EXPOSE_NATIVE_GLX)
@ -360,50 +415,6 @@ GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
#endif #endif
#if defined(GLFW_EXPOSE_NATIVE_MIR)
/*! @brief Returns the `MirConnection*` used by GLFW.
*
* @return The `MirConnection*` used by GLFW, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.2.
*
* @ingroup native
*/
GLFWAPI MirConnection* glfwGetMirDisplay(void);
/*! @brief Returns the Mir output ID of the specified monitor.
*
* @return The Mir output ID of the specified monitor, or zero if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.2.
*
* @ingroup native
*/
GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor);
/*! @brief Returns the `MirSurface*` of the specified window.
*
* @return The `MirSurface*` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.2.
*
* @ingroup native
*/
GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_EGL) #if defined(GLFW_EXPOSE_NATIVE_EGL)
/*! @brief Returns the `EGLDisplay` used by GLFW. /*! @brief Returns the `EGLDisplay` used by GLFW.
* *
@ -448,6 +459,64 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window); GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
#endif #endif
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
/*! @brief Retrieves the color buffer associated with the specified window.
*
* @param[in] window The window whose color buffer to retrieve.
* @param[out] width Where to store the width of the color buffer, or `NULL`.
* @param[out] height Where to store the height of the color buffer, or `NULL`.
* @param[out] format Where to store the OSMesa pixel format of the color
* buffer, or `NULL`.
* @param[out] buffer Where to store the address of the color buffer, or
* `NULL`.
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width, int* height, int* format, void** buffer);
/*! @brief Retrieves the depth buffer associated with the specified window.
*
* @param[in] window The window whose depth buffer to retrieve.
* @param[out] width Where to store the width of the depth buffer, or `NULL`.
* @param[out] height Where to store the height of the depth buffer, or `NULL`.
* @param[out] bytesPerValue Where to store the number of bytes per depth
* buffer element, or `NULL`.
* @param[out] buffer Where to store the address of the depth buffer, or
* `NULL`.
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width, int* height, int* bytesPerValue, void** buffer);
/*! @brief Returns the `OSMesaContext` of the specified window.
*
* @return The `OSMesaContext` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* window);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.2 - www.glfw.org // GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <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
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"
@ -38,13 +40,30 @@
////// 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)
{ {
_glfwInputError(GLFW_INVALID_ENUM, _glfwInputError(GLFW_INVALID_ENUM,
"Invalid context creation API %i", "Invalid context creation API 0x%08X",
ctxconfig->source); ctxconfig->source);
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -54,7 +73,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
ctxconfig->client != GLFW_OPENGL_ES_API) ctxconfig->client != GLFW_OPENGL_ES_API)
{ {
_glfwInputError(GLFW_INVALID_ENUM, _glfwInputError(GLFW_INVALID_ENUM,
"Invalid client API %i", "Invalid client API 0x%08X",
ctxconfig->client); ctxconfig->client);
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -84,7 +103,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE) ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE)
{ {
_glfwInputError(GLFW_INVALID_ENUM, _glfwInputError(GLFW_INVALID_ENUM,
"Invalid OpenGL profile %i", "Invalid OpenGL profile 0x%08X",
ctxconfig->profile); ctxconfig->profile);
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -133,7 +152,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET) ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET)
{ {
_glfwInputError(GLFW_INVALID_ENUM, _glfwInputError(GLFW_INVALID_ENUM,
"Invalid context robustness mode %i", "Invalid context robustness mode 0x%08X",
ctxconfig->robustness); ctxconfig->robustness);
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -145,7 +164,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH) ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH)
{ {
_glfwInputError(GLFW_INVALID_ENUM, _glfwInputError(GLFW_INVALID_ENUM,
"Invalid context release behavior %i", "Invalid context release behavior 0x%08X",
ctxconfig->release); ctxconfig->release);
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -154,6 +173,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)
@ -207,6 +228,9 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
// not important to us here, so we count them as one // not important to us here, so we count them as one
missing++; missing++;
} }
if (desired->transparent != current->transparent)
missing++;
} }
// These polynomials make many small channel size differences matter // These polynomials make many small channel size differences matter
@ -317,10 +341,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[] =
{ {
@ -330,11 +357,12 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
NULL NULL
}; };
window = _glfwPlatformGetCurrentContext();
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)
@ -342,6 +370,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;
} }
@ -359,6 +388,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;
} }
@ -390,6 +420,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;
} }
@ -419,6 +450,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;
} }
@ -434,6 +466,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;
} }
} }
@ -540,9 +573,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;
@ -577,13 +613,14 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle) GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFWwindow* previous = _glfwPlatformGetCurrentContext(); _GLFWwindow* previous = _glfwPlatformGetTls(&_glfw.contextSlot);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
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;
} }
@ -600,7 +637,7 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
GLFWAPI GLFWwindow* glfwGetCurrentContext(void) GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return (GLFWwindow*) _glfwPlatformGetCurrentContext(); return _glfwPlatformGetTls(&_glfw.contextSlot);
} }
GLFWAPI void glfwSwapBuffers(GLFWwindow* handle) GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
@ -612,7 +649,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;
} }
@ -625,10 +663,11 @@ GLFWAPI void glfwSwapInterval(int interval)
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
window = _glfwPlatformGetCurrentContext(); 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;
} }
@ -638,21 +677,21 @@ GLFWAPI void glfwSwapInterval(int interval)
GLFWAPI int glfwExtensionSupported(const char* extension) GLFWAPI int glfwExtensionSupported(const char* extension)
{ {
_GLFWwindow* window; _GLFWwindow* window;
assert(extension != NULL); assert(extension != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
window = _glfwPlatformGetCurrentContext(); 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;
} }
@ -708,10 +747,11 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
window = _glfwPlatformGetCurrentContext(); 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

@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.2 EGL - www.glfw.org // GLFW 3.3 EGL - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // Copyright (c) 2006-2019 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
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"
@ -113,7 +115,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
_GLFWfbconfig* u = usableConfigs + usableCount; _GLFWfbconfig* u = usableConfigs + usableCount;
// Only consider RGB(A) EGLConfigs // Only consider RGB(A) EGLConfigs
if (!(getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) & EGL_RGB_BUFFER)) if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
continue; continue;
// Only consider window EGLConfigs // Only consider window EGLConfigs
@ -121,9 +123,25 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
continue; continue;
#if defined(_GLFW_X11) #if defined(_GLFW_X11)
XVisualInfo vi = {0};
// Only consider EGLConfigs with associated Visuals // Only consider EGLConfigs with associated Visuals
if (!getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID)) vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
if (!vi.visualid)
continue; continue;
if (desired->transparent)
{
int count;
XVisualInfo* vis = XGetVisualInfo(_glfw.x11.display,
VisualIDMask, &vi,
&count);
if (vis)
{
u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
XFree(vis);
}
}
#endif // _GLFW_X11 #endif // _GLFW_X11
if (ctxconfig->client == GLFW_OPENGL_ES_API) if (ctxconfig->client == GLFW_OPENGL_ES_API)
@ -199,12 +217,12 @@ static void makeContextCurrentEGL(_GLFWwindow* window)
} }
} }
_glfwPlatformSetCurrentContext(window); _glfwPlatformSetTls(&_glfw.contextSlot, window);
} }
static void swapBuffersEGL(_GLFWwindow* window) static void swapBuffersEGL(_GLFWwindow* window)
{ {
if (window != _glfwPlatformGetCurrentContext()) if (window != _glfwPlatformGetTls(&_glfw.contextSlot))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: The context must be current on the calling thread when swapping buffers"); "EGL: The context must be current on the calling thread when swapping buffers");
@ -233,7 +251,7 @@ static int extensionSupportedEGL(const char* extension)
static GLFWglproc getProcAddressEGL(const char* procname) static GLFWglproc getProcAddressEGL(const char* procname)
{ {
_GLFWwindow* window = _glfwPlatformGetCurrentContext(); _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (window->context.egl.client) if (window->context.egl.client)
{ {
@ -286,11 +304,15 @@ GLFWbool _glfwInitEGL(void)
int i; int i;
const char* sonames[] = const char* sonames[] =
{ {
#if defined(_GLFW_WIN32) #if defined(_GLFW_EGL_LIBRARY)
_GLFW_EGL_LIBRARY,
#elif defined(_GLFW_WIN32)
"libEGL.dll", "libEGL.dll",
"EGL.dll", "EGL.dll",
#elif defined(_GLFW_COCOA) #elif defined(_GLFW_COCOA)
"libEGL.dylib", "libEGL.dylib",
#elif defined(__CYGWIN__)
"libEGL-1.so",
#else #else
"libEGL.so.1", "libEGL.so.1",
#endif #endif
@ -315,37 +337,37 @@ GLFWbool _glfwInitEGL(void)
_glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0); _glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);
_glfw.egl.GetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC) _glfw.egl.GetConfigAttrib = (PFN_eglGetConfigAttrib)
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib"); _glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
_glfw.egl.GetConfigs = (PFNEGLGETCONFIGSPROC) _glfw.egl.GetConfigs = (PFN_eglGetConfigs)
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigs"); _glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
_glfw.egl.GetDisplay = (PFNEGLGETDISPLAYPROC) _glfw.egl.GetDisplay = (PFN_eglGetDisplay)
_glfw_dlsym(_glfw.egl.handle, "eglGetDisplay"); _glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
_glfw.egl.GetError = (PFNEGLGETERRORPROC) _glfw.egl.GetError = (PFN_eglGetError)
_glfw_dlsym(_glfw.egl.handle, "eglGetError"); _glfw_dlsym(_glfw.egl.handle, "eglGetError");
_glfw.egl.Initialize = (PFNEGLINITIALIZEPROC) _glfw.egl.Initialize = (PFN_eglInitialize)
_glfw_dlsym(_glfw.egl.handle, "eglInitialize"); _glfw_dlsym(_glfw.egl.handle, "eglInitialize");
_glfw.egl.Terminate = (PFNEGLTERMINATEPROC) _glfw.egl.Terminate = (PFN_eglTerminate)
_glfw_dlsym(_glfw.egl.handle, "eglTerminate"); _glfw_dlsym(_glfw.egl.handle, "eglTerminate");
_glfw.egl.BindAPI = (PFNEGLBINDAPIPROC) _glfw.egl.BindAPI = (PFN_eglBindAPI)
_glfw_dlsym(_glfw.egl.handle, "eglBindAPI"); _glfw_dlsym(_glfw.egl.handle, "eglBindAPI");
_glfw.egl.CreateContext = (PFNEGLCREATECONTEXTPROC) _glfw.egl.CreateContext = (PFN_eglCreateContext)
_glfw_dlsym(_glfw.egl.handle, "eglCreateContext"); _glfw_dlsym(_glfw.egl.handle, "eglCreateContext");
_glfw.egl.DestroySurface = (PFNEGLDESTROYSURFACEPROC) _glfw.egl.DestroySurface = (PFN_eglDestroySurface)
_glfw_dlsym(_glfw.egl.handle, "eglDestroySurface"); _glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
_glfw.egl.DestroyContext = (PFNEGLDESTROYCONTEXTPROC) _glfw.egl.DestroyContext = (PFN_eglDestroyContext)
_glfw_dlsym(_glfw.egl.handle, "eglDestroyContext"); _glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
_glfw.egl.CreateWindowSurface = (PFNEGLCREATEWINDOWSURFACEPROC) _glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface)
_glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface"); _glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
_glfw.egl.MakeCurrent = (PFNEGLMAKECURRENTPROC) _glfw.egl.MakeCurrent = (PFN_eglMakeCurrent)
_glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent"); _glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
_glfw.egl.SwapBuffers = (PFNEGLSWAPBUFFERSPROC) _glfw.egl.SwapBuffers = (PFN_eglSwapBuffers)
_glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers"); _glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
_glfw.egl.SwapInterval = (PFNEGLSWAPINTERVALPROC) _glfw.egl.SwapInterval = (PFN_eglSwapInterval)
_glfw_dlsym(_glfw.egl.handle, "eglSwapInterval"); _glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
_glfw.egl.QueryString = (PFNEGLQUERYSTRINGPROC) _glfw.egl.QueryString = (PFN_eglQueryString)
_glfw_dlsym(_glfw.egl.handle, "eglQueryString"); _glfw_dlsym(_glfw.egl.handle, "eglQueryString");
_glfw.egl.GetProcAddress = (PFNEGLGETPROCADDRESSPROC) _glfw.egl.GetProcAddress = (PFN_eglGetProcAddress)
_glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress"); _glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress");
if (!_glfw.egl.GetConfigAttrib || if (!_glfw.egl.GetConfigAttrib ||
@ -399,6 +421,10 @@ GLFWbool _glfwInitEGL(void)
extensionSupportedEGL("EGL_KHR_create_context_no_error"); extensionSupportedEGL("EGL_KHR_create_context_no_error");
_glfw.egl.KHR_gl_colorspace = _glfw.egl.KHR_gl_colorspace =
extensionSupportedEGL("EGL_KHR_gl_colorspace"); extensionSupportedEGL("EGL_KHR_gl_colorspace");
_glfw.egl.KHR_get_all_proc_addresses =
extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
_glfw.egl.KHR_context_flush_control =
extensionSupportedEGL("EGL_KHR_context_flush_control");
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -420,11 +446,11 @@ void _glfwTerminateEGL(void)
} }
} }
#define setEGLattrib(attribName, attribValue) \ #define setAttrib(a, v) \
{ \ { \
attribs[index++] = attribName; \ assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = attribValue; \ attribs[index++] = a; \
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \ attribs[index++] = v; \
} }
// Create the OpenGL or OpenGL ES context // Create the OpenGL or OpenGL ES context
@ -436,6 +462,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
EGLint attribs[40]; EGLint attribs[40];
EGLConfig config; EGLConfig config;
EGLContext share = NULL; EGLContext share = NULL;
int index = 0;
if (!_glfw.egl.display) if (!_glfw.egl.display)
{ {
@ -476,7 +503,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
if (_glfw.egl.KHR_create_context) if (_glfw.egl.KHR_create_context)
{ {
int index = 0, mask = 0, flags = 0; int mask = 0, flags = 0;
if (ctxconfig->client == GLFW_OPENGL_API) if (ctxconfig->client == GLFW_OPENGL_API)
{ {
@ -487,12 +514,6 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE) else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
if (_glfw.egl.KHR_create_context_no_error)
{
if (ctxconfig->noerror)
flags |= EGL_CONTEXT_OPENGL_NO_ERROR_KHR;
}
} }
if (ctxconfig->debug) if (ctxconfig->debug)
@ -502,44 +523,57 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{ {
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION) if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
{ {
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
EGL_NO_RESET_NOTIFICATION_KHR); EGL_NO_RESET_NOTIFICATION_KHR);
} }
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET) else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
{ {
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
EGL_LOSE_CONTEXT_ON_RESET_KHR); EGL_LOSE_CONTEXT_ON_RESET_KHR);
} }
flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
} }
if (ctxconfig->noerror)
{
if (_glfw.egl.KHR_create_context_no_error)
setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
}
if (ctxconfig->major != 1 || ctxconfig->minor != 0) if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{ {
setEGLattrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major); setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
setEGLattrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor); setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
} }
if (mask) if (mask)
setEGLattrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask); setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
if (flags) if (flags)
setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags); setAttrib(EGL_CONTEXT_FLAGS_KHR, flags);
setEGLattrib(EGL_NONE, EGL_NONE);
} }
else else
{ {
int index = 0;
if (ctxconfig->client == GLFW_OPENGL_ES_API) if (ctxconfig->client == GLFW_OPENGL_ES_API)
setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major); setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
setEGLattrib(EGL_NONE, EGL_NONE);
} }
// Context release behaviors (GL_KHR_context_flush_control) are not yet if (_glfw.egl.KHR_context_flush_control)
// supported on EGL but are not a hard constraint, so ignore and continue {
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
{
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
}
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
{
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
}
}
setAttrib(EGL_NONE, EGL_NONE);
window->context.egl.handle = eglCreateContext(_glfw.egl.display, window->context.egl.handle = eglCreateContext(_glfw.egl.display,
config, share, attribs); config, share, attribs);
@ -559,12 +593,10 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
if (fbconfig->sRGB) if (fbconfig->sRGB)
{ {
if (_glfw.egl.KHR_gl_colorspace) if (_glfw.egl.KHR_gl_colorspace)
{ setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
setEGLattrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
}
} }
setEGLattrib(EGL_NONE, EGL_NONE); setAttrib(EGL_NONE, EGL_NONE);
} }
window->context.egl.surface = window->context.egl.surface =
@ -583,12 +615,15 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
window->context.egl.config = config; window->context.egl.config = config;
// Load the appropriate client library // Load the appropriate client library
if (!_glfw.egl.KHR_get_all_proc_addresses)
{ {
int i; int i;
const char** sonames; const char** sonames;
const char* es1sonames[] = const char* es1sonames[] =
{ {
#if defined(_GLFW_WIN32) #if defined(_GLFW_GLESV1_LIBRARY)
_GLFW_GLESV1_LIBRARY,
#elif defined(_GLFW_WIN32)
"GLESv1_CM.dll", "GLESv1_CM.dll",
"libGLES_CM.dll", "libGLES_CM.dll",
#elif defined(_GLFW_COCOA) #elif defined(_GLFW_COCOA)
@ -601,11 +636,15 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
}; };
const char* es2sonames[] = const char* es2sonames[] =
{ {
#if defined(_GLFW_WIN32) #if defined(_GLFW_GLESV2_LIBRARY)
_GLFW_GLESV2_LIBRARY,
#elif defined(_GLFW_WIN32)
"GLESv2.dll", "GLESv2.dll",
"libGLESv2.dll", "libGLESv2.dll",
#elif defined(_GLFW_COCOA) #elif defined(_GLFW_COCOA)
"libGLESv2.dylib", "libGLESv2.dylib",
#elif defined(__CYGWIN__)
"libGLESv2-2.so",
#else #else
"libGLESv2.so.2", "libGLESv2.so.2",
#endif #endif
@ -613,7 +652,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
}; };
const char* glsonames[] = const char* glsonames[] =
{ {
#if defined(_GLFW_WIN32) #if defined(_GLFW_OPENGL_LIBRARY)
_GLFW_OPENGL_LIBRARY,
#elif defined(_GLFW_WIN32)
#elif defined(_GLFW_COCOA) #elif defined(_GLFW_COCOA)
#else #else
"libGL.so.1", "libGL.so.1",
@ -661,12 +702,13 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
return GLFW_TRUE; return GLFW_TRUE;
} }
#undef setEGLattrib #undef setAttrib
// Returns the Visual and depth of the chosen EGLConfig // Returns the Visual and depth of the chosen EGLConfig
// //
#if defined(_GLFW_X11) #if defined(_GLFW_X11)
GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig, GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig, const _GLFWfbconfig* fbconfig,
Visual** visual, int* depth) Visual** visual, int* depth)
{ {

View File

@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.2 EGL - www.glfw.org // GLFW 3.3 EGL - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // Copyright (c) 2006-2017 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
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -25,15 +25,16 @@
// //
//======================================================================== //========================================================================
#ifndef _glfw3_egl_context_h_
#define _glfw3_egl_context_h_
#if defined(_GLFW_USE_EGLPLATFORM_H) #if defined(_GLFW_USE_EGLPLATFORM_H)
#include <EGL/eglplatform.h> #include <EGL/eglplatform.h>
#elif defined(_GLFW_WIN32) #elif defined(_GLFW_WIN32)
#define EGLAPIENTRY __stdcall #define EGLAPIENTRY __stdcall
typedef HDC EGLNativeDisplayType; typedef HDC EGLNativeDisplayType;
typedef HWND EGLNativeWindowType; typedef HWND EGLNativeWindowType;
#elif defined(_GLFW_COCOA)
#define EGLAPIENTRY
typedef void* EGLNativeDisplayType;
typedef id EGLNativeWindowType;
#elif defined(_GLFW_X11) #elif defined(_GLFW_X11)
#define EGLAPIENTRY #define EGLAPIENTRY
typedef Display* EGLNativeDisplayType; typedef Display* EGLNativeDisplayType;
@ -42,34 +43,30 @@ typedef Window EGLNativeWindowType;
#define EGLAPIENTRY #define EGLAPIENTRY
typedef struct wl_display* EGLNativeDisplayType; typedef struct wl_display* EGLNativeDisplayType;
typedef struct wl_egl_window* EGLNativeWindowType; typedef struct wl_egl_window* EGLNativeWindowType;
#elif defined(_GLFW_MIR)
#define EGLAPIENTRY
typedef MirEGLNativeDisplayType EGLNativeDisplayType;
typedef MirEGLNativeWindowType EGLNativeWindowType;
#else #else
#error "No supported EGL platform selected" #error "No supported EGL platform selected"
#endif #endif
#define EGL_SUCCESS 0x3000 #define EGL_SUCCESS 0x3000
#define EGL_NOT_INITIALIZED 0x3001 #define EGL_NOT_INITIALIZED 0x3001
#define EGL_BAD_ACCESS 0x3002 #define EGL_BAD_ACCESS 0x3002
#define EGL_BAD_ALLOC 0x3003 #define EGL_BAD_ALLOC 0x3003
#define EGL_BAD_ATTRIBUTE 0x3004 #define EGL_BAD_ATTRIBUTE 0x3004
#define EGL_BAD_CONFIG 0x3005 #define EGL_BAD_CONFIG 0x3005
#define EGL_BAD_CONTEXT 0x3006 #define EGL_BAD_CONTEXT 0x3006
#define EGL_BAD_CURRENT_SURFACE 0x3007 #define EGL_BAD_CURRENT_SURFACE 0x3007
#define EGL_BAD_DISPLAY 0x3008 #define EGL_BAD_DISPLAY 0x3008
#define EGL_BAD_MATCH 0x3009 #define EGL_BAD_MATCH 0x3009
#define EGL_BAD_NATIVE_PIXMAP 0x300a #define EGL_BAD_NATIVE_PIXMAP 0x300a
#define EGL_BAD_NATIVE_WINDOW 0x300b #define EGL_BAD_NATIVE_WINDOW 0x300b
#define EGL_BAD_PARAMETER 0x300c #define EGL_BAD_PARAMETER 0x300c
#define EGL_BAD_SURFACE 0x300d #define EGL_BAD_SURFACE 0x300d
#define EGL_CONTEXT_LOST 0x300e #define EGL_CONTEXT_LOST 0x300e
#define EGL_COLOR_BUFFER_TYPE 0x303f #define EGL_COLOR_BUFFER_TYPE 0x303f
#define EGL_RGB_BUFFER 0x308e #define EGL_RGB_BUFFER 0x308e
#define EGL_SURFACE_TYPE 0x3033 #define EGL_SURFACE_TYPE 0x3033
#define EGL_WINDOW_BIT 0x0004 #define EGL_WINDOW_BIT 0x0004
#define EGL_RENDERABLE_TYPE 0x3040 #define EGL_RENDERABLE_TYPE 0x3040
#define EGL_OPENGL_ES_BIT 0x0001 #define EGL_OPENGL_ES_BIT 0x0001
#define EGL_OPENGL_ES2_BIT 0x0004 #define EGL_OPENGL_ES2_BIT 0x0004
#define EGL_OPENGL_BIT 0x0008 #define EGL_OPENGL_BIT 0x0008
@ -79,7 +76,7 @@ typedef MirEGLNativeWindowType EGLNativeWindowType;
#define EGL_RED_SIZE 0x3024 #define EGL_RED_SIZE 0x3024
#define EGL_DEPTH_SIZE 0x3025 #define EGL_DEPTH_SIZE 0x3025
#define EGL_STENCIL_SIZE 0x3026 #define EGL_STENCIL_SIZE 0x3026
#define EGL_SAMPLES 0x3031 #define EGL_SAMPLES 0x3031
#define EGL_OPENGL_ES_API 0x30a0 #define EGL_OPENGL_ES_API 0x30a0
#define EGL_OPENGL_API 0x30a2 #define EGL_OPENGL_API 0x30a2
#define EGL_NONE 0x3038 #define EGL_NONE 0x3038
@ -106,6 +103,9 @@ typedef MirEGLNativeWindowType EGLNativeWindowType;
#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3 #define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3
#define EGL_GL_COLORSPACE_KHR 0x309d #define EGL_GL_COLORSPACE_KHR 0x309d
#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089 #define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
typedef int EGLint; typedef int EGLint;
typedef unsigned int EGLBoolean; typedef unsigned int EGLBoolean;
@ -116,22 +116,22 @@ typedef void* EGLDisplay;
typedef void* EGLSurface; typedef void* EGLSurface;
// EGL function pointer typedefs // EGL function pointer typedefs
typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETCONFIGATTRIBPROC)(EGLDisplay,EGLConfig,EGLint,EGLint*); typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETCONFIGSPROC)(EGLDisplay,EGLConfig*,EGLint,EGLint*); typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigs)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
typedef EGLDisplay (EGLAPIENTRY * PFNEGLGETDISPLAYPROC)(EGLNativeDisplayType); typedef EGLDisplay (EGLAPIENTRY * PFN_eglGetDisplay)(EGLNativeDisplayType);
typedef EGLint (EGLAPIENTRY * PFNEGLGETERRORPROC)(void); typedef EGLint (EGLAPIENTRY * PFN_eglGetError)(void);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLINITIALIZEPROC)(EGLDisplay,EGLint*,EGLint*); typedef EGLBoolean (EGLAPIENTRY * PFN_eglInitialize)(EGLDisplay,EGLint*,EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLTERMINATEPROC)(EGLDisplay); typedef EGLBoolean (EGLAPIENTRY * PFN_eglTerminate)(EGLDisplay);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLBINDAPIPROC)(EGLenum); typedef EGLBoolean (EGLAPIENTRY * PFN_eglBindAPI)(EGLenum);
typedef EGLContext (EGLAPIENTRY * PFNEGLCREATECONTEXTPROC)(EGLDisplay,EGLConfig,EGLContext,const EGLint*); typedef EGLContext (EGLAPIENTRY * PFN_eglCreateContext)(EGLDisplay,EGLConfig,EGLContext,const EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYSURFACEPROC)(EGLDisplay,EGLSurface); typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroySurface)(EGLDisplay,EGLSurface);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYCONTEXTPROC)(EGLDisplay,EGLContext); typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroyContext)(EGLDisplay,EGLContext);
typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*); typedef EGLSurface (EGLAPIENTRY * PFN_eglCreateWindowSurface)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLMAKECURRENTPROC)(EGLDisplay,EGLSurface,EGLSurface,EGLContext); typedef EGLBoolean (EGLAPIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPBUFFERSPROC)(EGLDisplay,EGLSurface); typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPINTERVALPROC)(EGLDisplay,EGLint); typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint);
typedef const char* (EGLAPIENTRY * PFNEGLQUERYSTRINGPROC)(EGLDisplay,EGLint); typedef const char* (EGLAPIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint);
typedef GLFWglproc (EGLAPIENTRY * PFNEGLGETPROCADDRESSPROC)(const char*); typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*);
#define eglGetConfigAttrib _glfw.egl.GetConfigAttrib #define eglGetConfigAttrib _glfw.egl.GetConfigAttrib
#define eglGetConfigs _glfw.egl.GetConfigs #define eglGetConfigs _glfw.egl.GetConfigs
#define eglGetDisplay _glfw.egl.GetDisplay #define eglGetDisplay _glfw.egl.GetDisplay
@ -176,25 +176,27 @@ typedef struct _GLFWlibraryEGL
GLFWbool KHR_create_context; GLFWbool KHR_create_context;
GLFWbool KHR_create_context_no_error; GLFWbool KHR_create_context_no_error;
GLFWbool KHR_gl_colorspace; GLFWbool KHR_gl_colorspace;
GLFWbool KHR_get_all_proc_addresses;
GLFWbool KHR_context_flush_control;
void* handle; void* handle;
PFNEGLGETCONFIGATTRIBPROC GetConfigAttrib; PFN_eglGetConfigAttrib GetConfigAttrib;
PFNEGLGETCONFIGSPROC GetConfigs; PFN_eglGetConfigs GetConfigs;
PFNEGLGETDISPLAYPROC GetDisplay; PFN_eglGetDisplay GetDisplay;
PFNEGLGETERRORPROC GetError; PFN_eglGetError GetError;
PFNEGLINITIALIZEPROC Initialize; PFN_eglInitialize Initialize;
PFNEGLTERMINATEPROC Terminate; PFN_eglTerminate Terminate;
PFNEGLBINDAPIPROC BindAPI; PFN_eglBindAPI BindAPI;
PFNEGLCREATECONTEXTPROC CreateContext; PFN_eglCreateContext CreateContext;
PFNEGLDESTROYSURFACEPROC DestroySurface; PFN_eglDestroySurface DestroySurface;
PFNEGLDESTROYCONTEXTPROC DestroyContext; PFN_eglDestroyContext DestroyContext;
PFNEGLCREATEWINDOWSURFACEPROC CreateWindowSurface; PFN_eglCreateWindowSurface CreateWindowSurface;
PFNEGLMAKECURRENTPROC MakeCurrent; PFN_eglMakeCurrent MakeCurrent;
PFNEGLSWAPBUFFERSPROC SwapBuffers; PFN_eglSwapBuffers SwapBuffers;
PFNEGLSWAPINTERVALPROC SwapInterval; PFN_eglSwapInterval SwapInterval;
PFNEGLQUERYSTRINGPROC QueryString; PFN_eglQueryString QueryString;
PFNEGLGETPROCADDRESSPROC GetProcAddress; PFN_eglGetProcAddress GetProcAddress;
} _GLFWlibraryEGL; } _GLFWlibraryEGL;
@ -205,9 +207,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig); const _GLFWfbconfig* fbconfig);
#if defined(_GLFW_X11) #if defined(_GLFW_X11)
GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig, GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig, const _GLFWfbconfig* fbconfig,
Visual** visual, int* depth); Visual** visual, int* depth);
#endif /*_GLFW_X11*/ #endif /*_GLFW_X11*/
#endif // _glfw3_egl_context_h_

View File

@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.2 - www.glfw.org // GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // Copyright (c) 2006-2018 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
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -24,130 +24,47 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"
#include "mappings.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <assert.h>
// The three 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
// These are documented in internal.h
// //
GLFWbool _glfwInitialized = GLFW_FALSE; _GLFWlibrary _glfw = { GLFW_FALSE };
_GLFWlibrary _glfw;
// This is outside of _glfw so it can be initialized and usable before // These are outside of _glfw so they can be used before initialization and
// glfwInit is called, which lets that function report errors // after termination
// //
static GLFWerrorfun _glfwErrorCallback = NULL; static _GLFWerror _glfwMainThreadError;
static GLFWerrorfun _glfwErrorCallback;
static _GLFWinitconfig _glfwInitHints =
{
GLFW_TRUE, // hat buttons
{
GLFW_TRUE, // macOS menu bar
GLFW_TRUE // macOS bundle chdir
}
};
// Terminate the library
// Returns a generic string representation of the specified error
// //
static const char* getErrorString(int error) static void terminate(void)
{
switch (error)
{
case GLFW_NOT_INITIALIZED:
return "The GLFW library is not initialized";
case GLFW_NO_CURRENT_CONTEXT:
return "There is no current context";
case GLFW_INVALID_ENUM:
return "Invalid argument for enum parameter";
case GLFW_INVALID_VALUE:
return "Invalid value for parameter";
case GLFW_OUT_OF_MEMORY:
return "Out of memory";
case GLFW_API_UNAVAILABLE:
return "The requested API is unavailable";
case GLFW_VERSION_UNAVAILABLE:
return "The requested API version is unavailable";
case GLFW_PLATFORM_ERROR:
return "A platform-specific error occurred";
case GLFW_FORMAT_UNAVAILABLE:
return "The requested format is unavailable";
case GLFW_NO_WINDOW_CONTEXT:
return "The specified window has no context";
default:
return "ERROR: UNKNOWN GLFW ERROR";
}
}
//////////////////////////////////////////////////////////////////////////
////// GLFW event API //////
//////////////////////////////////////////////////////////////////////////
void _glfwInputError(int error, const char* format, ...)
{
if (_glfwErrorCallback)
{
char buffer[8192];
const char* description;
if (format)
{
int count;
va_list vl;
va_start(vl, format);
count = vsnprintf(buffer, sizeof(buffer), format, vl);
va_end(vl);
if (count < 0)
buffer[sizeof(buffer) - 1] = '\0';
description = buffer;
}
else
description = getErrorString(error);
_glfwErrorCallback(error, description);
}
}
//////////////////////////////////////////////////////////////////////////
////// GLFW public API //////
//////////////////////////////////////////////////////////////////////////
GLFWAPI int glfwInit(void)
{
if (_glfwInitialized)
return GLFW_TRUE;
memset(&_glfw, 0, sizeof(_glfw));
if (!_glfwPlatformInit())
{
_glfwPlatformTerminate();
return GLFW_FALSE;
}
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
_glfwInitialized = GLFW_TRUE;
_glfw.timerOffset = _glfwPlatformGetTimerValue();
// Not all window hints have zero as their default value
glfwDefaultWindowHints();
return GLFW_TRUE;
}
GLFWAPI void glfwTerminate(void)
{ {
int i; int i;
if (!_glfwInitialized)
return;
memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks)); memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
while (_glfw.windowListHead) while (_glfw.windowListHead)
@ -161,28 +78,227 @@ GLFWAPI void glfwTerminate(void)
_GLFWmonitor* monitor = _glfw.monitors[i]; _GLFWmonitor* monitor = _glfw.monitors[i];
if (monitor->originalRamp.size) if (monitor->originalRamp.size)
_glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp); _glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
_glfwFreeMonitor(monitor);
} }
_glfwTerminateVulkan(); free(_glfw.monitors);
_glfwFreeMonitors(_glfw.monitors, _glfw.monitorCount);
_glfw.monitors = NULL; _glfw.monitors = NULL;
_glfw.monitorCount = 0; _glfw.monitorCount = 0;
free(_glfw.mappings);
_glfw.mappings = NULL;
_glfw.mappingCount = 0;
_glfwTerminateVulkan();
_glfwPlatformTerminate(); _glfwPlatformTerminate();
_glfw.initialized = GLFW_FALSE;
while (_glfw.errorListHead)
{
_GLFWerror* error = _glfw.errorListHead;
_glfw.errorListHead = error->next;
free(error);
}
_glfwPlatformDestroyTls(&_glfw.contextSlot);
_glfwPlatformDestroyTls(&_glfw.errorSlot);
_glfwPlatformDestroyMutex(&_glfw.errorLock);
memset(&_glfw, 0, sizeof(_glfw)); memset(&_glfw, 0, sizeof(_glfw));
_glfwInitialized = GLFW_FALSE; }
//////////////////////////////////////////////////////////////////////////
////// 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;
}
float _glfw_fminf(float a, float b)
{
if (a != a)
return b;
else if (b != b)
return a;
else if (a < b)
return a;
else
return b;
}
float _glfw_fmaxf(float a, float b)
{
if (a != a)
return b;
else if (b != b)
return a;
else if (a > b)
return a;
else
return b;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW event API //////
//////////////////////////////////////////////////////////////////////////
// Notifies shared code of an error
//
void _glfwInputError(int code, const char* format, ...)
{
_GLFWerror* error;
char description[_GLFW_MESSAGE_SIZE];
if (format)
{
va_list vl;
va_start(vl, format);
vsnprintf(description, sizeof(description), format, vl);
va_end(vl);
description[sizeof(description) - 1] = '\0';
}
else
{
if (code == GLFW_NOT_INITIALIZED)
strcpy(description, "The GLFW library is not initialized");
else if (code == GLFW_NO_CURRENT_CONTEXT)
strcpy(description, "There is no current context");
else if (code == GLFW_INVALID_ENUM)
strcpy(description, "Invalid argument for enum parameter");
else if (code == GLFW_INVALID_VALUE)
strcpy(description, "Invalid value for parameter");
else if (code == GLFW_OUT_OF_MEMORY)
strcpy(description, "Out of memory");
else if (code == GLFW_API_UNAVAILABLE)
strcpy(description, "The requested API is unavailable");
else if (code == GLFW_VERSION_UNAVAILABLE)
strcpy(description, "The requested API version is unavailable");
else if (code == GLFW_PLATFORM_ERROR)
strcpy(description, "A platform-specific error occurred");
else if (code == GLFW_FORMAT_UNAVAILABLE)
strcpy(description, "The requested format is unavailable");
else if (code == GLFW_NO_WINDOW_CONTEXT)
strcpy(description, "The specified window has no context");
else
strcpy(description, "ERROR: UNKNOWN GLFW ERROR");
}
if (_glfw.initialized)
{
error = _glfwPlatformGetTls(&_glfw.errorSlot);
if (!error)
{
error = calloc(1, sizeof(_GLFWerror));
_glfwPlatformSetTls(&_glfw.errorSlot, error);
_glfwPlatformLockMutex(&_glfw.errorLock);
error->next = _glfw.errorListHead;
_glfw.errorListHead = error;
_glfwPlatformUnlockMutex(&_glfw.errorLock);
}
}
else
error = &_glfwMainThreadError;
error->code = code;
strcpy(error->description, description);
if (_glfwErrorCallback)
_glfwErrorCallback(code, description);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW public API //////
//////////////////////////////////////////////////////////////////////////
GLFWAPI int glfwInit(void)
{
if (_glfw.initialized)
return GLFW_TRUE;
memset(&_glfw, 0, sizeof(_glfw));
_glfw.hints.init = _glfwInitHints;
if (!_glfwPlatformInit())
{
terminate();
return GLFW_FALSE;
}
if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
!_glfwPlatformCreateTls(&_glfw.errorSlot) ||
!_glfwPlatformCreateTls(&_glfw.contextSlot))
{
terminate();
return GLFW_FALSE;
}
_glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
_glfw.initialized = GLFW_TRUE;
_glfw.timer.offset = _glfwPlatformGetTimerValue();
glfwDefaultWindowHints();
{
int i;
for (i = 0; _glfwDefaultMappings[i]; i++)
{
if (!glfwUpdateGamepadMappings(_glfwDefaultMappings[i]))
{
terminate();
return GLFW_FALSE;
}
}
}
return GLFW_TRUE;
}
GLFWAPI void glfwTerminate(void)
{
if (!_glfw.initialized)
return;
terminate();
}
GLFWAPI void glfwInitHint(int hint, int value)
{
switch (hint)
{
case GLFW_JOYSTICK_HAT_BUTTONS:
_glfwInitHints.hatButtons = value;
return;
case GLFW_COCOA_CHDIR_RESOURCES:
_glfwInitHints.ns.chdir = value;
return;
case GLFW_COCOA_MENUBAR:
_glfwInitHints.ns.menubar = value;
return;
}
_glfwInputError(GLFW_INVALID_ENUM,
"Invalid init hint 0x%08X", hint);
} }
GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev) GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
{ {
if (major != NULL) if (major != NULL)
*major = GLFW_VERSION_MAJOR; *major = GLFW_VERSION_MAJOR;
if (minor != NULL) if (minor != NULL)
*minor = GLFW_VERSION_MINOR; *minor = GLFW_VERSION_MINOR;
if (rev != NULL) if (rev != NULL)
*rev = GLFW_VERSION_REVISION; *rev = GLFW_VERSION_REVISION;
} }
@ -192,6 +308,30 @@ GLFWAPI const char* glfwGetVersionString(void)
return _glfwPlatformGetVersionString(); return _glfwPlatformGetVersionString();
} }
GLFWAPI int glfwGetError(const char** description)
{
_GLFWerror* error;
int code = GLFW_NO_ERROR;
if (description)
*description = NULL;
if (_glfw.initialized)
error = _glfwPlatformGetTls(&_glfw.errorSlot);
else
error = &_glfwMainThreadError;
if (error)
{
code = error->code;
error->code = GLFW_NO_ERROR;
if (description && code)
*description = error->description;
}
return code;
}
GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun) GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
{ {
_GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun); _GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,478 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 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
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
// As mappings.h.in, this file is used by CMake to produce the mappings.h
// header file. If you are adding a GLFW specific gamepad mapping, this is
// where to put it.
//========================================================================
// As mappings.h, this provides all pre-defined gamepad mappings, including
// all available in SDL_GameControllerDB. Do not edit this file. Any gamepad
// mappings not specific to GLFW should be submitted to SDL_GameControllerDB.
// This file can be re-generated from mappings.h.in and the upstream
// gamecontrollerdb.txt with the GenerateMappings.cmake script.
//========================================================================
// All gamepad mappings not labeled GLFW are copied from the
// SDL_GameControllerDB project under the following license:
//
// Simple DirectMedia Layer
// Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the
// use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 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
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
const char* _glfwDefaultMappings[] =
{
"03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,",
"03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",
"03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",
"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,",
"03000000a00500003232000000000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,",
"030000008f0e00001200000000000000,Acme,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,",
"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,",
"03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows,",
"030000006b1400000055000000000000,bigben ps3padstreetnew,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
"0300000066f700000500000000000000,BrutalLegendTest,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
"03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows,",
"03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
"030000005e0400008e02000000000000,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
"03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows,",
"03000000a306000022f6000000000000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
"03000000791d00000103000000000000,Dual Box WII,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
"030000004f04000023b3000000000000,Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"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,",
"030000000d0f00008500000000000000,Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f00008400000000000000,Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f00008800000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,",
"030000000d0f00008700000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
"78696e70757403000000000000000000,Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows,",
"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,",
"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,",
"030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"03000000280400000140000000000000,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
"03000000ffff00000000000000000000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
"03000000451300000010000000000000,Generic USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
"03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f00004900000000000000,Hatsune Miku Sho Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"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,",
"030000000d0f00005f00000000000000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f00005e00000000000000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f00004000000000000000,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f00006e00000000000000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f00006600000000000000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f0000ee00000000000000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f00004d00000000000000,HORIPAD3 A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"03000000250900000017000000000000,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows,",
"030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Windows,",
"03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
"03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
"03000000830500006020000000000000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Windows,",
"03000000b50700001403000000000000,IMPACT BLACK,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
"030000006f0e00002401000000000000,INJUSTICE FightStick for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
"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,",
"030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows,",
"030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"030000006d04000018c2000000000000,Logitech F510 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"030000006d04000019c2000000000000,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"03000000380700005032000000000000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"03000000380700005082000000000000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"03000000380700008433000000000000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
"03000000380700008483000000000000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b6,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"03000000380700008134000000000000,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"03000000380700008184000000000000,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"03000000380700008532000000000000,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"03000000380700003888000000000000,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"03000000380700001888000000000000,MadCatz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
"03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"030000008305000031b0000000000000,MaxfireBlaze3,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
"03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows,",
"03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
"03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
"030000008f0e00001030000000000000,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows,",
"0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,",
"03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Windows,",
"03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,",
"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
"030000004b120000014d000000000000,NYKO AIRFLO,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,leftx:h0.6,lefty:h0.12,rightshoulder:b5,rightstick:a2,righttrigger:b7,rightx:h0.9,righty:h0.4,start:b9,x:b2,y:b3,platform:Windows,",
"03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,",
"03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",
"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,",
"03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"030000008f0e00007530000000000000,PS (R) Gamepad,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"03000000e30500009605000000000000,PS to USB convert cable,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,",
"03000000100800000100000000000000,PS1 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
"03000000100800000300000000000000,PS2 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
"03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,",
"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,",
"03000000250900000500000000000000,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,",
"03000000100000008200000000000000,PS360+ v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
"030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"03000000300f00000011000000000000,QanBa Arcade JoyStick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows,",
"03000000300f00001611000000000000,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,",
"03000000222c00000020000000000000,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows,",
"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,",
"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,",
"03000000222c00000223000000000000,Qanba Obsidian Arcade Joystick PS3 Mode,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"03000000222c00000023000000000000,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
"030000000d0f00001100000000000000,REAL ARCADE PRO.3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f00008b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f00008a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f00006b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f00006a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f00007000000000000000,REAL ARCADE PRO.4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f00002200000000000000,REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f00005c00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"030000000d0f00005b00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"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,",
"0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,",
"0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,",
"030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"030000006f0e00001e01000000000000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
"030000004f04000003d0000000000000,run'n'drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
"03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
"03000000a306000023f6000000000000,Saitek Cyborg V.1 Game pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
"03000000300f00001201000000000000,Saitek Dual Analog Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
"03000000a30600000cff000000000000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,x:b0,y:b1,platform:Windows,",
"03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
"03000000300f00001001000000000000,Saitek P480 Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
"03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
"03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows,",
"03000000300f00001101000000000000,saitek rumble pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
"0300000000050000289b000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,",
"030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,",
"03000000341a00000208000000000000,SL-6555-SBK,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,",
"030000008f0e00000800000000000000,SpeedLink Strike FX Wireless,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
"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,",
"03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
"03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
"030000004f04000015b3000000000000,Thrustmaster Dual Analog 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,",
"030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows,",
"030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,",
"03000000666600000488000000000000,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,",
"03000000d90400000200000000000000,TwinShock PS2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
"03000000380700006652000000000000,UnKnown,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
"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,",
"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,",
"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,",
"03000000172700004431000000000000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,",
"03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
"03000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",
"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,",
"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,",
"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,",
"030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
"03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X,",
"03000000a306000022f6000001030000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,",
"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,",
"03000000ad1b000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,",
"030000000d0f00005f00000000010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
"030000000d0f00005e00000000010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
"030000000d0f00005f00000000000000,HORI Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
"030000000d0f00005e00000000000000,HORI Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
"030000000d0f00004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
"030000000d0f00006e00000000010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
"030000000d0f00006600000000010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
"030000000d0f00006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
"030000008f0e00001330000011010000,HuiJia SNES Controller,a:b4,b:b2,back:b16,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b12,rightshoulder:b14,start:b18,x:b6,y:b0,platform:Mac OS X,",
"03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,",
"03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,",
"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,",
"030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
"030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
"030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
"030000006d04000015c2000010010000,Logitech Logitech Extreme 3D,a:b0,b:b4,back:b6,guide:b8,leftshoulder:b9,leftstick:h0.8,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:h0.2,start:b7,x:b2,y:b5,platform:Linux,",
"030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
"030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux,",
"05000000380700006652000025010000,Mad Catz C.T.R.L.R ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
"03000000380700005032000011010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
"03000000380700005082000011010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
"03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux,",
"03000000380700008034000011010000,Mad Catz fightstick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
"03000000380700008084000011010000,Mad Catz fightstick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
"03000000380700008433000011010000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
"03000000380700008483000011010000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
"03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
"03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller (SFIV),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
"03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
"03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
"03000000380700003888000010010000,MadCatz PC USB Wired Stick 8838,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
"03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,",
"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,",
"030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
"030000005e0400008e02000062230000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
"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,",
"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,",
"060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
"05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
"050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
"030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
"050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
"050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
"030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
"050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
"030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
"030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
"030000004c050000cc09000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
"030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
"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,",
"030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,",
"030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
"030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
"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,",
"03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
"03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
"050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
"0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
"03000000790000001100000010010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,",
"0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,",
"0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,",
"030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
"030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
"030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
"03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",
"03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,",
"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,",
"03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,",
"03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux,",
"03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",
"03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux,",
"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,",
"03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,",
"030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
"030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
"03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
"03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
"05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
"03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
"03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
"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,",
"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,",
"030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
"030000005e040000a102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
"030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
"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,",
"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,",
"78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"78696e70757403000000000000000000,XInput Arcade Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"78696e70757404000000000000000000,XInput Flight Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
NULL
};

View File

@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.2 - www.glfw.org // GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // Copyright (c) 2006-2019 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
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"
@ -54,6 +56,10 @@ static int compareVideoModes(const void* fp, const void* sp)
if (farea != sarea) if (farea != sarea)
return farea - sarea; return farea - sarea;
// Then sort on width
if (fm->width != sm->width)
return fm->width - sm->width;
// Lastly sort on refresh rate // Lastly sort on refresh rate
return fm->refreshRate - sm->refreshRate; return fm->refreshRate - sm->refreshRate;
} }
@ -86,83 +92,67 @@ static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
////// GLFW event API ////// ////// GLFW event API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void _glfwInputMonitorChange(void) // Notifies shared code of a monitor connection or disconnection
//
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
{ {
int i, j, monitorCount = _glfw.monitorCount; if (action == GLFW_CONNECTED)
_GLFWmonitor** monitors = _glfw.monitors;
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
// Re-use still connected monitor objects
for (i = 0; i < _glfw.monitorCount; i++)
{ {
for (j = 0; j < monitorCount; j++) _glfw.monitorCount++;
_glfw.monitors =
realloc(_glfw.monitors, sizeof(_GLFWmonitor*) * _glfw.monitorCount);
if (placement == _GLFW_INSERT_FIRST)
{ {
if (_glfwPlatformIsSameMonitor(_glfw.monitors[i], monitors[j])) memmove(_glfw.monitors + 1,
{ _glfw.monitors,
_glfwFreeMonitor(_glfw.monitors[i]); ((size_t) _glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
_glfw.monitors[i] = monitors[j]; _glfw.monitors[0] = monitor;
break;
}
} }
else
_glfw.monitors[_glfw.monitorCount - 1] = monitor;
} }
else if (action == GLFW_DISCONNECTED)
// Find and report disconnected monitors (not in the new list)
for (i = 0; i < monitorCount; i++)
{ {
int i;
_GLFWwindow* window; _GLFWwindow* window;
for (j = 0; j < _glfw.monitorCount; j++)
{
if (monitors[i] == _glfw.monitors[j])
break;
}
if (j < _glfw.monitorCount)
continue;
for (window = _glfw.windowListHead; window; window = window->next) for (window = _glfw.windowListHead; window; window = window->next)
{ {
if (window->monitor == monitors[i]) if (window->monitor == monitor)
{ {
int width, height; int width, height, xoff, yoff;
_glfwPlatformGetWindowSize(window, &width, &height); _glfwPlatformGetWindowSize(window, &width, &height);
_glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0); _glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0);
_glfwPlatformGetWindowFrameSize(window, &xoff, &yoff, NULL, NULL);
_glfwPlatformSetWindowPos(window, xoff, yoff);
} }
} }
if (_glfw.callbacks.monitor) for (i = 0; i < _glfw.monitorCount; i++)
_glfw.callbacks.monitor((GLFWmonitor*) monitors[i], GLFW_DISCONNECTED);
}
// Find and report newly connected monitors (not in the old list)
// Re-used monitor objects are then removed from the old list to avoid
// having them destroyed at the end of this function
for (i = 0; i < _glfw.monitorCount; i++)
{
for (j = 0; j < monitorCount; j++)
{ {
if (_glfw.monitors[i] == monitors[j]) if (_glfw.monitors[i] == monitor)
{ {
monitors[j] = NULL; _glfw.monitorCount--;
memmove(_glfw.monitors + i,
_glfw.monitors + i + 1,
((size_t) _glfw.monitorCount - i) * sizeof(_GLFWmonitor*));
break; break;
} }
} }
if (j < monitorCount)
continue;
if (_glfw.callbacks.monitor)
_glfw.callbacks.monitor((GLFWmonitor*) _glfw.monitors[i], GLFW_CONNECTED);
} }
_glfwFreeMonitors(monitors, monitorCount); if (_glfw.callbacks.monitor)
_glfw.callbacks.monitor((GLFWmonitor*) monitor, action);
if (action == GLFW_DISCONNECTED)
_glfwFreeMonitor(monitor);
} }
void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window) // Notifies shared code that a full screen window has acquired or released
// a monitor
//
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
{ {
monitor->window = window; monitor->window = window;
} }
@ -172,21 +162,29 @@ void _glfwInputMonitorWindowChange(_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));
monitor->name = strdup(name);
monitor->widthMM = widthMM; monitor->widthMM = widthMM;
monitor->heightMM = heightMM; monitor->heightMM = heightMM;
if (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);
@ -195,6 +193,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));
@ -203,6 +203,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);
@ -212,16 +214,8 @@ void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
memset(ramp, 0, sizeof(GLFWgammaramp)); memset(ramp, 0, sizeof(GLFWgammaramp));
} }
void _glfwFreeMonitors(_GLFWmonitor** monitors, int count) // Chooses the video mode most closely matching the desired one
{ //
int i;
for (i = 0; i < count; i++)
_glfwFreeMonitor(monitors[i]);
free(monitors);
}
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
const GLFWvidmode* desired) const GLFWvidmode* desired)
{ {
@ -272,11 +266,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;
@ -304,6 +302,7 @@ void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
GLFWAPI GLFWmonitor** glfwGetMonitors(int* count) GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
{ {
assert(count != NULL); assert(count != NULL);
*count = 0; *count = 0;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
@ -337,6 +336,27 @@ GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos)
_glfwPlatformGetMonitorPos(monitor, xpos, ypos); _glfwPlatformGetMonitorPos(monitor, xpos, ypos);
} }
GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle,
int* xpos, int* ypos,
int* width, int* height)
{
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
if (xpos)
*xpos = 0;
if (ypos)
*ypos = 0;
if (width)
*width = 0;
if (height)
*height = 0;
_GLFW_REQUIRE_INIT();
_glfwPlatformGetMonitorWorkarea(monitor, xpos, ypos, width, height);
}
GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM) GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
@ -355,6 +375,21 @@ GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int*
*heightMM = monitor->heightMM; *heightMM = monitor->heightMM;
} }
GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* handle,
float* xscale, float* yscale)
{
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
if (xscale)
*xscale = 0.f;
if (yscale)
*yscale = 0.f;
_GLFW_REQUIRE_INIT();
_glfwPlatformGetMonitorContentScale(monitor, xscale, yscale);
}
GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle) GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
@ -364,6 +399,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);
@ -401,9 +454,13 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle)
GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma) GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
{ {
int i; unsigned int i;
unsigned short values[256]; unsigned short* values;
GLFWgammaramp ramp; GLFWgammaramp ramp;
const GLFWgammaramp* original;
assert(handle != NULL);
assert(gamma > 0.f);
assert(gamma <= FLT_MAX);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
@ -413,18 +470,22 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
return; return;
} }
for (i = 0; i < 256; i++) original = glfwGetGammaRamp(handle);
if (!original)
return;
values = calloc(original->size, sizeof(unsigned short));
for (i = 0; i < original->size; i++)
{ {
double value; float value;
// Calculate intensity // Calculate intensity
value = i / 255.0; value = i / (float) (original->size - 1);
// 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) value = _glfw_fminf(value, 65535.f);
value = 65535.0;
values[i] = (unsigned short) value; values[i] = (unsigned short) value;
} }
@ -432,9 +493,10 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
ramp.red = values; ramp.red = values;
ramp.green = values; ramp.green = values;
ramp.blue = values; ramp.blue = values;
ramp.size = 256; ramp.size = original->size;
glfwSetGammaRamp(handle, &ramp); glfwSetGammaRamp(handle, &ramp);
free(values);
} }
GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle) GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
@ -445,7 +507,8 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_glfwFreeGammaArrays(&monitor->currentRamp); _glfwFreeGammaArrays(&monitor->currentRamp);
_glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp); if (!_glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp))
return NULL;
return &monitor->currentRamp; return &monitor->currentRamp;
} }
@ -455,6 +518,7 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL); assert(monitor != NULL);
assert(ramp != NULL); assert(ramp != NULL);
assert(ramp->size > 0);
assert(ramp->red != NULL); assert(ramp->red != NULL);
assert(ramp->green != NULL); assert(ramp->green != NULL);
assert(ramp->blue != NULL); assert(ramp->blue != NULL);
@ -470,7 +534,10 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (!monitor->originalRamp.size) if (!monitor->originalRamp.size)
_glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp); {
if (!_glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp))
return;
}
_glfwPlatformSetGammaRamp(monitor, ramp); _glfwPlatformSetGammaRamp(monitor, ramp);
} }

View File

@ -0,0 +1,372 @@
//========================================================================
// GLFW 3.3 OSMesa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 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
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "internal.h"
static void makeContextCurrentOSMesa(_GLFWwindow* window)
{
if (window)
{
int width, height;
_glfwPlatformGetFramebufferSize(window, &width, &height);
// Check to see if we need to allocate a new buffer
if ((window->context.osmesa.buffer == NULL) ||
(width != window->context.osmesa.width) ||
(height != window->context.osmesa.height))
{
free(window->context.osmesa.buffer);
// Allocate the new buffer (width * height * 8-bit RGBA)
window->context.osmesa.buffer = calloc(4, (size_t) width * height);
window->context.osmesa.width = width;
window->context.osmesa.height = height;
}
if (!OSMesaMakeCurrent(window->context.osmesa.handle,
window->context.osmesa.buffer,
GL_UNSIGNED_BYTE,
width, height))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"OSMesa: Failed to make context current");
return;
}
}
_glfwPlatformSetTls(&_glfw.contextSlot, window);
}
static GLFWglproc getProcAddressOSMesa(const char* procname)
{
return (GLFWglproc) OSMesaGetProcAddress(procname);
}
static void destroyContextOSMesa(_GLFWwindow* window)
{
if (window->context.osmesa.handle)
{
OSMesaDestroyContext(window->context.osmesa.handle);
window->context.osmesa.handle = NULL;
}
if (window->context.osmesa.buffer)
{
free(window->context.osmesa.buffer);
window->context.osmesa.width = 0;
window->context.osmesa.height = 0;
}
}
static void swapBuffersOSMesa(_GLFWwindow* window)
{
// No double buffering on OSMesa
}
static void swapIntervalOSMesa(int interval)
{
// No swap interval on OSMesa
}
static int extensionSupportedOSMesa(const char* extension)
{
// OSMesa does not have extensions
return GLFW_FALSE;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
GLFWbool _glfwInitOSMesa(void)
{
int i;
const char* sonames[] =
{
#if defined(_GLFW_OSMESA_LIBRARY)
_GLFW_OSMESA_LIBRARY,
#elif defined(_WIN32)
"libOSMesa.dll",
"OSMesa.dll",
#elif defined(__APPLE__)
"libOSMesa.8.dylib",
#elif defined(__CYGWIN__)
"libOSMesa-8.so",
#else
"libOSMesa.so.8",
"libOSMesa.so.6",
#endif
NULL
};
if (_glfw.osmesa.handle)
return GLFW_TRUE;
for (i = 0; sonames[i]; i++)
{
_glfw.osmesa.handle = _glfw_dlopen(sonames[i]);
if (_glfw.osmesa.handle)
break;
}
if (!_glfw.osmesa.handle)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: Library not found");
return GLFW_FALSE;
}
_glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt)
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextExt");
_glfw.osmesa.CreateContextAttribs = (PFN_OSMesaCreateContextAttribs)
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextAttribs");
_glfw.osmesa.DestroyContext = (PFN_OSMesaDestroyContext)
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaDestroyContext");
_glfw.osmesa.MakeCurrent = (PFN_OSMesaMakeCurrent)
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaMakeCurrent");
_glfw.osmesa.GetColorBuffer = (PFN_OSMesaGetColorBuffer)
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetColorBuffer");
_glfw.osmesa.GetDepthBuffer = (PFN_OSMesaGetDepthBuffer)
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetDepthBuffer");
_glfw.osmesa.GetProcAddress = (PFN_OSMesaGetProcAddress)
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetProcAddress");
if (!_glfw.osmesa.CreateContextExt ||
!_glfw.osmesa.DestroyContext ||
!_glfw.osmesa.MakeCurrent ||
!_glfw.osmesa.GetColorBuffer ||
!_glfw.osmesa.GetDepthBuffer ||
!_glfw.osmesa.GetProcAddress)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"OSMesa: Failed to load required entry points");
_glfwTerminateOSMesa();
return GLFW_FALSE;
}
return GLFW_TRUE;
}
void _glfwTerminateOSMesa(void)
{
if (_glfw.osmesa.handle)
{
_glfw_dlclose(_glfw.osmesa.handle);
_glfw.osmesa.handle = NULL;
}
}
#define setAttrib(a, v) \
{ \
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \
attribs[index++] = v; \
}
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
OSMesaContext share = NULL;
const int accumBits = fbconfig->accumRedBits +
fbconfig->accumGreenBits +
fbconfig->accumBlueBits +
fbconfig->accumAlphaBits;
if (ctxconfig->client == GLFW_OPENGL_ES_API)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"OSMesa: OpenGL ES is not available on OSMesa");
return GLFW_FALSE;
}
if (ctxconfig->share)
share = ctxconfig->share->context.osmesa.handle;
if (OSMesaCreateContextAttribs)
{
int index = 0, attribs[40];
setAttrib(OSMESA_FORMAT, OSMESA_RGBA);
setAttrib(OSMESA_DEPTH_BITS, fbconfig->depthBits);
setAttrib(OSMESA_STENCIL_BITS, fbconfig->stencilBits);
setAttrib(OSMESA_ACCUM_BITS, accumBits);
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
{
setAttrib(OSMESA_PROFILE, OSMESA_CORE_PROFILE);
}
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
{
setAttrib(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE);
}
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{
setAttrib(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major);
setAttrib(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor);
}
if (ctxconfig->forward)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"OSMesa: Forward-compatible contexts not supported");
return GLFW_FALSE;
}
setAttrib(0, 0);
window->context.osmesa.handle =
OSMesaCreateContextAttribs(attribs, share);
}
else
{
if (ctxconfig->profile)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"OSMesa: OpenGL profiles unavailable");
return GLFW_FALSE;
}
window->context.osmesa.handle =
OSMesaCreateContextExt(OSMESA_RGBA,
fbconfig->depthBits,
fbconfig->stencilBits,
accumBits,
share);
}
if (window->context.osmesa.handle == NULL)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"OSMesa: Failed to create context");
return GLFW_FALSE;
}
window->context.makeCurrent = makeContextCurrentOSMesa;
window->context.swapBuffers = swapBuffersOSMesa;
window->context.swapInterval = swapIntervalOSMesa;
window->context.extensionSupported = extensionSupportedOSMesa;
window->context.getProcAddress = getProcAddressOSMesa;
window->context.destroy = destroyContextOSMesa;
return GLFW_TRUE;
}
#undef setAttrib
//////////////////////////////////////////////////////////////////////////
////// GLFW native API //////
//////////////////////////////////////////////////////////////////////////
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
int* height, int* format, void** buffer)
{
void* mesaBuffer;
GLint mesaWidth, mesaHeight, mesaFormat;
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
if (!OSMesaGetColorBuffer(window->context.osmesa.handle,
&mesaWidth, &mesaHeight,
&mesaFormat, &mesaBuffer))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"OSMesa: Failed to retrieve color buffer");
return GLFW_FALSE;
}
if (width)
*width = mesaWidth;
if (height)
*height = mesaHeight;
if (format)
*format = mesaFormat;
if (buffer)
*buffer = mesaBuffer;
return GLFW_TRUE;
}
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
int* width, int* height,
int* bytesPerValue,
void** buffer)
{
void* mesaBuffer;
GLint mesaWidth, mesaHeight, mesaBytes;
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
if (!OSMesaGetDepthBuffer(window->context.osmesa.handle,
&mesaWidth, &mesaHeight,
&mesaBytes, &mesaBuffer))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"OSMesa: Failed to retrieve depth buffer");
return GLFW_FALSE;
}
if (width)
*width = mesaWidth;
if (height)
*height = mesaHeight;
if (bytesPerValue)
*bytesPerValue = mesaBytes;
if (buffer)
*buffer = mesaBuffer;
return GLFW_TRUE;
}
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (window->context.client == GLFW_NO_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL;
}
return window->context.osmesa.handle;
}

View File

@ -0,0 +1,94 @@
//========================================================================
// GLFW 3.3 OSMesa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 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
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#define OSMESA_RGBA 0x1908
#define OSMESA_FORMAT 0x22
#define OSMESA_DEPTH_BITS 0x30
#define OSMESA_STENCIL_BITS 0x31
#define OSMESA_ACCUM_BITS 0x32
#define OSMESA_PROFILE 0x33
#define OSMESA_CORE_PROFILE 0x34
#define OSMESA_COMPAT_PROFILE 0x35
#define OSMESA_CONTEXT_MAJOR_VERSION 0x36
#define OSMESA_CONTEXT_MINOR_VERSION 0x37
typedef void* OSMesaContext;
typedef void (*OSMESAproc)(void);
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextExt)(GLenum,GLint,GLint,GLint,OSMesaContext);
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextAttribs)(const int*,OSMesaContext);
typedef void (GLAPIENTRY * PFN_OSMesaDestroyContext)(OSMesaContext);
typedef int (GLAPIENTRY * PFN_OSMesaMakeCurrent)(OSMesaContext,void*,int,int,int);
typedef int (GLAPIENTRY * PFN_OSMesaGetColorBuffer)(OSMesaContext,int*,int*,int*,void**);
typedef int (GLAPIENTRY * PFN_OSMesaGetDepthBuffer)(OSMesaContext,int*,int*,int*,void**);
typedef GLFWglproc (GLAPIENTRY * PFN_OSMesaGetProcAddress)(const char*);
#define OSMesaCreateContextExt _glfw.osmesa.CreateContextExt
#define OSMesaCreateContextAttribs _glfw.osmesa.CreateContextAttribs
#define OSMesaDestroyContext _glfw.osmesa.DestroyContext
#define OSMesaMakeCurrent _glfw.osmesa.MakeCurrent
#define OSMesaGetColorBuffer _glfw.osmesa.GetColorBuffer
#define OSMesaGetDepthBuffer _glfw.osmesa.GetDepthBuffer
#define OSMesaGetProcAddress _glfw.osmesa.GetProcAddress
#define _GLFW_OSMESA_CONTEXT_STATE _GLFWcontextOSMesa osmesa
#define _GLFW_OSMESA_LIBRARY_CONTEXT_STATE _GLFWlibraryOSMesa osmesa
// OSMesa-specific per-context data
//
typedef struct _GLFWcontextOSMesa
{
OSMesaContext handle;
int width;
int height;
void* buffer;
} _GLFWcontextOSMesa;
// OSMesa-specific global data
//
typedef struct _GLFWlibraryOSMesa
{
void* handle;
PFN_OSMesaCreateContextExt CreateContextExt;
PFN_OSMesaCreateContextAttribs CreateContextAttribs;
PFN_OSMesaDestroyContext DestroyContext;
PFN_OSMesaMakeCurrent MakeCurrent;
PFN_OSMesaGetColorBuffer GetColorBuffer;
PFN_OSMesaGetDepthBuffer GetDepthBuffer;
PFN_OSMesaGetProcAddress GetProcAddress;
} _GLFWlibraryOSMesa;
GLFWbool _glfwInitOSMesa(void);
void _glfwTerminateOSMesa(void);
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig);

View File

@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.2 - www.glfw.org // GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // Copyright (c) 2006-2018 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
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"
@ -31,30 +33,40 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#define _GLFW_FIND_LOADER 1
#define _GLFW_REQUIRE_LOADER 2
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
GLFWbool _glfwInitVulkan(void) GLFWbool _glfwInitVulkan(int mode)
{ {
VkResult err; VkResult err;
VkExtensionProperties* ep; VkExtensionProperties* ep;
uint32_t i, count; uint32_t i, count;
#if !defined(_GLFW_VULKAN_STATIC)
#if defined(_GLFW_WIN32)
const char* name = "vulkan-1.dll";
#else
const char* name = "libvulkan.so.1";
#endif
if (_glfw.vk.available) if (_glfw.vk.available)
return GLFW_TRUE; return GLFW_TRUE;
_glfw.vk.handle = _glfw_dlopen(name); #if !defined(_GLFW_VULKAN_STATIC)
#if defined(_GLFW_VULKAN_LIBRARY)
_glfw.vk.handle = _glfw_dlopen(_GLFW_VULKAN_LIBRARY);
#elif defined(_GLFW_WIN32)
_glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
#elif defined(_GLFW_COCOA)
_glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
#else
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
#endif
if (!_glfw.vk.handle) if (!_glfw.vk.handle)
{
if (mode == _GLFW_REQUIRE_LOADER)
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
return GLFW_FALSE; return GLFW_FALSE;
}
_glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) _glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
_glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr"); _glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
@ -82,9 +94,13 @@ GLFWbool _glfwInitVulkan(void)
err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL); err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
if (err) if (err)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, // NOTE: This happens on systems with a loader but without any Vulkan ICD
"Vulkan: Failed to query instance extension count: %s", if (mode == _GLFW_REQUIRE_LOADER)
_glfwGetVulkanResultString(err)); {
_glfwInputError(GLFW_API_UNAVAILABLE,
"Vulkan: Failed to query instance extension count: %s",
_glfwGetVulkanResultString(err));
}
_glfwTerminateVulkan(); _glfwTerminateVulkan();
return GLFW_FALSE; return GLFW_FALSE;
@ -95,7 +111,7 @@ GLFWbool _glfwInitVulkan(void)
err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep); err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep);
if (err) if (err)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_API_UNAVAILABLE,
"Vulkan: Failed to query instance extensions: %s", "Vulkan: Failed to query instance extensions: %s",
_glfwGetVulkanResultString(err)); _glfwGetVulkanResultString(err));
@ -108,41 +124,38 @@ GLFWbool _glfwInitVulkan(void)
{ {
if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0) if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
_glfw.vk.KHR_surface = GLFW_TRUE; _glfw.vk.KHR_surface = GLFW_TRUE;
if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0) #if defined(_GLFW_WIN32)
else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
_glfw.vk.KHR_win32_surface = GLFW_TRUE; _glfw.vk.KHR_win32_surface = GLFW_TRUE;
if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0) #elif defined(_GLFW_COCOA)
else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
_glfw.vk.MVK_macos_surface = GLFW_TRUE;
#elif defined(_GLFW_X11)
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
_glfw.vk.KHR_xlib_surface = GLFW_TRUE; _glfw.vk.KHR_xlib_surface = GLFW_TRUE;
if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0) else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
_glfw.vk.KHR_xcb_surface = GLFW_TRUE; _glfw.vk.KHR_xcb_surface = GLFW_TRUE;
if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0) #elif defined(_GLFW_WAYLAND)
else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
_glfw.vk.KHR_wayland_surface = GLFW_TRUE; _glfw.vk.KHR_wayland_surface = GLFW_TRUE;
if (strcmp(ep[i].extensionName, "VK_KHR_mir_surface") == 0) #endif
_glfw.vk.KHR_mir_surface = GLFW_TRUE;
} }
free(ep); free(ep);
_glfw.vk.available = GLFW_TRUE; _glfw.vk.available = GLFW_TRUE;
if (_glfw.vk.KHR_surface) _glfwPlatformGetRequiredInstanceExtensions(_glfw.vk.extensions);
{
_glfw.vk.extensions =
_glfwPlatformGetRequiredInstanceExtensions(&_glfw.vk.extensionCount);
}
return GLFW_TRUE; return GLFW_TRUE;
} }
void _glfwTerminateVulkan(void) void _glfwTerminateVulkan(void)
{ {
uint32_t i; #if !defined(_GLFW_VULKAN_STATIC)
for (i = 0; i < _glfw.vk.extensionCount; i++)
free(_glfw.vk.extensions[i]);
free(_glfw.vk.extensions);
if (_glfw.vk.handle) if (_glfw.vk.handle)
_glfw_dlclose(_glfw.vk.handle); _glfw_dlclose(_glfw.vk.handle);
#endif
} }
const char* _glfwGetVulkanResultString(VkResult result) const char* _glfwGetVulkanResultString(VkResult result)
@ -208,22 +221,24 @@ const char* _glfwGetVulkanResultString(VkResult result)
GLFWAPI int glfwVulkanSupported(void) GLFWAPI int glfwVulkanSupported(void)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
return _glfwInitVulkan(); return _glfwInitVulkan(_GLFW_FIND_LOADER);
} }
GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count) GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
{ {
assert(count != NULL);
*count = 0; *count = 0;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (!_glfwInitVulkan()) if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
{
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
return NULL; return NULL;
}
*count = _glfw.vk.extensionCount; if (!_glfw.vk.extensions[0])
return NULL;
*count = 2;
return (const char**) _glfw.vk.extensions; return (const char**) _glfw.vk.extensions;
} }
@ -231,18 +246,24 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
const char* procname) const char* procname)
{ {
GLFWvkproc proc; GLFWvkproc proc;
assert(procname != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (!_glfwInitVulkan()) if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
{
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
return NULL; return NULL;
}
proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname); proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
#if defined(_GLFW_VULKAN_STATIC)
if (!proc)
{
if (strcmp(procname, "vkGetInstanceProcAddr") == 0)
return (GLFWvkproc) vkGetInstanceProcAddr;
}
#else
if (!proc) if (!proc)
proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname); proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);
#endif
return proc; return proc;
} }
@ -251,15 +272,15 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device, VkPhysicalDevice device,
uint32_t queuefamily) uint32_t queuefamily)
{ {
assert(instance != VK_NULL_HANDLE);
assert(device != VK_NULL_HANDLE);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
if (!_glfwInitVulkan()) if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
{
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
return GLFW_FALSE; return GLFW_FALSE;
}
if (!_glfw.vk.extensions) if (!_glfw.vk.extensions[0])
{ {
_glfwInputError(GLFW_API_UNAVAILABLE, _glfwInputError(GLFW_API_UNAVAILABLE,
"Vulkan: Window surface creation extensions not found"); "Vulkan: Window surface creation extensions not found");
@ -277,6 +298,7 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
VkSurfaceKHR* surface) VkSurfaceKHR* surface)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(instance != VK_NULL_HANDLE);
assert(window != NULL); assert(window != NULL);
assert(surface != NULL); assert(surface != NULL);
@ -284,19 +306,23 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
_GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED); _GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
if (!_glfwInitVulkan()) if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
{
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
return VK_ERROR_INITIALIZATION_FAILED; return VK_ERROR_INITIALIZATION_FAILED;
}
if (!_glfw.vk.extensions) if (!_glfw.vk.extensions[0])
{ {
_glfwInputError(GLFW_API_UNAVAILABLE, _glfwInputError(GLFW_API_UNAVAILABLE,
"Vulkan: Window surface creation extensions not found"); "Vulkan: Window surface creation extensions not found");
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

@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.2 WGL - www.glfw.org // GLFW 3.3 WGL - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // Copyright (c) 2006-2019 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
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"
@ -31,41 +33,94 @@
#include <malloc.h> #include <malloc.h>
#include <assert.h> #include <assert.h>
// Return the value corresponding to the specified attribute
// Returns the specified attribute of the specified pixel format
// //
static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib) static int findPixelFormatAttribValue(const int* attribs,
int attribCount,
const int* values,
int attrib)
{ {
int value = 0; int i;
assert(_glfw.wgl.ARB_pixel_format); for (i = 0; i < attribCount; i++)
if (!_glfw.wgl.GetPixelFormatAttribivARB(window->context.wgl.dc,
pixelFormat,
0, 1, &attrib, &value))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, if (attribs[i] == attrib)
"WGL: Failed to retrieve pixel format attribute %i", return values[i];
attrib);
return 0;
} }
return value; _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Unknown pixel format attribute requested");
return 0;
} }
#define addAttrib(a) \
{ \
assert((size_t) attribCount < sizeof(attribs) / sizeof(attribs[0])); \
attribs[attribCount++] = a; \
}
#define findAttribValue(a) \
findPixelFormatAttribValue(attribs, attribCount, values, a)
// Return a list of available and usable framebuffer configs // Return a list of available and usable framebuffer configs
// //
static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired) static int choosePixelFormat(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{ {
_GLFWfbconfig* usableConfigs; _GLFWfbconfig* usableConfigs;
const _GLFWfbconfig* closest; const _GLFWfbconfig* closest;
int i, pixelFormat, nativeCount, usableCount; int i, pixelFormat, nativeCount, usableCount = 0, attribCount = 0;
int attribs[40];
int values[sizeof(attribs) / sizeof(attribs[0])];
if (_glfw.wgl.ARB_pixel_format) if (_glfw.wgl.ARB_pixel_format)
{ {
nativeCount = getPixelFormatAttrib(window, const int attrib = WGL_NUMBER_PIXEL_FORMATS_ARB;
1,
WGL_NUMBER_PIXEL_FORMATS_ARB); if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc,
1, 0, 1, &attrib, &nativeCount))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve pixel format attribute");
return 0;
}
addAttrib(WGL_SUPPORT_OPENGL_ARB);
addAttrib(WGL_DRAW_TO_WINDOW_ARB);
addAttrib(WGL_PIXEL_TYPE_ARB);
addAttrib(WGL_ACCELERATION_ARB);
addAttrib(WGL_RED_BITS_ARB);
addAttrib(WGL_RED_SHIFT_ARB);
addAttrib(WGL_GREEN_BITS_ARB);
addAttrib(WGL_GREEN_SHIFT_ARB);
addAttrib(WGL_BLUE_BITS_ARB);
addAttrib(WGL_BLUE_SHIFT_ARB);
addAttrib(WGL_ALPHA_BITS_ARB);
addAttrib(WGL_ALPHA_SHIFT_ARB);
addAttrib(WGL_DEPTH_BITS_ARB);
addAttrib(WGL_STENCIL_BITS_ARB);
addAttrib(WGL_ACCUM_BITS_ARB);
addAttrib(WGL_ACCUM_RED_BITS_ARB);
addAttrib(WGL_ACCUM_GREEN_BITS_ARB);
addAttrib(WGL_ACCUM_BLUE_BITS_ARB);
addAttrib(WGL_ACCUM_ALPHA_BITS_ARB);
addAttrib(WGL_AUX_BUFFERS_ARB);
addAttrib(WGL_STEREO_ARB);
addAttrib(WGL_DOUBLE_BUFFER_ARB);
if (_glfw.wgl.ARB_multisample)
addAttrib(WGL_SAMPLES_ARB);
if (ctxconfig->client == GLFW_OPENGL_API)
{
if (_glfw.wgl.ARB_framebuffer_sRGB || _glfw.wgl.EXT_framebuffer_sRGB)
addAttrib(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
}
else
{
if (_glfw.wgl.EXT_colorspace)
addAttrib(WGL_COLORSPACE_EXT);
}
} }
else else
{ {
@ -76,77 +131,97 @@ static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired)
} }
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig)); usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
usableCount = 0;
for (i = 0; i < nativeCount; i++) for (i = 0; i < nativeCount; i++)
{ {
const int n = i + 1;
_GLFWfbconfig* u = usableConfigs + usableCount; _GLFWfbconfig* u = usableConfigs + usableCount;
pixelFormat = i + 1;
if (_glfw.wgl.ARB_pixel_format) if (_glfw.wgl.ARB_pixel_format)
{ {
// Get pixel format attributes through "modern" extension // Get pixel format attributes through "modern" extension
if (!getPixelFormatAttrib(window, n, WGL_SUPPORT_OPENGL_ARB) || if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc,
!getPixelFormatAttrib(window, n, WGL_DRAW_TO_WINDOW_ARB)) pixelFormat, 0,
attribCount,
attribs, values))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve pixel format attributes");
free(usableConfigs);
return 0;
}
if (!findAttribValue(WGL_SUPPORT_OPENGL_ARB) ||
!findAttribValue(WGL_DRAW_TO_WINDOW_ARB))
{ {
continue; continue;
} }
if (getPixelFormatAttrib(window, n, WGL_PIXEL_TYPE_ARB) != if (findAttribValue(WGL_PIXEL_TYPE_ARB) != WGL_TYPE_RGBA_ARB)
WGL_TYPE_RGBA_ARB)
{
continue; continue;
}
if (getPixelFormatAttrib(window, n, WGL_ACCELERATION_ARB) == if (findAttribValue(WGL_ACCELERATION_ARB) == WGL_NO_ACCELERATION_ARB)
WGL_NO_ACCELERATION_ARB)
{
continue; continue;
}
u->redBits = getPixelFormatAttrib(window, n, WGL_RED_BITS_ARB); u->redBits = findAttribValue(WGL_RED_BITS_ARB);
u->greenBits = getPixelFormatAttrib(window, n, WGL_GREEN_BITS_ARB); u->greenBits = findAttribValue(WGL_GREEN_BITS_ARB);
u->blueBits = getPixelFormatAttrib(window, n, WGL_BLUE_BITS_ARB); u->blueBits = findAttribValue(WGL_BLUE_BITS_ARB);
u->alphaBits = getPixelFormatAttrib(window, n, WGL_ALPHA_BITS_ARB); u->alphaBits = findAttribValue(WGL_ALPHA_BITS_ARB);
u->depthBits = getPixelFormatAttrib(window, n, WGL_DEPTH_BITS_ARB); u->depthBits = findAttribValue(WGL_DEPTH_BITS_ARB);
u->stencilBits = getPixelFormatAttrib(window, n, WGL_STENCIL_BITS_ARB); u->stencilBits = findAttribValue(WGL_STENCIL_BITS_ARB);
u->accumRedBits = getPixelFormatAttrib(window, n, WGL_ACCUM_RED_BITS_ARB); u->accumRedBits = findAttribValue(WGL_ACCUM_RED_BITS_ARB);
u->accumGreenBits = getPixelFormatAttrib(window, n, WGL_ACCUM_GREEN_BITS_ARB); u->accumGreenBits = findAttribValue(WGL_ACCUM_GREEN_BITS_ARB);
u->accumBlueBits = getPixelFormatAttrib(window, n, WGL_ACCUM_BLUE_BITS_ARB); u->accumBlueBits = findAttribValue(WGL_ACCUM_BLUE_BITS_ARB);
u->accumAlphaBits = getPixelFormatAttrib(window, n, WGL_ACCUM_ALPHA_BITS_ARB); u->accumAlphaBits = findAttribValue(WGL_ACCUM_ALPHA_BITS_ARB);
u->auxBuffers = getPixelFormatAttrib(window, n, WGL_AUX_BUFFERS_ARB); u->auxBuffers = findAttribValue(WGL_AUX_BUFFERS_ARB);
if (getPixelFormatAttrib(window, n, WGL_STEREO_ARB)) if (findAttribValue(WGL_STEREO_ARB))
u->stereo = GLFW_TRUE; u->stereo = GLFW_TRUE;
if (getPixelFormatAttrib(window, n, WGL_DOUBLE_BUFFER_ARB)) if (findAttribValue(WGL_DOUBLE_BUFFER_ARB))
u->doublebuffer = GLFW_TRUE; u->doublebuffer = GLFW_TRUE;
if (_glfw.wgl.ARB_multisample) if (_glfw.wgl.ARB_multisample)
u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB); u->samples = findAttribValue(WGL_SAMPLES_ARB);
if (_glfw.wgl.ARB_framebuffer_sRGB || if (ctxconfig->client == GLFW_OPENGL_API)
_glfw.wgl.EXT_framebuffer_sRGB)
{ {
if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB)) if (_glfw.wgl.ARB_framebuffer_sRGB ||
u->sRGB = GLFW_TRUE; _glfw.wgl.EXT_framebuffer_sRGB)
{
if (findAttribValue(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
u->sRGB = GLFW_TRUE;
}
}
else
{
if (_glfw.wgl.EXT_colorspace)
{
if (findAttribValue(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT)
u->sRGB = GLFW_TRUE;
}
} }
} }
else else
{ {
PIXELFORMATDESCRIPTOR pfd;
// Get pixel format attributes through legacy PFDs // Get pixel format attributes through legacy PFDs
PIXELFORMATDESCRIPTOR pfd;
if (!DescribePixelFormat(window->context.wgl.dc, if (!DescribePixelFormat(window->context.wgl.dc,
n, pixelFormat,
sizeof(PIXELFORMATDESCRIPTOR), sizeof(PIXELFORMATDESCRIPTOR),
&pfd)) &pfd))
{ {
continue; _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to describe pixel format");
free(usableConfigs);
return 0;
} }
if (!(pfd.dwFlags & PFD_DRAW_TO_WINDOW) || if (!(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
@ -185,7 +260,7 @@ static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired)
u->doublebuffer = GLFW_TRUE; u->doublebuffer = GLFW_TRUE;
} }
u->handle = n; u->handle = pixelFormat;
usableCount++; usableCount++;
} }
@ -198,7 +273,7 @@ static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired)
return 0; return 0;
} }
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount); closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);
if (!closest) if (!closest)
{ {
_glfwInputError(GLFW_FORMAT_UNAVAILABLE, _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
@ -214,54 +289,52 @@ static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired)
return pixelFormat; return pixelFormat;
} }
// Returns whether desktop compositing is enabled #undef addAttrib
// #undef findAttribValue
static GLFWbool isCompositionEnabled(void)
{
BOOL enabled;
if (!_glfw_DwmIsCompositionEnabled)
return FALSE;
if (_glfw_DwmIsCompositionEnabled(&enabled) != S_OK)
return FALSE;
return enabled;
}
static void makeContextCurrentWGL(_GLFWwindow* window) static void makeContextCurrentWGL(_GLFWwindow* window)
{ {
if (window) if (window)
{ {
if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle)) if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
_glfwPlatformSetCurrentContext(window); _glfwPlatformSetTls(&_glfw.contextSlot, window);
else else
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to make context current"); "WGL: Failed to make context current");
_glfwPlatformSetCurrentContext(NULL); _glfwPlatformSetTls(&_glfw.contextSlot, NULL);
} }
} }
else else
{ {
if (!wglMakeCurrent(NULL, NULL)) if (!wglMakeCurrent(NULL, NULL))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to clear current context"); "WGL: Failed to clear current context");
} }
_glfwPlatformSetCurrentContext(NULL); _glfwPlatformSetTls(&_glfw.contextSlot, NULL);
} }
} }
static void swapBuffersWGL(_GLFWwindow* window) static void swapBuffersWGL(_GLFWwindow* window)
{ {
// HACK: Use DwmFlush when desktop composition is enabled if (!window->monitor)
if (isCompositionEnabled() && !window->monitor)
{ {
int count = abs(window->context.wgl.interval); if (IsWindowsVistaOrGreater())
while (count--) {
_glfw_DwmFlush(); // DWM Composition is always enabled on Win8+
BOOL enabled = IsWindows8OrGreater();
// HACK: Use DwmFlush when desktop composition is enabled
if (enabled ||
(SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled))
{
int count = abs(window->context.wgl.interval);
while (count--)
DwmFlush();
}
}
} }
SwapBuffers(window->context.wgl.dc); SwapBuffers(window->context.wgl.dc);
@ -269,44 +342,42 @@ static void swapBuffersWGL(_GLFWwindow* window)
static void swapIntervalWGL(int interval) static void swapIntervalWGL(int interval)
{ {
_GLFWwindow* window = _glfwPlatformGetCurrentContext(); _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
window->context.wgl.interval = interval; window->context.wgl.interval = interval;
// HACK: Disable WGL swap interval when desktop composition is enabled to if (!window->monitor)
// avoid interfering with DWM vsync {
if (isCompositionEnabled() && !window->monitor) if (IsWindowsVistaOrGreater())
interval = 0; {
// DWM Composition is always enabled on Win8+
BOOL enabled = IsWindows8OrGreater();
// HACK: Disable WGL swap interval when desktop composition is enabled to
// avoid interfering with DWM vsync
if (enabled ||
(SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled))
interval = 0;
}
}
if (_glfw.wgl.EXT_swap_control) if (_glfw.wgl.EXT_swap_control)
_glfw.wgl.SwapIntervalEXT(interval); wglSwapIntervalEXT(interval);
} }
static int extensionSupportedWGL(const char* extension) static int extensionSupportedWGL(const char* extension)
{ {
const char* extensions; const char* extensions = NULL;
if (_glfw.wgl.GetExtensionsStringEXT)
{
extensions = _glfw.wgl.GetExtensionsStringEXT();
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
}
if (_glfw.wgl.GetExtensionsStringARB) if (_glfw.wgl.GetExtensionsStringARB)
{ extensions = wglGetExtensionsStringARB(wglGetCurrentDC());
extensions = _glfw.wgl.GetExtensionsStringARB(wglGetCurrentDC()); else if (_glfw.wgl.GetExtensionsStringEXT)
if (extensions) extensions = wglGetExtensionsStringEXT();
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
}
return GLFW_FALSE; if (!extensions)
return GLFW_FALSE;
return _glfwStringInExtensionString(extension, extensions);
} }
static GLFWglproc getProcAddressWGL(const char* procname) static GLFWglproc getProcAddressWGL(const char* procname)
@ -318,8 +389,6 @@ static GLFWglproc getProcAddressWGL(const char* procname)
return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname); return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname);
} }
// Destroy the OpenGL context
//
static void destroyContextWGL(_GLFWwindow* window) static void destroyContextWGL(_GLFWwindow* window)
{ {
if (window->context.wgl.handle) if (window->context.wgl.handle)
@ -329,21 +398,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;
@ -353,26 +453,29 @@ static void loadWGLExtensions(void)
if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd)) if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd))
{ {
_glfwInputError(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);
if (!rc) if (!rc)
{ {
_glfwInputError(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,
"WGL: Failed to make dummy context current");
wglMakeCurrent(pdc, prc);
wglDeleteContext(rc); wglDeleteContext(rc);
return GLFW_FALSE;
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to make dummy context current");
return;
} }
// 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
@ -404,49 +507,19 @@ static void loadWGLExtensions(void)
extensionSupportedWGL("WGL_EXT_create_context_es2_profile"); extensionSupportedWGL("WGL_EXT_create_context_es2_profile");
_glfw.wgl.ARB_create_context_robustness = _glfw.wgl.ARB_create_context_robustness =
extensionSupportedWGL("WGL_ARB_create_context_robustness"); extensionSupportedWGL("WGL_ARB_create_context_robustness");
_glfw.wgl.ARB_create_context_no_error =
extensionSupportedWGL("WGL_ARB_create_context_no_error");
_glfw.wgl.EXT_swap_control = _glfw.wgl.EXT_swap_control =
extensionSupportedWGL("WGL_EXT_swap_control"); extensionSupportedWGL("WGL_EXT_swap_control");
_glfw.wgl.EXT_colorspace =
extensionSupportedWGL("WGL_EXT_colorspace");
_glfw.wgl.ARB_pixel_format = _glfw.wgl.ARB_pixel_format =
extensionSupportedWGL("WGL_ARB_pixel_format"); extensionSupportedWGL("WGL_ARB_pixel_format");
_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)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "WGL: Failed to load opengl32.dll");
return GLFW_FALSE;
}
_glfw.wgl.CreateContext = (WGLCREATECONTEXT_T)
GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
_glfw.wgl.DeleteContext = (WGLDELETECONTEXT_T)
GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
_glfw.wgl.GetProcAddress = (WGLGETPROCADDRESS_T)
GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
_glfw.wgl.GetCurrentDC = (WGLGETCURRENTDC_T)
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
_glfw.wgl.MakeCurrent = (WGLMAKECURRENT_T)
GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
_glfw.wgl.ShareLists = (WGLSHARELISTS_T)
GetProcAddress(_glfw.wgl.instance, "wglShareLists");
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -458,11 +531,11 @@ void _glfwTerminateWGL(void)
FreeLibrary(_glfw.wgl.instance); FreeLibrary(_glfw.wgl.instance);
} }
#define setWGLattrib(attribName, attribValue) \ #define setAttrib(a, v) \
{ \ { \
attribs[index++] = attribName; \ assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = attribValue; \ attribs[index++] = a; \
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \ attribs[index++] = v; \
} }
// Create the OpenGL or OpenGL ES context // Create the OpenGL or OpenGL ES context
@ -476,9 +549,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;
@ -490,22 +560,22 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
pixelFormat = choosePixelFormat(window, fbconfig); pixelFormat = choosePixelFormat(window, ctxconfig, fbconfig);
if (!pixelFormat) if (!pixelFormat)
return GLFW_FALSE; return GLFW_FALSE;
if (!DescribePixelFormat(window->context.wgl.dc, if (!DescribePixelFormat(window->context.wgl.dc,
pixelFormat, sizeof(pfd), &pfd)) pixelFormat, sizeof(pfd), &pfd))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve PFD for selected pixel format"); "WGL: Failed to retrieve PFD for selected pixel format");
return GLFW_FALSE; return GLFW_FALSE;
} }
if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd)) if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to set selected pixel format"); "WGL: Failed to set selected pixel format");
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -562,8 +632,6 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
if (ctxconfig->debug) if (ctxconfig->debug)
flags |= WGL_CONTEXT_DEBUG_BIT_ARB; flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
if (ctxconfig->noerror)
flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;
if (ctxconfig->robustness) if (ctxconfig->robustness)
{ {
@ -571,13 +639,13 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
{ {
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION) if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
{ {
setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
WGL_NO_RESET_NOTIFICATION_ARB); WGL_NO_RESET_NOTIFICATION_ARB);
} }
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET) else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
{ {
setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
WGL_LOSE_CONTEXT_ON_RESET_ARB); WGL_LOSE_CONTEXT_ON_RESET_ARB);
} }
flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB; flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
@ -590,37 +658,42 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
{ {
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE) if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
{ {
setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB, setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB); WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
} }
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH) else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
{ {
setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB, setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB); WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
} }
} }
} }
if (ctxconfig->noerror)
{
if (_glfw.wgl.ARB_create_context_no_error)
setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
}
// NOTE: Only request an explicitly versioned context when necessary, as // NOTE: Only request an explicitly versioned context when necessary, as
// explicitly requesting version 1.0 does not always return the // explicitly requesting version 1.0 does not always return the
// highest version supported by the driver // highest version supported by the driver
if (ctxconfig->major != 1 || ctxconfig->minor != 0) if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{ {
setWGLattrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major); setAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
setWGLattrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor); setAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
} }
if (flags) if (flags)
setWGLattrib(WGL_CONTEXT_FLAGS_ARB, flags); setAttrib(WGL_CONTEXT_FLAGS_ARB, flags);
if (mask) if (mask)
setWGLattrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask); setAttrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
setWGLattrib(0, 0); setAttrib(0, 0);
window->context.wgl.handle = window->context.wgl.handle =
_glfw.wgl.CreateContextAttribsARB(window->context.wgl.dc, wglCreateContextAttribsARB(window->context.wgl.dc, share, attribs);
share, attribs);
if (!window->context.wgl.handle) if (!window->context.wgl.handle)
{ {
const DWORD error = GetLastError(); const DWORD error = GetLastError();
@ -647,6 +720,11 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
_glfwInputError(GLFW_VERSION_UNAVAILABLE, _glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: Driver does not support the requested OpenGL profile"); "WGL: Driver does not support the requested OpenGL profile");
} }
else if (error == (0xc0070000 | ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB))
{
_glfwInputError(GLFW_INVALID_VALUE,
"WGL: The share context is not compatible with the requested context");
}
else else
{ {
if (ctxconfig->client == GLFW_OPENGL_API) if (ctxconfig->client == GLFW_OPENGL_API)
@ -669,8 +747,8 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
window->context.wgl.handle = wglCreateContext(window->context.wgl.dc); window->context.wgl.handle = wglCreateContext(window->context.wgl.dc);
if (!window->context.wgl.handle) if (!window->context.wgl.handle)
{ {
_glfwInputError(GLFW_VERSION_UNAVAILABLE, _glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
"WGL: Failed to create OpenGL context"); "WGL: Failed to create OpenGL context");
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -678,8 +756,8 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
{ {
if (!wglShareLists(share, window->context.wgl.handle)) if (!wglShareLists(share, window->context.wgl.handle))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to enable sharing with specified OpenGL context"); "WGL: Failed to enable sharing with specified OpenGL context");
return GLFW_FALSE; return GLFW_FALSE;
} }
} }
@ -695,7 +773,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
return GLFW_TRUE; return GLFW_TRUE;
} }
#undef setWGLattrib #undef setAttrib
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View File

@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.2 WGL - www.glfw.org // GLFW 3.3 WGL - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // Copyright (c) 2006-2018 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
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -25,10 +25,6 @@
// //
//======================================================================== //========================================================================
#ifndef _glfw3_wgl_context_h_
#define _glfw3_wgl_context_h_
#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
#define WGL_SUPPORT_OPENGL_ARB 0x2010 #define WGL_SUPPORT_OPENGL_ARB 0x2010
#define WGL_DRAW_TO_WINDOW_ARB 0x2001 #define WGL_DRAW_TO_WINDOW_ARB 0x2001
@ -72,28 +68,39 @@
#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097 #define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0 #define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098 #define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
#define WGL_COLORSPACE_EXT 0x309d
#define WGL_COLORSPACE_SRGB_EXT 0x3089
#define ERROR_INVALID_VERSION_ARB 0x2095 #define ERROR_INVALID_VERSION_ARB 0x2095
#define ERROR_INVALID_PROFILE_ARB 0x2096 #define ERROR_INVALID_PROFILE_ARB 0x2096
#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
// WGL extension pointer typedefs
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int); typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*); typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);
typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void); typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void);
typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC); typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC);
typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC,HGLRC,const int*); typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC,HGLRC,const int*);
#define wglSwapIntervalEXT _glfw.wgl.SwapIntervalEXT
typedef HGLRC (WINAPI * WGLCREATECONTEXT_T)(HDC); #define wglGetPixelFormatAttribivARB _glfw.wgl.GetPixelFormatAttribivARB
typedef BOOL (WINAPI * WGLDELETECONTEXT_T)(HGLRC); #define wglGetExtensionsStringEXT _glfw.wgl.GetExtensionsStringEXT
typedef PROC (WINAPI * WGLGETPROCADDRESS_T)(LPCSTR); #define wglGetExtensionsStringARB _glfw.wgl.GetExtensionsStringARB
typedef HDC (WINAPI * WGLGETCURRENTDC_T)(void); #define wglCreateContextAttribsARB _glfw.wgl.CreateContextAttribsARB
typedef BOOL (WINAPI * WGLMAKECURRENT_T)(HDC,HGLRC);
typedef BOOL (WINAPI * WGLSHARELISTS_T)(HGLRC,HGLRC);
// opengl32.dll function pointer typedefs // opengl32.dll function pointer typedefs
typedef HGLRC (WINAPI * PFN_wglCreateContext)(HDC);
typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC);
typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR);
typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void);
typedef HGLRC (WINAPI * PFN_wglGetCurrentContext)(void);
typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC);
typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
#define wglCreateContext _glfw.wgl.CreateContext #define wglCreateContext _glfw.wgl.CreateContext
#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
@ -120,14 +127,13 @@ typedef struct _GLFWcontextWGL
typedef struct _GLFWlibraryWGL typedef struct _GLFWlibraryWGL
{ {
HINSTANCE instance; HINSTANCE instance;
WGLCREATECONTEXT_T CreateContext; PFN_wglCreateContext CreateContext;
WGLDELETECONTEXT_T DeleteContext; PFN_wglDeleteContext DeleteContext;
WGLGETPROCADDRESS_T GetProcAddress; PFN_wglGetProcAddress GetProcAddress;
WGLGETCURRENTDC_T GetCurrentDC; PFN_wglGetCurrentDC GetCurrentDC;
WGLMAKECURRENT_T MakeCurrent; PFN_wglGetCurrentContext GetCurrentContext;
WGLSHARELISTS_T ShareLists; PFN_wglMakeCurrent MakeCurrent;
PFN_wglShareLists ShareLists;
GLFWbool extensionsLoaded;
PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT; PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;
PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB; PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB;
@ -135,6 +141,7 @@ typedef struct _GLFWlibraryWGL
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB; PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB; PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
GLFWbool EXT_swap_control; GLFWbool EXT_swap_control;
GLFWbool EXT_colorspace;
GLFWbool ARB_multisample; GLFWbool ARB_multisample;
GLFWbool ARB_framebuffer_sRGB; GLFWbool ARB_framebuffer_sRGB;
GLFWbool EXT_framebuffer_sRGB; GLFWbool EXT_framebuffer_sRGB;
@ -143,6 +150,7 @@ typedef struct _GLFWlibraryWGL
GLFWbool ARB_create_context_profile; GLFWbool ARB_create_context_profile;
GLFWbool EXT_create_context_es2_profile; GLFWbool EXT_create_context_es2_profile;
GLFWbool ARB_create_context_robustness; GLFWbool ARB_create_context_robustness;
GLFWbool ARB_create_context_no_error;
GLFWbool ARB_context_flush_control; GLFWbool ARB_context_flush_control;
} _GLFWlibraryWGL; } _GLFWlibraryWGL;
@ -154,4 +162,3 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig); const _GLFWfbconfig* fbconfig);
#endif // _glfw3_wgl_context_h_

View File

@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.2 Win32 - www.glfw.org // GLFW 3.3 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // Copyright (c) 2006-2019 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
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -24,26 +24,30 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"
#include <stdlib.h> #include <stdlib.h>
#include <malloc.h> #include <malloc.h>
#include <initguid.h> static const GUID _glfw_GUID_DEVINTERFACE_HID =
DEFINE_GUID(GUID_DEVINTERFACE_HID,0x4d1e55b2,0xf16f,0x11cf,0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30); {0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}};
#define GUID_DEVINTERFACE_HID _glfw_GUID_DEVINTERFACE_HID
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG) #if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
// Applications exporting this symbol with this value will be automatically // Executables (but not DLLs) exporting this symbol with this value will be
// directed to the high-performance GPU on Nvidia Optimus systems with // automatically directed to the high-performance GPU on Nvidia Optimus systems
// up-to-date drivers // with up-to-date drivers
// //
__declspec(dllexport) DWORD NvOptimusEnablement = 1; __declspec(dllexport) DWORD NvOptimusEnablement = 1;
// Applications exporting this symbol with this value will be automatically // Executables (but not DLLs) exporting this symbol with this value will be
// directed to the high-performance GPU on AMD PowerXpress systems with // automatically directed to the high-performance GPU on AMD PowerXpress systems
// up-to-date drivers // with up-to-date drivers
// //
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
@ -67,29 +71,39 @@ static GLFWbool loadLibraries(void)
_glfw.win32.winmm.instance = LoadLibraryA("winmm.dll"); _glfw.win32.winmm.instance = LoadLibraryA("winmm.dll");
if (!_glfw.win32.winmm.instance) if (!_glfw.win32.winmm.instance)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load winmm.dll"); _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to load winmm.dll");
return GLFW_FALSE; return GLFW_FALSE;
} }
_glfw.win32.winmm.timeGetTime = (TIMEGETTIME_T) _glfw.win32.winmm.GetTime = (PFN_timeGetTime)
GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime"); GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");
_glfw.win32.user32.instance = LoadLibraryA("user32.dll"); _glfw.win32.user32.instance = LoadLibraryA("user32.dll");
if (!_glfw.win32.user32.instance) if (!_glfw.win32.user32.instance)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load user32.dll"); _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to load user32.dll");
return GLFW_FALSE; return GLFW_FALSE;
} }
_glfw.win32.user32.SetProcessDPIAware = (SETPROCESSDPIAWARE_T) _glfw.win32.user32.SetProcessDPIAware_ = (PFN_SetProcessDPIAware)
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware"); GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");
_glfw.win32.user32.ChangeWindowMessageFilterEx = (CHANGEWINDOWMESSAGEFILTEREX_T) _glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx)
GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx"); GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
_glfw.win32.user32.EnableNonClientDpiScaling_ = (PFN_EnableNonClientDpiScaling)
GetProcAddress(_glfw.win32.user32.instance, "EnableNonClientDpiScaling");
_glfw.win32.user32.SetProcessDpiAwarenessContext_ = (PFN_SetProcessDpiAwarenessContext)
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDpiAwarenessContext");
_glfw.win32.user32.GetDpiForWindow_ = (PFN_GetDpiForWindow)
GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow");
_glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)
GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll"); _glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
if (_glfw.win32.dinput8.instance) if (_glfw.win32.dinput8.instance)
{ {
_glfw.win32.dinput8.DirectInput8Create = (DIRECTINPUT8CREATE_T) _glfw.win32.dinput8.Create = (PFN_DirectInput8Create)
GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create"); GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create");
} }
@ -110,9 +124,9 @@ static GLFWbool loadLibraries(void)
_glfw.win32.xinput.instance = LoadLibraryA(names[i]); _glfw.win32.xinput.instance = LoadLibraryA(names[i]);
if (_glfw.win32.xinput.instance) if (_glfw.win32.xinput.instance)
{ {
_glfw.win32.xinput.XInputGetCapabilities = (XINPUTGETCAPABILITIES_T) _glfw.win32.xinput.GetCapabilities = (PFN_XInputGetCapabilities)
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities"); GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities");
_glfw.win32.xinput.XInputGetState = (XINPUTGETSTATE_T) _glfw.win32.xinput.GetState = (PFN_XInputGetState)
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState"); GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState");
break; break;
@ -123,17 +137,28 @@ static GLFWbool loadLibraries(void)
_glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll"); _glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
if (_glfw.win32.dwmapi.instance) if (_glfw.win32.dwmapi.instance)
{ {
_glfw.win32.dwmapi.DwmIsCompositionEnabled = (DWMISCOMPOSITIONENABLED_T) _glfw.win32.dwmapi.IsCompositionEnabled = (PFN_DwmIsCompositionEnabled)
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled"); GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
_glfw.win32.dwmapi.DwmFlush = (DWMFLUSH_T) _glfw.win32.dwmapi.Flush = (PFN_DwmFlush)
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush"); GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
_glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow)
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");
} }
_glfw.win32.shcore.instance = LoadLibraryA("shcore.dll"); _glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
if (_glfw.win32.shcore.instance) if (_glfw.win32.shcore.instance)
{ {
_glfw.win32.shcore.SetProcessDpiAwareness = (SETPROCESSDPIAWARENESS_T) _glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness)
GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness"); GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
_glfw.win32.shcore.GetDpiForMonitor_ = (PFN_GetDpiForMonitor)
GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor");
}
_glfw.win32.ntdll.instance = LoadLibraryA("ntdll.dll");
if (_glfw.win32.ntdll.instance)
{
_glfw.win32.ntdll.RtlVerifyVersionInfo_ = (PFN_RtlVerifyVersionInfo)
GetProcAddress(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo");
} }
return GLFW_TRUE; return GLFW_TRUE;
@ -160,6 +185,9 @@ static void freeLibraries(void)
if (_glfw.win32.shcore.instance) if (_glfw.win32.shcore.instance)
FreeLibrary(_glfw.win32.shcore.instance); FreeLibrary(_glfw.win32.shcore.instance);
if (_glfw.win32.ntdll.instance)
FreeLibrary(_glfw.win32.ntdll.instance);
} }
// Create key code translation tables // Create key code translation tables
@ -168,160 +196,165 @@ static void createKeyTables(void)
{ {
int scancode; int scancode;
memset(_glfw.win32.publicKeys, -1, sizeof(_glfw.win32.publicKeys)); memset(_glfw.win32.keycodes, -1, sizeof(_glfw.win32.keycodes));
memset(_glfw.win32.nativeKeys, -1, sizeof(_glfw.win32.nativeKeys)); memset(_glfw.win32.scancodes, -1, sizeof(_glfw.win32.scancodes));
_glfw.win32.publicKeys[0x00B] = GLFW_KEY_0; _glfw.win32.keycodes[0x00B] = GLFW_KEY_0;
_glfw.win32.publicKeys[0x002] = GLFW_KEY_1; _glfw.win32.keycodes[0x002] = GLFW_KEY_1;
_glfw.win32.publicKeys[0x003] = GLFW_KEY_2; _glfw.win32.keycodes[0x003] = GLFW_KEY_2;
_glfw.win32.publicKeys[0x004] = GLFW_KEY_3; _glfw.win32.keycodes[0x004] = GLFW_KEY_3;
_glfw.win32.publicKeys[0x005] = GLFW_KEY_4; _glfw.win32.keycodes[0x005] = GLFW_KEY_4;
_glfw.win32.publicKeys[0x006] = GLFW_KEY_5; _glfw.win32.keycodes[0x006] = GLFW_KEY_5;
_glfw.win32.publicKeys[0x007] = GLFW_KEY_6; _glfw.win32.keycodes[0x007] = GLFW_KEY_6;
_glfw.win32.publicKeys[0x008] = GLFW_KEY_7; _glfw.win32.keycodes[0x008] = GLFW_KEY_7;
_glfw.win32.publicKeys[0x009] = GLFW_KEY_8; _glfw.win32.keycodes[0x009] = GLFW_KEY_8;
_glfw.win32.publicKeys[0x00A] = GLFW_KEY_9; _glfw.win32.keycodes[0x00A] = GLFW_KEY_9;
_glfw.win32.publicKeys[0x01E] = GLFW_KEY_A; _glfw.win32.keycodes[0x01E] = GLFW_KEY_A;
_glfw.win32.publicKeys[0x030] = GLFW_KEY_B; _glfw.win32.keycodes[0x030] = GLFW_KEY_B;
_glfw.win32.publicKeys[0x02E] = GLFW_KEY_C; _glfw.win32.keycodes[0x02E] = GLFW_KEY_C;
_glfw.win32.publicKeys[0x020] = GLFW_KEY_D; _glfw.win32.keycodes[0x020] = GLFW_KEY_D;
_glfw.win32.publicKeys[0x012] = GLFW_KEY_E; _glfw.win32.keycodes[0x012] = GLFW_KEY_E;
_glfw.win32.publicKeys[0x021] = GLFW_KEY_F; _glfw.win32.keycodes[0x021] = GLFW_KEY_F;
_glfw.win32.publicKeys[0x022] = GLFW_KEY_G; _glfw.win32.keycodes[0x022] = GLFW_KEY_G;
_glfw.win32.publicKeys[0x023] = GLFW_KEY_H; _glfw.win32.keycodes[0x023] = GLFW_KEY_H;
_glfw.win32.publicKeys[0x017] = GLFW_KEY_I; _glfw.win32.keycodes[0x017] = GLFW_KEY_I;
_glfw.win32.publicKeys[0x024] = GLFW_KEY_J; _glfw.win32.keycodes[0x024] = GLFW_KEY_J;
_glfw.win32.publicKeys[0x025] = GLFW_KEY_K; _glfw.win32.keycodes[0x025] = GLFW_KEY_K;
_glfw.win32.publicKeys[0x026] = GLFW_KEY_L; _glfw.win32.keycodes[0x026] = GLFW_KEY_L;
_glfw.win32.publicKeys[0x032] = GLFW_KEY_M; _glfw.win32.keycodes[0x032] = GLFW_KEY_M;
_glfw.win32.publicKeys[0x031] = GLFW_KEY_N; _glfw.win32.keycodes[0x031] = GLFW_KEY_N;
_glfw.win32.publicKeys[0x018] = GLFW_KEY_O; _glfw.win32.keycodes[0x018] = GLFW_KEY_O;
_glfw.win32.publicKeys[0x019] = GLFW_KEY_P; _glfw.win32.keycodes[0x019] = GLFW_KEY_P;
_glfw.win32.publicKeys[0x010] = GLFW_KEY_Q; _glfw.win32.keycodes[0x010] = GLFW_KEY_Q;
_glfw.win32.publicKeys[0x013] = GLFW_KEY_R; _glfw.win32.keycodes[0x013] = GLFW_KEY_R;
_glfw.win32.publicKeys[0x01F] = GLFW_KEY_S; _glfw.win32.keycodes[0x01F] = GLFW_KEY_S;
_glfw.win32.publicKeys[0x014] = GLFW_KEY_T; _glfw.win32.keycodes[0x014] = GLFW_KEY_T;
_glfw.win32.publicKeys[0x016] = GLFW_KEY_U; _glfw.win32.keycodes[0x016] = GLFW_KEY_U;
_glfw.win32.publicKeys[0x02F] = GLFW_KEY_V; _glfw.win32.keycodes[0x02F] = GLFW_KEY_V;
_glfw.win32.publicKeys[0x011] = GLFW_KEY_W; _glfw.win32.keycodes[0x011] = GLFW_KEY_W;
_glfw.win32.publicKeys[0x02D] = GLFW_KEY_X; _glfw.win32.keycodes[0x02D] = GLFW_KEY_X;
_glfw.win32.publicKeys[0x015] = GLFW_KEY_Y; _glfw.win32.keycodes[0x015] = GLFW_KEY_Y;
_glfw.win32.publicKeys[0x02C] = GLFW_KEY_Z; _glfw.win32.keycodes[0x02C] = GLFW_KEY_Z;
_glfw.win32.publicKeys[0x028] = GLFW_KEY_APOSTROPHE; _glfw.win32.keycodes[0x028] = GLFW_KEY_APOSTROPHE;
_glfw.win32.publicKeys[0x02B] = GLFW_KEY_BACKSLASH; _glfw.win32.keycodes[0x02B] = GLFW_KEY_BACKSLASH;
_glfw.win32.publicKeys[0x033] = GLFW_KEY_COMMA; _glfw.win32.keycodes[0x033] = GLFW_KEY_COMMA;
_glfw.win32.publicKeys[0x00D] = GLFW_KEY_EQUAL; _glfw.win32.keycodes[0x00D] = GLFW_KEY_EQUAL;
_glfw.win32.publicKeys[0x029] = GLFW_KEY_GRAVE_ACCENT; _glfw.win32.keycodes[0x029] = GLFW_KEY_GRAVE_ACCENT;
_glfw.win32.publicKeys[0x01A] = GLFW_KEY_LEFT_BRACKET; _glfw.win32.keycodes[0x01A] = GLFW_KEY_LEFT_BRACKET;
_glfw.win32.publicKeys[0x00C] = GLFW_KEY_MINUS; _glfw.win32.keycodes[0x00C] = GLFW_KEY_MINUS;
_glfw.win32.publicKeys[0x034] = GLFW_KEY_PERIOD; _glfw.win32.keycodes[0x034] = GLFW_KEY_PERIOD;
_glfw.win32.publicKeys[0x01B] = GLFW_KEY_RIGHT_BRACKET; _glfw.win32.keycodes[0x01B] = GLFW_KEY_RIGHT_BRACKET;
_glfw.win32.publicKeys[0x027] = GLFW_KEY_SEMICOLON; _glfw.win32.keycodes[0x027] = GLFW_KEY_SEMICOLON;
_glfw.win32.publicKeys[0x035] = GLFW_KEY_SLASH; _glfw.win32.keycodes[0x035] = GLFW_KEY_SLASH;
_glfw.win32.publicKeys[0x056] = GLFW_KEY_WORLD_2; _glfw.win32.keycodes[0x056] = GLFW_KEY_WORLD_2;
_glfw.win32.publicKeys[0x00E] = GLFW_KEY_BACKSPACE; _glfw.win32.keycodes[0x00E] = GLFW_KEY_BACKSPACE;
_glfw.win32.publicKeys[0x153] = GLFW_KEY_DELETE; _glfw.win32.keycodes[0x153] = GLFW_KEY_DELETE;
_glfw.win32.publicKeys[0x14F] = GLFW_KEY_END; _glfw.win32.keycodes[0x14F] = GLFW_KEY_END;
_glfw.win32.publicKeys[0x01C] = GLFW_KEY_ENTER; _glfw.win32.keycodes[0x01C] = GLFW_KEY_ENTER;
_glfw.win32.publicKeys[0x001] = GLFW_KEY_ESCAPE; _glfw.win32.keycodes[0x001] = GLFW_KEY_ESCAPE;
_glfw.win32.publicKeys[0x147] = GLFW_KEY_HOME; _glfw.win32.keycodes[0x147] = GLFW_KEY_HOME;
_glfw.win32.publicKeys[0x152] = GLFW_KEY_INSERT; _glfw.win32.keycodes[0x152] = GLFW_KEY_INSERT;
_glfw.win32.publicKeys[0x15D] = GLFW_KEY_MENU; _glfw.win32.keycodes[0x15D] = GLFW_KEY_MENU;
_glfw.win32.publicKeys[0x151] = GLFW_KEY_PAGE_DOWN; _glfw.win32.keycodes[0x151] = GLFW_KEY_PAGE_DOWN;
_glfw.win32.publicKeys[0x149] = GLFW_KEY_PAGE_UP; _glfw.win32.keycodes[0x149] = GLFW_KEY_PAGE_UP;
_glfw.win32.publicKeys[0x045] = GLFW_KEY_PAUSE; _glfw.win32.keycodes[0x045] = GLFW_KEY_PAUSE;
_glfw.win32.publicKeys[0x146] = GLFW_KEY_PAUSE; _glfw.win32.keycodes[0x146] = GLFW_KEY_PAUSE;
_glfw.win32.publicKeys[0x039] = GLFW_KEY_SPACE; _glfw.win32.keycodes[0x039] = GLFW_KEY_SPACE;
_glfw.win32.publicKeys[0x00F] = GLFW_KEY_TAB; _glfw.win32.keycodes[0x00F] = GLFW_KEY_TAB;
_glfw.win32.publicKeys[0x03A] = GLFW_KEY_CAPS_LOCK; _glfw.win32.keycodes[0x03A] = GLFW_KEY_CAPS_LOCK;
_glfw.win32.publicKeys[0x145] = GLFW_KEY_NUM_LOCK; _glfw.win32.keycodes[0x145] = GLFW_KEY_NUM_LOCK;
_glfw.win32.publicKeys[0x046] = GLFW_KEY_SCROLL_LOCK; _glfw.win32.keycodes[0x046] = GLFW_KEY_SCROLL_LOCK;
_glfw.win32.publicKeys[0x03B] = GLFW_KEY_F1; _glfw.win32.keycodes[0x03B] = GLFW_KEY_F1;
_glfw.win32.publicKeys[0x03C] = GLFW_KEY_F2; _glfw.win32.keycodes[0x03C] = GLFW_KEY_F2;
_glfw.win32.publicKeys[0x03D] = GLFW_KEY_F3; _glfw.win32.keycodes[0x03D] = GLFW_KEY_F3;
_glfw.win32.publicKeys[0x03E] = GLFW_KEY_F4; _glfw.win32.keycodes[0x03E] = GLFW_KEY_F4;
_glfw.win32.publicKeys[0x03F] = GLFW_KEY_F5; _glfw.win32.keycodes[0x03F] = GLFW_KEY_F5;
_glfw.win32.publicKeys[0x040] = GLFW_KEY_F6; _glfw.win32.keycodes[0x040] = GLFW_KEY_F6;
_glfw.win32.publicKeys[0x041] = GLFW_KEY_F7; _glfw.win32.keycodes[0x041] = GLFW_KEY_F7;
_glfw.win32.publicKeys[0x042] = GLFW_KEY_F8; _glfw.win32.keycodes[0x042] = GLFW_KEY_F8;
_glfw.win32.publicKeys[0x043] = GLFW_KEY_F9; _glfw.win32.keycodes[0x043] = GLFW_KEY_F9;
_glfw.win32.publicKeys[0x044] = GLFW_KEY_F10; _glfw.win32.keycodes[0x044] = GLFW_KEY_F10;
_glfw.win32.publicKeys[0x057] = GLFW_KEY_F11; _glfw.win32.keycodes[0x057] = GLFW_KEY_F11;
_glfw.win32.publicKeys[0x058] = GLFW_KEY_F12; _glfw.win32.keycodes[0x058] = GLFW_KEY_F12;
_glfw.win32.publicKeys[0x064] = GLFW_KEY_F13; _glfw.win32.keycodes[0x064] = GLFW_KEY_F13;
_glfw.win32.publicKeys[0x065] = GLFW_KEY_F14; _glfw.win32.keycodes[0x065] = GLFW_KEY_F14;
_glfw.win32.publicKeys[0x066] = GLFW_KEY_F15; _glfw.win32.keycodes[0x066] = GLFW_KEY_F15;
_glfw.win32.publicKeys[0x067] = GLFW_KEY_F16; _glfw.win32.keycodes[0x067] = GLFW_KEY_F16;
_glfw.win32.publicKeys[0x068] = GLFW_KEY_F17; _glfw.win32.keycodes[0x068] = GLFW_KEY_F17;
_glfw.win32.publicKeys[0x069] = GLFW_KEY_F18; _glfw.win32.keycodes[0x069] = GLFW_KEY_F18;
_glfw.win32.publicKeys[0x06A] = GLFW_KEY_F19; _glfw.win32.keycodes[0x06A] = GLFW_KEY_F19;
_glfw.win32.publicKeys[0x06B] = GLFW_KEY_F20; _glfw.win32.keycodes[0x06B] = GLFW_KEY_F20;
_glfw.win32.publicKeys[0x06C] = GLFW_KEY_F21; _glfw.win32.keycodes[0x06C] = GLFW_KEY_F21;
_glfw.win32.publicKeys[0x06D] = GLFW_KEY_F22; _glfw.win32.keycodes[0x06D] = GLFW_KEY_F22;
_glfw.win32.publicKeys[0x06E] = GLFW_KEY_F23; _glfw.win32.keycodes[0x06E] = GLFW_KEY_F23;
_glfw.win32.publicKeys[0x076] = GLFW_KEY_F24; _glfw.win32.keycodes[0x076] = GLFW_KEY_F24;
_glfw.win32.publicKeys[0x038] = GLFW_KEY_LEFT_ALT; _glfw.win32.keycodes[0x038] = GLFW_KEY_LEFT_ALT;
_glfw.win32.publicKeys[0x01D] = GLFW_KEY_LEFT_CONTROL; _glfw.win32.keycodes[0x01D] = GLFW_KEY_LEFT_CONTROL;
_glfw.win32.publicKeys[0x02A] = GLFW_KEY_LEFT_SHIFT; _glfw.win32.keycodes[0x02A] = GLFW_KEY_LEFT_SHIFT;
_glfw.win32.publicKeys[0x15B] = GLFW_KEY_LEFT_SUPER; _glfw.win32.keycodes[0x15B] = GLFW_KEY_LEFT_SUPER;
_glfw.win32.publicKeys[0x137] = GLFW_KEY_PRINT_SCREEN; _glfw.win32.keycodes[0x137] = GLFW_KEY_PRINT_SCREEN;
_glfw.win32.publicKeys[0x138] = GLFW_KEY_RIGHT_ALT; _glfw.win32.keycodes[0x138] = GLFW_KEY_RIGHT_ALT;
_glfw.win32.publicKeys[0x11D] = GLFW_KEY_RIGHT_CONTROL; _glfw.win32.keycodes[0x11D] = GLFW_KEY_RIGHT_CONTROL;
_glfw.win32.publicKeys[0x036] = GLFW_KEY_RIGHT_SHIFT; _glfw.win32.keycodes[0x036] = GLFW_KEY_RIGHT_SHIFT;
_glfw.win32.publicKeys[0x15C] = GLFW_KEY_RIGHT_SUPER; _glfw.win32.keycodes[0x15C] = GLFW_KEY_RIGHT_SUPER;
_glfw.win32.publicKeys[0x150] = GLFW_KEY_DOWN; _glfw.win32.keycodes[0x150] = GLFW_KEY_DOWN;
_glfw.win32.publicKeys[0x14B] = GLFW_KEY_LEFT; _glfw.win32.keycodes[0x14B] = GLFW_KEY_LEFT;
_glfw.win32.publicKeys[0x14D] = GLFW_KEY_RIGHT; _glfw.win32.keycodes[0x14D] = GLFW_KEY_RIGHT;
_glfw.win32.publicKeys[0x148] = GLFW_KEY_UP; _glfw.win32.keycodes[0x148] = GLFW_KEY_UP;
_glfw.win32.publicKeys[0x052] = GLFW_KEY_KP_0; _glfw.win32.keycodes[0x052] = GLFW_KEY_KP_0;
_glfw.win32.publicKeys[0x04F] = GLFW_KEY_KP_1; _glfw.win32.keycodes[0x04F] = GLFW_KEY_KP_1;
_glfw.win32.publicKeys[0x050] = GLFW_KEY_KP_2; _glfw.win32.keycodes[0x050] = GLFW_KEY_KP_2;
_glfw.win32.publicKeys[0x051] = GLFW_KEY_KP_3; _glfw.win32.keycodes[0x051] = GLFW_KEY_KP_3;
_glfw.win32.publicKeys[0x04B] = GLFW_KEY_KP_4; _glfw.win32.keycodes[0x04B] = GLFW_KEY_KP_4;
_glfw.win32.publicKeys[0x04C] = GLFW_KEY_KP_5; _glfw.win32.keycodes[0x04C] = GLFW_KEY_KP_5;
_glfw.win32.publicKeys[0x04D] = GLFW_KEY_KP_6; _glfw.win32.keycodes[0x04D] = GLFW_KEY_KP_6;
_glfw.win32.publicKeys[0x047] = GLFW_KEY_KP_7; _glfw.win32.keycodes[0x047] = GLFW_KEY_KP_7;
_glfw.win32.publicKeys[0x048] = GLFW_KEY_KP_8; _glfw.win32.keycodes[0x048] = GLFW_KEY_KP_8;
_glfw.win32.publicKeys[0x049] = GLFW_KEY_KP_9; _glfw.win32.keycodes[0x049] = GLFW_KEY_KP_9;
_glfw.win32.publicKeys[0x04E] = GLFW_KEY_KP_ADD; _glfw.win32.keycodes[0x04E] = GLFW_KEY_KP_ADD;
_glfw.win32.publicKeys[0x053] = GLFW_KEY_KP_DECIMAL; _glfw.win32.keycodes[0x053] = GLFW_KEY_KP_DECIMAL;
_glfw.win32.publicKeys[0x135] = GLFW_KEY_KP_DIVIDE; _glfw.win32.keycodes[0x135] = GLFW_KEY_KP_DIVIDE;
_glfw.win32.publicKeys[0x11C] = GLFW_KEY_KP_ENTER; _glfw.win32.keycodes[0x11C] = GLFW_KEY_KP_ENTER;
_glfw.win32.publicKeys[0x037] = GLFW_KEY_KP_MULTIPLY; _glfw.win32.keycodes[0x059] = GLFW_KEY_KP_EQUAL;
_glfw.win32.publicKeys[0x04A] = GLFW_KEY_KP_SUBTRACT; _glfw.win32.keycodes[0x037] = GLFW_KEY_KP_MULTIPLY;
_glfw.win32.keycodes[0x04A] = GLFW_KEY_KP_SUBTRACT;
for (scancode = 0; scancode < 512; scancode++) for (scancode = 0; scancode < 512; scancode++)
{ {
if (_glfw.win32.publicKeys[scancode] > 0) if (_glfw.win32.keycodes[scancode] > 0)
_glfw.win32.nativeKeys[_glfw.win32.publicKeys[scancode]] = scancode; _glfw.win32.scancodes[_glfw.win32.keycodes[scancode]] = scancode;
} }
} }
// Creates a dummy window for behind-the-scenes work // Creates a dummy window for behind-the-scenes work
// //
static HWND createHelperWindow(void) static GLFWbool createHelperWindow(void)
{ {
HWND window = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW, MSG msg;
_GLFW_WNDCLASSNAME,
L"GLFW helper window", _glfw.win32.helperWindowHandle =
WS_CLIPSIBLINGS | WS_CLIPCHILDREN, CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
0, 0, 1, 1, _GLFW_WNDCLASSNAME,
HWND_MESSAGE, NULL, L"GLFW message window",
GetModuleHandleW(NULL), WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
NULL); 0, 0, 1, 1,
if (!window) NULL, NULL,
GetModuleHandleW(NULL),
NULL);
if (!_glfw.win32.helperWindowHandle)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to create helper window"); "Win32: Failed to create helper window");
return NULL; return GLFW_FALSE;
} }
// HACK: The first call to ShowWindow is ignored if the parent process // HACK: The command to the first ShowWindow call is ignored if the parent
// passed along a STARTUPINFO, so clear that flag with a no-op call // process passed along a STARTUPINFO, so clear that with a no-op call
ShowWindow(window, SW_HIDE); ShowWindow(_glfw.win32.helperWindowHandle, SW_HIDE);
// Register for HID device notifications // Register for HID device notifications
{ {
@ -331,12 +364,19 @@ 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(_glfw.win32.helperWindowHandle,
DEVICE_NOTIFY_WINDOW_HANDLE); (DEV_BROADCAST_HDR*) &dbi,
DEVICE_NOTIFY_WINDOW_HANDLE);
} }
return window; while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return GLFW_TRUE;
} }
@ -349,16 +389,22 @@ static HWND createHelperWindow(void)
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source) WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
{ {
WCHAR* target; WCHAR* target;
int length; int count;
length = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0); count = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
if (!length) if (!count)
return NULL;
target = calloc(length, sizeof(WCHAR));
if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, length))
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert string from UTF-8");
return NULL;
}
target = calloc(count, sizeof(WCHAR));
if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, count))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert string from UTF-8");
free(target); free(target);
return NULL; return NULL;
} }
@ -371,16 +417,22 @@ WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source) char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
{ {
char* target; char* target;
int length; int size;
length = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL); size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
if (!length) if (!size)
return NULL;
target = calloc(length, 1);
if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, length, NULL, NULL))
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert string to UTF-8");
return NULL;
}
target = calloc(size, 1);
if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert string to UTF-8");
free(target); free(target);
return NULL; return NULL;
} }
@ -388,6 +440,111 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
return target; return target;
} }
// Reports the specified error, appending information about the last Win32 error
//
void _glfwInputErrorWin32(int error, const char* description)
{
WCHAR buffer[_GLFW_MESSAGE_SIZE] = L"";
char message[_GLFW_MESSAGE_SIZE] = "";
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK,
NULL,
GetLastError() & 0xffff,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
buffer,
sizeof(buffer) / sizeof(WCHAR),
NULL);
WideCharToMultiByte(CP_UTF8, 0, buffer, -1, message, sizeof(message), NULL, NULL);
_glfwInputError(error, "%s: %s", description, message);
}
// Updates key names according to the current keyboard layout
//
void _glfwUpdateKeyNamesWin32(void)
{
int key;
BYTE state[256] = {0};
memset(_glfw.win32.keynames, 0, sizeof(_glfw.win32.keynames));
for (key = GLFW_KEY_SPACE; key <= GLFW_KEY_LAST; key++)
{
UINT vk;
int scancode, length;
WCHAR chars[16];
scancode = _glfw.win32.scancodes[key];
if (scancode == -1)
continue;
if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD)
{
const UINT vks[] = {
VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,
VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, VK_DIVIDE,
VK_MULTIPLY, VK_SUBTRACT, VK_ADD
};
vk = vks[key - GLFW_KEY_KP_0];
}
else
vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK);
length = ToUnicode(vk, scancode, state,
chars, sizeof(chars) / sizeof(WCHAR),
0);
if (length == -1)
{
length = ToUnicode(vk, scancode, state,
chars, sizeof(chars) / sizeof(WCHAR),
0);
}
if (length < 1)
continue;
WideCharToMultiByte(CP_UTF8, 0, chars, 1,
_glfw.win32.keynames[key],
sizeof(_glfw.win32.keynames[key]),
NULL, NULL);
}
}
// Replacement for IsWindowsVersionOrGreater as MinGW lacks versionhelpers.h
//
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp)
{
OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, {0}, sp };
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
// HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
// latter lies unless the user knew to embed a non-default manifest
// announcing support for Windows 10 via supportedOS GUID
return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
}
// Checks whether we are on at least the specified build of Windows 10
//
BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build)
{
OSVERSIONINFOEXW osvi = { sizeof(osvi), 10, 0, build };
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER;
ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
cond = VerSetConditionMask(cond, VER_BUILDNUMBER, VER_GREATER_EQUAL);
// HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
// latter lies unless the user knew to embed a non-default manifest
// announcing support for Windows 10 via supportedOS GUID
return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW platform API ////// ////// GLFW platform API //////
@ -395,9 +552,6 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
int _glfwPlatformInit(void) int _glfwPlatformInit(void)
{ {
if (!_glfwInitThreadLocalStorageWin32())
return GLFW_FALSE;
// To make SetForegroundWindow work as we want, we need to fiddle // To make SetForegroundWindow work as we want, we need to fiddle
// with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early // with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
// as possible in the hope of still being the foreground process) // as possible in the hope of still being the foreground process)
@ -410,29 +564,33 @@ int _glfwPlatformInit(void)
return GLFW_FALSE; return GLFW_FALSE;
createKeyTables(); createKeyTables();
_glfwUpdateKeyNamesWin32();
if (_glfw_SetProcessDpiAwareness) if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
_glfw_SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
else if (_glfw_SetProcessDPIAware) else if (IsWindows8Point1OrGreater())
_glfw_SetProcessDPIAware(); SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
else if (IsWindowsVistaOrGreater())
SetProcessDPIAware();
if (!_glfwRegisterWindowClassWin32()) if (!_glfwRegisterWindowClassWin32())
return GLFW_FALSE; return GLFW_FALSE;
_glfw.win32.helperWindowHandle = createHelperWindow(); if (!createHelperWindow())
if (!_glfw.win32.helperWindowHandle)
return GLFW_FALSE; return GLFW_FALSE;
_glfwPlatformPollEvents();
_glfwInitTimerWin32(); _glfwInitTimerWin32();
_glfwInitJoysticksWin32(); _glfwInitJoysticksWin32();
_glfwPollMonitorsWin32();
return GLFW_TRUE; return GLFW_TRUE;
} }
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);
@ -444,19 +602,19 @@ void _glfwPlatformTerminate(void)
SPIF_SENDCHANGE); SPIF_SENDCHANGE);
free(_glfw.win32.clipboardString); free(_glfw.win32.clipboardString);
free(_glfw.win32.rawInput);
_glfwTerminateWGL(); _glfwTerminateWGL();
_glfwTerminateEGL(); _glfwTerminateEGL();
_glfwTerminateJoysticksWin32(); _glfwTerminateJoysticksWin32();
_glfwTerminateThreadLocalStorageWin32();
freeLibraries(); freeLibraries();
} }
const char* _glfwPlatformGetVersionString(void) const char* _glfwPlatformGetVersionString(void)
{ {
return _GLFW_VERSION_NUMBER " Win32 WGL EGL" return _GLFW_VERSION_NUMBER " Win32 WGL EGL OSMesa"
#if defined(__MINGW32__) #if defined(__MINGW32__)
" MinGW" " MinGW"
#elif defined(_MSC_VER) #elif defined(_MSC_VER)

View File

@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.1 Win32 - www.glfw.org // GLFW 3.3 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // Copyright (c) 2006-2019 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
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -24,16 +24,14 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"
#include <stdio.h>
#include <math.h> #include <math.h>
#include <initguid.h>
#define _GLFW_PRESENCE_ONLY 1
#define _GLFW_UPDATE_STATE 2
#define _GLFW_TYPE_AXIS 0 #define _GLFW_TYPE_AXIS 0
#define _GLFW_TYPE_SLIDER 1 #define _GLFW_TYPE_SLIDER 1
#define _GLFW_TYPE_BUTTON 2 #define _GLFW_TYPE_BUTTON 2
@ -52,18 +50,36 @@ typedef struct _GLFWobjenumWin32
int povCount; int povCount;
} _GLFWobjenumWin32; } _GLFWobjenumWin32;
// Define only the necessary GUIDs (it's bad enough that we're exporting these) // Define local copies of the necessary GUIDs
// //
DEFINE_GUID(IID_IDirectInput8W,0xbf798031,0x483a,0x4da2,0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00); static const GUID _glfw_IID_IDirectInput8W =
DEFINE_GUID(GUID_XAxis,0xa36d02e0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00); {0xbf798031,0x483a,0x4da2,{0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00}};
DEFINE_GUID(GUID_YAxis,0xa36d02e1,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00); static const GUID _glfw_GUID_XAxis =
DEFINE_GUID(GUID_ZAxis,0xa36d02e2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00); {0xa36d02e0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
DEFINE_GUID(GUID_RxAxis,0xa36d02f4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00); static const GUID _glfw_GUID_YAxis =
DEFINE_GUID(GUID_RyAxis,0xa36d02f5,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00); {0xa36d02e1,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
DEFINE_GUID(GUID_RzAxis,0xa36d02e3,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00); static const GUID _glfw_GUID_ZAxis =
DEFINE_GUID(GUID_Slider,0xa36d02e4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00); {0xa36d02e2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
DEFINE_GUID(GUID_Button,0xa36d02f0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00); static const GUID _glfw_GUID_RxAxis =
DEFINE_GUID(GUID_POV,0xa36d02f2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00); {0xa36d02f4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_RyAxis =
{0xa36d02f5,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_RzAxis =
{0xa36d02e3,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_Slider =
{0xa36d02e4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_POV =
{0xa36d02f2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
#define IID_IDirectInput8W _glfw_IID_IDirectInput8W
#define GUID_XAxis _glfw_GUID_XAxis
#define GUID_YAxis _glfw_GUID_YAxis
#define GUID_ZAxis _glfw_GUID_ZAxis
#define GUID_RxAxis _glfw_GUID_RxAxis
#define GUID_RyAxis _glfw_GUID_RyAxis
#define GUID_RzAxis _glfw_GUID_RzAxis
#define GUID_Slider _glfw_GUID_Slider
#define GUID_POV _glfw_GUID_POV
// Object data array for our clone of c_dfDIJoystick // Object data array for our clone of c_dfDIJoystick
// Generated with https://github.com/elmindreda/c_dfDIJoystick2 // Generated with https://github.com/elmindreda/c_dfDIJoystick2
@ -149,9 +165,9 @@ static const char* getDeviceDescription(const XINPUT_CAPABILITIES* xic)
case XINPUT_DEVSUBTYPE_GAMEPAD: case XINPUT_DEVSUBTYPE_GAMEPAD:
{ {
if (xic->Flags & XINPUT_CAPS_WIRELESS) if (xic->Flags & XINPUT_CAPS_WIRELESS)
return "Wireless Xbox 360 Controller"; return "Wireless Xbox Controller";
else else
return "Xbox 360 Controller"; return "Xbox Controller";
} }
} }
@ -238,25 +254,22 @@ static GLFWbool supportsXInput(const GUID* guid)
// Frees all resources associated with the specified joystick // Frees all resources associated with the specified joystick
// //
static void closeJoystick(_GLFWjoystickWin32* js) static void closeJoystick(_GLFWjoystick* js)
{ {
if (js->device) if (js->win32.device)
{ {
IDirectInputDevice8_Unacquire(js->device); IDirectInputDevice8_Unacquire(js->win32.device);
IDirectInputDevice8_Release(js->device); IDirectInputDevice8_Release(js->win32.device);
} }
free(js->name); free(js->win32.objects);
free(js->axes);
free(js->buttons);
free(js->objects);
memset(js, 0, sizeof(_GLFWjoystickWin32));
_glfwInputJoystickChange((int) (js - _glfw.win32_js), GLFW_DISCONNECTED); _glfwFreeJoystick(js);
_glfwInputJoystick(js, GLFW_DISCONNECTED);
} }
// DirectInput device object enumeration callback // DirectInput device object enumeration callback
// Insights gleaned from SDL2 // Insights gleaned from SDL
// //
static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi, static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
void* user) void* user)
@ -332,28 +345,25 @@ static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
// //
static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user) static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
{ {
int joy = 0; int jid = 0;
DIDEVCAPS dc; DIDEVCAPS dc;
DIPROPDWORD dipd; DIPROPDWORD dipd;
IDirectInputDevice8* device; IDirectInputDevice8* device;
_GLFWobjenumWin32 data; _GLFWobjenumWin32 data;
_GLFWjoystickWin32* js; _GLFWjoystick* js;
char guid[33];
char name[256];
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++) for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{ {
if (memcmp(&_glfw.win32_js[joy].guid, &di->guidInstance, sizeof(GUID)) == 0) _GLFWjoystick* js = _glfw.joysticks + jid;
return DIENUM_CONTINUE; if (js->present)
{
if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
return DIENUM_CONTINUE;
}
} }
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{
if (!_glfw.win32_js[joy].present)
break;
}
if (joy > GLFW_JOYSTICK_LAST)
return DIENUM_STOP;
if (supportsXInput(&di->guidProduct)) if (supportsXInput(&di->guidProduct))
return DIENUM_CONTINUE; return DIENUM_CONTINUE;
@ -362,14 +372,14 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
&device, &device,
NULL))) NULL)))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, "DI: Failed to create device"); _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create device");
return DIENUM_CONTINUE; return DIENUM_CONTINUE;
} }
if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat))) if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"DI: Failed to set device data format"); "Win32: Failed to set device data format");
IDirectInputDevice8_Release(device); IDirectInputDevice8_Release(device);
return DIENUM_CONTINUE; return DIENUM_CONTINUE;
@ -381,7 +391,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
if (FAILED(IDirectInputDevice8_GetCapabilities(device, &dc))) if (FAILED(IDirectInputDevice8_GetCapabilities(device, &dc)))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"DI: Failed to query device capabilities"); "Win32: Failed to query device capabilities");
IDirectInputDevice8_Release(device); IDirectInputDevice8_Release(device);
return DIENUM_CONTINUE; return DIENUM_CONTINUE;
@ -398,7 +408,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
&dipd.diph))) &dipd.diph)))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"DI: Failed to set device axis mode"); "Win32: Failed to set device axis mode");
IDirectInputDevice8_Release(device); IDirectInputDevice8_Release(device);
return DIENUM_CONTINUE; return DIENUM_CONTINUE;
@ -406,7 +416,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
memset(&data, 0, sizeof(data)); memset(&data, 0, sizeof(data));
data.device = device; data.device = device;
data.objects = calloc(dc.dwAxes + dc.dwButtons + dc.dwPOVs, data.objects = calloc(dc.dwAxes + (size_t) dc.dwButtons + dc.dwPOVs,
sizeof(_GLFWjoyobjectWin32)); sizeof(_GLFWjoyobjectWin32));
if (FAILED(IDirectInputDevice8_EnumObjects(device, if (FAILED(IDirectInputDevice8_EnumObjects(device,
@ -415,7 +425,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV))) DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"DI: Failed to enumerate device objects"); "Win32: Failed to enumerate device objects");
IDirectInputDevice8_Release(device); IDirectInputDevice8_Release(device);
free(data.objects); free(data.objects);
@ -426,224 +436,54 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
sizeof(_GLFWjoyobjectWin32), sizeof(_GLFWjoyobjectWin32),
compareJoystickObjects); compareJoystickObjects);
js = _glfw.win32_js + joy; if (!WideCharToMultiByte(CP_UTF8, 0,
js->device = device; di->tszInstanceName, -1,
js->guid = di->guidInstance; name, sizeof(name),
js->axisCount = data.axisCount + data.sliderCount; NULL, NULL))
js->axes = calloc(js->axisCount, sizeof(float));
js->buttonCount += data.buttonCount + data.povCount * 4;
js->buttons = calloc(js->buttonCount, 1);
js->objects = data.objects;
js->objectCount = data.objectCount;
js->name = _glfwCreateUTF8FromWideStringWin32(di->tszInstanceName);
js->present = GLFW_TRUE;
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
return DIENUM_CONTINUE;
}
// Attempt to open the specified joystick device
// TODO: Pack state arrays for non-gamepad devices
//
static GLFWbool openXinputDevice(DWORD index)
{
int joy;
XINPUT_CAPABILITIES xic;
_GLFWjoystickWin32* js;
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{ {
if (_glfw.win32_js[joy].present && _glfwInputError(GLFW_PLATFORM_ERROR,
_glfw.win32_js[joy].device == NULL && "Win32: Failed to convert joystick name to UTF-8");
_glfw.win32_js[joy].index == index)
{ IDirectInputDevice8_Release(device);
return GLFW_FALSE; free(data.objects);
} return DIENUM_STOP;
} }
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++) // Generate a joystick GUID that matches the SDL 2.0.5+ one
if (memcmp(&di->guidProduct.Data4[2], "PIDVID", 6) == 0)
{ {
if (!_glfw.win32_js[joy].present) sprintf(guid, "03000000%02x%02x0000%02x%02x000000000000",
break; (uint8_t) di->guidProduct.Data1,
} (uint8_t) (di->guidProduct.Data1 >> 8),
(uint8_t) (di->guidProduct.Data1 >> 16),
if (joy > GLFW_JOYSTICK_LAST) (uint8_t) (di->guidProduct.Data1 >> 24));
return GLFW_FALSE;
if (_glfw_XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
return GLFW_FALSE;
js = _glfw.win32_js + joy;
js->axisCount = 6;
js->axes = calloc(js->axisCount, sizeof(float));
js->buttonCount = 14;
js->buttons = calloc(js->buttonCount, 1);
js->present = GLFW_TRUE;
js->name = strdup(getDeviceDescription(&xic));
js->index = index;
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
return GLFW_TRUE;
}
// Polls for and processes events the specified joystick
//
static GLFWbool pollJoystickState(_GLFWjoystickWin32* js, int mode)
{
if (!js->present)
return GLFW_FALSE;
if (js->device)
{
int i, j, ai = 0, bi = 0;
HRESULT result;
DIJOYSTATE state;
IDirectInputDevice8_Poll(js->device);
result = IDirectInputDevice8_GetDeviceState(js->device,
sizeof(state),
&state);
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
{
IDirectInputDevice8_Acquire(js->device);
IDirectInputDevice8_Poll(js->device);
result = IDirectInputDevice8_GetDeviceState(js->device,
sizeof(state),
&state);
}
if (FAILED(result))
{
closeJoystick(js);
return GLFW_FALSE;
}
if (mode == _GLFW_PRESENCE_ONLY)
return GLFW_TRUE;
for (i = 0; i < js->objectCount; i++)
{
const void* data = (char*) &state + js->objects[i].offset;
switch (js->objects[i].type)
{
case _GLFW_TYPE_AXIS:
case _GLFW_TYPE_SLIDER:
{
js->axes[ai++] = (*((LONG*) data) + 0.5f) / 32767.5f;
break;
}
case _GLFW_TYPE_BUTTON:
{
if (*((BYTE*) data) & 0x80)
js->buttons[bi++] = GLFW_PRESS;
else
js->buttons[bi++] = GLFW_RELEASE;
break;
}
case _GLFW_TYPE_POV:
{
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
// Screams of horror are appropriate at this point
int value = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
if (value < 0 || value > 8)
value = 8;
for (j = 0; j < 4; j++)
{
if (directions[value] & (1 << j))
js->buttons[bi++] = GLFW_PRESS;
else
js->buttons[bi++] = GLFW_RELEASE;
}
break;
}
}
}
return GLFW_TRUE;
} }
else else
{ {
int i; sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
DWORD result; name[0], name[1], name[2], name[3],
XINPUT_STATE xis; name[4], name[5], name[6], name[7],
const WORD buttons[14] = name[8], name[9], name[10]);
{
XINPUT_GAMEPAD_A,
XINPUT_GAMEPAD_B,
XINPUT_GAMEPAD_X,
XINPUT_GAMEPAD_Y,
XINPUT_GAMEPAD_LEFT_SHOULDER,
XINPUT_GAMEPAD_RIGHT_SHOULDER,
XINPUT_GAMEPAD_BACK,
XINPUT_GAMEPAD_START,
XINPUT_GAMEPAD_LEFT_THUMB,
XINPUT_GAMEPAD_RIGHT_THUMB,
XINPUT_GAMEPAD_DPAD_UP,
XINPUT_GAMEPAD_DPAD_RIGHT,
XINPUT_GAMEPAD_DPAD_DOWN,
XINPUT_GAMEPAD_DPAD_LEFT
};
result = _glfw_XInputGetState(js->index, &xis);
if (result != ERROR_SUCCESS)
{
if (result == ERROR_DEVICE_NOT_CONNECTED)
closeJoystick(js);
return GLFW_FALSE;
}
if (mode == _GLFW_PRESENCE_ONLY)
return GLFW_TRUE;
if (sqrt((double) (xis.Gamepad.sThumbLX * xis.Gamepad.sThumbLX +
xis.Gamepad.sThumbLY * xis.Gamepad.sThumbLY)) >
(double) XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
{
js->axes[0] = (xis.Gamepad.sThumbLX + 0.5f) / 32767.f;
js->axes[1] = (xis.Gamepad.sThumbLY + 0.5f) / 32767.f;
}
else
{
js->axes[0] = 0.f;
js->axes[1] = 0.f;
}
if (sqrt((double) (xis.Gamepad.sThumbRX * xis.Gamepad.sThumbRX +
xis.Gamepad.sThumbRY * xis.Gamepad.sThumbRY)) >
(double) XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
{
js->axes[2] = (xis.Gamepad.sThumbRX + 0.5f) / 32767.f;
js->axes[3] = (xis.Gamepad.sThumbRY + 0.5f) / 32767.f;
}
else
{
js->axes[2] = 0.f;
js->axes[3] = 0.f;
}
if (xis.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
js->axes[4] = xis.Gamepad.bLeftTrigger / 127.5f - 1.f;
else
js->axes[4] = -1.f;
if (xis.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
js->axes[5] = xis.Gamepad.bRightTrigger / 127.5f - 1.f;
else
js->axes[5] = -1.f;
for (i = 0; i < 14; i++)
js->buttons[i] = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
return GLFW_TRUE;
} }
js = _glfwAllocJoystick(name, guid,
data.axisCount + data.sliderCount,
data.buttonCount,
data.povCount);
if (!js)
{
IDirectInputDevice8_Release(device);
free(data.objects);
return DIENUM_STOP;
}
js->win32.device = device;
js->win32.guid = di->guidInstance;
js->win32.objects = data.objects;
js->win32.objectCount = data.objectCount;
_glfwInputJoystick(js, GLFW_CONNECTED);
return DIENUM_CONTINUE;
} }
@ -657,14 +497,14 @@ void _glfwInitJoysticksWin32(void)
{ {
if (_glfw.win32.dinput8.instance) if (_glfw.win32.dinput8.instance)
{ {
if (FAILED(_glfw_DirectInput8Create(GetModuleHandle(NULL), if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
DIRECTINPUT_VERSION, DIRECTINPUT_VERSION,
&IID_IDirectInput8W, &IID_IDirectInput8W,
(void**) &_glfw.win32.dinput8.api, (void**) &_glfw.win32.dinput8.api,
NULL))) NULL)))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"DI: Failed to create interface"); "Win32: Failed to create interface");
} }
} }
@ -675,10 +515,10 @@ void _glfwInitJoysticksWin32(void)
// //
void _glfwTerminateJoysticksWin32(void) void _glfwTerminateJoysticksWin32(void)
{ {
int joy; int jid;
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++) for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
closeJoystick(_glfw.win32_js + joy); closeJoystick(_glfw.joysticks + jid);
if (_glfw.win32.dinput8.api) if (_glfw.win32.dinput8.api)
IDirectInput8_Release(_glfw.win32.dinput8.api); IDirectInput8_Release(_glfw.win32.dinput8.api);
@ -690,10 +530,43 @@ void _glfwDetectJoystickConnectionWin32(void)
{ {
if (_glfw.win32.xinput.instance) if (_glfw.win32.xinput.instance)
{ {
DWORD i; DWORD index;
for (i = 0; i < XUSER_MAX_COUNT; i++) for (index = 0; index < XUSER_MAX_COUNT; index++)
openXinputDevice(i); {
int jid;
char guid[33];
XINPUT_CAPABILITIES xic;
_GLFWjoystick* js;
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
if (_glfw.joysticks[jid].present &&
_glfw.joysticks[jid].win32.device == NULL &&
_glfw.joysticks[jid].win32.index == index)
{
break;
}
}
if (jid <= GLFW_JOYSTICK_LAST)
continue;
if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
continue;
// Generate a joystick GUID that matches the SDL 2.0.5+ one
sprintf(guid, "78696e707574%02x000000000000000000",
xic.SubType & 0xff);
js = _glfwAllocJoystick(getDeviceDescription(&xic), guid, 6, 10, 1);
if (!js)
continue;
js->win32.index = index;
_glfwInputJoystick(js, GLFW_CONNECTED);
}
} }
if (_glfw.win32.dinput8.api) if (_glfw.win32.dinput8.api)
@ -715,10 +588,14 @@ void _glfwDetectJoystickConnectionWin32(void)
// //
void _glfwDetectJoystickDisconnectionWin32(void) void _glfwDetectJoystickDisconnectionWin32(void)
{ {
int joy; int jid;
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++) for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
pollJoystickState(_glfw.win32_js + joy, _GLFW_PRESENCE_ONLY); {
_GLFWjoystick* js = _glfw.joysticks + jid;
if (js->present)
_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
}
} }
@ -726,38 +603,153 @@ void _glfwDetectJoystickDisconnectionWin32(void)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
int _glfwPlatformJoystickPresent(int joy) int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
{ {
_GLFWjoystickWin32* js = _glfw.win32_js + joy; if (js->win32.device)
return pollJoystickState(js, _GLFW_PRESENCE_ONLY); {
int i, ai = 0, bi = 0, pi = 0;
HRESULT result;
DIJOYSTATE state;
IDirectInputDevice8_Poll(js->win32.device);
result = IDirectInputDevice8_GetDeviceState(js->win32.device,
sizeof(state),
&state);
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
{
IDirectInputDevice8_Acquire(js->win32.device);
IDirectInputDevice8_Poll(js->win32.device);
result = IDirectInputDevice8_GetDeviceState(js->win32.device,
sizeof(state),
&state);
}
if (FAILED(result))
{
closeJoystick(js);
return GLFW_FALSE;
}
if (mode == _GLFW_POLL_PRESENCE)
return GLFW_TRUE;
for (i = 0; i < js->win32.objectCount; i++)
{
const void* data = (char*) &state + js->win32.objects[i].offset;
switch (js->win32.objects[i].type)
{
case _GLFW_TYPE_AXIS:
case _GLFW_TYPE_SLIDER:
{
const float value = (*((LONG*) data) + 0.5f) / 32767.5f;
_glfwInputJoystickAxis(js, ai, value);
ai++;
break;
}
case _GLFW_TYPE_BUTTON:
{
const char value = (*((BYTE*) data) & 0x80) != 0;
_glfwInputJoystickButton(js, bi, value);
bi++;
break;
}
case _GLFW_TYPE_POV:
{
const int states[9] =
{
GLFW_HAT_UP,
GLFW_HAT_RIGHT_UP,
GLFW_HAT_RIGHT,
GLFW_HAT_RIGHT_DOWN,
GLFW_HAT_DOWN,
GLFW_HAT_LEFT_DOWN,
GLFW_HAT_LEFT,
GLFW_HAT_LEFT_UP,
GLFW_HAT_CENTERED
};
// Screams of horror are appropriate at this point
int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
if (state < 0 || state > 8)
state = 8;
_glfwInputJoystickHat(js, pi, states[state]);
pi++;
break;
}
}
}
}
else
{
int i, dpad = 0;
DWORD result;
XINPUT_STATE xis;
const WORD buttons[10] =
{
XINPUT_GAMEPAD_A,
XINPUT_GAMEPAD_B,
XINPUT_GAMEPAD_X,
XINPUT_GAMEPAD_Y,
XINPUT_GAMEPAD_LEFT_SHOULDER,
XINPUT_GAMEPAD_RIGHT_SHOULDER,
XINPUT_GAMEPAD_BACK,
XINPUT_GAMEPAD_START,
XINPUT_GAMEPAD_LEFT_THUMB,
XINPUT_GAMEPAD_RIGHT_THUMB
};
result = XInputGetState(js->win32.index, &xis);
if (result != ERROR_SUCCESS)
{
if (result == ERROR_DEVICE_NOT_CONNECTED)
closeJoystick(js);
return GLFW_FALSE;
}
if (mode == _GLFW_POLL_PRESENCE)
return GLFW_TRUE;
_glfwInputJoystickAxis(js, 0, (xis.Gamepad.sThumbLX + 0.5f) / 32767.5f);
_glfwInputJoystickAxis(js, 1, -(xis.Gamepad.sThumbLY + 0.5f) / 32767.5f);
_glfwInputJoystickAxis(js, 2, (xis.Gamepad.sThumbRX + 0.5f) / 32767.5f);
_glfwInputJoystickAxis(js, 3, -(xis.Gamepad.sThumbRY + 0.5f) / 32767.5f);
_glfwInputJoystickAxis(js, 4, xis.Gamepad.bLeftTrigger / 127.5f - 1.f);
_glfwInputJoystickAxis(js, 5, xis.Gamepad.bRightTrigger / 127.5f - 1.f);
for (i = 0; i < 10; i++)
{
const char value = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
_glfwInputJoystickButton(js, i, value);
}
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
dpad |= GLFW_HAT_UP;
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
dpad |= GLFW_HAT_RIGHT;
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
dpad |= GLFW_HAT_DOWN;
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
dpad |= GLFW_HAT_LEFT;
_glfwInputJoystickHat(js, 0, dpad);
}
return GLFW_TRUE;
} }
const float* _glfwPlatformGetJoystickAxes(int joy, int* count) void _glfwPlatformUpdateGamepadGUID(char* guid)
{ {
_GLFWjoystickWin32* js = _glfw.win32_js + joy; if (strcmp(guid + 20, "504944564944") == 0)
if (!pollJoystickState(js, _GLFW_UPDATE_STATE)) {
return NULL; char original[33];
strncpy(original, guid, sizeof(original) - 1);
*count = js->axisCount; sprintf(guid, "03000000%.4s0000%.4s000000000000",
return js->axes; original, original + 4);
} }
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
{
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
return NULL;
*count = js->buttonCount;
return js->buttons;
}
const char* _glfwPlatformGetJoystickName(int joy)
{
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
if (!pollJoystickState(js, _GLFW_PRESENCE_ONLY))
return NULL;
return js->name;
} }

View File

@ -1,7 +1,7 @@
//======================================================================== //========================================================================
// GLFW 3.2 Win32 - www.glfw.org // GLFW 3.3 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // Copyright (c) 2006-2017 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
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -24,11 +24,10 @@
// //
//======================================================================== //========================================================================
#ifndef _glfw3_win32_joystick_h_ #define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickWin32 win32
#define _glfw3_win32_joystick_h_ #define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE int dummy
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \ #define _GLFW_PLATFORM_MAPPING_NAME "Windows"
_GLFWjoystickWin32 win32_js[GLFW_JOYSTICK_LAST + 1]
// Joystick element (axis, button or slider) // Joystick element (axis, button or slider)
// //
@ -42,14 +41,8 @@ typedef struct _GLFWjoyobjectWin32
// //
typedef struct _GLFWjoystickWin32 typedef struct _GLFWjoystickWin32
{ {
GLFWbool present;
float* axes;
int axisCount;
unsigned char* buttons;
int buttonCount;
_GLFWjoyobjectWin32* objects; _GLFWjoyobjectWin32* objects;
int objectCount; int objectCount;
char* name;
IDirectInputDevice8W* device; IDirectInputDevice8W* device;
DWORD index; DWORD index;
GUID guid; GUID guid;
@ -61,4 +54,3 @@ void _glfwTerminateJoysticksWin32(void);
void _glfwDetectJoystickConnectionWin32(void); void _glfwDetectJoystickConnectionWin32(void);
void _glfwDetectJoystickDisconnectionWin32(void); void _glfwDetectJoystickDisconnectionWin32(void);
#endif // _glfw3_win32_joystick_h_

View File

@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.2 Win32 - www.glfw.org // GLFW 3.3 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // Copyright (c) 2006-2019 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
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"
@ -33,33 +35,66 @@
#include <malloc.h> #include <malloc.h>
// Callback for EnumDisplayMonitors in createMonitor
//
static BOOL CALLBACK monitorCallback(HMONITOR handle,
HDC dc,
RECT* rect,
LPARAM data)
{
MONITORINFOEXW mi;
ZeroMemory(&mi, sizeof(mi));
mi.cbSize = sizeof(mi);
if (GetMonitorInfoW(handle, (MONITORINFO*) &mi))
{
_GLFWmonitor* monitor = (_GLFWmonitor*) data;
if (wcscmp(mi.szDevice, monitor->win32.adapterName) == 0)
monitor->win32.handle = handle;
}
return TRUE;
}
// Create monitor from an adapter and (optionally) a display // Create monitor from an adapter and (optionally) a display
// //
static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter, static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
DISPLAY_DEVICEW* display) DISPLAY_DEVICEW* display)
{ {
_GLFWmonitor* monitor; _GLFWmonitor* monitor;
int widthMM, heightMM;
char* name; char* name;
HDC dc; HDC dc;
DEVMODEW dm;
RECT rect;
if (display) if (display)
name = _glfwCreateUTF8FromWideStringWin32(display->DeviceString); name = _glfwCreateUTF8FromWideStringWin32(display->DeviceString);
else else
name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString); name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString);
if (!name) if (!name)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert string to UTF-8");
return NULL; return NULL;
}
ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(dm);
EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm);
dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL); dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
monitor = _glfwAllocMonitor(name, if (IsWindows8Point1OrGreater())
GetDeviceCaps(dc, HORZSIZE), {
GetDeviceCaps(dc, VERTSIZE)); widthMM = GetDeviceCaps(dc, HORZSIZE);
heightMM = GetDeviceCaps(dc, VERTSIZE);
}
else
{
widthMM = (int) (dm.dmPelsWidth * 25.4f / GetDeviceCaps(dc, LOGPIXELSX));
heightMM = (int) (dm.dmPelsHeight * 25.4f / GetDeviceCaps(dc, LOGPIXELSY));
}
DeleteDC(dc); DeleteDC(dc);
monitor = _glfwAllocMonitor(name, widthMM, heightMM);
free(name); free(name);
if (adapter->StateFlags & DISPLAY_DEVICE_MODESPRUNED) if (adapter->StateFlags & DISPLAY_DEVICE_MODESPRUNED)
@ -82,6 +117,12 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
NULL, NULL); NULL, NULL);
} }
rect.left = dm.dmPosition.x;
rect.top = dm.dmPosition.y;
rect.right = dm.dmPosition.x + dm.dmPelsWidth;
rect.bottom = dm.dmPosition.y + dm.dmPelsHeight;
EnumDisplayMonitors(NULL, &rect, monitorCallback, (LPARAM) monitor);
return monitor; return monitor;
} }
@ -90,21 +131,132 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Poll for changes in the set of connected monitors
//
void _glfwPollMonitorsWin32(void)
{
int i, disconnectedCount;
_GLFWmonitor** disconnected = NULL;
DWORD adapterIndex, displayIndex;
DISPLAY_DEVICEW adapter, display;
_GLFWmonitor* monitor;
disconnectedCount = _glfw.monitorCount;
if (disconnectedCount)
{
disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
memcpy(disconnected,
_glfw.monitors,
_glfw.monitorCount * sizeof(_GLFWmonitor*));
}
for (adapterIndex = 0; ; adapterIndex++)
{
int type = _GLFW_INSERT_LAST;
ZeroMemory(&adapter, sizeof(adapter));
adapter.cb = sizeof(adapter);
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
break;
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
continue;
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
type = _GLFW_INSERT_FIRST;
for (displayIndex = 0; ; displayIndex++)
{
ZeroMemory(&display, sizeof(display));
display.cb = sizeof(display);
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
break;
if (!(display.StateFlags & DISPLAY_DEVICE_ACTIVE))
continue;
for (i = 0; i < disconnectedCount; i++)
{
if (disconnected[i] &&
wcscmp(disconnected[i]->win32.displayName,
display.DeviceName) == 0)
{
disconnected[i] = NULL;
break;
}
}
if (i < disconnectedCount)
continue;
monitor = createMonitor(&adapter, &display);
if (!monitor)
{
free(disconnected);
return;
}
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
type = _GLFW_INSERT_LAST;
}
// HACK: If an active adapter does not have any display devices
// (as sometimes happens), add it directly as a monitor
if (displayIndex == 0)
{
for (i = 0; i < disconnectedCount; i++)
{
if (disconnected[i] &&
wcscmp(disconnected[i]->win32.adapterName,
adapter.DeviceName) == 0)
{
disconnected[i] = NULL;
break;
}
}
if (i < disconnectedCount)
continue;
monitor = createMonitor(&adapter, NULL);
if (!monitor)
{
free(disconnected);
return;
}
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
}
}
for (i = 0; i < disconnectedCount; i++)
{
if (disconnected[i])
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
}
free(disconnected);
}
// 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;
DEVMODEW dm; DEVMODEW dm;
LONG result;
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(DEVMODEW); dm.dmSize = sizeof(dm);
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL |
DM_DISPLAYFREQUENCY; DM_DISPLAYFREQUENCY;
dm.dmPelsWidth = best->width; dm.dmPelsWidth = best->width;
@ -115,18 +267,36 @@ GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desire
if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24) if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24)
dm.dmBitsPerPel = 32; dm.dmBitsPerPel = 32;
if (ChangeDisplaySettingsExW(monitor->win32.adapterName, result = ChangeDisplaySettingsExW(monitor->win32.adapterName,
&dm, &dm,
NULL, NULL,
CDS_FULLSCREEN, CDS_FULLSCREEN,
NULL) != DISP_CHANGE_SUCCESSFUL) NULL);
if (result == DISP_CHANGE_SUCCESSFUL)
monitor->win32.modeChanged = GLFW_TRUE;
else
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to set video mode"); const char* description = "Unknown error";
return GLFW_FALSE;
}
monitor->win32.modeChanged = GLFW_TRUE; if (result == DISP_CHANGE_BADDUALVIEW)
return GLFW_TRUE; description = "The system uses DualView";
else if (result == DISP_CHANGE_BADFLAGS)
description = "Invalid flags";
else if (result == DISP_CHANGE_BADMODE)
description = "Graphics mode not supported";
else if (result == DISP_CHANGE_BADPARAM)
description = "Invalid parameter";
else if (result == DISP_CHANGE_FAILED)
description = "Graphics mode failed";
else if (result == DISP_CHANGE_NOTUPDATED)
description = "Failed to write to registry";
else if (result == DISP_CHANGE_RESTART)
description = "Computer restart required";
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to set video mode: %s",
description);
}
} }
// Restore the previously saved (original) video mode // Restore the previously saved (original) video mode
@ -141,111 +311,73 @@ void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor)
} }
} }
void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale)
{
UINT xdpi, ydpi;
if (IsWindows8Point1OrGreater())
GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);
else
{
const HDC dc = GetDC(NULL);
xdpi = GetDeviceCaps(dc, LOGPIXELSX);
ydpi = GetDeviceCaps(dc, LOGPIXELSY);
ReleaseDC(NULL, dc);
}
if (xscale)
*xscale = xdpi / (float) USER_DEFAULT_SCREEN_DPI;
if (yscale)
*yscale = ydpi / (float) USER_DEFAULT_SCREEN_DPI;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
_GLFWmonitor** _glfwPlatformGetMonitors(int* count) void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
{ {
int found = 0;
DWORD adapterIndex, displayIndex, primaryIndex = 0;
DISPLAY_DEVICEW adapter, display;
GLFWbool hasDisplays = GLFW_FALSE;
_GLFWmonitor** monitors = NULL;
*count = 0;
// HACK: Check if any active adapters have connected displays
// If not, this is a headless system or a VMware guest
for (adapterIndex = 0; ; adapterIndex++)
{
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
adapter.cb = sizeof(DISPLAY_DEVICEW);
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
break;
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
continue;
ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
display.cb = sizeof(DISPLAY_DEVICEW);
if (EnumDisplayDevicesW(adapter.DeviceName, 0, &display, 0))
{
hasDisplays = GLFW_TRUE;
break;
}
}
for (adapterIndex = 0; ; adapterIndex++)
{
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
adapter.cb = sizeof(DISPLAY_DEVICEW);
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
break;
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
continue;
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
primaryIndex = found;
if (hasDisplays)
{
for (displayIndex = 0; ; displayIndex++)
{
ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
display.cb = sizeof(DISPLAY_DEVICEW);
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
break;
found++;
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
monitors[found - 1] = createMonitor(&adapter, &display);
}
}
else
{
found++;
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
monitors[found - 1] = createMonitor(&adapter, NULL);
}
}
_GLFW_SWAP_POINTERS(monitors[0], monitors[primaryIndex]);
*count = found;
return monitors;
}
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
{
if (wcslen(first->win32.displayName))
return wcscmp(first->win32.displayName, second->win32.displayName) == 0;
else
return wcscmp(first->win32.adapterName, second->win32.adapterName) == 0;
} }
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{ {
DEVMODEW settings; DEVMODEW dm;
ZeroMemory(&settings, sizeof(DEVMODEW)); ZeroMemory(&dm, sizeof(dm));
settings.dmSize = sizeof(DEVMODEW); dm.dmSize = sizeof(dm);
EnumDisplaySettingsExW(monitor->win32.adapterName, EnumDisplaySettingsExW(monitor->win32.adapterName,
ENUM_CURRENT_SETTINGS, ENUM_CURRENT_SETTINGS,
&settings, &dm,
EDS_ROTATEDMODE); EDS_ROTATEDMODE);
if (xpos) if (xpos)
*xpos = settings.dmPosition.x; *xpos = dm.dmPosition.x;
if (ypos) if (ypos)
*ypos = settings.dmPosition.y; *ypos = dm.dmPosition.y;
}
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
float* xscale, float* yscale)
{
_glfwGetMonitorContentScaleWin32(monitor->win32.handle, xscale, yscale);
}
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
int* xpos, int* ypos,
int* width, int* height)
{
MONITORINFO mi = { sizeof(mi) };
GetMonitorInfo(monitor->win32.handle, &mi);
if (xpos)
*xpos = mi.rcWork.left;
if (ypos)
*ypos = mi.rcWork.top;
if (width)
*width = mi.rcWork.right - mi.rcWork.left;
if (height)
*height = mi.rcWork.bottom - mi.rcWork.top;
} }
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
@ -261,8 +393,8 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
GLFWvidmode mode; GLFWvidmode mode;
DEVMODEW dm; DEVMODEW dm;
ZeroMemory(&dm, sizeof(DEVMODEW)); ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(DEVMODEW); dm.dmSize = sizeof(dm);
if (!EnumDisplaySettingsW(monitor->win32.adapterName, modeIndex, &dm)) if (!EnumDisplaySettingsW(monitor->win32.adapterName, modeIndex, &dm))
break; break;
@ -328,9 +460,8 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
{ {
DEVMODEW dm; DEVMODEW dm;
ZeroMemory(&dm, sizeof(dm));
ZeroMemory(&dm, sizeof(DEVMODEW)); dm.dmSize = sizeof(dm);
dm.dmSize = sizeof(DEVMODEW);
EnumDisplaySettingsW(monitor->win32.adapterName, ENUM_CURRENT_SETTINGS, &dm); EnumDisplaySettingsW(monitor->win32.adapterName, ENUM_CURRENT_SETTINGS, &dm);
@ -343,10 +474,10 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
&mode->blueBits); &mode->blueBits);
} }
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{ {
HDC dc; HDC dc;
WORD values[768]; WORD values[3][256];
dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL); dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
GetDeviceGammaRamp(dc, values); GetDeviceGammaRamp(dc, values);
@ -354,15 +485,17 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
_glfwAllocGammaArrays(ramp, 256); _glfwAllocGammaArrays(ramp, 256);
memcpy(ramp->red, values + 0, 256 * sizeof(unsigned short)); memcpy(ramp->red, values[0], sizeof(values[0]));
memcpy(ramp->green, values + 256, 256 * sizeof(unsigned short)); memcpy(ramp->green, values[1], sizeof(values[1]));
memcpy(ramp->blue, values + 512, 256 * sizeof(unsigned short)); memcpy(ramp->blue, values[2], sizeof(values[2]));
return GLFW_TRUE;
} }
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
{ {
HDC dc; HDC dc;
WORD values[768]; WORD values[3][256];
if (ramp->size != 256) if (ramp->size != 256)
{ {
@ -371,9 +504,9 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
return; return;
} }
memcpy(values + 0, ramp->red, 256 * sizeof(unsigned short)); memcpy(values[0], ramp->red, sizeof(values[0]));
memcpy(values + 256, ramp->green, 256 * sizeof(unsigned short)); memcpy(values[1], ramp->green, sizeof(values[1]));
memcpy(values + 512, ramp->blue, 256 * sizeof(unsigned short)); memcpy(values[2], ramp->blue, sizeof(values[2]));
dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL); dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
SetDeviceGammaRamp(dc, values); SetDeviceGammaRamp(dc, values);

View File

@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.2 Win32 - www.glfw.org // GLFW 3.3 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // Copyright (c) 2006-2019 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
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -25,9 +25,6 @@
// //
//======================================================================== //========================================================================
#ifndef _glfw3_win32_platform_h_
#define _glfw3_win32_platform_h_
// We don't need all the fancy stuff // We don't need all the fancy stuff
#ifndef NOMINMAX #ifndef NOMINMAX
#define NOMINMAX #define NOMINMAX
@ -64,18 +61,15 @@
// GLFW uses DirectInput8 interfaces // GLFW uses DirectInput8 interfaces
#define DIRECTINPUT_VERSION 0x0800 #define DIRECTINPUT_VERSION 0x0800
// GLFW uses OEM cursor resources
#define OEMRESOURCE
#include <wctype.h> #include <wctype.h>
#include <windows.h> #include <windows.h>
#include <mmsystem.h>
#include <dinput.h> #include <dinput.h>
#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
@ -104,28 +98,89 @@
#ifndef DISPLAY_DEVICE_ACTIVE #ifndef DISPLAY_DEVICE_ACTIVE
#define DISPLAY_DEVICE_ACTIVE 0x00000001 #define DISPLAY_DEVICE_ACTIVE 0x00000001
#endif #endif
#ifndef _WIN32_WINNT_WINBLUE
#define _WIN32_WINNT_WINBLUE 0x0602
#endif
#ifndef _WIN32_WINNT_WIN8
#define _WIN32_WINNT_WIN8 0x0602
#endif
#ifndef WM_GETDPISCALEDSIZE
#define WM_GETDPISCALEDSIZE 0x02e4
#endif
#ifndef USER_DEFAULT_SCREEN_DPI
#define USER_DEFAULT_SCREEN_DPI 96
#endif
#ifndef OCR_HAND
#define OCR_HAND 32649
#endif
#if WINVER < 0x0601 #if WINVER < 0x0601
typedef struct tagCHANGEFILTERSTRUCT typedef struct
{ {
DWORD cbSize; DWORD cbSize;
DWORD ExtStatus; DWORD ExtStatus;
} CHANGEFILTERSTRUCT;
} CHANGEFILTERSTRUCT, *PCHANGEFILTERSTRUCT;
#ifndef MSGFLT_ALLOW #ifndef MSGFLT_ALLOW
#define MSGFLT_ALLOW 1 #define MSGFLT_ALLOW 1
#endif #endif
#endif /*Windows 7*/ #endif /*Windows 7*/
#if WINVER < 0x0600
#define DWM_BB_ENABLE 0x00000001
#define DWM_BB_BLURREGION 0x00000002
typedef struct
{
DWORD dwFlags;
BOOL fEnable;
HRGN hRgnBlur;
BOOL fTransitionOnMaximized;
} DWM_BLURBEHIND;
#else
#include <dwmapi.h>
#endif /*Windows Vista*/
#ifndef DPI_ENUMS_DECLARED #ifndef DPI_ENUMS_DECLARED
typedef enum PROCESS_DPI_AWARENESS typedef enum
{ {
PROCESS_DPI_UNAWARE = 0, PROCESS_DPI_UNAWARE = 0,
PROCESS_SYSTEM_DPI_AWARE = 1, PROCESS_SYSTEM_DPI_AWARE = 1,
PROCESS_PER_MONITOR_DPI_AWARE = 2 PROCESS_PER_MONITOR_DPI_AWARE = 2
} PROCESS_DPI_AWARENESS; } PROCESS_DPI_AWARENESS;
typedef enum
{
MDT_EFFECTIVE_DPI = 0,
MDT_ANGULAR_DPI = 1,
MDT_RAW_DPI = 2,
MDT_DEFAULT = MDT_EFFECTIVE_DPI
} MONITOR_DPI_TYPE;
#endif /*DPI_ENUMS_DECLARED*/ #endif /*DPI_ENUMS_DECLARED*/
#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE) -4)
#endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
#define IsWindowsXPOrGreater() \
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINXP), \
LOBYTE(_WIN32_WINNT_WINXP), 0)
#define IsWindowsVistaOrGreater() \
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_VISTA), \
LOBYTE(_WIN32_WINNT_VISTA), 0)
#define IsWindows7OrGreater() \
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN7), \
LOBYTE(_WIN32_WINNT_WIN7), 0)
#define IsWindows8OrGreater() \
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN8), \
LOBYTE(_WIN32_WINNT_WIN8), 0)
#define IsWindows8Point1OrGreater() \
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINBLUE), \
LOBYTE(_WIN32_WINNT_WINBLUE), 0)
#define _glfwIsWindows10AnniversaryUpdateOrGreaterWin32() \
_glfwIsWindows10BuildOrGreaterWin32(14393)
#define _glfwIsWindows10CreatorsUpdateOrGreaterWin32() \
_glfwIsWindows10BuildOrGreaterWin32(15063)
// HACK: Define macros that some xinput.h variants don't // HACK: Define macros that some xinput.h variants don't
#ifndef XINPUT_CAPS_WIRELESS #ifndef XINPUT_CAPS_WIRELESS
#define XINPUT_CAPS_WIRELESS 0x0002 #define XINPUT_CAPS_WIRELESS 0x0002
@ -157,38 +212,54 @@ typedef enum PROCESS_DPI_AWARENESS
// HACK: Define macros that some dinput.h variants don't // HACK: Define macros that some dinput.h variants don't
#ifndef DIDFT_OPTIONAL #ifndef DIDFT_OPTIONAL
#define DIDFT_OPTIONAL 0x80000000 #define DIDFT_OPTIONAL 0x80000000
#endif #endif
// winmm.dll function pointer typedefs // winmm.dll function pointer typedefs
typedef DWORD (WINAPI * TIMEGETTIME_T)(void); typedef DWORD (WINAPI * PFN_timeGetTime)(void);
#define _glfw_timeGetTime _glfw.win32.winmm.timeGetTime #define timeGetTime _glfw.win32.winmm.GetTime
// xinput.dll function pointer typedefs // xinput.dll function pointer typedefs
typedef DWORD (WINAPI * XINPUTGETCAPABILITIES_T)(DWORD,DWORD,XINPUT_CAPABILITIES*); typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*);
typedef DWORD (WINAPI * XINPUTGETSTATE_T)(DWORD,XINPUT_STATE*); typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
#define _glfw_XInputGetCapabilities _glfw.win32.xinput.XInputGetCapabilities #define XInputGetCapabilities _glfw.win32.xinput.GetCapabilities
#define _glfw_XInputGetState _glfw.win32.xinput.XInputGetState #define XInputGetState _glfw.win32.xinput.GetState
// dinput8.dll function pointer typedefs // dinput8.dll function pointer typedefs
typedef HRESULT (WINAPI * DIRECTINPUT8CREATE_T)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN); typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
#define _glfw_DirectInput8Create _glfw.win32.dinput8.DirectInput8Create #define DirectInput8Create _glfw.win32.dinput8.Create
// user32.dll function pointer typedefs // user32.dll function pointer typedefs
typedef BOOL (WINAPI * SETPROCESSDPIAWARE_T)(void); typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void);
typedef BOOL (WINAPI * CHANGEWINDOWMESSAGEFILTEREX_T)(HWND,UINT,DWORD,PCHANGEFILTERSTRUCT); typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,CHANGEFILTERSTRUCT*);
#define _glfw_SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND);
#define _glfw_ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE);
typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
#define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
#define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_
#define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_
#define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_
// dwmapi.dll function pointer typedefs // dwmapi.dll function pointer typedefs
typedef HRESULT (WINAPI * DWMISCOMPOSITIONENABLED_T)(BOOL*); typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
typedef HRESULT (WINAPI * DWMFLUSH_T)(VOID); typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
#define _glfw_DwmIsCompositionEnabled _glfw.win32.dwmapi.DwmIsCompositionEnabled typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*);
#define _glfw_DwmFlush _glfw.win32.dwmapi.DwmFlush #define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled
#define DwmFlush _glfw.win32.dwmapi.Flush
#define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow
// shcore.dll function pointer typedefs // shcore.dll function pointer typedefs
typedef HRESULT (WINAPI * SETPROCESSDPIAWARENESS_T)(PROCESS_DPI_AWARENESS); typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
#define _glfw_SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);
#define SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness_
#define GetDpiForMonitor _glfw.win32.shcore.GetDpiForMonitor_
// ntdll.dll function pointer typedefs
typedef LONG (WINAPI * PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*,ULONG,ULONGLONG);
#define RtlVerifyVersionInfo _glfw.win32.ntdll.RtlVerifyVersionInfo_
typedef VkFlags VkWin32SurfaceCreateFlagsKHR; typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
@ -207,8 +278,11 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
#include "win32_joystick.h" #include "win32_joystick.h"
#include "wgl_context.h" #include "wgl_context.h"
#include "egl_context.h" #include "egl_context.h"
#include "osmesa_context.h"
#define _GLFW_WNDCLASSNAME L"GLFW30" #if !defined(_GLFW_WNDCLASSNAME)
#define _GLFW_WNDCLASSNAME L"GLFW30"
#endif
#define _glfw_dlopen(name) LoadLibraryA(name) #define _glfw_dlopen(name) LoadLibraryA(name)
#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle) #define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
@ -219,10 +293,11 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32 #define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32 #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time #define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerWin32 win32
#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsWin32 win32_tls
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 win32 #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 win32
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWin32 win32 #define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWin32 win32
#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsWin32 win32
#define _GLFW_PLATFORM_MUTEX_STATE _GLFWmutexWin32 win32
// Win32-specific per-window data // Win32-specific per-window data
@ -234,7 +309,12 @@ typedef struct _GLFWwindowWin32
HICON smallIcon; HICON smallIcon;
GLFWbool cursorTracked; GLFWbool cursorTracked;
GLFWbool frameAction;
GLFWbool iconified; GLFWbool iconified;
GLFWbool maximized;
// Whether to enable framebuffer transparency on DWM
GLFWbool transparent;
GLFWbool scaleToMonitor;
// The last received cursor position, regardless of source // The last received cursor position, regardless of source
int lastCursorPosX, lastCursorPosY; int lastCursorPosX, lastCursorPosY;
@ -246,61 +326,78 @@ typedef struct _GLFWwindowWin32
typedef struct _GLFWlibraryWin32 typedef struct _GLFWlibraryWin32
{ {
HWND helperWindowHandle; HWND helperWindowHandle;
HDEVNOTIFY deviceNotificationHandle;
DWORD foregroundLockTimeout; DWORD foregroundLockTimeout;
int acquiredMonitorCount;
char* clipboardString; char* clipboardString;
char keyName[64]; short int keycodes[512];
short int publicKeys[512]; short int scancodes[GLFW_KEY_LAST + 1];
short int nativeKeys[GLFW_KEY_LAST + 1]; char keynames[GLFW_KEY_LAST + 1][5];
// Where to place the cursor when re-enabled // Where to place the cursor when re-enabled
double restoreCursorPosX, restoreCursorPosY; double restoreCursorPosX, restoreCursorPosY;
// The window whose disabled cursor mode is active // The window whose disabled cursor mode is active
_GLFWwindow* disabledCursorWindow; _GLFWwindow* disabledCursorWindow;
RAWINPUT* rawInput;
int rawInputSize;
UINT mouseTrailSize;
struct { struct {
HINSTANCE instance; HINSTANCE instance;
TIMEGETTIME_T timeGetTime; PFN_timeGetTime GetTime;
} winmm; } winmm;
struct { struct {
HINSTANCE instance; HINSTANCE instance;
DIRECTINPUT8CREATE_T DirectInput8Create; PFN_DirectInput8Create Create;
IDirectInput8W* api; IDirectInput8W* api;
} dinput8; } dinput8;
struct { struct {
HINSTANCE instance; HINSTANCE instance;
XINPUTGETCAPABILITIES_T XInputGetCapabilities; PFN_XInputGetCapabilities GetCapabilities;
XINPUTGETSTATE_T XInputGetState; PFN_XInputGetState GetState;
} xinput; } xinput;
struct { struct {
HINSTANCE instance; HINSTANCE instance;
SETPROCESSDPIAWARE_T SetProcessDPIAware; PFN_SetProcessDPIAware SetProcessDPIAware_;
CHANGEWINDOWMESSAGEFILTEREX_T ChangeWindowMessageFilterEx; PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx_;
PFN_EnableNonClientDpiScaling EnableNonClientDpiScaling_;
PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
PFN_GetDpiForWindow GetDpiForWindow_;
PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi_;
} user32; } user32;
struct { struct {
HINSTANCE instance; HINSTANCE instance;
DWMISCOMPOSITIONENABLED_T DwmIsCompositionEnabled; PFN_DwmIsCompositionEnabled IsCompositionEnabled;
DWMFLUSH_T DwmFlush; PFN_DwmFlush Flush;
PFN_DwmEnableBlurBehindWindow EnableBlurBehindWindow;
} dwmapi; } dwmapi;
struct { struct {
HINSTANCE instance; HINSTANCE instance;
SETPROCESSDPIAWARENESS_T SetProcessDpiAwareness; PFN_SetProcessDpiAwareness SetProcessDpiAwareness_;
PFN_GetDpiForMonitor GetDpiForMonitor_;
} shcore; } shcore;
struct {
HINSTANCE instance;
PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_;
} ntdll;
} _GLFWlibraryWin32; } _GLFWlibraryWin32;
// Win32-specific per-monitor data // Win32-specific per-monitor data
// //
typedef struct _GLFWmonitorWin32 typedef struct _GLFWmonitorWin32
{ {
HMONITOR handle;
// This size matches the static size of DISPLAY_DEVICE.DeviceName // This size matches the static size of DISPLAY_DEVICE.DeviceName
WCHAR adapterName[32]; WCHAR adapterName[32];
WCHAR displayName[32]; WCHAR displayName[32];
char publicAdapterName[64]; char publicAdapterName[32];
char publicDisplayName[64]; char publicDisplayName[32];
GLFWbool modesPruned; GLFWbool modesPruned;
GLFWbool modeChanged; GLFWbool modeChanged;
@ -310,41 +407,52 @@ typedef struct _GLFWmonitorWin32
// //
typedef struct _GLFWcursorWin32 typedef struct _GLFWcursorWin32
{ {
HCURSOR handle; HCURSOR handle;
} _GLFWcursorWin32; } _GLFWcursorWin32;
// Win32-specific global timer data // Win32-specific global timer data
// //
typedef struct _GLFWtimeWin32 typedef struct _GLFWtimerWin32
{ {
GLFWbool hasPC; GLFWbool hasPC;
uint64_t frequency; uint64_t frequency;
} _GLFWtimeWin32; } _GLFWtimerWin32;
// Win32-specific global TLS data // Win32-specific thread local storage data
// //
typedef struct _GLFWtlsWin32 typedef struct _GLFWtlsWin32
{ {
GLFWbool allocated; GLFWbool allocated;
DWORD context; DWORD index;
} _GLFWtlsWin32; } _GLFWtlsWin32;
// Win32-specific mutex data
//
typedef struct _GLFWmutexWin32
{
GLFWbool allocated;
CRITICAL_SECTION section;
} _GLFWmutexWin32;
GLFWbool _glfwRegisterWindowClassWin32(void); GLFWbool _glfwRegisterWindowClassWin32(void);
void _glfwUnregisterWindowClassWin32(void); void _glfwUnregisterWindowClassWin32(void);
GLFWbool _glfwInitThreadLocalStorageWin32(void);
void _glfwTerminateThreadLocalStorageWin32(void);
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source); WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source); char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp);
BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build);
void _glfwInputErrorWin32(int error, const char* description);
void _glfwUpdateKeyNamesWin32(void);
void _glfwInitTimerWin32(void); void _glfwInitTimerWin32(void);
GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired); void _glfwPollMonitorsWin32(void);
void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor); void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale);
#endif // _glfw3_win32_platform_h_

View File

@ -0,0 +1,99 @@
//========================================================================
// GLFW 3.3 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 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
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h"
#include <assert.h>
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
{
assert(tls->win32.allocated == GLFW_FALSE);
tls->win32.index = TlsAlloc();
if (tls->win32.index == TLS_OUT_OF_INDEXES)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to allocate TLS index");
return GLFW_FALSE;
}
tls->win32.allocated = GLFW_TRUE;
return GLFW_TRUE;
}
void _glfwPlatformDestroyTls(_GLFWtls* tls)
{
if (tls->win32.allocated)
TlsFree(tls->win32.index);
memset(tls, 0, sizeof(_GLFWtls));
}
void* _glfwPlatformGetTls(_GLFWtls* tls)
{
assert(tls->win32.allocated == GLFW_TRUE);
return TlsGetValue(tls->win32.index);
}
void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
{
assert(tls->win32.allocated == GLFW_TRUE);
TlsSetValue(tls->win32.index, value);
}
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
{
assert(mutex->win32.allocated == GLFW_FALSE);
InitializeCriticalSection(&mutex->win32.section);
return mutex->win32.allocated = GLFW_TRUE;
}
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
{
if (mutex->win32.allocated)
DeleteCriticalSection(&mutex->win32.section);
memset(mutex, 0, sizeof(_GLFWmutex));
}
void _glfwPlatformLockMutex(_GLFWmutex* mutex)
{
assert(mutex->win32.allocated == GLFW_TRUE);
EnterCriticalSection(&mutex->win32.section);
}
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
{
assert(mutex->win32.allocated == GLFW_TRUE);
LeaveCriticalSection(&mutex->win32.section);
}

View File

@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.2 Win32 - www.glfw.org // GLFW 3.3 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // Copyright (c) 2006-2017 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
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"
@ -40,13 +42,13 @@ void _glfwInitTimerWin32(void)
if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency)) if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
{ {
_glfw.win32_time.hasPC = GLFW_TRUE; _glfw.timer.win32.hasPC = GLFW_TRUE;
_glfw.win32_time.frequency = frequency; _glfw.timer.win32.frequency = frequency;
} }
else else
{ {
_glfw.win32_time.hasPC = GLFW_FALSE; _glfw.timer.win32.hasPC = GLFW_FALSE;
_glfw.win32_time.frequency = 1000; _glfw.timer.win32.frequency = 1000;
} }
} }
@ -57,18 +59,18 @@ void _glfwInitTimerWin32(void)
uint64_t _glfwPlatformGetTimerValue(void) uint64_t _glfwPlatformGetTimerValue(void)
{ {
if (_glfw.win32_time.hasPC) if (_glfw.timer.win32.hasPC)
{ {
uint64_t value; uint64_t value;
QueryPerformanceCounter((LARGE_INTEGER*) &value); QueryPerformanceCounter((LARGE_INTEGER*) &value);
return value; return value;
} }
else else
return (uint64_t) _glfw_timeGetTime(); return (uint64_t) timeGetTime();
} }
uint64_t _glfwPlatformGetTimerFrequency(void) uint64_t _glfwPlatformGetTimerFrequency(void)
{ {
return _glfw.win32_time.frequency; return _glfw.timer.win32.frequency;
} }

View File

@ -1,69 +0,0 @@
//========================================================================
// GLFW 3.2 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 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
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include "internal.h"
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
GLFWbool _glfwInitThreadLocalStorageWin32(void)
{
_glfw.win32_tls.context = TlsAlloc();
if (_glfw.win32_tls.context == TLS_OUT_OF_INDEXES)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to allocate TLS index");
return GLFW_FALSE;
}
_glfw.win32_tls.allocated = GLFW_TRUE;
return GLFW_TRUE;
}
void _glfwTerminateThreadLocalStorageWin32(void)
{
if (_glfw.win32_tls.allocated)
TlsFree(_glfw.win32_tls.context);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformSetCurrentContext(_GLFWwindow* context)
{
TlsSetValue(_glfw.win32_tls.context, context);
}
_GLFWwindow* _glfwPlatformGetCurrentContext(void)
{
return TlsGetValue(_glfw.win32_tls.context);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.2 - www.glfw.org // GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net> // Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
@ -25,6 +25,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"
@ -38,80 +40,111 @@
////// 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 (focused) if (window->callbacks.focus)
{ window->callbacks.focus((GLFWwindow*) window, focused);
if (window->callbacks.focus)
window->callbacks.focus((GLFWwindow*) window, focused);
}
else
{
int i;
if (window->callbacks.focus) if (!focused)
window->callbacks.focus((GLFWwindow*) window, focused); {
int key, button;
// Release all pressed keyboard keys for (key = 0; key <= GLFW_KEY_LAST; key++)
for (i = 0; i <= GLFW_KEY_LAST; i++)
{ {
if (window->keys[i] == GLFW_PRESS) if (window->keys[key] == GLFW_PRESS)
_glfwInputKey(window, i, 0, GLFW_RELEASE, 0); {
const int scancode = _glfwPlatformGetKeyScancode(key);
_glfwInputKey(window, key, scancode, GLFW_RELEASE, 0);
}
} }
// Release all pressed mouse buttons for (button = 0; button <= GLFW_MOUSE_BUTTON_LAST; button++)
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
{ {
if (window->mouseButtons[i] == GLFW_PRESS) if (window->mouseButtons[button] == GLFW_PRESS)
_glfwInputMouseClick(window, i, GLFW_RELEASE, 0); _glfwInputMouseClick(window, button, GLFW_RELEASE, 0);
} }
} }
} }
// Notifies shared code that a window has moved
// The position is specified in content 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)
{
if (window->callbacks.maximize)
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->closed = GLFW_TRUE; window->shouldClose = GLFW_TRUE;
if (window->callbacks.close) if (window->callbacks.close)
window->callbacks.close((GLFWwindow*) window); window->callbacks.close((GLFWwindow*) window);
} }
void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor) // Notifies shared code that a window has changed its desired monitor
//
void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor)
{ {
window->monitor = monitor; window->monitor = monitor;
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW public API ////// ////// GLFW public API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -125,9 +158,10 @@ 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(height >= 0);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
@ -149,16 +183,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;
@ -178,6 +202,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
window->decorated = wndconfig.decorated; window->decorated = wndconfig.decorated;
window->autoIconify = wndconfig.autoIconify; window->autoIconify = wndconfig.autoIconify;
window->floating = wndconfig.floating; window->floating = wndconfig.floating;
window->focusOnShow = wndconfig.focusOnShow;
window->cursorMode = GLFW_CURSOR_NORMAL; window->cursorMode = GLFW_CURSOR_NORMAL;
window->minwidth = GLFW_DONT_CARE; window->minwidth = GLFW_DONT_CARE;
@ -187,36 +212,28 @@ 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 = _glfwPlatformGetCurrentContext();
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)
_glfwCenterCursorInContentArea(window);
}
else
{ {
if (wndconfig.visible) if (wndconfig.visible)
{ {
@ -233,23 +250,26 @@ void glfwDefaultWindowHints(void)
{ {
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
memset(&_glfw.hints, 0, sizeof(_glfw.hints));
// The default is OpenGL with minimum version 1.0 // The default is OpenGL with minimum version 1.0
memset(&_glfw.hints.context, 0, sizeof(_glfw.hints.context));
_glfw.hints.context.client = GLFW_OPENGL_API; _glfw.hints.context.client = GLFW_OPENGL_API;
_glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API; _glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API;
_glfw.hints.context.major = 1; _glfw.hints.context.major = 1;
_glfw.hints.context.minor = 0; _glfw.hints.context.minor = 0;
// The default is a focused, visible, resizable window with decorations // The default is a focused, visible, resizable window with decorations
_glfw.hints.window.resizable = GLFW_TRUE; memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
_glfw.hints.window.visible = GLFW_TRUE; _glfw.hints.window.resizable = GLFW_TRUE;
_glfw.hints.window.decorated = GLFW_TRUE; _glfw.hints.window.visible = GLFW_TRUE;
_glfw.hints.window.focused = GLFW_TRUE; _glfw.hints.window.decorated = GLFW_TRUE;
_glfw.hints.window.autoIconify = GLFW_TRUE; _glfw.hints.window.focused = GLFW_TRUE;
_glfw.hints.window.autoIconify = GLFW_TRUE;
_glfw.hints.window.centerCursor = GLFW_TRUE;
_glfw.hints.window.focusOnShow = GLFW_TRUE;
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil, // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
// double buffered // double buffered
memset(&_glfw.hints.framebuffer, 0, sizeof(_glfw.hints.framebuffer));
_glfw.hints.framebuffer.redBits = 8; _glfw.hints.framebuffer.redBits = 8;
_glfw.hints.framebuffer.greenBits = 8; _glfw.hints.framebuffer.greenBits = 8;
_glfw.hints.framebuffer.blueBits = 8; _glfw.hints.framebuffer.blueBits = 8;
@ -260,6 +280,9 @@ void glfwDefaultWindowHints(void)
// The default is to select the highest available refresh rate // The default is to select the highest available refresh rate
_glfw.hints.refreshRate = GLFW_DONT_CARE; _glfw.hints.refreshRate = GLFW_DONT_CARE;
// The default is to use full Retina resolution framebuffers
_glfw.hints.window.ns.retina = GLFW_TRUE;
} }
GLFWAPI void glfwWindowHint(int hint, int value) GLFWAPI void glfwWindowHint(int hint, int value)
@ -270,107 +293,149 @@ GLFWAPI void glfwWindowHint(int hint, int value)
{ {
case GLFW_RED_BITS: case GLFW_RED_BITS:
_glfw.hints.framebuffer.redBits = value; _glfw.hints.framebuffer.redBits = value;
break; return;
case GLFW_GREEN_BITS: case GLFW_GREEN_BITS:
_glfw.hints.framebuffer.greenBits = value; _glfw.hints.framebuffer.greenBits = value;
break; return;
case GLFW_BLUE_BITS: case GLFW_BLUE_BITS:
_glfw.hints.framebuffer.blueBits = value; _glfw.hints.framebuffer.blueBits = value;
break; return;
case GLFW_ALPHA_BITS: case GLFW_ALPHA_BITS:
_glfw.hints.framebuffer.alphaBits = value; _glfw.hints.framebuffer.alphaBits = value;
break; return;
case GLFW_DEPTH_BITS: case GLFW_DEPTH_BITS:
_glfw.hints.framebuffer.depthBits = value; _glfw.hints.framebuffer.depthBits = value;
break; return;
case GLFW_STENCIL_BITS: case GLFW_STENCIL_BITS:
_glfw.hints.framebuffer.stencilBits = value; _glfw.hints.framebuffer.stencilBits = value;
break; return;
case GLFW_ACCUM_RED_BITS: case GLFW_ACCUM_RED_BITS:
_glfw.hints.framebuffer.accumRedBits = value; _glfw.hints.framebuffer.accumRedBits = value;
break; return;
case GLFW_ACCUM_GREEN_BITS: case GLFW_ACCUM_GREEN_BITS:
_glfw.hints.framebuffer.accumGreenBits = value; _glfw.hints.framebuffer.accumGreenBits = value;
break; return;
case GLFW_ACCUM_BLUE_BITS: case GLFW_ACCUM_BLUE_BITS:
_glfw.hints.framebuffer.accumBlueBits = value; _glfw.hints.framebuffer.accumBlueBits = value;
break; return;
case GLFW_ACCUM_ALPHA_BITS: case GLFW_ACCUM_ALPHA_BITS:
_glfw.hints.framebuffer.accumAlphaBits = value; _glfw.hints.framebuffer.accumAlphaBits = value;
break; return;
case GLFW_AUX_BUFFERS: case GLFW_AUX_BUFFERS:
_glfw.hints.framebuffer.auxBuffers = value; _glfw.hints.framebuffer.auxBuffers = value;
break; return;
case GLFW_STEREO: case GLFW_STEREO:
_glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE;
break; return;
case GLFW_DOUBLEBUFFER: case GLFW_DOUBLEBUFFER:
_glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
break; return;
case GLFW_TRANSPARENT_FRAMEBUFFER:
_glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_SAMPLES: case GLFW_SAMPLES:
_glfw.hints.framebuffer.samples = value; _glfw.hints.framebuffer.samples = value;
break; return;
case GLFW_SRGB_CAPABLE: case GLFW_SRGB_CAPABLE:
_glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;
break; return;
case GLFW_RESIZABLE: case GLFW_RESIZABLE:
_glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE;
break; return;
case GLFW_DECORATED: case GLFW_DECORATED:
_glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
break; return;
case GLFW_FOCUSED: case GLFW_FOCUSED:
_glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
break; return;
case GLFW_AUTO_ICONIFY: case GLFW_AUTO_ICONIFY:
_glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE;
break; return;
case GLFW_FLOATING: case GLFW_FLOATING:
_glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
break; return;
case GLFW_MAXIMIZED: case GLFW_MAXIMIZED:
_glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
break; return;
case GLFW_VISIBLE: case GLFW_VISIBLE:
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
break; return;
case GLFW_COCOA_RETINA_FRAMEBUFFER:
_glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_COCOA_GRAPHICS_SWITCHING:
_glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_SCALE_TO_MONITOR:
_glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_CENTER_CURSOR:
_glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_FOCUS_ON_SHOW:
_glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_CLIENT_API: case GLFW_CLIENT_API:
_glfw.hints.context.client = value; _glfw.hints.context.client = value;
break; return;
case GLFW_CONTEXT_CREATION_API: case GLFW_CONTEXT_CREATION_API:
_glfw.hints.context.source = value; _glfw.hints.context.source = value;
break; return;
case GLFW_CONTEXT_VERSION_MAJOR: case GLFW_CONTEXT_VERSION_MAJOR:
_glfw.hints.context.major = value; _glfw.hints.context.major = value;
break; return;
case GLFW_CONTEXT_VERSION_MINOR: case GLFW_CONTEXT_VERSION_MINOR:
_glfw.hints.context.minor = value; _glfw.hints.context.minor = value;
break; return;
case GLFW_CONTEXT_ROBUSTNESS: case GLFW_CONTEXT_ROBUSTNESS:
_glfw.hints.context.robustness = value; _glfw.hints.context.robustness = value;
break; return;
case GLFW_OPENGL_FORWARD_COMPAT: case GLFW_OPENGL_FORWARD_COMPAT:
_glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
break; return;
case GLFW_OPENGL_DEBUG_CONTEXT: case GLFW_OPENGL_DEBUG_CONTEXT:
_glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
break; return;
case GLFW_CONTEXT_NO_ERROR: case GLFW_CONTEXT_NO_ERROR:
_glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
break; return;
case GLFW_OPENGL_PROFILE: case GLFW_OPENGL_PROFILE:
_glfw.hints.context.profile = value; _glfw.hints.context.profile = value;
break; return;
case GLFW_CONTEXT_RELEASE_BEHAVIOR: case GLFW_CONTEXT_RELEASE_BEHAVIOR:
_glfw.hints.context.release = value; _glfw.hints.context.release = value;
break; return;
case GLFW_REFRESH_RATE: case GLFW_REFRESH_RATE:
_glfw.hints.refreshRate = value; _glfw.hints.refreshRate = value;
break; return;
default:
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint %i", hint);
break;
} }
_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)
@ -388,7 +453,7 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
// The window's context must not be current on another thread when the // The window's context must not be current on another thread when the
// window is destroyed // window is destroyed
if (window == _glfwPlatformGetCurrentContext()) if (window == _glfwPlatformGetTls(&_glfw.contextSlot))
glfwMakeContextCurrent(NULL); glfwMakeContextCurrent(NULL);
_glfwPlatformDestroyWindow(window); _glfwPlatformDestroyWindow(window);
@ -412,7 +477,7 @@ GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle)
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(0); _GLFW_REQUIRE_INIT_OR_RETURN(0);
return window->closed; return window->shouldClose;
} }
GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value) GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
@ -421,14 +486,13 @@ GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
window->closed = value; window->shouldClose = value;
} }
GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title) GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
assert(title != NULL); assert(title != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
@ -492,6 +556,8 @@ GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
assert(width >= 0);
assert(height >= 0);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
@ -550,6 +616,8 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
assert(numer != 0);
assert(denom != 0);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
@ -607,6 +675,49 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle,
_glfwPlatformGetWindowFrameSize(window, left, top, right, bottom); _glfwPlatformGetWindowFrameSize(window, left, top, right, bottom);
} }
GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle,
float* xscale, float* yscale)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (xscale)
*xscale = 0.f;
if (yscale)
*yscale = 0.f;
_GLFW_REQUIRE_INIT();
_glfwPlatformGetWindowContentScale(window, xscale, yscale);
}
GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(1.f);
return _glfwPlatformGetWindowOpacity(window);
}
GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(opacity == opacity);
assert(opacity >= 0.f);
assert(opacity <= 1.f);
_GLFW_REQUIRE_INIT();
if (opacity != opacity || opacity < 0.f || opacity > 1.f)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid window opacity %f", opacity);
return;
}
_glfwPlatformSetWindowOpacity(window, opacity);
}
GLFWAPI void glfwIconifyWindow(GLFWwindow* handle) GLFWAPI void glfwIconifyWindow(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
@ -631,6 +742,10 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle)
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (window->monitor)
return;
_glfwPlatformMaximizeWindow(window); _glfwPlatformMaximizeWindow(window);
} }
@ -645,7 +760,19 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle)
return; return;
_glfwPlatformShowWindow(window); _glfwPlatformShowWindow(window);
_glfwPlatformFocusWindow(window);
if (window->focusOnShow)
_glfwPlatformFocusWindow(window);
}
GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT();
_glfwPlatformRequestWindowAttention(window);
} }
GLFWAPI void glfwHideWindow(GLFWwindow* handle) GLFWAPI void glfwHideWindow(GLFWwindow* handle)
@ -688,12 +815,20 @@ 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_FOCUS_ON_SHOW:
return window->focusOnShow;
case GLFW_TRANSPARENT_FRAMEBUFFER:
return _glfwPlatformFramebufferTransparent(window);
case GLFW_RESIZABLE: case GLFW_RESIZABLE:
return window->resizable; return window->resizable;
case GLFW_DECORATED: case GLFW_DECORATED:
return window->decorated; return window->decorated;
case GLFW_FLOATING: case GLFW_FLOATING:
return window->floating; return window->floating;
case GLFW_AUTO_ICONIFY:
return window->autoIconify;
case GLFW_CLIENT_API: case GLFW_CLIENT_API:
return window->context.client; return window->context.client;
case GLFW_CONTEXT_CREATION_API: case GLFW_CONTEXT_CREATION_API:
@ -718,10 +853,54 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
return window->context.noerror; return window->context.noerror;
} }
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute %i", attrib); _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
return 0; return 0;
} }
GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT();
value = value ? GLFW_TRUE : GLFW_FALSE;
if (attrib == GLFW_AUTO_ICONIFY)
window->autoIconify = value;
else if (attrib == GLFW_RESIZABLE)
{
if (window->resizable == value)
return;
window->resizable = value;
if (!window->monitor)
_glfwPlatformSetWindowResizable(window, value);
}
else if (attrib == GLFW_DECORATED)
{
if (window->decorated == value)
return;
window->decorated = value;
if (!window->monitor)
_glfwPlatformSetWindowDecorated(window, value);
}
else if (attrib == GLFW_FLOATING)
{
if (window->floating == value)
return;
window->floating = value;
if (!window->monitor)
_glfwPlatformSetWindowFloating(window, value);
}
else if (attrib == GLFW_FOCUS_ON_SHOW)
window->focusOnShow = value;
else
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
}
GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle) GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
@ -740,6 +919,8 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,
_GLFWwindow* window = (_GLFWwindow*) wh; _GLFWwindow* window = (_GLFWwindow*) wh;
_GLFWmonitor* monitor = (_GLFWmonitor*) mh; _GLFWmonitor* monitor = (_GLFWmonitor*) mh;
assert(window != NULL); assert(window != NULL);
assert(width >= 0);
assert(height >= 0);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
@ -852,6 +1033,17 @@ GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle,
return cbfun; return cbfun;
} }
GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle,
GLFWwindowmaximizefun cbfun)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.maximize, cbfun);
return cbfun;
}
GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle, GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle,
GLFWframebuffersizefun cbfun) GLFWframebuffersizefun cbfun)
{ {
@ -863,6 +1055,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();
@ -872,16 +1075,15 @@ GLFWAPI void glfwPollEvents(void)
GLFWAPI void glfwWaitEvents(void) GLFWAPI void glfwWaitEvents(void)
{ {
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (!_glfw.windowListHead)
return;
_glfwPlatformWaitEvents(); _glfwPlatformWaitEvents();
} }
GLFWAPI void glfwWaitEventsTimeout(double timeout) GLFWAPI void glfwWaitEventsTimeout(double timeout)
{ {
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
assert(timeout == timeout);
assert(timeout >= 0.0);
assert(timeout <= DBL_MAX);
if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX) if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)
{ {
@ -895,10 +1097,5 @@ GLFWAPI void glfwWaitEventsTimeout(double timeout)
GLFWAPI void glfwPostEmptyEvent(void) GLFWAPI void glfwPostEmptyEvent(void)
{ {
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (!_glfw.windowListHead)
return;
_glfwPlatformPostEmptyEvent(); _glfwPlatformPostEmptyEvent();
} }

View File

@ -21,7 +21,7 @@ import (
"image" "image"
"sync" "sync"
"github.com/go-gl/glfw/v3.2/glfw" "github.com/go-gl/glfw/v3.3/glfw"
) )
type windows map[*glfw.Window]*Window type windows map[*glfw.Window]*Window
@ -231,12 +231,16 @@ func CreateWindow(width, height int, title string, monitor *Monitor, share *Wind
return theWindows.add(w), nil return theWindows.add(w), nil
} }
func GetJoystickAxes(joy Joystick) []float32 { func (j Joystick) GetAxes() []float32 {
return glfw.GetJoystickAxes(glfw.Joystick(joy)) return glfw.Joystick(j).GetAxes()
} }
func GetJoystickButtons(joy Joystick) []byte { func (j Joystick) GetButtons() []Action {
return glfw.GetJoystickButtons(glfw.Joystick(joy)) var bs []Action
for _, b := range glfw.Joystick(j).GetButtons() {
bs = append(bs, Action(b))
}
return bs
} }
func GetMonitors() []*Monitor { func GetMonitors() []*Monitor {
@ -263,23 +267,23 @@ func Init() error {
return glfw.Init() return glfw.Init()
} }
func JoystickPresent(joy Joystick) bool { func (j Joystick) Present() bool {
return glfw.JoystickPresent(glfw.Joystick(joy)) return glfw.Joystick(j).Present()
} }
func PollEvents() { func PollEvents() {
glfw.PollEvents() glfw.PollEvents()
} }
func SetMonitorCallback(cbfun func(monitor *Monitor, event MonitorEvent)) { func SetMonitorCallback(cbfun func(monitor *Monitor, event PeripheralEvent)) {
var gcb func(monitor *glfw.Monitor, event glfw.MonitorEvent) var gcb func(monitor *glfw.Monitor, event glfw.PeripheralEvent)
if cbfun != nil { if cbfun != nil {
gcb = func(monitor *glfw.Monitor, event glfw.MonitorEvent) { gcb = func(monitor *glfw.Monitor, event glfw.PeripheralEvent) {
var m *Monitor var m *Monitor
if monitor != nil { if monitor != nil {
m = &Monitor{monitor} m = &Monitor{monitor}
} }
cbfun(m, MonitorEvent(event)) cbfun(m, PeripheralEvent(event))
} }
} }
glfw.SetMonitorCallback(gcb) glfw.SetMonitorCallback(gcb)

View File

@ -306,9 +306,9 @@ func CreateWindow(width, height int, title string, monitor *Monitor, share *Wind
return theGLFWWindows.add(w), nil return theGLFWWindows.add(w), nil
} }
func GetJoystickAxes(joy Joystick) []float32 { func (j Joystick) GetAxes() []float32 {
var l int32 var l int32
ptr := glfwDLL.call("glfwGetJoystickAxes", uintptr(joy), uintptr(unsafe.Pointer(&l))) ptr := glfwDLL.call("glfwGetJoystickAxes", uintptr(j), uintptr(unsafe.Pointer(&l)))
panicError() panicError()
as := make([]float32, l) as := make([]float32, l)
for i := int32(0); i < l; i++ { for i := int32(0); i < l; i++ {
@ -318,9 +318,9 @@ func GetJoystickAxes(joy Joystick) []float32 {
return as return as
} }
func GetJoystickButtons(joy Joystick) []byte { func (j Joystick) GetButtons() []byte {
var l int32 var l int32
ptr := glfwDLL.call("glfwGetJoystickButtons", uintptr(joy), uintptr(unsafe.Pointer(&l))) ptr := glfwDLL.call("glfwGetJoystickButtons", uintptr(j), uintptr(unsafe.Pointer(&l)))
panicError() panicError()
bs := make([]byte, l) bs := make([]byte, l)
for i := int32(0); i < l; i++ { for i := int32(0); i < l; i++ {
@ -359,8 +359,8 @@ func Init() error {
return acceptError(APIUnavailable) return acceptError(APIUnavailable)
} }
func JoystickPresent(joy Joystick) bool { func (j Joystick) Present() bool {
r := glfwDLL.call("glfwJoystickPresent", uintptr(joy)) r := glfwDLL.call("glfwJoystickPresent", uintptr(j))
panicError() panicError()
return r == True return r == True
} }
@ -370,10 +370,10 @@ func PollEvents() {
panicError() panicError()
} }
func SetMonitorCallback(cbfun func(monitor *Monitor, event MonitorEvent)) { func SetMonitorCallback(cbfun func(monitor *Monitor, event PeripheralEvent)) {
var gcb uintptr var gcb uintptr
if cbfun != nil { if cbfun != nil {
gcb = windows.NewCallbackCDecl(func(monitor uintptr, event MonitorEvent) uintptr { gcb = windows.NewCallbackCDecl(func(monitor uintptr, event PeripheralEvent) uintptr {
var m *Monitor var m *Monitor
if monitor != 0 { if monitor != 0 {
m = &Monitor{monitor} m = &Monitor{monitor}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -14,6 +14,10 @@
package glfw package glfw
func (w *Window) GetCocoaWindow() uintptr { import (
"unsafe"
)
func (w *Window) GetCocoaWindow() unsafe.Pointer {
return w.w.GetCocoaWindow() return w.w.GetCocoaWindow()
} }

View File

@ -14,8 +14,12 @@
package glfw package glfw
func (w *Window) GetWin32Window() uintptr { import (
"unsafe"
)
func (w *Window) GetWin32Window() unsafe.Pointer {
r := glfwDLL.call("glfwGetWin32Window", w.w) r := glfwDLL.call("glfwGetWin32Window", w.w)
panicError() panicError()
return r return unsafe.Pointer(r)
} }

View File

@ -23,7 +23,7 @@ void *MakeMetalLayer() {
// TODO: Enable colorspace on iOS: this will be available as of iOS 13.0. // TODO: Enable colorspace on iOS: this will be available as of iOS 13.0.
#if !TARGET_OS_IPHONE #if !TARGET_OS_IPHONE
CGColorSpaceRef colorspace = CGColorSpaceRef colorspace =
CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3); CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3);
layer.colorspace = colorspace; layer.colorspace = colorspace;
CGColorSpaceRelease(colorspace); CGColorSpaceRelease(colorspace);
#endif #endif

View File

@ -337,7 +337,7 @@ func (d *Driver) End() {
}) })
} }
func (d *Driver) SetWindow(window uintptr) { func (d *Driver) SetWindow(window unsafe.Pointer) {
d.t.Call(func() error { d.t.Call(func() error {
// Note that [NSApp mainWindow] returns nil when the window is borderless. // Note that [NSApp mainWindow] returns nil when the window is borderless.
// Then the window is needed to be given explicitly. // Then the window is needed to be given explicitly.

View File

@ -36,11 +36,11 @@ import "C"
// //
// Reference: https://developer.apple.com/documentation/appkit/nswindow. // Reference: https://developer.apple.com/documentation/appkit/nswindow.
type Window struct { type Window struct {
window uintptr window unsafe.Pointer
} }
// NewWindow returns a Window that wraps an existing NSWindow * pointer. // NewWindow returns a Window that wraps an existing NSWindow * pointer.
func NewWindow(window uintptr) Window { func NewWindow(window unsafe.Pointer) Window {
return Window{window} return Window{window}
} }
@ -49,7 +49,7 @@ func NewWindow(window uintptr) Window {
// //
// Reference: https://developer.apple.com/documentation/appkit/nswindow/1419160-contentview. // Reference: https://developer.apple.com/documentation/appkit/nswindow/1419160-contentview.
func (w Window) ContentView() View { func (w Window) ContentView() View {
return View{C.Window_ContentView(C.uintptr_t(w.window))} return View{C.Window_ContentView(w.window)}
} }
// View is the infrastructure for drawing, printing, and handling events in an app. // View is the infrastructure for drawing, printing, and handling events in an app.

View File

@ -18,7 +18,7 @@
typedef signed char BOOL; typedef signed char BOOL;
void *Window_ContentView(uintptr_t window); void *Window_ContentView(void *window);
void View_SetLayer(void *view, void *layer); void View_SetLayer(void *view, void *layer);
void View_SetWantsLayer(void *view, BOOL wantsLayer); void View_SetWantsLayer(void *view, BOOL wantsLayer);

View File

@ -17,7 +17,7 @@
#include "ns.h" #include "ns.h"
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
void *Window_ContentView(uintptr_t window) { void *Window_ContentView(void *window) {
return ((NSWindow *)window).contentView; return ((NSWindow *)window).contentView;
} }

View File

@ -18,13 +18,14 @@ package metal
import ( import (
"sync" "sync"
"unsafe"
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/ca" "github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/ca"
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/mtl" "github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/mtl"
) )
type view struct { type view struct {
window uintptr window unsafe.Pointer
uiview uintptr uiview uintptr
device mtl.Device device mtl.Device

View File

@ -39,7 +39,7 @@ import (
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/mtl" "github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/mtl"
) )
func (v *view) setWindow(window uintptr) { func (v *view) setWindow(window unsafe.Pointer) {
panic("metal: setWindow is not available on iOS") panic("metal: setWindow is not available on iOS")
} }

View File

@ -18,11 +18,13 @@
package metal package metal
import ( import (
"unsafe"
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/mtl" "github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/mtl"
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/ns" "github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/ns"
) )
func (v *view) setWindow(window uintptr) { func (v *view) setWindow(window unsafe.Pointer) {
v.window = window v.window = window
} }

View File

@ -16,6 +16,7 @@ package opengl
import ( import (
"fmt" "fmt"
"unsafe"
"github.com/hajimehoshi/ebiten/internal/affine" "github.com/hajimehoshi/ebiten/internal/affine"
"github.com/hajimehoshi/ebiten/internal/driver" "github.com/hajimehoshi/ebiten/internal/driver"
@ -49,7 +50,7 @@ func (d *Driver) End() {
// Do nothing. // Do nothing.
} }
func (d *Driver) SetWindow(window uintptr) { func (d *Driver) SetWindow(window unsafe.Pointer) {
// Do nothing. // Do nothing.
} }

View File

@ -250,12 +250,12 @@ func (i *Input) update(window *glfw.Window, scale float64) {
i.cursorY = int(y / scale) i.cursorY = int(y / scale)
for id := glfw.Joystick(0); id < glfw.Joystick(len(i.gamepads)); id++ { for id := glfw.Joystick(0); id < glfw.Joystick(len(i.gamepads)); id++ {
i.gamepads[id].valid = false i.gamepads[id].valid = false
if !glfw.JoystickPresent(id) { if !id.Present() {
continue continue
} }
i.gamepads[id].valid = true i.gamepads[id].valid = true
axes32 := glfw.GetJoystickAxes(id) axes32 := id.GetAxes()
i.gamepads[id].axisNum = len(axes32) i.gamepads[id].axisNum = len(axes32)
for a := 0; a < len(i.gamepads[id].axes); a++ { for a := 0; a < len(i.gamepads[id].axes); a++ {
if len(axes32) <= a { if len(axes32) <= a {
@ -264,7 +264,7 @@ func (i *Input) update(window *glfw.Window, scale float64) {
} }
i.gamepads[id].axes[a] = float64(axes32[a]) i.gamepads[id].axes[a] = float64(axes32[a])
} }
buttons := glfw.GetJoystickButtons(id) buttons := id.GetButtons()
i.gamepads[id].buttonNum = len(buttons) i.gamepads[id].buttonNum = len(buttons)
for b := 0; b < len(i.gamepads[id].buttonPressed); b++ { for b := 0; b < len(i.gamepads[id].buttonPressed); b++ {
if len(buttons) <= b { if len(buttons) <= b {

View File

@ -27,6 +27,7 @@ import (
"runtime" "runtime"
"sync" "sync"
"time" "time"
"unsafe"
"github.com/hajimehoshi/ebiten/internal/devicescale" "github.com/hajimehoshi/ebiten/internal/devicescale"
"github.com/hajimehoshi/ebiten/internal/driver" "github.com/hajimehoshi/ebiten/internal/driver"
@ -101,7 +102,7 @@ func init() {
if err := initialize(); err != nil { if err := initialize(); err != nil {
panic(err) panic(err)
} }
glfw.SetMonitorCallback(func(monitor *glfw.Monitor, event glfw.MonitorEvent) { glfw.SetMonitorCallback(func(monitor *glfw.Monitor, event glfw.PeripheralEvent) {
cacheMonitors() cacheMonitors()
}) })
cacheMonitors() cacheMonitors()
@ -692,7 +693,7 @@ func (u *UserInterface) run(width, height int, scale float64, title string, cont
return err return err
} }
var w uintptr var w unsafe.Pointer
_ = u.t.Call(func() error { _ = u.t.Call(func() error {
w = u.nativeWindow() w = u.nativeWindow()
return nil return nil

View File

@ -22,7 +22,7 @@ package glfw
// //
// #import <AppKit/AppKit.h> // #import <AppKit/AppKit.h>
// //
// static void currentMonitorPos(uintptr_t windowPtr, int* x, int* y) { // static void currentMonitorPos(void* windowPtr, int* x, int* y) {
// NSScreen* screen = [NSScreen mainScreen]; // NSScreen* screen = [NSScreen mainScreen];
// if (windowPtr) { // if (windowPtr) {
// NSWindow* window = (NSWindow*)windowPtr; // NSWindow* window = (NSWindow*)windowPtr;
@ -42,6 +42,8 @@ package glfw
import "C" import "C"
import ( import (
"unsafe"
"github.com/hajimehoshi/ebiten/internal/glfw" "github.com/hajimehoshi/ebiten/internal/glfw"
) )
@ -58,7 +60,7 @@ func (u *UserInterface) currentMonitorFromPosition() *glfw.Monitor {
y := C.int(0) y := C.int(0)
// Note: [NSApp mainWindow] is nil when it doesn't have its border. Use u.window here. // Note: [NSApp mainWindow] is nil when it doesn't have its border. Use u.window here.
win := u.window.GetCocoaWindow() win := u.window.GetCocoaWindow()
C.currentMonitorPos(C.uintptr_t(win), &x, &y) C.currentMonitorPos(win, &x, &y)
for _, m := range glfw.GetMonitors() { for _, m := range glfw.GetMonitors() {
mx, my := m.GetPos() mx, my := m.GetPos()
if int(x) == mx && int(y) == my { if int(x) == mx && int(y) == my {
@ -68,6 +70,6 @@ func (u *UserInterface) currentMonitorFromPosition() *glfw.Monitor {
return glfw.GetPrimaryMonitor() return glfw.GetPrimaryMonitor()
} }
func (u *UserInterface) nativeWindow() uintptr { func (u *UserInterface) nativeWindow() unsafe.Pointer {
return u.window.GetCocoaWindow() return u.window.GetCocoaWindow()
} }

View File

@ -19,6 +19,8 @@
package glfw package glfw
import ( import (
"unsafe"
"github.com/hajimehoshi/ebiten/internal/devicescale" "github.com/hajimehoshi/ebiten/internal/devicescale"
"github.com/hajimehoshi/ebiten/internal/glfw" "github.com/hajimehoshi/ebiten/internal/glfw"
) )
@ -44,7 +46,7 @@ func (u *UserInterface) currentMonitorFromPosition() *glfw.Monitor {
return glfw.GetPrimaryMonitor() return glfw.GetPrimaryMonitor()
} }
func (u *UserInterface) nativeWindow() uintptr { func (u *UserInterface) nativeWindow() unsafe.Pointer {
// TODO: Implement this. // TODO: Implement this.
return 0 return nil
} }

View File

@ -165,6 +165,6 @@ func (u *UserInterface) currentMonitorFromPosition() *glfw.Monitor {
return glfw.GetPrimaryMonitor() return glfw.GetPrimaryMonitor()
} }
func (u *UserInterface) nativeWindow() uintptr { func (u *UserInterface) nativeWindow() unsafe.Pointer {
return u.window.GetWin32Window() return u.window.GetWin32Window()
} }