Merge branch 'master' of github.com:glfw/glfw

This commit is contained in:
Andy Somogyi 2018-10-23 16:16:48 -04:00
commit 469d9e6e93
97 changed files with 22407 additions and 16703 deletions

2
.gitignore vendored
View File

@ -58,6 +58,7 @@ examples/heightmap
examples/offscreen
examples/particles
examples/splitview
examples/sharing
examples/simple
examples/wave
tests/*.app
@ -74,7 +75,6 @@ tests/joysticks
tests/monitors
tests/msaa
tests/reopen
tests/sharing
tests/tearing
tests/threads
tests/timeout

View File

@ -4,31 +4,71 @@ branches:
only:
- ci
- master
os:
- linux
- osx
sudo: false
dist: trusty
addons:
apt:
sources:
- kubuntu-backports
packages:
- cmake
- libxrandr-dev
- libxinerama-dev
- libxcursor-dev
- libxi-dev
env:
global:
- CFLAGS=-Werror
matrix:
matrix:
include:
- os: linux
env:
- BUILD_SHARED_LIBS=ON
- CFLAGS=-Werror
- os: linux
env:
- BUILD_SHARED_LIBS=OFF
- CFLAGS=-Werror
- os: linux
sudo: required
addons:
apt:
packages:
- libwayland-dev
- libxkbcommon-dev
- libegl1-mesa-dev
env:
- USE_WAYLAND=ON
- BUILD_SHARED_LIBS=ON
- CFLAGS=-Werror
- os: linux
sudo: required
addons:
apt:
packages:
- libwayland-dev
- libxkbcommon-dev
- libegl1-mesa-dev
env:
- USE_WAYLAND=ON
- BUILD_SHARED_LIBS=OFF
- CFLAGS=-Werror
- os: osx
env:
- BUILD_SHARED_LIBS=ON
- CFLAGS=-Werror
- os: osx
env:
- BUILD_SHARED_LIBS=OFF
- CFLAGS=-Werror
script:
- if grep -Inr '\s$' src include docs tests examples CMake *.md .gitattributes .gitignore; then echo Trailing whitespace found, aborting.; exit 1; fi
- mkdir build
- cd build
- cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} ..
- if test -n "${USE_WAYLAND}";
then wget https://mirrors.kernel.org/ubuntu/pool/universe/e/extra-cmake-modules/extra-cmake-modules_5.38.0a-0ubuntu1_amd64.deb;
sudo dpkg -i extra-cmake-modules_5.38.0a-0ubuntu1_amd64.deb;
git clone git://anongit.freedesktop.org/wayland/wayland-protocols;
pushd wayland-protocols;
git checkout 1.15 && ./autogen.sh --prefix=/usr && make && sudo make install;
popd;
fi
- cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} -DGLFW_USE_WAYLAND=${USE_WAYLAND} ..
- cmake --build .
notifications:
email:

View File

@ -24,7 +24,7 @@ endif()
file(STRINGS "${source_path}" lines)
foreach(line ${lines})
if ("${line}" MATCHES "^[0-9a-fA-F].*$")
set(GLFW_GAMEPAD_MAPPINGS "${GLFW_GAMEPAD_MAPPINGS}\"${line}\\n\"\n")
set(GLFW_GAMEPAD_MAPPINGS "${GLFW_GAMEPAD_MAPPINGS}\"${line}\",\n")
endif()
endforeach()

View File

@ -0,0 +1,17 @@
# Find EpollShim
# Once done, this will define
#
# EPOLLSHIM_FOUND - System has EpollShim
# EPOLLSHIM_INCLUDE_DIRS - The EpollShim include directories
# EPOLLSHIM_LIBRARIES - The libraries needed to use EpollShim
find_path(EPOLLSHIM_INCLUDE_DIRS NAMES sys/epoll.h sys/timerfd.h HINTS /usr/local/include/libepoll-shim)
find_library(EPOLLSHIM_LIBRARIES NAMES epoll-shim libepoll-shim HINTS /usr/local/lib)
if (EPOLLSHIM_INCLUDE_DIRS AND EPOLLSHIM_LIBRARIES)
set(EPOLLSHIM_FOUND TRUE)
endif (EPOLLSHIM_INCLUDE_DIRS AND EPOLLSHIM_LIBRARIES)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(EPOLLSHIM DEFAULT_MSG EPOLLSHIM_LIBRARIES EPOLLSHIM_INCLUDE_DIRS)
mark_as_advanced(EPOLLSHIM_INCLUDE_DIRS EPOLLSHIM_LIBRARIES)

View File

@ -1,34 +0,0 @@
# FindMir
# -------
# Finds the Mir library
#
# This will will define the following variables::
#
# MIR_FOUND - the system has Mir
# MIR_INCLUDE_DIRS - the Mir include directory
# MIR_LIBRARIES - the Mir libraries
# MIR_DEFINITIONS - the Mir definitions
find_package (PkgConfig)
if(PKG_CONFIG_FOUND)
pkg_check_modules (PC_MIR mirclient>=0.26.2 QUIET)
find_path(MIR_INCLUDE_DIR NAMES mir_toolkit/mir_client_library.h
PATHS ${PC_MIR_INCLUDE_DIRS})
find_library(MIR_LIBRARY NAMES mirclient
PATHS ${PC_MIR_LIBRARIES} ${PC_MIR_LIBRARY_DIRS})
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (MIR
REQUIRED_VARS MIR_LIBRARY MIR_INCLUDE_DIR)
if (MIR_FOUND)
set(MIR_LIBRARIES ${MIR_LIBRARY})
set(MIR_INCLUDE_DIRS ${PC_MIR_INCLUDE_DIRS})
set(MIR_DEFINITIONS -DHAVE_MIR=1)
endif()
mark_as_advanced (MIR_LIBRARY MIR_INCLUDE_DIR)
endif()

View File

@ -27,13 +27,6 @@ if (WIN32)
"$ENV{VULKAN_SDK}/Bin32"
"$ENV{VK_SDK_PATH}/Bin32")
endif()
elseif (APPLE)
set(CMAKE_FIND_FRAMEWORK NEVER)
find_library(VULKAN_LIBRARY MoltenVK)
set(CMAKE_FIND_FRAMEWORK ONLY)
find_library(VULKAN_STATIC_LIBRARY MoltenVK)
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
"${VULKAN_LIBRARY}/Headers")
else()
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
"$ENV{VULKAN_SDK}/include")

View File

@ -1,15 +1,9 @@
cmake_minimum_required(VERSION 2.8.12)
cmake_minimum_required(VERSION 3.0)
project(GLFW C)
set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
if (NOT CMAKE_VERSION VERSION_LESS "3.0")
# Until all major package systems have moved to CMake 3,
# we stick with the older INSTALL_NAME_DIR mechanism
cmake_policy(SET CMP0042 OLD)
endif()
if (NOT CMAKE_VERSION VERSION_LESS "3.1")
cmake_policy(SET CMP0054 NEW)
endif()
@ -30,7 +24,6 @@ option(GLFW_BUILD_TESTS "Build the GLFW test programs" ON)
option(GLFW_BUILD_DOCS "Build the GLFW documentation" ON)
option(GLFW_INSTALL "Generate installation target" ON)
option(GLFW_VULKAN_STATIC "Use the Vulkan loader statically linked into application" OFF)
option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF)
if (UNIX)
option(GLFW_USE_OSMESA "Use OSMesa for offscreen context creation" OFF)
@ -42,7 +35,6 @@ endif()
if (UNIX AND NOT APPLE)
option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF)
option(GLFW_USE_MIR "Use Mir for window creation" OFF)
endif()
if (MSVC)
@ -142,24 +134,12 @@ if (MINGW)
endif()
endif()
if (APPLE)
# Dependencies required by the MoltenVK static library
set(GLFW_VULKAN_DEPS
"-lc++"
"-framework Cocoa"
"-framework Metal"
"-framework QuartzCore")
endif()
#--------------------------------------------------------------------
# Detect and select backend APIs
#--------------------------------------------------------------------
if (GLFW_USE_WAYLAND)
set(_GLFW_WAYLAND 1)
message(STATUS "Using Wayland for window creation")
elseif (GLFW_USE_MIR)
set(_GLFW_MIR 1)
message(STATUS "Using Mir for window creation")
elseif (GLFW_USE_OSMESA)
set(_GLFW_OSMESA 1)
message(STATUS "Using OSMesa for headless context creation")
@ -181,7 +161,7 @@ endif()
#--------------------------------------------------------------------
if (GLFW_VULKAN_STATIC)
if (VULKAN_FOUND AND VULKAN_STATIC_LIBRARY)
list(APPEND glfw_LIBRARIES "${VULKAN_STATIC_LIBRARY}" ${GLFW_VULKAN_DEPS})
list(APPEND glfw_LIBRARIES "${VULKAN_STATIC_LIBRARY}")
if (BUILD_SHARED_LIBS)
message(WARNING "Linking Vulkan loader static library into GLFW")
endif()
@ -276,35 +256,30 @@ if (_GLFW_WAYLAND)
find_package(ECM REQUIRED NO_MODULE)
list(APPEND CMAKE_MODULE_PATH "${ECM_MODULE_PATH}")
find_package(Wayland REQUIRED)
find_package(Wayland REQUIRED Client Cursor Egl)
find_package(WaylandScanner REQUIRED)
find_package(WaylandProtocols 1.1 REQUIRED)
find_package(WaylandProtocols 1.15 REQUIRED)
list(APPEND glfw_PKG_DEPS "wayland-egl")
list(APPEND glfw_INCLUDE_DIRS "${Wayland_INCLUDE_DIR}")
list(APPEND glfw_INCLUDE_DIRS "${Wayland_INCLUDE_DIRS}")
list(APPEND glfw_LIBRARIES "${Wayland_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}")
find_package(XKBCommon REQUIRED)
list(APPEND glfw_PKG_DEPS "xkbcommon")
list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}")
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
endif()
#--------------------------------------------------------------------
# Use Mir for window creation
#--------------------------------------------------------------------
if (_GLFW_MIR)
find_package(Mir REQUIRED)
list(APPEND glfw_PKG_DEPS "mirclient")
include(CheckIncludeFiles)
include(CheckFunctionExists)
check_include_files(xkbcommon/xkbcommon-compose.h HAVE_XKBCOMMON_COMPOSE_H)
check_function_exists(memfd_create HAVE_MEMFD_CREATE)
list(APPEND glfw_INCLUDE_DIRS "${MIR_INCLUDE_DIRS}")
list(APPEND glfw_LIBRARIES "${MIR_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}")
find_package(XKBCommon REQUIRED)
list(APPEND glfw_PKG_DEPS "xkbcommon")
list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}")
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
if (NOT ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux"))
find_package(EpollShim)
if (EPOLLSHIM_FOUND)
list(APPEND glfw_INCLUDE_DIRS "${EPOLLSHIM_INCLUDE_DIRS}")
list(APPEND glfw_LIBRARIES "${EPOLLSHIM_LIBRARIES}")
endif()
endif()
endif()
#--------------------------------------------------------------------
@ -403,6 +378,7 @@ if (GLFW_INSTALL)
add_custom_target(uninstall
"${CMAKE_COMMAND}" -P
"${GLFW_BINARY_DIR}/cmake_uninstall.cmake")
set_target_properties(uninstall PROPERTIES FOLDER "GLFW3")
endif()
endif()

View File

@ -11,8 +11,8 @@ application development. It provides a simple, platform-independent API for
creating windows, contexts and surfaces, reading input, handling events, etc.
GLFW natively supports Windows, macOS and Linux and other Unix-like systems.
Experimental implementations for the Wayland protocol and the Mir display server
are available but not yet officially supported.
An experimental implementation for the Wayland protocol is available but not
yet officially supported.
GLFW is licensed under the [zlib/libpng
license](http://www.glfw.org/license.html).
@ -69,7 +69,7 @@ and the API reference.
## Contributing to GLFW
See the [contribution
guide](https://github.com/glfw/glfw/blob/master/.github/CONTRIBUTING.md) for
guide](https://github.com/glfw/glfw/blob/master/docs/CONTRIBUTING.md) for
more information.
@ -106,9 +106,9 @@ located in the `deps/` directory.
- [stb\_image\_write](https://github.com/nothings/stb) for writing images to disk
- [Vulkan headers](https://www.khronos.org/registry/vulkan/) for Vulkan tests
The Vulkan example additionally requires the Vulkan SDK to be installed, or it
will not be included in the build. On macOS you need to provide the path to the
MoltenVK SDK manually as it has no standard installation location.
The Vulkan example additionally requires the LunarG Vulkan SDK to be installed,
or it will not be included in the build. On macOS you need to provide the path
to the SDK manually as it has no standard installation location.
The documentation is generated with [Doxygen](http://doxygen.org/) if CMake can
find that tool.
@ -118,7 +118,7 @@ find that tool.
Bugs are reported to our [issue tracker](https://github.com/glfw/glfw/issues).
Please check the [contribution
guide](https://github.com/glfw/glfw/blob/master/.github/CONTRIBUTING.md) for
guide](https://github.com/glfw/glfw/blob/master/docs/CONTRIBUTING.md) for
information on what to include when reporting a bug.
@ -136,8 +136,9 @@ information on what to include when reporting a bug.
gamepad mapping (#900)
- Added `glfwGetGamepadState` function, `GLFW_GAMEPAD_*` and `GLFWgamepadstate`
for retrieving gamepad input state (#900)
- Added `glfwGetWindowContentScale` and `glfwGetMonitorContentScale` for
DPI-aware rendering (#235,#439,#677,#845,#898)
- Added `glfwGetWindowContentScale`, `glfwGetMonitorContentScale` and
`glfwSetWindowContentScaleCallback` for DPI-aware rendering
(#235,#439,#677,#845,#898)
- Added `glfwRequestWindowAttention` function for requesting attention from the
user (#732,#988)
- Added `glfwGetKeyScancode` function that allows retrieving platform dependent
@ -147,27 +148,44 @@ information on what to include when reporting a bug.
- Added `glfwSetWindowAttrib` function for changing window attributes (#537)
- Added `glfwGetJoystickHats` function for querying joystick hats
(#889,#906,#934)
- Added `glfwInitHint` and `glfwInitHintString` for setting initialization hints
- Added `glfwInitHint` for setting initialization hints
- Added `glfwWindowHintString` for setting string type window hints (#893,#1139)
- Added `glfwGetWindowOpacity` and `glfwSetWindowOpacity` for controlling whole
window transparency (#1089)
- Added `glfwSetMonitorUserPointer` and `glfwGetMonitorUserPointer` for
per-monitor user pointers
- Added `glfwSetJoystickUserPointer` and `glfwGetJoystickUserPointer` for
per-joystick user pointers
- Added `glfwGetX11SelectionString` and `glfwSetX11SelectionString`
functions for accessing X11 primary selection (#894,#1056)
- Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#850)
- Added definition of `GLAPIENTRY` to public header
- Added `GLFW_TRANSPARENT` window hint for enabling window framebuffer
transparency (#197,#663,#715,#723,#1078)
- Added `GLFW_TRANSPARENT_FRAMEBUFFER` window hint and attribute for controlling
per-pixel framebuffer transparency (#197,#663,#715,#723,#1078)
- Added `GLFW_HOVERED` window attribute for polling cursor hover state (#1166)
- Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering
(#749,#842)
- Added `GLFW_FOCUS_ON_SHOW` window hint and attribute to control input focus
on calling show window (#1189)
- Added `GLFW_SCALE_TO_MONITOR` window hint for automatic window resizing
(#676,#1115)
- Added `GLFW_JOYSTICK_HAT_BUTTONS` init hint (#889)
- Added `GLFW_LOCK_KEY_MODS` input mode and `GLFW_MOD_*_LOCK` mod bits (#946)
- Added macOS specific `GLFW_COCOA_RETINA_FRAMEBUFFER` window hint
- Added macOS specific `GLFW_COCOA_FRAME_AUTOSAVE` window hint (#195)
- Added macOS specific `GLFW_COCOA_FRAME_NAME` window hint (#195)
- Added macOS specific `GLFW_COCOA_GRAPHICS_SWITCHING` window hint (#377,#935)
- Added macOS specific `GLFW_COCOA_CHDIR_RESOURCES` init hint
- Added macOS specific `GLFW_COCOA_MENUBAR` init hint
- Added X11 specific `GLFW_X11_WM_CLASS_NAME` and `GLFW_X11_WM_CLASS_CLASS` init
hints (#893)
- Added X11 specific `GLFW_X11_CLASS_NAME` and `GLFW_X11_INSTANCE_NAME` window
hints (#893,#1139)
- Added `GLFW_INCLUDE_ES32` for including the OpenGL ES 3.2 header
- Added `GLFW_OSMESA_CONTEXT_API` for creating OpenGL contexts with
[OSMesa](https://www.mesa3d.org/osmesa.html) (#281)
- Added `GenerateMappings.cmake` script for updating gamepad mappings
- Made `glfwCreateWindowSurface` emit an error when the window has a context
(#1194,#1205)
- Deprecated window parameter of clipboard string functions
- Deprecated charmods callback
- Removed `GLFW_USE_RETINA` compile-time option
- Removed `GLFW_USE_CHDIR` compile-time option
- Removed `GLFW_USE_MENUBAR` compile-time option
@ -200,6 +218,13 @@ information on what to include when reporting a bug.
- [Win32] Bugfix: Disabled cursor mode prevented use of caption buttons
(#650,#1071)
- [Win32] Bugfix: Returned key names did not match other platforms (#943)
- [Win32] Bugfix: Undecorated windows did not maximize to workarea (#899)
- [Win32] Bugfix: Window was resized twice when entering full screen (#1085)
- [Win32] Bugfix: The HID device notification was not unregistered (#1170)
- [Win32] Bugfix: `glfwCreateWindow` activated window even with `GLFW_FOCUSED`
hint set to false (#1179,#1180)
- [Win32] Bugfix: The keypad equals key was reported as `GLFW_KEY_UNKNOWN`
(#1315,#1316)
- [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125)
- [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading
- [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X
@ -213,6 +238,9 @@ information on what to include when reporting a bug.
- [X11] Bugfix: Incremental reading of selections was not supported (#275)
- [X11] Bugfix: Selection I/O reported but did not support `COMPOUND_TEXT`
- [X11] Bugfix: Latin-1 text read from selections was not converted to UTF-8
- [X11] Bugfix: NVidia EGL would segfault if unloaded before closing the display
- [Linux] Added workaround for missing `SYN_DROPPED` in pre-2.6.39 kernel
headers (#1196)
- [Linux] Moved to evdev for joystick input (#906,#1005)
- [Linux] Bugfix: Event processing did not detect joystick disconnection (#932)
- [Linux] Bugfix: The joystick device path could be truncated (#1025)
@ -240,6 +268,9 @@ information on what to include when reporting a bug.
notification was shown (#971,#1028)
- [Cocoa] Bugfix: Some characters did not repeat due to Press and Hold (#1010)
- [Cocoa] Bugfix: Window title was lost when full screen or undecorated (#1082)
- [Cocoa] Bugfix: Window was resized twice when entering full screen (#1085)
- [Cocoa] Bugfix: Duplicate size events were not filtered (#1085)
- [Cocoa] Bugfix: Event polling did not initialize AppKit if necessary (#1218)
- [WGL] Added support for `WGL_EXT_colorspace` for OpenGL ES contexts
- [WGL] Added support for `WGL_ARB_create_context_no_error`
- [GLX] Added support for `GLX_ARB_create_context_no_error`
@ -277,6 +308,7 @@ skills.
- David Avedissian
- Keith Bauer
- John Bartholomew
- Coşku Baş
- Niklas Behrens
- Niklas Bergström
- Denis Bernard
@ -315,6 +347,8 @@ skills.
- Mário Freitas
- GeO4d
- Marcus Geelnard
- Stephen Gowen
- Kovid Goyal
- Eloi Marín Gratacós
- Stefan Gustavson
- Jonathan Hale
@ -380,6 +414,7 @@ skills.
- Keith Pitt
- Stanislav Podgorskiy
- Alexandre Pretyman
- przemekmirek
- Philip Rideout
- Eddie Ringle
- Jorge Rodriguez
@ -419,6 +454,7 @@ skills.
- Ricardo Vieira
- Nicholas Vitovitch
- Simon Voordouw
- Corentin Wallez
- Torsten Walluhn
- Patrick Walton
- Xo Wang

17723
deps/nuklear.h vendored

File diff suppressed because it is too large Load Diff

View File

@ -75,6 +75,8 @@ static struct nk_glfw {
int text_len;
struct nk_vec2 scroll;
double last_button_click;
int is_double_click_down;
struct nk_vec2 double_click_pos;
} glfw;
NK_INTERN void
@ -219,10 +221,12 @@ nk_glfw3_mouse_button_callback(GLFWwindow* window, int button, int action, int m
glfwGetCursorPos(window, &x, &y);
if (action == GLFW_PRESS) {
double dt = glfwGetTime() - glfw.last_button_click;
if (dt > NK_GLFW_DOUBLE_CLICK_LO && dt < NK_GLFW_DOUBLE_CLICK_HI)
nk_input_button(&glfw.ctx, NK_BUTTON_DOUBLE, (int)x, (int)y, nk_true);
if (dt > NK_GLFW_DOUBLE_CLICK_LO && dt < NK_GLFW_DOUBLE_CLICK_HI) {
glfw.is_double_click_down = nk_true;
glfw.double_click_pos = nk_vec2((float)x, (float)y);
}
glfw.last_button_click = glfwGetTime();
} else nk_input_button(&glfw.ctx, NK_BUTTON_DOUBLE, (int)x, (int)y, nk_false);
} else glfw.is_double_click_down = nk_false;
}
NK_INTERN void
@ -261,6 +265,10 @@ nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state init_state)
glfw.ctx.clip.paste = nk_glfw3_clipbard_paste;
glfw.ctx.clip.userdata = nk_handle_ptr(0);
nk_buffer_init_default(&glfw.ogl.cmds);
glfw.is_double_click_down = nk_false;
glfw.double_click_pos = nk_vec2(0, 0);
return &glfw.ctx;
}
@ -344,7 +352,7 @@ nk_glfw3_new_frame(void)
glfwGetCursorPos(win, &x, &y);
nk_input_motion(ctx, (int)x, (int)y);
if (ctx->input.mouse.grabbed) {
glfwSetCursorPos(glfw.win, ctx->input.mouse.prev.x, ctx->input.mouse.prev.y);
glfwSetCursorPos(glfw.win, (double)ctx->input.mouse.prev.x, (double)ctx->input.mouse.prev.y);
ctx->input.mouse.pos.x = ctx->input.mouse.prev.x;
ctx->input.mouse.pos.y = ctx->input.mouse.prev.y;
}
@ -352,6 +360,7 @@ nk_glfw3_new_frame(void)
nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
nk_input_button(ctx, NK_BUTTON_DOUBLE, (int)glfw.double_click_pos.x, (int)glfw.double_click_pos.y, glfw.is_double_click_down);
nk_input_scroll(ctx, glfw.scroll);
nk_input_end(&glfw.ctx);
glfw.text_len = 0;

View File

@ -2,7 +2,7 @@
// File: vk_platform.h
//
/*
** Copyright (c) 2014-2015 The Khronos Group Inc.
** Copyright (c) 2014-2017 The Khronos Group Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@ -89,32 +89,4 @@ extern "C"
} // extern "C"
#endif // __cplusplus
// Platform-specific headers required by platform window system extensions.
// These are enabled prior to #including "vulkan.h". The same enable then
// controls inclusion of the extension interfaces in vulkan.h.
#ifdef VK_USE_PLATFORM_ANDROID_KHR
#include <android/native_window.h>
#endif
#ifdef VK_USE_PLATFORM_MIR_KHR
#include <mir_toolkit/client_types.h>
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
#include <wayland-client.h>
#endif
#ifdef VK_USE_PLATFORM_WIN32_KHR
#include <windows.h>
#endif
#ifdef VK_USE_PLATFORM_XLIB_KHR
#include <X11/Xlib.h>
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
#include <xcb/xcb.h>
#endif
#endif

4756
deps/vulkan/vulkan.h vendored

File diff suppressed because it is too large Load Diff

7334
deps/vulkan/vulkan_core.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -14,13 +14,8 @@ set(glfw_DOCS_SOURCES
"${GLFW_SOURCE_DIR}/docs/window.dox"
"${GLFW_SOURCE_DIR}/docs/input.dox"
"${GLFW_SOURCE_DIR}/docs/vulkan.dox"
"${GLFW_SOURCE_DIR}/docs/compat.dox")
if (GLFW_DOCUMENT_INTERNALS)
list(APPEND glfw_DOCS_SOURCES
"${GLFW_SOURCE_DIR}/docs/internal.dox"
"${GLFW_SOURCE_DIR}/src/internal.h")
endif()
"${GLFW_SOURCE_DIR}/docs/compat.dox"
"${GLFW_SOURCE_DIR}/docs/internal.dox")
foreach(arg ${glfw_DOCS_SOURCES})
set(GLFW_DOCS_SOURCES "${GLFW_DOCS_SOURCES} \\\n\"${arg}\"")

View File

@ -1573,7 +1573,6 @@ PREDEFINED = GLFWAPI= \
GLFW_EXPOSE_NATIVE_WGL \
GLFW_EXPOSE_NATIVE_X11 \
GLFW_EXPOSE_NATIVE_WAYLAND \
GLFW_EXPOSE_NATIVE_MIR \
GLFW_EXPOSE_NATIVE_GLX \
GLFW_EXPOSE_NATIVE_COCOA \
GLFW_EXPOSE_NATIVE_NSGL \

View File

@ -161,11 +161,12 @@ David Drysdale.
The static version of the GLFW library is named `glfw3`. When using this
version, it is also necessary to link with some libraries that GLFW uses.
When linking an application under Windows that uses the static version of GLFW,
you must link with `opengl32`. On some versions of MinGW, you must also
explicitly link with `gdi32`, while other versions of MinGW include it in the
set of default libraries along with other dependencies like `user32` and
`kernel32`. If you are using GLU, you must also link with `glu32`.
When using MinGW to link an application with the static version of GLFW, you
must also explicitly link with `gdi32`. Other toolchains including MinGW-w64
include it in the set of default libraries along with other dependencies like
`user32` and `kernel32`.
If you are using GLU, you must also link with `glu32`.
The link library for the GLFW DLL is named `glfw3dll`. When compiling an
application that uses the DLL version of GLFW, you need to define the @ref
@ -173,8 +174,7 @@ GLFW_DLL macro _before_ any inclusion of the GLFW header. This can be done
either with a compiler switch or by defining it in your source code.
An application using the GLFW DLL does not need to link against any of its
dependencies, but you still have to link against `opengl32` if your application
uses OpenGL and `glu32` if it uses GLU.
dependencies, but you still have to link against `glu32` if it uses GLU.
@subsection build_link_cmake_source With CMake and GLFW source
@ -226,7 +226,7 @@ If OpenGL is found, the `OPENGL_FOUND` variable is true and the
`OPENGL_INCLUDE_DIR` and `OPENGL_gl_LIBRARY` cache variables can be used.
@code{.cmake}
target_include_directories(myapp ${OPENGL_INCLUDE_DIR})
target_include_directories(myapp PUBLIC ${OPENGL_INCLUDE_DIR})
target_link_libraries(myapp ${OPENGL_gl_LIBRARY})
@endcode
@ -279,7 +279,7 @@ If OpenGL is found, the `OPENGL_FOUND` variable is true and the
`OPENGL_INCLUDE_DIR` and `OPENGL_gl_LIBRARY` cache variables can be used.
@code{.cmake}
target_include_directories(myapp ${OPENGL_INCLUDE_DIR})
target_include_directories(myapp PUBLIC ${OPENGL_INCLUDE_DIR})
target_link_libraries(myapp ${OPENGL_gl_LIBRARY})
@endcode

View File

@ -82,8 +82,57 @@ extension, regular accelerated mouse motion will be used.
GLFW uses both the XRender extension and the compositing manager to support
transparent window framebuffers. If the running X server does not support this
extension or there is no running compositing manager, the `GLFW_TRANSPARENT`
framebuffer hint will have no effect.
extension or there is no running compositing manager, the
`GLFW_TRANSPARENT_FRAMEBUFFER` framebuffer hint will have no effect.
@section compat_wayland Wayland protocols and IPC standards
As GLFW uses libwayland directly, without any intervening toolkit library, it
has sole responsibility for interacting well with every compositor in use on
Unix-like systems. Most of the features are provided by the core protocol,
while cursor support is provided by the libwayland-cursor helper library, EGL
integration by libwayland-egl, and keyboard handling by
[libxkbcommon](https://xkbcommon.org/). In addition, GLFW uses some protocols
from wayland-protocols to provide additional features if the compositor
supports them.
GLFW uses xkbcommon 0.5.0 to provide compose key support. When it has been
built against an older xkbcommon, the compose key will be disabled even if it
has been configured in the compositor.
GLFW uses the [xdg-shell
protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/xdg-shell/xdg-shell.xml)
to provide better window management. This protocol is part of
wayland-protocols 1.12, and mandatory at build time. If the running compositor
does not support this protocol, the older [wl_shell
interface](https://cgit.freedesktop.org/wayland/wayland/tree/protocol/wayland.xml#n972)
will be used instead. This will result in a worse integration with the
desktop, especially on tiling compositors.
GLFW uses the [relative pointer
protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/relative-pointer/relative-pointer-unstable-v1.xml)
alongside the [pointer constraints
protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml)
to implement disabled cursor. These two protocols are part of
wayland-protocols 1.1, and mandatory at build time. If the running compositor
does not support both of these protocols, disabling the cursor will have no
effect.
GLFW uses the [idle inhibit
protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml)
to prohibit the screensaver from starting. This protocol is part of
wayland-protocols 1.6, and mandatory at build time. If the running compositor
does not support this protocol, the screensaver may start even for full screen
windows.
GLFW uses the [viewporter
protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/viewporter/viewporter.xml)
alongside
[subsurfaces](https://cgit.freedesktop.org/wayland/wayland/tree/protocol/wayland.xml#n2598)
to draw decorations around windows. This protocol is part of wayland-protocols
1.4, and mandatory at build time. If the running compositor does not support
this protocol, no decorations will be drawn around windows.
@section compat_glx GLX extensions
@ -228,9 +277,4 @@ surfaces on Wayland. If any of these extensions are not available, @ref
glfwGetRequiredInstanceExtensions will return an empty list and window surface
creation will fail.
GLFW uses the `VK_KHR_surface` and `VK_KHR_mir_surface` extensions to create
surfaces on Mir. If any of these extensions are not available, @ref
glfwGetRequiredInstanceExtensions will return an empty list and window surface
creation will fail.
*/

View File

@ -52,9 +52,9 @@ example, Cygwin has the `mingw64-i686-gcc` and `mingw64-x86_64-gcc` packages
for 32- and 64-bit version of MinGW-w64, while Debian GNU/Linux and derivatives
like Ubuntu have the `mingw-w64` package for both.
GLFW has CMake toolchain files in the `CMake/` directory that allow for easy
cross-compilation of Windows binaries. To use these files you need to add a
special parameter when generating the project files or makefiles:
GLFW has CMake toolchain files in the `CMake/` directory that set up
cross-compilation of Windows binaries. To use these files you add an option
when running `cmake` to generate the project files or makefiles:
@code{.sh}
cmake -DCMAKE_TOOLCHAIN_FILE=<toolchain-file> .
@ -97,6 +97,19 @@ Once you have installed the necessary packages, move on to @ref
compile_generate.
@subsubsection compile_deps_wayland Dependencies for Linux and Wayland
To compile GLFW for Wayland, you need to have the Wayland packages installed,
as well as the basic development tools like GCC and make. For example, on
Ubuntu and other distributions based on Debian GNU/Linux, you need to install
the `libwayland-dev` package, which contains all Wayland headers and pulls in
wayland-scanner, as well as the `wayland-protocols` and `extra-cmake-modules`
packages.
Once you have installed the necessary packages, move on to @ref
compile_generate.
@subsection compile_deps_osmesa Dependencies for Linux and OSMesa
To compile GLFW for OSMesa, you need to install the OSMesa library and header
@ -255,7 +268,6 @@ ramps and clipboard. The options are:
- @b _GLFW_WIN32 to use the Win32 API
- @b _GLFW_X11 to use the X Window System
- @b _GLFW_WAYLAND to use the Wayland API (experimental and incomplete)
- @b _GLFW_MIR to use the Mir API (experimental and incomplete)
- @b _GLFW_OSMESA to use the OSMesa API (headless and non-interactive)
If you are building GLFW as a shared library / dynamic library / DLL then you
@ -273,8 +285,8 @@ _GLFW_GLESV2_LIBRARY. Otherwise, GLFW will use the built-in default names.
For the EGL context creation API, the following options are available:
- @b _GLFW_USE_EGLPLATFORM_H to use `EGL/eglplatform.h` for native handle
definitions (fallback)
- @b _GLFW_USE_EGLPLATFORM_H to use an existing `EGL/eglplatform.h` header file
for native handle types (fallback)
@note None of the @ref build_macros may be defined during the compilation of
GLFW. If you define any of these in your build files, make sure they are not

View File

@ -61,7 +61,7 @@ information. The name and number of this chapter unfortunately varies between
versions and APIs, but has at times been named _Shared Objects and Multiple
Contexts_.
GLFW comes with a barebones object sharing test program called `sharing`.
GLFW comes with a barebones object sharing example program called `sharing`.
@subsection context_offscreen Offscreen contexts
@ -103,6 +103,9 @@ Before you can make OpenGL or OpenGL ES calls, you need to have a current
context of the correct type. A context can only be current for a single thread
at a time, and a thread can only have a single context current at a time.
When moving a context between threads, you must make it non-current on the old
thread before making it current on the new one.
The context of a window is made current with @ref glfwMakeContextCurrent.
@code
@ -126,8 +129,7 @@ error.
@section context_swap Buffer swapping
Buffer swapping is part of the window and framebuffer, not the context. See
@ref buffer_swap.
See @ref buffer_swap in the window guide.
@section context_glext OpenGL and OpenGL ES extensions

View File

@ -162,7 +162,7 @@ missed the key press. The recommended solution for this is to use a
key callback, but there is also the `GLFW_STICKY_KEYS` input mode.
@code
glfwSetInputMode(window, GLFW_STICKY_KEYS, 1);
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
@endcode
When sticky keys mode is enabled, the pollable state of a key will remain
@ -170,6 +170,19 @@ When sticky keys mode is enabled, the pollable state of a key will remain
it has been polled, if a key release event had been processed in the meantime,
the state will reset to `GLFW_RELEASE`, otherwise it will remain `GLFW_PRESS`.
@anchor GLFW_LOCK_KEY_MODS
If you wish to know what the state of the Caps Lock and Num Lock keys was when
input events were generated, set the `GLFW_LOCK_KEY_MODS` input mode.
@code
glfwSetInputMode(window, GLFW_LOCK_KEY_MODS, GLFW_TRUE);
@endcode
When this input mode is enabled, any callback that receives
[modifier bits](@ref mods) will have the @ref GLFW_MOD_CAPS_LOCK bit set if Caps
Lock was on when the event occurred and the @ref GLFW_MOD_NUM_LOCK bit set if
Num Lock was on.
The `GLFW_KEY_LAST` constant holds the highest value of any
[named key](@ref keys).
@ -186,8 +199,7 @@ encode the code points into UTF-8 or any other encoding you prefer.
Because an `unsigned int` is 32 bits long on all platforms supported by GLFW,
you can treat the code point argument as native endian UTF-32.
There are two callbacks for receiving Unicode code points. If you wish to
offer regular text input, set a character callback.
If you wish to offer regular text input, set a character callback.
@code
glfwSetCharCallback(window, character_callback);
@ -203,23 +215,6 @@ void character_callback(GLFWwindow* window, unsigned int codepoint)
}
@endcode
If you also wish to receive those Unicode code points generated with modifier
key combinations that a plain text field would ignore, or want to know exactly
what modifier keys were used, set a character with modifiers callback.
@code
glfwSetCharModsCallback(window, charmods_callback);
@endcode
The callback function receives Unicode code points and
[modifier bits](@ref mods).
@code
void charmods_callback(GLFWwindow* window, unsigned int codepoint, int mods)
{
}
@endcode
@subsection input_key_name Key names
@ -371,8 +366,7 @@ glfwDestroyCursor(cursor);
Cursor destruction always succeeds. If the cursor is current for any window,
that window will revert to the default cursor. This does not affect the cursor
mode. All remaining cursors remaining are destroyed when @ref glfwTerminate is
called.
mode. All remaining cursors are destroyed when @ref glfwTerminate is called.
@subsubsection cursor_set Cursor setting
@ -424,6 +418,16 @@ void cursor_enter_callback(GLFWwindow* window, int entered)
}
@endcode
You can query whether the cursor is currently inside the client area of the
window with the [GLFW_HOVERED](@ref GLFW_HOVERED_attrib) window attribute.
@code
if (glfwGetWindowAttrib(window, GLFW_HOVERED))
{
highlight_interface();
}
@endcode
@subsection input_mouse_button Mouse button input
@ -471,7 +475,7 @@ mouse button callback, but there is also the `GLFW_STICKY_MOUSE_BUTTONS`
input mode.
@code
glfwSetInputMode(window, GLFW_STICKY_MOUSE_BUTTONS, 1);
glfwSetInputMode(window, GLFW_STICKY_MOUSE_BUTTONS, GLFW_TRUE);
@endcode
When sticky mouse buttons mode is enabled, the pollable state of a mouse button
@ -516,6 +520,9 @@ present with @ref glfwJoystickPresent.
int present = glfwJoystickPresent(GLFW_JOYSTICK_1);
@endcode
Each joystick has zero or more axes, zero or more buttons, zero or more hats,
a human-readable name, a user pointer and an SDL compatible GUID.
When GLFW is initialized, detected joysticks are added to to the beginning of
the array. Once a joystick is detected, it keeps its assigned ID until it is
disconnected or the library is terminated, so as joysticks are connected and
@ -618,6 +625,17 @@ and make may have the same name. Only the [joystick token](@ref joysticks) is
guaranteed to be unique, and only until that joystick is disconnected.
@subsection joystick_userptr Joystick user pointer
Each joystick has a user pointer that can be set with @ref
glfwSetJoystickUserPointer and queried with @ref glfwGetJoystickUserPointer.
This can be used for any purpose you need and will not be modified by GLFW. The
value will be kept until the joystick is disconnected or until the library is
terminated.
The initial value of the pointer is `NULL`.
@subsection joystick_event Joystick configuration changes
If you wish to be notified when a joystick is connected or disconnected, set
@ -650,6 +668,10 @@ functions. Joystick disconnection may also be detected and the callback
called by joystick functions. The function will then return whatever it
returns for a disconnected joystick.
Only @ref glfwGetJoystickName and @ref glfwGetJoystickUserPointer will return
useful values for a disconnected joystick and only before the monitor callback
returns.
@subsection gamepad Gamepad input
@ -781,6 +803,12 @@ a hat bitmask or empty. Joystick buttons are specified as `bN`, for example
example `h0.8` for left on the first hat. More than one bit may be set in the
mask.
Before an axis there may be a `+` or `-` range modifier, for example `+a3` for
the positive half of the fourth axis. This restricts input to only the positive
or negative halves of the joystick axis. After an axis or half-axis there may
be the `~` inversion modifier, for example `a2~` or `-a7~`. This negates the
values of the gamepad axis.
The hat bit mask match the [hat states](@ref hat_state) in the joystick
functions.
@ -799,8 +827,9 @@ 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,
@endcode
@note GLFW does not yet support the range and inversion modifiers `+`, `-` and
`~` that were recently added to SDL.
@note GLFW does not yet support the output range and modifiers `+` and `-` that
were recently added to SDL. The input modifiers `+`, `-` and `~` are supported
and described above.
@section time Time input
@ -846,7 +875,7 @@ converted to one, you can retrieve it with @ref glfwGetClipboardString. See the
reference documentation for the lifetime of the returned string.
@code
const char* text = glfwGetClipboardString(window);
const char* text = glfwGetClipboardString(NULL);
if (text)
{
insert_text(text);
@ -860,13 +889,9 @@ The contents of the system clipboard can be set to a UTF-8 encoded string with
@ref glfwSetClipboardString.
@code
glfwSetClipboardString(window, "A string with words in it");
glfwSetClipboardString(NULL, "A string with words in it");
@endcode
The clipboard functions take a window handle argument because some window
systems require a window to communicate with the system clipboard. Any valid
window may be used.
@section path_drop Path drop input

View File

@ -19,8 +19,7 @@ The public interface uses the OpenGL naming conventions except with GLFW and
glfw instead of GL and gl. For struct members, where OpenGL sets no precedent,
it use headless camel case.
Examples: @ref glfwCreateWindow, @ref GLFWwindow, @ref GLFWvidmode.redBits,
`GLFW_RED_BITS`
Examples: `glfwCreateWindow`, `GLFWwindow`, `GLFW_RED_BITS`
@section internals_native Native interface
@ -34,7 +33,7 @@ The function names of the native interface are similar to those of the public
interface, but embeds the name of the interface that the returned handle is
from.
Examples: @ref glfwGetX11Window, @ref glfwGetWGLContext
Examples: `glfwGetX11Window`, `glfwGetWGLContext`
@section internals_internal Internal interface
@ -50,7 +49,7 @@ a `_GLFWlibrary` struct named `_glfw`.
The internal interface uses the same style as the public interface, except all
global names have a leading underscore.
Examples: @ref _glfwIsValidContextConfig, @ref _GLFWwindow, `_glfw.currentRamp`
Examples: `_glfwIsValidContextConfig`, `_GLFWwindow`, `_glfw.monitorCount`
@section internals_platform Platform interface
@ -67,7 +66,7 @@ perform platform-specific operations on some or all platforms. The are also
named the same except that the glfw function prefix is replaced by
_glfwPlatform.
Examples: @ref _glfwPlatformCreateWindow
Examples: `_glfwPlatformCreateWindow`
The platform interface also defines structs that contain platform-specific
global and per-object state. Their names mirror those of the internal
@ -79,7 +78,7 @@ These structs are incorporated as members into the internal interface structs
using special macros that name them after the specific interface used. This
prevents shared code from accidentally using these members.
Examples: `window.win32.handle`, `_glfw.x11.display`
Examples: `window->win32.handle`, `_glfw.x11.display`
@section internals_event Event interface
@ -91,7 +90,7 @@ application, either via callbacks, via window state changes or both.
The function names of the event interface use a `_glfwInput` prefix and the
ObjectEvent pattern.
Examples: @ref _glfwInputWindowFocus, @ref _glfwInputCursorMotion
Examples: `_glfwInputWindowFocus`, `_glfwInputCursorPos`
@section internals_static Static functions
@ -99,7 +98,7 @@ Examples: @ref _glfwInputWindowFocus, @ref _glfwInputCursorMotion
Static functions may be used by any interface and have no prefixes or suffixes.
These use headless camel case.
Examples: `clearScrollOffsets`
Examples: `isValidElementForJoystick`
@section internals_config Configuration macros
@ -111,6 +110,6 @@ which is generated from the `glfw_config.h.in` file by CMake.
Configuration macros the same style as tokens in the public interface, except
with a leading underscore.
Examples: `_GLFW_USE_HYBRID_HPG`
Examples: `_GLFW_WIN32`, `_GLFW_BUILD_DLL`
*/

View File

@ -33,7 +33,6 @@ successfully initialized, and only from the main thread.
- @ref glfwGetError
- @ref glfwSetErrorCallback
- @ref glfwInitHint
- @ref glfwInitHintString
- @ref glfwInit
- @ref glfwTerminate
@ -67,8 +66,7 @@ settings and these might not be restored without termination.
@subsection init_hints Initialization hints
Initialization hints are set before @ref glfwInit and affect how the library
behaves until termination. Integer type hints are set with @ref glfwInitHint
and string type hints with @ref glfwInitHintString.
behaves until termination. Hints are set with @ref glfwInitHint.
@code
glfwInitHint(GLFW_JOYSTICK_HAT_BUTTONS, GLFW_FALSE);
@ -104,15 +102,6 @@ a nib or manually, when the first window is created, which is when AppKit is
initialized. Set this with @ref glfwInitHint.
@subsubsection init_hints_x11 X11 specific init hints
@anchor GLFW_X11_WM_CLASS_NAME
@anchor GLFW_X11_WM_CLASS_CLASS
__GLFW_X11_WM_CLASS_NAME__ and __GLFW_X11_WM_CLASS_CLASS__ specifies the desired
ASCII encoded name and class parts of the ICCCM `WM_CLASS` hint for all windows.
Set this with @ref glfwInitHintString.
@subsubsection init_hints_values Supported and default values
Initialization hint | Default value | Supported values
@ -120,8 +109,6 @@ Initialization hint | Default value | Supported values
@ref GLFW_JOYSTICK_HAT_BUTTONS | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_COCOA_CHDIR_RESOURCES | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_COCOA_MENUBAR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_X11_WM_CLASS_NAME | `""` | An ASCII encoded `WM_CLASS` name
@ref GLFW_X11_WM_CLASS_CLASS | `""` | An ASCII encoded `WM_CLASS` class
@subsection intro_init_terminate Terminating GLFW
@ -378,10 +365,10 @@ allow calls from any thread in future releases.
@subsection compatibility Version compatibility
GLFW guarantees source and binary backward compatibility with earlier minor
versions of the API. This means that you can drop in a newer version of the
library and existing programs will continue to compile and existing binaries
will continue to run.
GLFW uses [Semantic Versioning](https://semver.org/). This guarantees source
and binary backward compatibility with earlier minor versions of the API. This
means that you can drop in a newer version of the library and existing programs
will continue to compile and existing binaries will continue to run.
Once a function or constant has been added, the signature of that function or
value of that constant will remain unchanged until the next major version of

View File

@ -85,15 +85,17 @@ void monitor_callback(GLFWmonitor* monitor, int event)
}
@endcode
If a monitor is disconnected, any windows that are full screen on it get forced
into windowed mode.
If a monitor is disconnected, all windows that are full screen on it will be
switched to windowed mode before the callback is called. Only @ref
glfwGetMonitorName and @ref glfwGetMonitorUserPointer will return useful values
for a disconnected monitor and only before the monitor callback returns.
@section monitor_properties Monitor properties
Each monitor has a current video mode, a list of supported video modes,
a virtual position, a human-readable name, an estimated physical size and
a gamma ramp.
a virtual position, a human-readable name, a user pointer, an estimated physical
size and a gamma ramp.
@subsection monitor_modes Video modes
@ -187,6 +189,17 @@ and make may have the same name. Only the monitor handle is guaranteed to be
unique, and only until that monitor is disconnected.
@subsection monitor_userptr User pointer
Each monitor has a user pointer that can be set with @ref
glfwSetMonitorUserPointer and queried with @ref glfwGetMonitorUserPointer. This
can be used for any purpose you need and will not be modified by GLFW. The
value will be kept until the monitor is disconnected or until the library is
terminated.
The initial value of the pointer is `NULL`.
@subsection monitor_gamma Gamma ramp
The gamma ramp of a monitor can be set with @ref glfwSetGammaRamp, which accepts

View File

@ -4,6 +4,12 @@
@section news_33 Release notes for 3.3
@subsection news_33_focusonshow GLFW_FOCUS_ON_SHOW window hint and attribute
GLFW now supports the [GLFW_FOCUS_ON_SHOW](@ref GLFW_DECORATED_hint) window hint
and attribute for controlling input focus when calling @ref glfwShowWindow
@see @ref window_hide
@subsection news_33_geterror Error query
@ -64,14 +70,20 @@ GLFW now supports querying the window and monitor content scale, i.e. the ratio
between the current DPI and the platform's default DPI, with @ref
glfwGetWindowContentScale and @ref glfwGetMonitorContentScale.
Changes of the content scale of a window can be received with the window content
scale callback, set with @ref glfwSetWindowContentScaleCallback.
The @ref GLFW_SCALE_TO_MONITOR window hint enables automatic resizing of a
window by the content scale of the monitor it is placed, on platforms like
Windows and X11 where this is necessary.
@see @ref window_scale
@subsection news_33_inithint Support for initialization hints
GLFW now supports setting library initialization hints with @ref glfwInitHint
or @ref glfwInitHintString. These must be set before initialization to take
effect.
GLFW now supports setting library initialization hints with @ref glfwInitHint.
These must be set before initialization to take effect.
@see @ref init_hints
@ -94,11 +106,17 @@ be disabled with the @ref GLFW_JOYSTICK_HAT_BUTTONS init hint.
@see @ref joystick_hat
@subsection news_33_transparent Support for transparent window framebuffer
@subsection news_33_transparent Support for transparent windows and framebuffers
GLFW now supports the creation of windows with transparent framebuffers on
systems with desktop compositing enabled with the @ref GLFW_TRANSPARENT window
hint and attribute. Any window decorations will still be opaque.
systems with desktop compositing enabled with the @ref
GLFW_TRANSPARENT_FRAMEBUFFER window hint and attribute. This hint must be set
before window creation and leaves any window decorations opaque.
GLFW now also supports whole window transparency with @ref glfwGetWindowOpacity
and @ref glfwSetWindowOpacity. This value controls the opacity of the whole
window including decorations and unlike framebuffer transparency can be changed
at any time after window creation.
@subsection news_33_centercursor Cursor centering window hint
@ -108,6 +126,13 @@ full screen windows with the [GLFW_CENTER_CURSOR](@ref GLFW_CENTER_CURSOR_hint)
window hint. It is enabled by default.
@subsection news_33_hover Mouse cursor hover window attribute
GLFW now supports polling whether the cursor is hovering over the window client
area with the [GLFW_HOVERED](@ref GLFW_HOVERED_attrib) window attribute. This
attribute corresponds to the [cursor enter/leave](@ref cursor_enter) event.
@subsection news_33_rawmotion Support for raw mouse motion
GLFW now uses raw (unscaled and unaccelerated) mouse motion in disabled cursor
@ -117,7 +142,7 @@ mode on platforms where this is available, specifically Windows and X11.
@subsection news_33_moltenvk Support for Vulkan on macOS via MoltenVK
GLFW now supports the `VK_MVK_macos_surface` window surface creation extension
provided by [MoltenVK](https://moltengl.com/moltenvk/).
provided by MoltenVK in the [LunarG Vulkan SDK](https://vulkan.lunarg.com/).
@see @ref vulkan_guide
@ -134,6 +159,13 @@ creation API, intended for automated testing. This backend does not provide
input.
@subsection news_33_userptr Monitor and joystick user pointers
GLFW now supports setting and querying user pointers for connected monitors and
joysticks with @ref glfwSetMonitorUserPointer, @ref glfwGetMonitorUserPointer,
@ref glfwSetJoystickUserPointer and @ref glfwGetJoystickUserPointer.
@subsection news_33_primary X11 primary selection access
GLFW now supports querying and setting the X11 primary selection via the native
@ -141,6 +173,14 @@ access functions @ref glfwGetX11SelectionString and @ref
glfwSetX11SelectionString.
@subsection news_33_mir_removal Experimental Mir support has been removed
As per the release of Mir 1.0, the recommended API is now Wayland, the
experimental Mir display server backend introduced in GLFW 3.1 has thus been
removed. To use the experimental Wayland backend, pass -DGLFW_USE_WAYLAND=ON
to cmake where you previously passed the now-removed -DGLFW_USE_MIR=ON.
@section news_32 Release notes for 3.2

View File

@ -10,21 +10,14 @@ documentation and is not a replacement for either. It assumes some familiarity
with Vulkan concepts like loaders, devices, queues and surfaces and leaves it to
the Vulkan documentation to explain the details of Vulkan functions.
To develop for Vulkan you should install an SDK for your platform, for example
the [LunarG Vulkan SDK](https://vulkan.lunarg.com/) for Windows and Linux or
[MoltenVK](https://moltengl.com/moltenvk/) for macOS. Apart from headers and
link libraries, they should also provide the validation layers necessary for
development.
To develop for Vulkan you should download the [LunarG Vulkan
SDK](https://vulkan.lunarg.com/) for your platform. Apart from headers and link
libraries, they also provide the validation layers necessary for development.
The GLFW library does not need the Vulkan SDK to enable support for Vulkan.
However, any Vulkan-specific test and example programs are built only if the
CMake files find a Vulkan SDK.
@macos Because MoltenVK is typically not installed system-wide, you will need to
point CMake to it using the `CMAKE_FRAMEWORK_PATH` variable when configuring the
GLFW source tree. Set this variable to the `MoltenVK/macOS` subdirectory of the
SDK, either on the command-line or in the CMake GUI.
For details on a specific function in this category, see the @ref vulkan. There
are also guides for the other areas of the GLFW API.
@ -39,7 +32,7 @@ are also guides for the other areas of the GLFW API.
By default, GLFW will look for the Vulkan loader on demand at runtime via its
standard name (`vulkan-1.dll` on Windows, `libvulkan.so.1` on Linux and other
Unix-like systems and `libMoltenVK.dylib` on macOS). This means that GLFW does
Unix-like systems and `libvulkan.1.dylib` on macOS). This means that GLFW does
not need to be linked against the loader. However, it also means that if you
are using the static library form of the Vulkan loader GLFW will either fail to
find it or (worse) use the wrong one.
@ -48,9 +41,16 @@ The @ref GLFW_VULKAN_STATIC CMake option makes GLFW link directly against the
static library form. Not linking against the Vulkan loader will then be
a compile-time error.
@macos When using the static library form of MoltenVK (i.e. `MetalVK.framework`
and not `libMoltenVK.dylib`) you must also link against its dependencies: the
`Cocoa`, `Metal` and `QuartzCore` system frameworks and the `libc++` library.
@macos Because the Vulkan loader and ICD are not installed globally on macOS,
you need to set up the application bundle according to the LunarG SDK
documentation. To help the GLFW CMake files find the SDK, you can set the
`VULKAN_SDK` environment variable to the `macOS` subdirectory of the SDK.
@code{.sh}
env VULKAN_SDK=/example/path/to/vulkansdk/macOS cmake .
@endcode
This is explained in more detail in the LunarG Vulkan SDK release notes.
@section vulkan_include Including the Vulkan and GLFW header files
@ -164,9 +164,9 @@ If it fails it will return `NULL` and GLFW will not be able to create Vulkan
window surfaces. You can still use Vulkan for off-screen rendering and compute
work.
The returned array will always contain `VK_KHR_surface`, so if you don't
require any additional extensions you can pass this list directly to the
`VkInstanceCreateInfo` struct.
If successful the returned array will always include `VK_KHR_surface`, so if
you don't require any additional extensions you can pass this list directly to
the `VkInstanceCreateInfo` struct.
@code
VkInstanceCreateInfo ici;
@ -230,6 +230,10 @@ if (err)
}
@endcode
If an OpenGL or OpenGL ES context was created on the window, the context has
ownership of the presentation on the window and a Vulkan surface cannot be
created.
It is your responsibility to destroy the surface. GLFW does not destroy it for
you. Call `vkDestroySurfaceKHR` function from the same extension to destroy it.

View File

@ -89,8 +89,8 @@ the desktop. This behavior can be disabled with the
[GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_hint) window hint, for example if you
wish to simultaneously cover multiple monitors with full screen windows.
If a monitor is disconnected, any window that is full screen on that monitor
will be forced into windowed mode. See @ref monitor_event for more information.
If a monitor is disconnected, all windows that are full screen on that monitor
will be switched to windowed mode. See @ref monitor_event for more information.
@subsubsection window_windowed_full_screen "Windowed full screen" windows
@ -146,16 +146,18 @@ is restored, but the gamma ramp is left untouched.
There are a number of hints that can be set before the creation of a window and
context. Some affect the window itself, others affect the framebuffer or
context. These hints are set to their default values each time the library is
initialized with @ref glfwInit, can be set individually with @ref glfwWindowHint
and reset all at once to their defaults with @ref glfwDefaultWindowHints.
initialized with @ref glfwInit. Integer value hints can be set individually
with @ref glfwWindowHint and string value hints with @ref glfwWindowHintString.
You can reset all at once to their defaults with @ref glfwDefaultWindowHints.
Some hints are platform specific. These are always valid to set on any
platform but they will only affect their specific platform. Other platforms
will ignore them. Setting these hints requires no platform specific headers or
calls.
Note that hints need to be set _before_ the creation of the window and context
you wish to have the specified attributes.
@note Window hints need to be set before the creation of the window and context
you wish to have the specified attributes. They function as additional
arguments to @ref glfwCreateWindow.
@subsubsection window_hints_hard Hard and soft constraints
@ -225,13 +227,27 @@ __GLFW_CENTER_CURSOR__ specifies whether the cursor should be centered over
newly created full screen windows. Possible values are `GLFW_TRUE` and
`GLFW_FALSE`. This hint is ignored for windowed mode windows.
@anchor GLFW_TRANSPARENT_hint
__GLFW_TRANSPARENT__ specifies whether the window framebuffer will be
transparent. If enabled and supported by the system, the window framebuffer
@anchor GLFW_TRANSPARENT_FRAMEBUFFER_hint
__GLFW_TRANSPARENT_FRAMEBUFFER__ specifies whether the window framebuffer will
be transparent. If enabled and supported by the system, the window framebuffer
alpha channel will be used to combine the framebuffer with the background. This
does not affect window decorations. Possible values are `GLFW_TRUE` and
`GLFW_FALSE`.
@anchor GLFW_FOCUS_ON_SHOW_hint
__GLFW_FOCUS_ON_SHOW__ specifies whether the window will be given input
focus when @ref glfwShowWindow is called. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
@anchor GLFW_SCALE_TO_MONITOR
__GLFW_SCALE_TO_MONITOR__ specified whether the window content area should be
resized based on the [monitor content scale](@ref monitor_scale) of any monitor
it is placed on. This includes the initial placement when the window is
created. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
This hint only has an effect on platforms where screen coordinates and pixels
always map 1:1 such as Windows and X11. On platforms like macOS the resolution
of the framebuffer is changed independently of the window size.
@subsubsection window_hints_fb Framebuffer related hints
@ -321,7 +337,7 @@ constraint. If no client API is requested, this hint is ignored.
will fail.
@par
__Wayland, Mir:__ The EGL API _is_ the native context creation API, so this hint
__Wayland:__ The EGL API _is_ the native context creation API, so this hint
will have no effect.
@par
@ -441,10 +457,10 @@ __GLFW_COCOA_RETINA_FRAMEBUFFER__ specifies whether to use full resolution
framebuffers on Retina displays. Possible values are `GLFW_TRUE` and
`GLFW_FALSE`. This is ignored on other platforms.
@anchor GLFW_COCOA_FRAME_AUTOSAVE_hint
__GLFW_COCOA_FRAME_AUTOSAVE__ specifies whether to activate frame autosaving
using the window title specified at window creation. Possible values are
`GLFW_TRUE` and `GLFW_FALSE`. This is ignored on other platforms.
@anchor GLFW_COCOA_FRAME_NAME_hint
__GLFW_COCOA_FRAME_NAME__ specifies the UTF-8 encoded name to use for autosaving
the window frame, or if empty disables frame autosaving for the window. This is
ignored on other platforms. This is set with @ref glfwWindowHintString.
@anchor GLFW_COCOA_GRAPHICS_SWITCHING_hint
__GLFW_COCOA_GRAPHICS_SWITCHING__ specifies whether to in Automatic Graphics
@ -465,6 +481,15 @@ should also declare this in its `Info.plist` by setting the
`NSSupportsAutomaticGraphicsSwitching` key to `true`.
@subsubsection window_hints_x11 X11 specific window hints
@anchor GLFW_X11_CLASS_NAME
@anchor GLFW_X11_INSTANCE_NAME
__GLFW_X11_CLASS_NAME__ and __GLFW_X11_INSTANCE_NAME__ specifies the desired
ASCII encoded class and instance parts of the ICCCM `WM_CLASS` window property.
These are set with @ref glfwWindowHintString.
@subsubsection window_hints_values Supported and default values
Window hint | Default value | Supported values
@ -477,7 +502,9 @@ GLFW_AUTO_ICONIFY | `GLFW_TRUE` | `GLFW_TRUE` or `GL
GLFW_FLOATING | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_MAXIMIZED | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_CENTER_CURSOR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_TRANSPARENT | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_TRANSPARENT_FRAMEBUFFER | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_FOCUS_ON_SHOW | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_SCALE_TO_MONITOR | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_RED_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_GREEN_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_BLUE_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
@ -504,8 +531,10 @@ GLFW_OPENGL_FORWARD_COMPAT | `GLFW_FALSE` | `GLFW_TRUE` or `GL
GLFW_OPENGL_DEBUG_CONTEXT | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_OPENGL_PROFILE | `GLFW_OPENGL_ANY_PROFILE` | `GLFW_OPENGL_ANY_PROFILE`, `GLFW_OPENGL_COMPAT_PROFILE` or `GLFW_OPENGL_CORE_PROFILE`
GLFW_COCOA_RETINA_FRAMEBUFFER | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_COCOA_FRAME_AUTOSAVE | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_COCOA_FRAME_NAME | `""` | A UTF-8 encoded frame autosave name
GLFW_COCOA_GRAPHICS_SWITCHING | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_X11_CLASS_NAME | `""` | An ASCII encoded `WM_CLASS` class name
GLFW_X11_INSTANCE_NAME | `""` | An ASCII encoded `WM_CLASS` instance name
@section window_events Window event processing
@ -518,7 +547,7 @@ See @ref events.
@subsection window_userptr User pointer
Each window has a user pointer that can be set with @ref
glfwSetWindowUserPointer and fetched with @ref glfwGetWindowUserPointer. This
glfwSetWindowUserPointer and queried with @ref glfwGetWindowUserPointer. This
can be used for any purpose you need and will not be modified by GLFW throughout
the life-time of the window.
@ -682,6 +711,29 @@ On systems where each monitors can have its own content scale, the window
content scale will depend on which monitor the system considers the window to be
on.
If you wish to be notified when the content scale of a window changes, whether
because of a system setting change or because it was moved to a monitor with
a different scale, set a content scale callback.
@code
glfwSetWindowContentScaleCallback(window, window_content_scale_callback);
@endcode
The callback function receives the new content scale of the window.
@code
void window_content_scale_callback(GLFWwindow* window, float xscale, float yscale)
{
set_interface_scale(xscale, yscale);
}
@endcode
On platforms where pixels and screen coordinates always map 1:1, the window
will need to be resized to appear the same size when it is moved to a monitor
with a different content scale. To have this done automatically both when the
window is created and when its content scale later changes, set the @ref
GLFW_SCALE_TO_MONITOR window hint.
@subsection window_sizelimits Window size limits
@ -979,6 +1031,10 @@ Hidden windows can be shown with @ref glfwShowWindow.
glfwShowWindow(window);
@endcode
By default, this function will also set the input focus to that window. Set
the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint to change
this behavior for all newly created windows, or change the behavior for an
existing window with @ref glfwSetWindowAttrib.
You can also get the current visibility state with @ref glfwGetWindowAttrib.
@ -1091,27 +1147,63 @@ the window or framebuffer is resized.
@subsection window_transparency Window transparency
GLFW supports two kinds of transparency for windows; framebuffer transparency
and whole window transparency. A single window may not use both methods. The
results of doing this are undefined.
Both methods require the platform to support it and not every version of every
platform GLFW supports does this, so there are mechanisms to check whether the
window really is transparent.
Window framebuffers can be made transparent on a per-pixel per-frame basis with
the [GLFW_TRANSPARENT](@ref GLFW_TRANSPARENT_hint) window hint.
the [GLFW_TRANSPARENT_FRAMEBUFFER](@ref GLFW_TRANSPARENT_FRAMEBUFFER_hint)
window hint.
@code
glfwWindowHint(GLFW_TRANSPARENT, GLFW_TRUE);
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
@endcode
If supported by the system, the window framebuffer will be composited with the
If supported by the system, the window content area will be composited with the
background using the framebuffer per-pixel alpha channel. This requires desktop
compositing to be enabled on the system. It does not affect window decorations.
You can check whether the window framebuffer was successfully made transparent
with the [GLFW_TRANSPARENT](@ref GLFW_TRANSPARENT_attrib) window attribute.
with the
[GLFW_TRANSPARENT_FRAMEBUFFER](@ref GLFW_TRANSPARENT_FRAMEBUFFER_attrib)
window attribute.
@code
if (glfwGetWindowAttrib(window, GLFW_TRANSPARENT))
if (glfwGetWindowAttrib(window, GLFW_TRANSPARENT_FRAMEBUFFER))
{
// window framebuffer is currently transparent
}
@endcode
GLFW comes with an example that enabled framebuffer transparency called `gears`.
The opacity of the whole window, including any decorations, can be set with @ref
glfwSetWindowOpacity.
@code
glfwSetWindowOpacity(window, 0.5f);
@endcode
The opacity (or alpha) value is a positive finite number between zero and one,
where 0 (zero) is fully transparent and 1 (one) is fully opaque. The initial
opacity value for newly created windows is 1.
The current opacity of a window can be queried with @ref glfwGetWindowOpacity.
@code
float opacity = glfwGetWindowOpacity(window);
@endcode
If the system does not support whole window transparency, this function always
returns one.
GLFW comes with a test program that lets you control whole window transparency
at run-time called `opacity`.
@subsection window_attribs Window attributes
@ -1130,8 +1222,9 @@ if (glfwGetWindowAttrib(window, GLFW_FOCUSED))
The [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
[GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib),
[GLFW_FLOATING](@ref GLFW_FLOATING_attrib) and
[GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) window attributes can be
[GLFW_FLOATING](@ref GLFW_FLOATING_attrib),
[GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and
[GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib) window attributes can be
changed with @ref glfwSetWindowAttrib.
@code
@ -1154,6 +1247,11 @@ See @ref window_iconify for details.
__GLFW_MAXIMIZED__ indicates whether the specified window is maximized. See
@ref window_maximize for details.
@anchor GLFW_HOVERED_attrib
__GLFW_HOVERED__ indicates whether the cursor is currently directly over the
client area of the window, with no other windows between. See @ref cursor_enter
for details.
@anchor GLFW_VISIBLE_attrib
__GLFW_VISIBLE__ indicates whether the specified window is visible. See @ref
window_hide for details.
@ -1182,11 +1280,17 @@ called topmost or always-on-top. This can be set before creation with the
[GLFW_FLOATING](@ref GLFW_FLOATING_hint) window hint or after with @ref
glfwSetWindowAttrib.
@anchor GLFW_TRANSPARENT_attrib
__GLFW_TRANSPARENT__ indicates whether the specified window has a transparent
framebuffer, i.e. the window contents is composited with the background using
the window framebuffer alpha channel. See @ref window_transparency for details.
@anchor GLFW_TRANSPARENT_FRAMEBUFFER_attrib
__GLFW_TRANSPARENT_FRAMEBUFFER__ indicates whether the specified window has
a transparent framebuffer, i.e. the window contents is composited with the
background using the window framebuffer alpha channel. See @ref
window_transparency for details.
@anchor GLFW_FOCUS_ON_SHOW_attrib
__GLFW_FOCUS_ON_SHOW__ specifies whether the window will be given input
focus when @ref glfwShowWindow is called. This can be set before creation
with the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint or
after with @ref glfwSetWindowAttrib.
@subsubsection window_attribs_ctx Context related attributes
@ -1297,4 +1401,10 @@ Note that this may not work on all machines, as some drivers have
user-controlled settings that override any swap interval the application
requests.
A context that supports either the `WGL_EXT_swap_control_tear` or the
`GLX_EXT_swap_control_tear` extension also accepts _negative_ swap intervals,
which allows the driver to swap immediately even if a frame arrives a little bit
late. This trades the risk of visible tears for greater framerate stability.
You can check for these extensions with @ref glfwExtensionSupported.
*/

View File

@ -35,6 +35,7 @@ add_executable(gears WIN32 MACOSX_BUNDLE gears.c ${ICON} ${GLAD})
add_executable(heightmap WIN32 MACOSX_BUNDLE heightmap.c ${ICON} ${GLAD})
add_executable(offscreen offscreen.c ${ICON} ${GLAD})
add_executable(particles WIN32 MACOSX_BUNDLE particles.c ${ICON} ${TINYCTHREAD} ${GETOPT} ${GLAD})
add_executable(sharing WIN32 MACOSX_BUNDLE sharing.c ${ICON} ${GLAD})
add_executable(simple WIN32 MACOSX_BUNDLE simple.c ${ICON} ${GLAD})
add_executable(splitview WIN32 MACOSX_BUNDLE splitview.c ${ICON} ${GLAD})
add_executable(wave WIN32 MACOSX_BUNDLE wave.c ${ICON} ${GLAD})
@ -44,7 +45,7 @@ if (RT_LIBRARY)
target_link_libraries(particles "${RT_LIBRARY}")
endif()
set(WINDOWS_BINARIES boing gears heightmap particles simple splitview wave)
set(WINDOWS_BINARIES boing gears heightmap particles sharing simple splitview wave)
set(CONSOLE_BINARIES offscreen)
set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
@ -61,6 +62,7 @@ if (APPLE)
set_target_properties(gears PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gears")
set_target_properties(heightmap PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Heightmap")
set_target_properties(particles PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Particles")
set_target_properties(sharing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Sharing")
set_target_properties(simple PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Simple")
set_target_properties(splitview PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "SplitView")
set_target_properties(wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave")

View File

@ -312,7 +312,7 @@ int main(int argc, char *argv[])
}
glfwWindowHint(GLFW_DEPTH_BITS, 16);
glfwWindowHint(GLFW_TRANSPARENT, GLFW_TRUE);
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
window = glfwCreateWindow( 300, 300, "Gears", NULL, NULL );
if (!window)

View File

@ -1,5 +1,5 @@
//========================================================================
// Context sharing test program
// Context sharing example
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
@ -22,15 +22,10 @@
// distribution.
//
//========================================================================
//
// This program is used to test sharing of objects between contexts
//
//========================================================================
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
@ -71,17 +66,6 @@ static void error_callback(int error, const char* description)
fprintf(stderr, "Error: %s\n", description);
}
void APIENTRY debug_callback(GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
const void* user)
{
fprintf(stderr, "Error: %s\n", message);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action == GLFW_PRESS && key == GLFW_KEY_ESCAPE)
@ -90,28 +74,15 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
int main(int argc, char** argv)
{
int ch;
GLFWwindow* windows[2];
GLuint texture, program, vertex_buffer;
GLint mvp_location, vpos_location, color_location, texture_location;
srand((unsigned int) time(NULL));
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
while ((ch = getopt(argc, argv, "d")) != -1)
{
switch (ch)
{
case 'd':
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
break;
}
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
@ -134,12 +105,6 @@ int main(int argc, char** argv)
// pointers should be re-usable between them
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
if (GLAD_GL_KHR_debug)
{
glDebugMessageCallback(debug_callback, NULL);
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
}
// Create the OpenGL objects inside the first context, created above
// All objects will be shared with the second context, created below
{
@ -150,6 +115,8 @@ int main(int argc, char** argv)
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
srand((unsigned int) glfwGetTimerValue());
for (y = 0; y < 16; y++)
{
for (x = 0; x < 16; x++)
@ -235,8 +202,8 @@ int main(int argc, char** argv)
int i;
const vec3 colors[2] =
{
{ 0.3f, 0.4f, 1.f },
{ 0.8f, 0.4f, 1.f }
{ 0.8f, 0.4f, 1.f },
{ 0.3f, 0.4f, 1.f }
};
for (i = 0; i < 2; i++)

View File

@ -455,6 +455,7 @@ int main(int argc, char* argv[])
glfwPollEvents();
}
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -493,17 +493,37 @@ extern "C" {
* @{ */
/*! @brief If this bit is set one or more Shift keys were held down.
*
* If this bit is set one or more Shift keys were held down.
*/
#define GLFW_MOD_SHIFT 0x0001
/*! @brief If this bit is set one or more Control keys were held down.
*
* If this bit is set one or more Control keys were held down.
*/
#define GLFW_MOD_CONTROL 0x0002
/*! @brief If this bit is set one or more Alt keys were held down.
*
* If this bit is set one or more Alt keys were held down.
*/
#define GLFW_MOD_ALT 0x0004
/*! @brief If this bit is set one or more Super keys were held down.
*
* If this bit is set one or more Super keys were held down.
*/
#define GLFW_MOD_SUPER 0x0008
/*! @brief If this bit is set the Caps Lock key is enabled.
*
* If this bit is set the Caps Lock key is enabled and the @ref
* GLFW_LOCK_KEY_MODS input mode is set.
*/
#define GLFW_MOD_CAPS_LOCK 0x0010
/*! @brief If this bit is set the Num Lock key is enabled.
*
* If this bit is set the Num Lock key is enabled and the @ref
* GLFW_LOCK_KEY_MODS input mode is set.
*/
#define GLFW_MOD_NUM_LOCK 0x0020
/*! @} */
@ -789,10 +809,22 @@ extern "C" {
#define GLFW_CENTER_CURSOR 0x00020009
/*! @brief Window framebuffer transparency hint and attribute
*
* Window framebuffer transparency [window hint](@ref GLFW_TRANSPARENT_hint)
* and [window attribute](@ref GLFW_TRANSPARENT_attrib).
* Window framebuffer transparency
* [window hint](@ref GLFW_TRANSPARENT_FRAMEBUFFER_hint) and
* [window attribute](@ref GLFW_TRANSPARENT_FRAMEBUFFER_attrib).
*/
#define GLFW_TRANSPARENT 0x0002000A
#define GLFW_TRANSPARENT_FRAMEBUFFER 0x0002000A
/*! @brief Mouse cursor hover window attribute.
*
* Mouse cursor hover [window attribute](@ref GLFW_HOVERED_attrib).
*/
#define GLFW_HOVERED 0x0002000B
/*! @brief Input focus on calling show window hint and attribute
*
* Input focus [window hint](@ref GLFW_FOCUS_ON_SHOW_hint) or
* [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib).
*/
#define GLFW_FOCUS_ON_SHOW 0x0002000C
/*! @brief Framebuffer bit depth hint.
*
@ -941,10 +973,17 @@ extern "C" {
* [attribute](@ref GLFW_CLIENT_API_attrib).
*/
#define GLFW_CONTEXT_CREATION_API 0x0002200B
/*! @brief Window content area scaling window
* [window hint](@ref GLFW_SCALE_TO_MONITOR).
*/
#define GLFW_SCALE_TO_MONITOR 0x0002200C
#define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001
#define GLFW_COCOA_FRAME_AUTOSAVE 0x00023002
#define GLFW_COCOA_FRAME_NAME 0x00023002
#define GLFW_COCOA_GRAPHICS_SWITCHING 0x00023003
#define GLFW_X11_CLASS_NAME 0x00024001
#define GLFW_X11_INSTANCE_NAME 0x00024002
/*! @} */
#define GLFW_NO_API 0
@ -962,6 +1001,7 @@ extern "C" {
#define GLFW_CURSOR 0x00033001
#define GLFW_STICKY_KEYS 0x00033002
#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003
#define GLFW_LOCK_KEY_MODS 0x00033004
#define GLFW_CURSOR_NORMAL 0x00034001
#define GLFW_CURSOR_HIDDEN 0x00034002
@ -1024,9 +1064,6 @@ extern "C" {
#define GLFW_COCOA_CHDIR_RESOURCES 0x00051001
#define GLFW_COCOA_MENUBAR 0x00051002
#define GLFW_X11_WM_CLASS_NAME 0x00052001
#define GLFW_X11_WM_CLASS_CLASS 0x00052002
/*! @} */
#define GLFW_DONT_CARE -1
@ -1045,7 +1082,7 @@ extern "C" {
* @sa @ref glfwGetProcAddress
*
* @since Added in version 3.0.
*
* @ingroup context
*/
typedef void (*GLFWglproc)(void);
@ -1256,6 +1293,24 @@ typedef void (* GLFWwindowmaximizefun)(GLFWwindow*,int);
*/
typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int);
/*! @brief The function signature for window content scale callbacks.
*
* This is the function signature for window content scale callback
* functions.
*
* @param[in] window The window whose content scale changed.
* @param[in] xscale The new x-axis content scale of the window.
* @param[in] yscale The new y-axis content scale of the window.
*
* @sa @ref window_scale
* @sa @ref glfwSetWindowContentScaleCallback
*
* @since Added in version 3.3.
*
* @ingroup window
*/
typedef void (* GLFWwindowcontentscalefun)(GLFWwindow*,float,float);
/*! @brief The function signature for mouse button callbacks.
*
* This is the function signature for mouse button callback functions.
@ -1383,6 +1438,8 @@ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int);
* @sa @ref input_char
* @sa @ref glfwSetCharModsCallback
*
* @deprecated Scheduled for removal in version 4.0.
*
* @since Added in version 3.1.
*
* @ingroup input
@ -1411,7 +1468,8 @@ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**);
* This is the function signature for monitor configuration callback functions.
*
* @param[in] monitor The monitor that was connected or disconnected.
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. Remaining
* values reserved for future use.
*
* @sa @ref monitor_event
* @sa @ref glfwSetMonitorCallback
@ -1428,7 +1486,8 @@ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int);
* functions.
*
* @param[in] jid The joystick that was connected or disconnected.
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. Remaining
* values reserved for future use.
*
* @sa @ref joystick_event
* @sa @ref glfwSetJoystickCallback
@ -1620,8 +1679,7 @@ GLFWAPI void glfwTerminate(void);
/*! @brief Sets the specified init hint to the desired value.
*
* This function sets hints for the next initialization of GLFW. Only integer
* type hints can be set with this function.
* This function sets hints for the next initialization of GLFW.
*
* The values you set hints to are never reset by GLFW, but they only take
* effect during initialization. Once GLFW has been initialized, any values
@ -1644,7 +1702,6 @@ GLFWAPI void glfwTerminate(void);
*
* @sa init_hints
* @sa glfwInit
* @sa glfwInitHintString
*
* @since Added in version 3.3.
*
@ -1652,40 +1709,6 @@ GLFWAPI void glfwTerminate(void);
*/
GLFWAPI void glfwInitHint(int hint, int value);
/*! @brief Sets the specified init hint to the desired value.
*
* This function sets hints for the next initialization of GLFW. Only string
* type hints can be set with this function.
*
* The values you set hints to are never reset by GLFW, but they only take
* effect during initialization. Once GLFW has been initialized, any values
* you set will be ignored until the library is terminated and initialized
* again.
*
* Some hints are platform specific. These may be set on any platform but they
* will only affect their specific platform. Other platforms will ignore them.
* Setting these hints requires no platform specific headers or functions.
*
* @param[in] hint The [init hint](@ref init_hints) to set.
* @param[in] value The new value of the init hint.
*
* @errors Possible errors include @ref GLFW_INVALID_ENUM and @ref
* GLFW_INVALID_VALUE.
*
* @remarks This function may be called before @ref glfwInit.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa init_hints
* @sa glfwInit
* @sa glfwInitHint
*
* @since Added in version 3.3.
*
* @ingroup init
*/
GLFWAPI void glfwInitHintString(int hint, const char* value);
/*! @brief Retrieves the version of the GLFW library.
*
* This function retrieves the major, minor and revision numbers of the GLFW
@ -1982,6 +2005,56 @@ GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* monitor, float* xscale, flo
*/
GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* monitor);
/*! @brief Sets the user pointer of the specified monitor.
*
* This function sets the user-defined pointer of the specified monitor. The
* current value is retained until the monitor is disconnected. The initial
* value is `NULL`.
*
* This function may be called from the monitor callback, even for a monitor
* that is being disconnected.
*
* @param[in] monitor The monitor whose pointer to set.
* @param[in] pointer The new value.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @sa @ref monitor_userptr
* @sa @ref glfwGetMonitorUserPointer
*
* @since Added in version 3.3.
*
* @ingroup monitor
*/
GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* monitor, void* pointer);
/*! @brief Returns the user pointer of the specified monitor.
*
* This function returns the current value of the user-defined pointer of the
* specified monitor. The initial value is `NULL`.
*
* This function may be called from the monitor callback, even for a monitor
* that is being disconnected.
*
* @param[in] monitor The monitor whose pointer to return.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @sa @ref monitor_userptr
* @sa @ref glfwSetMonitorUserPointer
*
* @since Added in version 3.3.
*
* @ingroup monitor
*/
GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* monitor);
/*! @brief Sets the monitor configuration callback.
*
* This function sets the monitor configuration callback, or removes the
@ -2086,8 +2159,8 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
*
* @remark @wayland Gamma handling is currently unavailable, this function will
* always emit @ref GLFW_PLATFORM_ERROR.
* @remark @wayland Gamma handling is a priviledged protocol, this function
* will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR.
*
* @thread_safety This function must only be called from the main thread.
*
@ -2110,8 +2183,9 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @remark @wayland Gamma handling is currently unavailable, this function will
* always return `NULL` and emit @ref GLFW_PLATFORM_ERROR.
* @remark @wayland Gamma handling is a priviledged protocol, this function
* will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR while
* returning `NULL`.
*
* @pointer_lifetime The returned structure and its arrays are allocated and
* freed by GLFW. You should not free them yourself. They are valid until the
@ -2153,8 +2227,8 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
*
* @remark @win32 The gamma ramp size must be 256.
*
* @remark @wayland Gamma handling is currently unavailable, this function will
* always emit @ref GLFW_PLATFORM_ERROR.
* @remark @wayland Gamma handling is a priviledged protocol, this function
* will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR.
*
* @pointer_lifetime The specified gamma ramp is copied before this function
* returns.
@ -2180,6 +2254,7 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* monitor, const GLFWgammaramp* ramp);
*
* @sa @ref window_hints
* @sa @ref glfwWindowHint
* @sa @ref glfwWindowHintString
*
* @since Added in version 3.0.
*
@ -2190,14 +2265,20 @@ GLFWAPI void glfwDefaultWindowHints(void);
/*! @brief Sets the specified window hint to the desired value.
*
* This function sets hints for the next call to @ref glfwCreateWindow. The
* hints, once set, retain their values until changed by a call to @ref
* glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is
* terminated.
* hints, once set, retain their values until changed by a call to this
* function or @ref glfwDefaultWindowHints, or until the library is terminated.
*
* Only integer value hints can be set with this function. String value hints
* are set with @ref glfwWindowHintString.
*
* This function does not check whether the specified hint values are valid.
* If you set hints to invalid values this will instead be reported by the next
* call to @ref glfwCreateWindow.
*
* Some hints are platform specific. These may be set on any platform but they
* will only affect their specific platform. Other platforms will ignore them.
* Setting these hints requires no platform specific headers or functions.
*
* @param[in] hint The [window hint](@ref window_hints) to set.
* @param[in] value The new value of the window hint.
*
@ -2207,6 +2288,7 @@ GLFWAPI void glfwDefaultWindowHints(void);
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_hints
* @sa @ref glfwWindowHintString
* @sa @ref glfwDefaultWindowHints
*
* @since Added in version 3.0. Replaces `glfwOpenWindowHint`.
@ -2215,6 +2297,44 @@ GLFWAPI void glfwDefaultWindowHints(void);
*/
GLFWAPI void glfwWindowHint(int hint, int value);
/*! @brief Sets the specified window hint to the desired value.
*
* This function sets hints for the next call to @ref glfwCreateWindow. The
* hints, once set, retain their values until changed by a call to this
* function or @ref glfwDefaultWindowHints, or until the library is terminated.
*
* Only string type hints can be set with this function. Integer value hints
* are set with @ref glfwWindowHint.
*
* This function does not check whether the specified hint values are valid.
* If you set hints to invalid values this will instead be reported by the next
* call to @ref glfwCreateWindow.
*
* Some hints are platform specific. These may be set on any platform but they
* will only affect their specific platform. Other platforms will ignore them.
* Setting these hints requires no platform specific headers or functions.
*
* @param[in] hint The [window hint](@ref window_hints) to set.
* @param[in] value The new value of the window hint.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_INVALID_ENUM.
*
* @pointer_lifetime The specified string is copied before this function
* returns.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_hints
* @sa @ref glfwWindowHint
* @sa @ref glfwDefaultWindowHints
*
* @since Added in version 3.3.
*
* @ingroup window
*/
GLFWAPI void glfwWindowHintString(int hint, const char* value);
/*! @brief Creates a window and its associated context.
*
* This function creates a window and its associated OpenGL or OpenGL ES
@ -2288,8 +2408,8 @@ GLFWAPI void glfwWindowHint(int hint, int value);
*
* @remark @win32 If the executable has an icon resource named `GLFW_ICON,` it
* will be set as the initial icon for the window. If no such icon is present,
* the `IDI_WINLOGO` icon will be used instead. To set a different icon, see
* @ref glfwSetWindowIcon.
* the `IDI_APPLICATION` icon will be used instead. To set a different icon,
* see @ref glfwSetWindowIcon.
*
* @remark @win32 The context to share resources with must not be current on
* any other thread.
@ -2325,9 +2445,8 @@ GLFWAPI void glfwWindowHint(int hint, int value);
* `CMake/MacOSXBundleInfo.plist.in` in the source tree.
*
* @remark @macos When activating frame autosaving with
* [GLFW_COCOA_FRAME_AUTOSAVE](@ref GLFW_COCOA_FRAME_AUTOSAVE_hint), the
* specified window size may be overriden by a previously saved size and
* position.
* [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified
* window size and position may be overriden by previously saved values.
*
* @remark @x11 Some window managers will not respect the placement of
* initially hidden windows.
@ -2337,24 +2456,24 @@ GLFWAPI void glfwWindowHint(int hint, int value);
* query the final size, position or other attributes directly after window
* creation.
*
* @remark @x11 The name and class of the `WM_CLASS` window property will by
* default be set to the window title passed to this function. Set the @ref
* GLFW_X11_WM_CLASS_NAME and @ref GLFW_X11_WM_CLASS_CLASS init hints before
* initialization to override this.
* @remark @x11 The class part of the `WM_CLASS` window property will by
* default be set to the window title passed to this function. The instance
* part will use the contents of the `RESOURCE_NAME` environment variable, if
* present and not empty, or fall back to the window title. Set the @ref
* GLFW_X11_CLASS_NAME and @ref GLFW_X11_INSTANCE_NAME window hints to override
* this.
*
* @remark @wayland The window frame is currently unimplemented, as if
* [GLFW_DECORATED](@ref GLFW_DECORATED_hint) was always set to `GLFW_FALSE`.
* A compositor can still emit close, resize or maximize events, using for
* example a keybind mechanism.
* @remark @wayland The window frame is currently very simple, only allowing
* window resize or move. A compositor can still emit close, maximize or
* fullscreen events, using for example a keybind mechanism. Additionally,
* the wp_viewporter protocol is required for this feature, otherwise the
* window will not be decorated.
*
* @remark @wayland A full screen window will not attempt to change the mode,
* no matter what the requested size or refresh rate.
*
* @remark @wayland The wl_shell protocol does not support window
* icons, the window will inherit the one defined in the application's
* desktop file, so this function emits @ref GLFW_PLATFORM_ERROR.
*
* @remark @wayland Screensaver inhibition is currently unimplemented.
* @remark @wayland Screensaver inhibition requires the idle-inhibit protocol
* to be implemented in the user's compositor.
*
* @thread_safety This function must only be called from the main thread.
*
@ -2496,9 +2615,9 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
* [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
* in the Mac Developer Library.
*
* @remark @wayland The wl_shell protocol does not support icons, the window
* will inherit the one defined in the application's desktop file, so this
* function emits @ref GLFW_PLATFORM_ERROR.
* @remark @wayland There is no existing protocol to change an icon, the
* window will thus inherit the one defined in the application's desktop file.
* This function always emits @ref GLFW_PLATFORM_ERROR.
*
* @thread_safety This function must only be called from the main thread.
*
@ -2790,10 +2909,6 @@ GLFWAPI void glfwGetFramebufferSize(GLFWwindow* window, int* width, int* height)
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @remark @wayland The window frame is currently unimplemented, as if
* [GLFW_DECORATED](@ref GLFW_DECORATED_hint) was always set to `GLFW_FALSE`,
* so the returned values will always be zero.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_size
@ -2826,6 +2941,7 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_scale
* @sa @ref glfwSetWindowContentScaleCallback
* @sa @ref glfwGetMonitorContentScale
*
* @since Added in version 3.3.
@ -2834,6 +2950,62 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int
*/
GLFWAPI void glfwGetWindowContentScale(GLFWwindow* window, float* xscale, float* yscale);
/*! @brief Returns the opacity of the whole window.
*
* This function returns the opacity of the window, including any decorations.
*
* The opacity (or alpha) value is a positive finite number between zero and
* one, where zero is fully transparent and one is fully opaque. If the system
* does not support whole window transparency, this function always returns one.
*
* The initial opacity value for newly created windows is one.
*
* @param[in] window The window to query.
* @return The opacity value of the specified window.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_transparency
* @sa @ref glfwSetWindowOpacity
*
* @since Added in version 3.3.
*
* @ingroup window
*/
GLFWAPI float glfwGetWindowOpacity(GLFWwindow* window);
/*! @brief Sets the opacity of the whole window.
*
* This function sets the opacity of the window, including any decorations.
*
* The opacity (or alpha) value is a positive finite number between zero and
* one, where zero is fully transparent and one is fully opaque.
*
* The initial opacity value for newly created windows is one.
*
* A window created with framebuffer transparency may not use whole window
* transparency. The results of doing this are undefined.
*
* @param[in] window The window to set the opacity for.
* @param[in] opacity The desired opacity of the specified window.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_transparency
* @sa @ref glfwGetWindowOpacity
*
* @since Added in version 3.3.
*
* @ingroup window
*/
GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity);
/*! @brief Iconifies the specified window.
*
* This function iconifies (minimizes) the specified window if it was
@ -2849,7 +3021,8 @@ GLFWAPI void glfwGetWindowContentScale(GLFWwindow* window, float* xscale, float*
* GLFW_PLATFORM_ERROR.
*
* @remark @wayland There is no concept of iconification in wl_shell, this
* function will always emit @ref GLFW_PLATFORM_ERROR.
* function will emit @ref GLFW_PLATFORM_ERROR when using this deprecated
* protocol.
*
* @thread_safety This function must only be called from the main thread.
*
@ -2922,6 +3095,11 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* window);
* hidden. If the window is already visible or is in full screen mode, this
* function does nothing.
*
* By default, windowed mode windows are focused when shown
* Set the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint
* to change this behavior for all newly created windows, or change the
* behavior for an existing window with @ref glfwSetWindowAttrib.
*
* @param[in] window The window to make visible.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
@ -2969,6 +3147,10 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window);
* initially created. Set the [GLFW_FOCUSED](@ref GLFW_FOCUSED_hint) to
* disable this behavior.
*
* Also by default, windowed mode windows are focused when shown
* with @ref glfwShowWindow. Set the
* [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) to disable this behavior.
*
* __Do not use this function__ to steal focus from other applications unless
* you are certain that is what the user wants. Focus stealing can be
* extremely disruptive.
@ -3143,8 +3325,9 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
*
* The supported attributes are [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
* [GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib),
* [GLFW_FLOATING](@ref GLFW_FLOATING_attrib) and
* [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib).
* [GLFW_FLOATING](@ref GLFW_FLOATING_attrib),
* [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and
* [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib).
*
* Some of these attributes are ignored for full screen windows. The new
* value will take effect if the window is later made windowed.
@ -3374,7 +3557,7 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwi
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @remark @wayland The wl_shell protocol has no concept of iconification,
* this callback will never be called.
* this callback will never be called when using this deprecated protocol.
*
* @thread_safety This function must only be called from the main thread.
*
@ -3432,6 +3615,30 @@ GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* window,
*/
GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun cbfun);
/*! @brief Sets the window content scale callback for the specified window.
*
* This function sets the window content scale callback of the specified window,
* which is called when the content scale of the specified window changes.
*
* @param[in] window The window whose callback to set.
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
* callback.
* @return The previously set callback, or `NULL` if no callback was set or the
* library had not been [initialized](@ref intro_init).
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_scale
* @sa @ref glfwGetWindowContentScale
*
* @since Added in version 3.3.
*
* @ingroup window
*/
GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* window, GLFWwindowcontentscalefun cbfun);
/*! @brief Processes all pending events.
*
* This function processes only those events that are already in the event
@ -3596,12 +3803,12 @@ GLFWAPI void glfwPostEmptyEvent(void);
/*! @brief Returns the value of an input option for the specified window.
*
* This function returns the value of an input option for the specified window.
* The mode must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS or
* @ref GLFW_STICKY_MOUSE_BUTTONS.
* The mode must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS,
* @ref GLFW_STICKY_MOUSE_BUTTONS or @ref GLFW_LOCK_KEY_MODS.
*
* @param[in] window The window to query.
* @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or
* `GLFW_STICKY_MOUSE_BUTTONS`.
* @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`,
* `GLFW_STICKY_MOUSE_BUTTONS` or `GLFW_LOCK_KEY_MODS`.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_INVALID_ENUM.
@ -3619,8 +3826,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
/*! @brief Sets an input option for the specified window.
*
* This function sets an input mode option for the specified window. The mode
* must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS or
* @ref GLFW_STICKY_MOUSE_BUTTONS.
* must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS,
* @ref GLFW_STICKY_MOUSE_BUTTONS or @ref GLFW_LOCK_KEY_MODS.
*
* If the mode is `GLFW_CURSOR`, the value must be one of the following cursor
* modes:
@ -3646,9 +3853,15 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
* you are only interested in whether mouse buttons have been pressed but not
* when or in which order.
*
* If the mode is `GLFW_LOCK_KEY_MODS`, the value must be either `GLFW_TRUE` to
* enable lock key modifier bits, or `GLFW_FALSE` to disable them. If enabled,
* callbacks that receive modifier bits will also have the @ref
* GLFW_MOD_CAPS_LOCK bit set when the event was generated with Caps Lock on,
* and the @ref GLFW_MOD_NUM_LOCK bit when Num Lock was on.
*
* @param[in] window The window whose input mode to set.
* @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or
* `GLFW_STICKY_MOUSE_BUTTONS`.
* @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`,
* `GLFW_STICKY_MOUSE_BUTTONS` or `GLFW_LOCK_KEY_MODS`.
* @param[in] value The new value of the specified input mode.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
@ -3802,8 +4015,8 @@ GLFWAPI int glfwGetKey(GLFWwindow* window, int key);
* `GLFW_RELEASE`.
*
* If the @ref GLFW_STICKY_MOUSE_BUTTONS input mode is enabled, this function
* `GLFW_PRESS` the first time you call it for a mouse button that was pressed,
* even if that mouse button has already been released.
* returns `GLFW_PRESS` the first time you call it for a mouse button that was
* pressed, even if that mouse button has already been released.
*
* @param[in] window The desired window.
* @param[in] button The desired [mouse button](@ref buttons).
@ -4118,6 +4331,8 @@ GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun cbfun);
* @return The previously set callback, or `NULL` if no callback was set or an
* [error](@ref error_handling) occurred.
*
* @deprecated Scheduled for removal in version 4.0.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function must only be called from the main thread.
@ -4493,6 +4708,56 @@ GLFWAPI const char* glfwGetJoystickName(int jid);
*/
GLFWAPI const char* glfwGetJoystickGUID(int jid);
/*! @brief Sets the user pointer of the specified joystick.
*
* This function sets the user-defined pointer of the specified joystick. The
* current value is retained until the joystick is disconnected. The initial
* value is `NULL`.
*
* This function may be called from the joystick callback, even for a joystick
* that is being disconnected.
*
* @param[in] jid The joystick whose pointer to set.
* @param[in] pointer The new value.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @sa @ref joystick_userptr
* @sa @ref glfwGetJoystickUserPointer
*
* @since Added in version 3.3.
*
* @ingroup input
*/
GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer);
/*! @brief Returns the user pointer of the specified joystick.
*
* This function returns the current value of the user-defined pointer of the
* specified joystick. The initial value is `NULL`.
*
* This function may be called from the joystick callback, even for a joystick
* that is being disconnected.
*
* @param[in] jid The joystick whose pointer to return.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @sa @ref joystick_userptr
* @sa @ref glfwSetJoystickUserPointer
*
* @since Added in version 3.3.
*
* @ingroup input
*/
GLFWAPI void* glfwGetJoystickUserPointer(int jid);
/*! @brief Returns whether the specified joystick has a gamepad mapping.
*
* This function returns whether the specified joystick is both present and has
@ -4629,7 +4894,7 @@ GLFWAPI const char* glfwGetGamepadName(int jid);
*
* Not all devices have all the buttons or axes provided by @ref
* GLFWgamepadstate. Unavailable buttons and axes will always report
* `GLFW_RELEASE` and 1.0 respectively.
* `GLFW_RELEASE` and 0.0 respectively.
*
* @param[in] jid The [joystick](@ref joysticks) to query.
* @param[out] state The gamepad input state of the joystick.
@ -4640,6 +4905,8 @@ GLFWAPI const char* glfwGetGamepadName(int jid);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_INVALID_ENUM.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref gamepad
* @sa @ref glfwUpdateGamepadMappings
* @sa @ref glfwJoystickIsGamepad
@ -4655,7 +4922,7 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state);
* This function sets the system clipboard to the specified, UTF-8 encoded
* string.
*
* @param[in] window The window that will own the clipboard contents.
* @param[in] window Deprecated. Any valid window or `NULL`.
* @param[in] string A UTF-8 encoded string.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
@ -4684,7 +4951,7 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
* if its contents cannot be converted, `NULL` is returned and a @ref
* GLFW_FORMAT_UNAVAILABLE error is generated.
*
* @param[in] window The window that will request the clipboard contents.
* @param[in] window Deprecated. Any valid window or `NULL`.
* @return The contents of the clipboard as a UTF-8 encoded string, or `NULL`
* if an [error](@ref error_handling) occurred.
*
@ -4809,10 +5076,13 @@ GLFWAPI uint64_t glfwGetTimerFrequency(void);
* thread.
*
* This function makes the OpenGL or OpenGL ES context of the specified window
* current on the calling thread. A context can only be made current on
* current on the calling thread. A context must only be made current on
* a single thread at a time and each thread can have only a single current
* context at a time.
*
* When moving a context between threads, you must make it non-current on the
* old thread before making it current on the new one.
*
* By default, making a context non-current implicitly forces a pipeline flush.
* On machines that support `GL_KHR_context_flush_control`, you can control
* whether a context performs this flush by setting the
@ -4903,12 +5173,11 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* window);
* is sometimes called _vertical synchronization_, _vertical retrace
* synchronization_ or just _vsync_.
*
* Contexts that support either of the `WGL_EXT_swap_control_tear` and
* `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals,
* which allow the driver to swap even if a frame arrives a little bit late.
* You can check for the presence of these extensions using @ref
* glfwExtensionSupported. For more information about swap tearing, see the
* extension specifications.
* A context that supports either of the `WGL_EXT_swap_control_tear` and
* `GLX_EXT_swap_control_tear` extensions also accepts _negative_ swap
* intervals, which allows the driver to swap immediately even if a frame
* arrives a little bit late. You can check for these extensions with @ref
* glfwExtensionSupported.
*
* A context must be current on the calling thread. Calling this function
* without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
@ -5193,6 +5462,11 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhys
* glfwGetRequiredInstanceExtensions to check what instance extensions are
* required.
*
* The window surface cannot be shared with another API so the window must
* have been created with the [client api hint](@ref GLFW_CLIENT_API_attrib)
* set to `GLFW_NO_API` otherwise it generates a @ref GLFW_INVALID_VALUE error
* and returns `VK_ERROR_NATIVE_WINDOW_IN_USE_KHR`.
*
* The window surface must be destroyed before the specified Vulkan instance.
* It is the responsibility of the caller to destroy the window surface. GLFW
* does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the
@ -5208,7 +5482,7 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhys
* [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
* GLFW_API_UNAVAILABLE, @ref GLFW_PLATFORM_ERROR and @ref GLFW_INVALID_VALUE
*
* @remark If an error occurs before the creation call is made, GLFW returns
* the Vulkan error code most appropriate for the error. Appropriate use of

View File

@ -62,7 +62,6 @@ extern "C" {
* * `GLFW_EXPOSE_NATIVE_COCOA`
* * `GLFW_EXPOSE_NATIVE_X11`
* * `GLFW_EXPOSE_NATIVE_WAYLAND`
* * `GLFW_EXPOSE_NATIVE_MIR`
*
* The available context API macros are:
* * `GLFW_EXPOSE_NATIVE_WGL`
@ -103,8 +102,6 @@ extern "C" {
#include <X11/extensions/Xrandr.h>
#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
#include <wayland-client.h>
#elif defined(GLFW_EXPOSE_NATIVE_MIR)
#include <mir_toolkit/mir_client_library.h>
#endif
#if defined(GLFW_EXPOSE_NATIVE_WGL)
@ -418,50 +415,6 @@ GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
#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 `MirWindow*` of the specified window.
*
* @return The `MirWindow*` 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 MirWindow* glfwGetMirWindow(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_EGL)
/*! @brief Returns the `EGLDisplay` used by GLFW.
*

View File

@ -23,22 +23,26 @@ elseif (_GLFW_X11)
set(glfw_SOURCES ${common_SOURCES} x11_init.c x11_monitor.c x11_window.c
xkb_unicode.c posix_time.c posix_thread.c glx_context.c
egl_context.c osmesa_context.c)
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(glfw_HEADERS ${glfw_HEADERS} linux_joystick.h)
set(glfw_SOURCES ${glfw_SOURCES} linux_joystick.c)
else()
set(glfw_HEADERS ${glfw_HEADERS} null_joystick.h)
set(glfw_SOURCES ${glfw_SOURCES} null_joystick.c)
endif()
elseif (_GLFW_WAYLAND)
set(glfw_HEADERS ${common_HEADERS} wl_platform.h linux_joystick.h
set(glfw_HEADERS ${common_HEADERS} wl_platform.h
posix_time.h posix_thread.h xkb_unicode.h egl_context.h
osmesa_context.h)
set(glfw_SOURCES ${common_SOURCES} wl_init.c wl_monitor.c wl_window.c
linux_joystick.c posix_time.c posix_thread.c xkb_unicode.c
posix_time.c posix_thread.c xkb_unicode.c
egl_context.c osmesa_context.c)
ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/xdg-shell/xdg-shell.xml"
BASENAME xdg-shell)
ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
BASENAME xdg-decoration)
ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/viewporter/viewporter.xml"
BASENAME viewporter)
ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml"
@ -47,13 +51,10 @@ elseif (_GLFW_WAYLAND)
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml"
BASENAME pointer-constraints-unstable-v1)
elseif (_GLFW_MIR)
set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
posix_time.h posix_thread.h xkb_unicode.h egl_context.h
osmesa_context.h)
set(glfw_SOURCES ${common_SOURCES} mir_init.c mir_monitor.c mir_window.c
linux_joystick.c posix_time.c posix_thread.c xkb_unicode.c
egl_context.c osmesa_context.c)
ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml"
BASENAME idle-inhibit-unstable-v1)
elseif (_GLFW_OSMESA)
set(glfw_HEADERS ${common_HEADERS} null_platform.h null_joystick.h
posix_time.h posix_thread.h osmesa_context.h)
@ -61,6 +62,16 @@ elseif (_GLFW_OSMESA)
null_joystick.c posix_time.c posix_thread.c osmesa_context.c)
endif()
if (_GLFW_X11 OR _GLFW_WAYLAND)
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(glfw_HEADERS ${glfw_HEADERS} linux_joystick.h)
set(glfw_SOURCES ${glfw_SOURCES} linux_joystick.c)
else()
set(glfw_HEADERS ${glfw_HEADERS} null_joystick.h)
set(glfw_SOURCES ${glfw_SOURCES} null_joystick.c)
endif()
endif()
if (APPLE)
# For some reason, CMake doesn't know about .m
set_source_files_properties(${glfw_SOURCES} PROPERTIES LANGUAGE C)
@ -86,9 +97,7 @@ set_target_properties(glfw PROPERTIES
POSITION_INDEPENDENT_CODE ON
FOLDER "GLFW3")
target_compile_definitions(glfw PRIVATE
_GLFW_USE_CONFIG_H
$<$<BOOL:${UNIX}>:_XOPEN_SOURCE=600>)
target_compile_definitions(glfw PRIVATE _GLFW_USE_CONFIG_H)
target_include_directories(glfw PUBLIC
"$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>")

View File

@ -247,9 +247,9 @@ static void matchCallback(void* context,
compareElements, NULL);
js = _glfwAllocJoystick(name, guid,
CFArrayGetCount(axes),
CFArrayGetCount(buttons),
CFArrayGetCount(hats));
(int) CFArrayGetCount(axes),
(int) CFArrayGetCount(buttons),
(int) CFArrayGetCount(hats));
js->ns.device = device;
js->ns.axes = axes;
@ -399,11 +399,11 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
const long delta = axis->maximum - axis->minimum;
if (delta == 0)
_glfwInputJoystickAxis(js, i, 0.f);
_glfwInputJoystickAxis(js, (int) i, 0.f);
else
{
const float value = (2.f * (raw - axis->minimum) / delta) - 1.f;
_glfwInputJoystickAxis(js, i, value);
_glfwInputJoystickAxis(js, (int) i, value);
}
}
}
@ -417,7 +417,7 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
CFArrayGetValueAtIndex(js->ns.buttons, i);
const char value = getElementValue(js, button) - button->minimum;
_glfwInputJoystickButton(js, i, value);
_glfwInputJoystickButton(js, (int) i, value);
}
for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
@ -441,7 +441,7 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
if (state < 0 || state > 8)
state = 8;
_glfwInputJoystickHat(js, i, states[state]);
_glfwInputJoystickHat(js, (int) i, states[state]);
}
}

View File

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

View File

@ -88,6 +88,11 @@ typedef struct _GLFWwindowNS
GLFWbool maximized;
// Cached window properties to filter out duplicate events
int width, height;
int fbWidth, fbHeight;
float xscale, yscale;
// The total sum of the distances the cursor has been warped
// since the last cursor motion event was processed
// This is kept to counteract Cocoa doing the same internally
@ -159,7 +164,7 @@ typedef struct _GLFWtimerNS
void _glfwInitTimerNS(void);
void _glfwPollMonitorsNS(void);
GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
// If GLFW is running as a stand-alone application, we create a global autorelease

View File

@ -43,6 +43,7 @@
#define NSEventModifierFlagControl NSControlKeyMask
#define NSEventModifierFlagOption NSAlternateKeyMask
#define NSEventModifierFlagShift NSShiftKeyMask
#define NSEventModifierFlagCapsLock NSAlphaShiftKeyMask
#define NSEventModifierFlagDeviceIndependentFlagsMask NSDeviceIndependentModifierFlagsMask
#define NSEventMaskAny NSAnyEventMask
#define NSEventTypeApplicationDefined NSApplicationDefined
@ -127,6 +128,32 @@ static void updateCursorImage(_GLFWwindow* window)
hideCursor(window);
}
// Apply chosen cursor mode to a focused window
//
static void updateCursorMode(_GLFWwindow* window)
{
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
_glfw.ns.disabledCursorWindow = window;
_glfwPlatformGetCursorPos(window,
&_glfw.ns.restoreCursorPosX,
&_glfw.ns.restoreCursorPosY);
centerCursor(window);
CGAssociateMouseAndMouseCursorPosition(false);
}
else if (_glfw.ns.disabledCursorWindow == window)
{
_glfw.ns.disabledCursorWindow = NULL;
CGAssociateMouseAndMouseCursorPosition(true);
_glfwPlatformSetCursorPos(window,
_glfw.ns.restoreCursorPosX,
_glfw.ns.restoreCursorPosY);
}
if (cursorInClientArea(window))
updateCursorImage(window);
}
// Transforms the specified y-coordinate between the CG display and NS screen
// coordinate systems
//
@ -137,9 +164,9 @@ static float transformY(float y)
// Make the specified window and its video mode active on its monitor
//
static GLFWbool acquireMonitor(_GLFWwindow* window)
static void acquireMonitor(_GLFWwindow* window)
{
const GLFWbool status = _glfwSetVideoModeNS(window->monitor, &window->videoMode);
_glfwSetVideoModeNS(window->monitor, &window->videoMode);
const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID);
const NSRect frame = NSMakeRect(bounds.origin.x,
transformY(bounds.origin.y + bounds.size.height),
@ -149,7 +176,6 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
[window->ns.object setFrame:frame display:YES];
_glfwInputMonitorWindow(window->monitor, window);
return status;
}
// Remove the window and restore the original video mode
@ -177,6 +203,8 @@ static int translateFlags(NSUInteger flags)
mods |= GLFW_MOD_ALT;
if (flags & NSEventModifierFlagCommand)
mods |= GLFW_MOD_SUPER;
if (flags & NSEventModifierFlagCapsLock)
mods |= GLFW_MOD_CAPS_LOCK;
return mods;
}
@ -267,8 +295,21 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
const NSRect contentRect = [window->ns.view frame];
const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
if (fbRect.size.width != window->ns.fbWidth ||
fbRect.size.height != window->ns.fbHeight)
{
window->ns.fbWidth = fbRect.size.width;
window->ns.fbHeight = fbRect.size.height;
_glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
}
if (contentRect.size.width != window->ns.width ||
contentRect.size.height != window->ns.height)
{
window->ns.width = contentRect.size.width;
window->ns.height = contentRect.size.height;
_glfwInputWindowSize(window, contentRect.size.width, contentRect.size.height);
}
}
- (void)windowDidMove:(NSNotification *)notification
@ -306,7 +347,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
centerCursor(window);
_glfwInputWindowFocus(window, GLFW_TRUE);
_glfwPlatformSetCursorMode(window, window->cursorMode);
updateCursorMode(window);
}
- (void)windowDidResignKey:(NSNotification *)notification
@ -551,7 +592,26 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
const NSRect contentRect = [window->ns.view frame];
const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
if (fbRect.size.width != window->ns.fbWidth ||
fbRect.size.height != window->ns.fbHeight)
{
window->ns.fbWidth = fbRect.size.width;
window->ns.fbHeight = fbRect.size.height;
_glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
}
const float xscale = fbRect.size.width / contentRect.size.width;
const float yscale = fbRect.size.height / contentRect.size.height;
if (xscale != window->ns.xscale || yscale != window->ns.yscale)
{
window->ns.xscale = xscale;
window->ns.yscale = yscale;
_glfwInputWindowContentScale(window, xscale, yscale);
if (window->ns.layer)
[window->ns.layer setContentsScale:[window->ns.object backingScaleFactor]];
}
}
- (void)drawRect:(NSRect)rect
@ -667,17 +727,17 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
[sender draggingLocation].x,
contentRect.size.height - [sender draggingLocation].y);
const int count = [files count];
const NSUInteger count = [files count];
if (count)
{
NSEnumerator* e = [files objectEnumerator];
char** paths = calloc(count, sizeof(char*));
int i;
NSUInteger i;
for (i = 0; i < count; i++)
paths[i] = strdup([[e nextObject] UTF8String]);
paths[i] = _glfw_strdup([[e nextObject] UTF8String]);
_glfwInputDrop(window, count, (const char**) paths);
_glfwInputDrop(window, (int) count, (const char**) paths);
for (i = 0; i < count; i++)
free(paths[i]);
@ -841,7 +901,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)loadMainMenu
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 100800
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
[[NSBundle mainBundle] loadNibNamed:@"MainMenu"
owner:NSApp
topLevelObjects:&nibObjects];
@ -1074,8 +1134,8 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
[window->ns.object zoom:nil];
}
if (wndconfig->ns.frame)
[window->ns.object setFrameAutosaveName:[NSString stringWithUTF8String:wndconfig->title]];
if (strlen(wndconfig->ns.frameName))
[window->ns.object setFrameAutosaveName:[NSString stringWithUTF8String:wndconfig->ns.frameName]];
window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
@ -1095,6 +1155,9 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
[window->ns.object setAcceptsMouseMovedEvents:YES];
[window->ns.object setRestorable:NO];
_glfwPlatformGetWindowSize(window, &window->ns.width, &window->ns.height);
_glfwPlatformGetFramebufferSize(window, &window->ns.fbWidth, &window->ns.fbHeight);
return GLFW_TRUE;
}
@ -1143,11 +1206,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
{
_glfwPlatformShowWindow(window);
_glfwPlatformFocusWindow(window);
if (!acquireMonitor(window))
return GLFW_FALSE;
if (wndconfig->centerCursor)
centerCursor(window);
acquireMonitor(window);
}
return GLFW_TRUE;
@ -1382,30 +1441,9 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
const NSUInteger styleMask = getStyleMask(window);
[window->ns.object setStyleMask:styleMask];
// HACK: Changing the style mask can cause the first responder to be cleared
[window->ns.object makeFirstResponder:window->ns.view];
NSRect contentRect;
if (monitor)
{
GLFWvidmode mode;
_glfwPlatformGetVideoMode(window->monitor, &mode);
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
contentRect = NSMakeRect(xpos, transformY(ypos + mode.height),
mode.width, mode.height);
}
else
{
contentRect = NSMakeRect(xpos, transformY(ypos + height),
width, height);
}
NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect
styleMask:styleMask];
[window->ns.object setFrame:frameRect display:YES];
if (monitor)
{
[window->ns.object setLevel:NSMainMenuWindowLevel + 1];
@ -1415,6 +1453,12 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
}
else
{
NSRect contentRect = NSMakeRect(xpos, transformY(ypos + height),
width, height);
NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect
styleMask:styleMask];
[window->ns.object setFrame:frameRect display:YES];
if (window->numer != GLFW_DONT_CARE &&
window->denom != GLFW_DONT_CARE)
{
@ -1468,6 +1512,20 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return [window->ns.object isZoomed];
}
int _glfwPlatformWindowHovered(_GLFWwindow* window)
{
const NSPoint point = [NSEvent mouseLocation];
if ([NSWindow windowNumberAtPoint:point belowWindowWithWindowNumber:0] !=
[window->ns.object windowNumber])
{
return GLFW_FALSE;
}
return NSPointInRect(point,
[window->ns.object convertRectToScreen:[window->ns.view bounds]]);
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{
return ![window->ns.object isOpaque] && ![window->ns.view isOpaque];
@ -1492,8 +1550,21 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
[window->ns.object setLevel:NSNormalWindowLevel];
}
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
{
return (float) [window->ns.object alphaValue];
}
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
{
[window->ns.object setAlphaValue:opacity];
}
void _glfwPlatformPollEvents(void)
{
if (!initializeAppKit())
return;
for (;;)
{
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
@ -1591,26 +1662,8 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{
if (mode == GLFW_CURSOR_DISABLED)
{
_glfw.ns.disabledCursorWindow = window;
_glfwPlatformGetCursorPos(window,
&_glfw.ns.restoreCursorPosX,
&_glfw.ns.restoreCursorPosY);
centerCursor(window);
CGAssociateMouseAndMouseCursorPosition(false);
}
else if (_glfw.ns.disabledCursorWindow == window)
{
_glfw.ns.disabledCursorWindow = NULL;
CGAssociateMouseAndMouseCursorPosition(true);
_glfwPlatformSetCursorPos(window,
_glfw.ns.restoreCursorPosX,
_glfw.ns.restoreCursorPosY);
}
if (cursorInClientArea(window))
updateCursorImage(window);
if (_glfwPlatformWindowFocused(window))
updateCursorMode(window);
}
const char* _glfwPlatformGetScancodeName(int scancode)
@ -1738,7 +1791,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
updateCursorImage(window);
}
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
void _glfwPlatformSetClipboardString(const char* string)
{
NSArray* types = [NSArray arrayWithObjects:NSStringPboardType, nil];
@ -1748,7 +1801,7 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
forType:NSStringPboardType];
}
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
const char* _glfwPlatformGetClipboardString(void)
{
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
@ -1768,7 +1821,7 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
}
free(_glfw.ns.clipboardString);
_glfw.ns.clipboardString = strdup([object UTF8String]);
_glfw.ns.clipboardString = _glfw_strdup([object UTF8String]);
return _glfw.ns.clipboardString;
}
@ -1827,6 +1880,7 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
[window->ns.layer setContentsScale:[window->ns.object backingScaleFactor]];
[window->ns.view setWantsLayer:YES];
memset(&sci, 0, sizeof(sci));

View File

@ -38,8 +38,24 @@
////// 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)
{
if (ctxconfig->share)
{
if (ctxconfig->client == GLFW_NO_API ||
ctxconfig->share->context.client == GLFW_NO_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return GLFW_FALSE;
}
}
if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
ctxconfig->source != GLFW_EGL_CONTEXT_API &&
ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
@ -155,6 +171,8 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
return GLFW_TRUE;
}
// Chooses the framebuffer config that best matches the desired one
//
const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
const _GLFWfbconfig* alternatives,
unsigned int count)
@ -321,10 +339,13 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
return closest;
}
GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
// Retrieves the attributes of the current context
//
GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig)
{
int i;
_GLFWwindow* window;
_GLFWwindow* previous;
const char* version;
const char* prefixes[] =
{
@ -334,11 +355,12 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
NULL
};
window = _glfwPlatformGetTls(&_glfw.contextSlot);
window->context.source = ctxconfig->source;
window->context.client = GLFW_OPENGL_API;
previous = _glfwPlatformGetTls(&_glfw.contextSlot);;
glfwMakeContextCurrent((GLFWwindow*) window);
window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
window->context.getProcAddress("glGetIntegerv");
window->context.GetString = (PFNGLGETSTRINGPROC)
@ -346,6 +368,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
if (!window->context.GetIntegerv || !window->context.GetString)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_FALSE;
}
@ -363,6 +386,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
"OpenGL ES version string retrieval is broken");
}
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_FALSE;
}
@ -394,6 +418,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
"No version found in OpenGL ES version string");
}
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_FALSE;
}
@ -423,6 +448,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
window->context.major, window->context.minor);
}
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_FALSE;
}
@ -438,6 +464,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Entry point retrieval is broken");
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_FALSE;
}
}
@ -544,9 +571,12 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
window->context.swapBuffers(window);
}
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_TRUE;
}
// Searches an extension string for the specified extension
//
GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions)
{
const char* start = extensions;
@ -587,7 +617,8 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
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;
}
@ -616,7 +647,8 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
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;
}
@ -632,7 +664,8 @@ GLFWAPI void glfwSwapInterval(int interval)
window = _glfwPlatformGetTls(&_glfw.contextSlot);
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;
}
@ -649,13 +682,14 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
window = _glfwPlatformGetTls(&_glfw.contextSlot);
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;
}
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;
}
@ -714,7 +748,8 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
window = _glfwPlatformGetTls(&_glfw.contextSlot);
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;
}

View File

@ -43,10 +43,6 @@ typedef Window EGLNativeWindowType;
#define EGLAPIENTRY
typedef struct wl_display* EGLNativeDisplayType;
typedef struct wl_egl_window* EGLNativeWindowType;
#elif defined(_GLFW_MIR)
#define EGLAPIENTRY
typedef MirEGLNativeDisplayType EGLNativeDisplayType;
typedef MirEGLNativeWindowType EGLNativeWindowType;
#else
#error "No supported EGL platform selected"
#endif

View File

@ -42,8 +42,6 @@
#cmakedefine _GLFW_COCOA
// Define this to 1 if building GLFW for Wayland
#cmakedefine _GLFW_WAYLAND
// Define this to 1 if building GLFW for Mir
#cmakedefine _GLFW_MIR
// Define this to 1 if building GLFW for OSMesa
#cmakedefine _GLFW_OSMESA
@ -55,3 +53,8 @@
// Define this to 1 to force use of high-performance GPU on hybrid systems
#cmakedefine _GLFW_USE_HYBRID_HPG
// Define this to 1 if xkbcommon supports the compose key
#cmakedefine HAVE_XKBCOMMON_COMPOSE_H
// Define this to 1 if the libc supports memfd_create()
#cmakedefine HAVE_MEMFD_CREATE

View File

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

View File

@ -35,8 +35,9 @@
#include <assert.h>
// The global variables below comprise all global data in GLFW.
// Any other global variable is a bug.
// The global variables below comprise all mutable global data in GLFW
//
// Any other global variable is a bug
// Global state shared between compilation units of GLFW
//
@ -53,44 +54,9 @@ static _GLFWinitconfig _glfwInitHints =
{
GLFW_TRUE, // macOS menu bar
GLFW_TRUE // macOS bundle chdir
},
{
"", // X11 WM_CLASS name
"" // X11 WM_CLASS class
}
};
// Returns a generic string representation of the specified error
//
static const char* getErrorString(int code)
{
switch (code)
{
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 "An undocumented 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";
}
}
// Terminate the library
//
static void terminate(void)
@ -141,10 +107,25 @@ static void terminate(void)
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
char* _glfw_strdup(const char* source)
{
const size_t length = strlen(source);
char* result = calloc(length + 1, 1);
strcpy(result, source);
return result;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW event API //////
//////////////////////////////////////////////////////////////////////////
// Notifies shared code of an error
//
void _glfwInputError(int code, const char* format, ...)
{
_GLFWerror* error;
@ -161,7 +142,30 @@ void _glfwInputError(int code, const char* format, ...)
description[sizeof(description) - 1] = '\0';
}
else
strcpy(description, getErrorString(code));
{
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)
{
@ -205,12 +209,13 @@ GLFWAPI int glfwInit(void)
return GLFW_FALSE;
}
if (!_glfwPlatformCreateMutex(&_glfw.errorLock))
return GLFW_FALSE;
if (!_glfwPlatformCreateTls(&_glfw.errorSlot))
return GLFW_FALSE;
if (!_glfwPlatformCreateTls(&_glfw.contextSlot))
if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
!_glfwPlatformCreateTls(&_glfw.errorSlot) ||
!_glfwPlatformCreateTls(&_glfw.contextSlot))
{
terminate();
return GLFW_FALSE;
}
_glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
@ -218,7 +223,19 @@ GLFWAPI int glfwInit(void)
_glfw.timer.offset = _glfwPlatformGetTimerValue();
glfwDefaultWindowHints();
glfwUpdateGamepadMappings(_glfwDefaultMappings);
{
int i;
for (i = 0; _glfwDefaultMappings[i]; i++)
{
if (!glfwUpdateGamepadMappings(_glfwDefaultMappings[i]))
{
terminate();
return GLFW_FALSE;
}
}
}
return GLFW_TRUE;
}
@ -247,27 +264,7 @@ GLFWAPI void glfwInitHint(int hint, int value)
}
_glfwInputError(GLFW_INVALID_ENUM,
"Invalid integer type init hint 0x%08X", hint);
}
GLFWAPI void glfwInitHintString(int hint, const char* value)
{
assert(value != NULL);
switch (hint)
{
case GLFW_X11_WM_CLASS_NAME:
strncpy(_glfwInitHints.x11.className, value,
sizeof(_glfwInitHints.x11.className) - 1);
break;
case GLFW_X11_WM_CLASS_CLASS:
strncpy(_glfwInitHints.x11.classClass, value,
sizeof(_glfwInitHints.x11.classClass) - 1);
break;
}
_glfwInputError(GLFW_INVALID_ENUM,
"Invalid string type init hint 0x%08X", hint);
"Invalid init hint 0x%08X", hint);
}
GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)

View File

@ -32,7 +32,6 @@
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// Internal key state used for sticky keys
#define _GLFW_STICK 3
@ -57,6 +56,58 @@ static _GLFWmapping* findMapping(const char* guid)
return NULL;
}
// Checks whether a gamepad mapping element is present in the hardware
//
static GLFWbool isValidElementForJoystick(const _GLFWmapelement* e,
const _GLFWjoystick* js)
{
if (e->type == _GLFW_JOYSTICK_HATBIT && (e->index >> 4) >= js->hatCount)
return GLFW_FALSE;
else if (e->type == _GLFW_JOYSTICK_BUTTON && e->index >= js->buttonCount)
return GLFW_FALSE;
else if (e->type == _GLFW_JOYSTICK_AXIS && e->index >= js->axisCount)
return GLFW_FALSE;
return GLFW_TRUE;
}
// Finds a mapping based on joystick GUID and verifies element indices
//
static _GLFWmapping* findValidMapping(const _GLFWjoystick* js)
{
_GLFWmapping* mapping = findMapping(js->guid);
if (mapping)
{
int i;
for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++)
{
if (!isValidElementForJoystick(mapping->buttons + i, js))
{
_glfwInputError(GLFW_INVALID_VALUE,
"Invalid button in gamepad mapping %s (%s)",
mapping->guid,
mapping->name);
return NULL;
}
}
for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++)
{
if (!isValidElementForJoystick(mapping->axes + i, js))
{
_glfwInputError(GLFW_INVALID_VALUE,
"Invalid axis in gamepad mapping %s (%s)",
mapping->guid,
mapping->name);
return NULL;
}
}
}
return mapping;
}
// Parses an SDL_GameControllerDB line and adds it to the mapping list
//
static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
@ -115,6 +166,10 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
while (*c)
{
// TODO: Implement output modifiers
if (*c == '+' || *c == '-')
return GLFW_FALSE;
for (i = 0; i < sizeof(fields) / sizeof(fields[0]); i++)
{
length = strlen(fields[i].name);
@ -125,23 +180,50 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
if (fields[i].element)
{
_GLFWmapelement* e = fields[i].element;
int8_t minimum = -1;
int8_t maximum = 1;
if (*c == '+')
{
minimum = 0;
c += 1;
}
else if (*c == '-')
{
maximum = 0;
c += 1;
}
if (*c == 'a')
fields[i].element->type = _GLFW_JOYSTICK_AXIS;
e->type = _GLFW_JOYSTICK_AXIS;
else if (*c == 'b')
fields[i].element->type = _GLFW_JOYSTICK_BUTTON;
e->type = _GLFW_JOYSTICK_BUTTON;
else if (*c == 'h')
fields[i].element->type = _GLFW_JOYSTICK_HATBIT;
e->type = _GLFW_JOYSTICK_HATBIT;
else
break;
if (fields[i].element->type == _GLFW_JOYSTICK_HATBIT)
if (e->type == _GLFW_JOYSTICK_HATBIT)
{
const unsigned int hat = strtoul(c + 1, (char**) &c, 10);
const unsigned int bit = strtoul(c + 1, (char**) &c, 10);
fields[i].element->value = (hat << 4) | bit;
const unsigned long hat = strtoul(c + 1, (char**) &c, 10);
const unsigned long bit = strtoul(c + 1, (char**) &c, 10);
e->index = (uint8_t) ((hat << 4) | bit);
}
else
fields[i].element->value = (uint8_t) strtoul(c + 1, (char**) &c, 10);
e->index = (uint8_t) strtoul(c + 1, (char**) &c, 10);
if (e->type == _GLFW_JOYSTICK_AXIS)
{
e->axisScale = 2 / (maximum - minimum);
e->axisOffset = -(maximum + minimum);
if (*c == '~')
{
e->axisScale = -e->axisScale;
e->axisOffset = -e->axisOffset;
}
}
}
else
{
@ -172,6 +254,8 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
////// GLFW event API //////
//////////////////////////////////////////////////////////////////////////
// Notifies shared code of a physical key event
//
void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key >= 0 && key <= GLFW_KEY_LAST)
@ -193,15 +277,24 @@ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int m
action = GLFW_REPEAT;
}
if (!window->lockKeyMods)
mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
if (window->callbacks.key)
window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods);
}
// Notifies shared code of a Unicode codepoint input event
// The 'plain' parameter determines whether to emit a regular character event
//
void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain)
{
if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
return;
if (!window->lockKeyMods)
mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
if (window->callbacks.charmods)
window->callbacks.charmods((GLFWwindow*) window, codepoint, mods);
@ -212,17 +305,24 @@ void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWb
}
}
// Notifies shared code of a scroll event
//
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
{
if (window->callbacks.scroll)
window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
}
// Notifies shared code of a mouse button click event
//
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
{
if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
return;
if (!window->lockKeyMods)
mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
if (action == GLFW_RELEASE && window->stickyMouseButtons)
window->mouseButtons[button] = _GLFW_STICK;
else
@ -232,6 +332,9 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods);
}
// Notifies shared code of a cursor motion event
// The position is specified in client-area relative screen coordinates
//
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
{
if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)
@ -244,18 +347,24 @@ void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos);
}
// Notifies shared code of a cursor enter/leave event
//
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
{
if (window->callbacks.cursorEnter)
window->callbacks.cursorEnter((GLFWwindow*) window, entered);
}
// Notifies shared code of files or directories dropped on a window
//
void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
{
if (window->callbacks.drop)
window->callbacks.drop((GLFWwindow*) window, count, paths);
}
// Notifies shared code of a joystick connection or disconnection
//
void _glfwInputJoystick(_GLFWjoystick* js, int event)
{
const int jid = (int) (js - _glfw.joysticks);
@ -264,16 +373,22 @@ void _glfwInputJoystick(_GLFWjoystick* js, int event)
_glfw.callbacks.joystick(jid, event);
}
// Notifies shared code of the new value of a joystick axis
//
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value)
{
js->axes[axis] = value;
}
// Notifies shared code of the new value of a joystick button
//
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value)
{
js->buttons[button] = value;
}
// Notifies shared code of the new value of a joystick hat
//
void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
{
const int base = js->buttonCount + hat * 4;
@ -291,6 +406,8 @@ void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Returns an available joystick object with arrays and name allocated
//
_GLFWjoystick* _glfwAllocJoystick(const char* name,
const char* guid,
int axisCount,
@ -311,20 +428,22 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
js = _glfw.joysticks + jid;
js->present = GLFW_TRUE;
js->name = strdup(name);
js->name = _glfw_strdup(name);
js->axes = calloc(axisCount, sizeof(float));
js->buttons = calloc(buttonCount + hatCount * 4, 1);
js->hats = calloc(hatCount, 1);
js->axisCount = axisCount;
js->buttonCount = buttonCount;
js->hatCount = hatCount;
js->mapping = findMapping(guid);
strcpy(js->guid, guid);
js->mapping = findValidMapping(js);
return js;
}
// Frees arrays and name and flags the joystick object as unused
//
void _glfwFreeJoystick(_GLFWjoystick* js)
{
free(js->name);
@ -354,6 +473,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
return window->stickyKeys;
case GLFW_STICKY_MOUSE_BUTTONS:
return window->stickyMouseButtons;
case GLFW_LOCK_KEY_MODS:
return window->lockKeyMods;
}
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
@ -387,8 +508,6 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
_glfwPlatformGetCursorPos(window,
&window->virtualCursorPosX,
&window->virtualCursorPosY);
if (_glfwPlatformWindowFocused(window))
_glfwPlatformSetCursorMode(window, value);
}
else if (mode == GLFW_STICKY_KEYS)
@ -409,7 +528,7 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
}
}
window->stickyKeys = value ? GLFW_TRUE : GLFW_FALSE;
window->stickyKeys = value;
}
else if (mode == GLFW_STICKY_MOUSE_BUTTONS)
{
@ -429,8 +548,10 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
}
}
window->stickyMouseButtons = value ? GLFW_TRUE : GLFW_FALSE;
window->stickyMouseButtons = value;
}
else if (mode == GLFW_LOCK_KEY_MODS)
window->lockKeyMods = value ? GLFW_TRUE : GLFW_FALSE;
else
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
}
@ -914,6 +1035,38 @@ GLFWAPI const char* glfwGetJoystickGUID(int jid)
return js->guid;
}
GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer)
{
_GLFWjoystick* js;
assert(jid >= GLFW_JOYSTICK_1);
assert(jid <= GLFW_JOYSTICK_LAST);
_GLFW_REQUIRE_INIT();
js = _glfw.joysticks + jid;
if (!js->present)
return;
js->userPointer = pointer;
}
GLFWAPI void* glfwGetJoystickUserPointer(int jid)
{
_GLFWjoystick* js;
assert(jid >= GLFW_JOYSTICK_1);
assert(jid <= GLFW_JOYSTICK_LAST);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
js = _glfw.joysticks + jid;
if (!js->present)
return NULL;
return js->userPointer;
}
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
@ -932,7 +1085,9 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string)
while (*c)
{
if (isxdigit(*c))
if ((*c >= '0' && *c <= '9') ||
(*c >= 'a' && *c <= 'f') ||
(*c >= 'A' && *c <= 'F'))
{
char line[1024];
@ -973,7 +1128,7 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string)
{
_GLFWjoystick* js = _glfw.joysticks + jid;
if (js->present)
js->mapping = findMapping(js->guid);
js->mapping = findValidMapping(js);
}
return GLFW_TRUE;
@ -1063,35 +1218,41 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++)
{
if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_AXIS)
const _GLFWmapelement* e = js->mapping->buttons + i;
if (e->type == _GLFW_JOYSTICK_AXIS)
{
if (fabs(js->axes[js->mapping->buttons[i].value]) > 0.5)
const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
if (value > 0.f)
state->buttons[i] = GLFW_PRESS;
}
else if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_HATBIT)
else if (e->type == _GLFW_JOYSTICK_HATBIT)
{
const unsigned int hat = js->mapping->buttons[i].value >> 4;
const unsigned int bit = js->mapping->buttons[i].value & 0xf;
const unsigned int hat = e->index >> 4;
const unsigned int bit = e->index & 0xf;
if (js->hats[hat] & bit)
state->buttons[i] = GLFW_PRESS;
}
else if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_BUTTON)
state->buttons[i] = js->buttons[js->mapping->buttons[i].value];
else if (e->type == _GLFW_JOYSTICK_BUTTON)
state->buttons[i] = js->buttons[e->index];
}
for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++)
{
if (js->mapping->axes[i].type == _GLFW_JOYSTICK_AXIS)
state->axes[i] = js->axes[js->mapping->axes[i].value];
else if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_HATBIT)
const _GLFWmapelement* e = js->mapping->axes + i;
if (e->type == _GLFW_JOYSTICK_AXIS)
{
const unsigned int hat = js->mapping->buttons[i].value >> 4;
const unsigned int bit = js->mapping->buttons[i].value & 0xf;
const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
state->axes[i] = fminf(fmaxf(value, -1.f), 1.f);
}
else if (e->type == _GLFW_JOYSTICK_HATBIT)
{
const unsigned int hat = e->index >> 4;
const unsigned int bit = e->index & 0xf;
if (js->hats[hat] & bit)
state->axes[i] = 1.f;
}
else if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_BUTTON)
state->axes[i] = (float) js->buttons[js->mapping->axes[i].value];
else if (e->type == _GLFW_JOYSTICK_BUTTON)
state->axes[i] = (float) js->buttons[e->index];
}
return GLFW_TRUE;
@ -1099,21 +1260,16 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(string != NULL);
_GLFW_REQUIRE_INIT();
_glfwPlatformSetClipboardString(window, string);
_glfwPlatformSetClipboardString(string);
}
GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return _glfwPlatformGetClipboardString(window);
return _glfwPlatformGetClipboardString();
}
GLFWAPI double glfwGetTime(void)

View File

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

View File

@ -38,6 +38,11 @@
#include <string.h>
#include <unistd.h>
#ifndef SYN_DROPPED // < v2.6.39 kernel headers
// Workaround for CentOS-6, which is supported till 2020-11-30, but still on v2.6.32
#define SYN_DROPPED 3
#endif
// Apply an EV_KEY event to the specified joystick
//
static void handleKeyEvent(_GLFWjoystick* js, int code, int value)
@ -223,7 +228,7 @@ static GLFWbool openJoystickDevice(const char* path)
return GLFW_FALSE;
}
strncpy(linjs.path, path, sizeof(linjs.path));
strncpy(linjs.path, path, sizeof(linjs.path) - 1);
memcpy(&js->linjs, &linjs, sizeof(linjs));
pollAbsState(js);

View File

@ -58,184 +58,421 @@
//
// 3. This notice may not be removed or altered from any source distribution.
const char* _glfwDefaultMappings =
"8f0e1200000000000000504944564944,Acme,platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,\n"
"341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n"
"ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n"
"6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n"
"0d0f6e00000000000000504944564944,HORIPAD 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n"
"88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,\n"
"4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,\n"
"25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,\n"
"4c05c405000000000000504944564944,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows,\n"
"4c05cc09000000000000504944564944,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows,\n"
"4c05a00b000000000000504944564944,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows,\n"
"6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"36280100000000000000504944564944,OUYA Controller,platform:Windows,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13,\n"
"4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Windows,\n"
"00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,\n"
"00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,\n"
"28040140000000000000504944564944,GamePad Pro USB,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,\n"
"ff113133000000000000504944564944,SVEN X-PAD,platform:Windows,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9,\n"
"8f0e0300000000000000504944564944,Piranha xtreme,platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,\n"
"8f0e0d31000000000000504944564944,Multilaser JS071 USB,platform:Windows,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,\n"
"10080300000000000000504944564944,PS2 USB,platform:Windows,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5,\n"
"79000600000000000000504944564944,G-Shark GS-GP702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftstick:a0,rightstick:a2,leftshoulder:a3,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:h0.6,lefty:h0.12,rightx:h0.9,righty:h0.4,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,y:b1,x:b0,start:b4,guide:b10,back:b5,leftstick:b8,rightstick:b9,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows,\n"
"4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,platform:Windows,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"6f0e1e01000000000000504944564944,Rock Candy Gamepad for PS3,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,\n"
"83056020000000000000504944564944,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Windows,\n"
"10080100000000000000504944564944,PS1 USB,platform:Windows,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,\n"
"49190204000000000000504944564944,Ipega PG-9023,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,platform:Windows,\n"
"4f0423b3000000000000504944564944,Dual Trigger 3-in-1,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"0d0f4900000000000000504944564944,Hatsune Miku Sho Controller,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"79004318000000000000504944564944,Mayflash GameCube Controller Adapter,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b0,start:b9,guide:b0,leftshoulder:b4,rightshoulder:b7,leftstick:b0,rightstick:b0,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,\n"
"79000018000000000000504944564944,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"2509e803000000000000504944564944,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"300f1001000000000000504944564944,Saitek P480 Rumble Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,platform:Windows,\n"
"10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,y:b3,x:b4,start:b11,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,platform:Windows,\n"
"63252305000000000000504944564944,USB Vibration Joystick (BM),platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"20380900000000000000504944564944,8Bitdo NES30 PRO Wireless,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
"02200090000000000000504944564944,8Bitdo NES30 PRO USB,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
"ff113133000000000000504944564944,Gembird JPD-DualForce,platform:Windows,a:b2,b:b3,x:b0,y:b1,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,leftstick:b10,rightstick:b11,\n"
"341a0108000000000000504944564944,EXEQ RF USB Gamepad 8206,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,leftstick:b8,rightstick:b7,back:b8,start:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows,\n"
"c0111352000000000000504944564944,Battalife Joystick,platform:Windows,x:b4,a:b6,b:b7,y:b5,back:b2,start:b3,leftshoulder:b0,rightshoulder:b1,leftx:a0,lefty:a1,\n"
"100801e5000000000000504944564944,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Windows,\n"
"79000600000000000000504944564944,NGS Phantom,a:b2,b:b3,y:b1,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,\n"
"6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n"
"6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n"
"6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n"
"6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n"
"4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,\n"
"4c05000000000000c405000000000000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X,\n"
"4c05000000000000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X,\n"
"5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n"
"891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Mac OS X,\n"
"4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Mac OS X,\n"
"8f0e0000000000000300000000000000,Piranha xtreme,platform:Mac OS X,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,\n"
"0d0f0000000000004d00000000000000,HORI Gem Pad 3,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,\n"
"79000000000000000600000000000000,G-Shark GP-702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,\n"
"4f0400000000000015b3000000000000,Thrustmaster Dual Analog 3.2,platform:Mac OS X,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"AD1B00000000000001F9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n"
"050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,y:b9,x:b10,start:b6,guide:b8,back:b7,dpup:b2,dpleft:b0,dpdown:b3,dpright:b1,leftx:a0,lefty:a1,lefttrigger:b12,righttrigger:,leftshoulder:b11,platform:Mac OS X,\n"
"83050000000000006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X,\n"
"bd1200000000000015d0000000000000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X,\n"
"79000000000000001100000000000000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a3,lefty:a4,platform:Mac OS X,\n"
"5e04000000000000dd02000000000000,Xbox One Wired Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"5e04000000000000ea02000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"5e04000000000000e002000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b10,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,x:b18,y:b17,back:b7,guide:b8,start:b6,leftstick:b23,rightstick:b24,leftshoulder:b19,rightshoulder:b20,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b21,righttrigger:b22,platform:Mac OS X,\n"
"79000000000000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,x:b0,y:b12,back:b32,start:b36,leftstick:b40,rightstick:b44,leftshoulder:b16,rightshoulder:b20,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a4,rightx:a8,righty:a12,lefttrigger:b24,righttrigger:b28,platform:Mac OS X,\n"
"2509000000000000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,\n"
"351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,\n"
"b4040000000000000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,x:b3,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,\n"
"81170000000000007e05000000000000,Sega Saturn,x:b0,a:b2,b:b4,y:b6,start:b13,dpleft:b15,dpdown:b16,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,lefttrigger:b10,rightshoulder:b9,righttrigger:a4,righttrigger:b11,leftx:a0,lefty:a2,platform:Mac OS X,\n"
"10280000000000000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,\n"
"d814000000000000cecf000000000000,MC Cthulhu,platform:Mac OS X,leftx:,lefty:,rightx:,righty:,lefttrigger:b6,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,righttrigger:b7,\n"
"0d0f0000000000006600000000000000,HORIPAD FPS PLUS 4,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:a4,\n"
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n"
"03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,\n"
"030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n"
"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,\n"
"030000006d04000016c2000011010000,Logitech F310 Gamepad (DInput),x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux,\n"
"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,\n"
"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,\n"
"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,\n"
"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,\n"
"030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,\n"
"050000004c050000c405000000010000,Sony DualShock 4 BT,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n"
"030000004c050000cc09000011010000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,\n"
"050000004c050000cc09000000010000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,\n"
"030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,\n"
"030000006f0e00003001000001010000,EA Sports PS3 Controller,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,\n"
"03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n"
"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,\n"
"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,\n"
"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,\n"
"03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux,\n"
"03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Linux,\n"
"030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux,\n"
"030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,\n"
"030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,\n"
"030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,\n"
"030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,\n"
"030000006d04000016c2000010010000,Logitech Logitech Dual Action,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Linux,\n"
"030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,platform:Linux,\n"
"030000006d04000018c2000010010000,Logitech Logitech RumblePad 2 USB,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"05000000d6200000ad0d000001000000,Moga Pro,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,\n"
"030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,\n"
"030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,\n"
"0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux,\n"
"0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux,\n"
"030000006f0e00001f01000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"03000000280400000140000000010000,Gravis GamePad Pro USB ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,\n"
"030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"030000005e0400008502000000010000,Microsoft X-Box pad (Japan),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,\n"
"03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,platform:Linux,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,\n"
"030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,\n"
"030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux,\n"
"03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,\n"
"060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux,\n"
"050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux,\n"
"03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick ,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a3,rightx:a1,righty:a4,\n"
"03000000666600000488000000010000,Super Joy Box 5 Pro,platform:Linux,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13,\n"
"05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,\n"
"05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,\n"
"030000008916000001fd000024010000,Razer Onza Classic Edition,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"030000005e040000d102000001010000,Microsoft X-Box One pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"030000005e040000dd02000003020000,Microsoft X-Box One pad v2,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux,\n"
"03000000790000001100000010010000,RetroLink Saturn Classic Controller,platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,\n"
"050000007e0500003003000001000000,Nintendo Wii U Pro Controller,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b8,start:b9,guide:b10,leftshoulder:b4,rightshoulder:b5,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:b13,dpleft:b15,dpdown:b14,dpright:b16,\n"
"030000005e0400008e02000004010000,Microsoft X-Box 360 pad,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,\n"
"030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,\n"
"030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7\n"
"03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b7,back:b6,guide:b8,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,lefttrigger:a5,righttrigger:a4,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux,\n"
"030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"030000006f0e00001304000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:a0,rightstick:a3,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux,\n"
"03000000bd12000015d0000010010000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux,\n"
"03000000790000001100000010010000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux,\n"
"03000000c9110000f055000011010000,HJC Game GAMEPAD,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:h0.8,lefttrigger:b6,x:b2,dpup:h0.1,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:h0.2,righttrigger:b7,b:b1,platform:Linux,\n"
"03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux,\n"
"03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,y:b3,x:b0,start:b9,guide:,back:,leftstick:,rightstick:,leftshoulder:,dpleft:b15,dpdown:b14,dpright:b13,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,rightshoulder:b7,dpup:b12,platform:Linux,\n"
"030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,platform:Linux,x:b0,a:b2,b:b3,y:b1,back:b10,guide:b12,start:b11,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,platform:Linux,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,guide:b8,leftstick:b9,rightstick:b10,lefttrigger:a2,righttrigger:a5,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux,\n"
"030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,platform:Linux,a:b0,b:b2,x:b1,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,\n"
"05000000102800000900000000010000,8Bitdo SFC30 GamePad,platform:Linux,x:b4,a:b1,b:b0,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,\n"
"03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,leftx:a0,lefty:a1,\n"
"030000000d0f00000d00000000010000,hori,platform:Linux,a:b0,b:b6,y:b2,x:b1,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,start:b9,guide:b10,back:b8,leftshoulder:b3,rightshoulder:b7,leftx:b4,lefty:b5,\n"
"03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,\n"
"03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,platform:Linux,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,\n"
"03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),platform:Linux,a:b3,b:b4,y:b1,x:b0,start:b7,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,\n"
"05000000010000000100000003000000,Nintendo Wiimote,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b9,guide:b10,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,\n"
"030000005e0400008e02000062230000,Microsoft X-Box 360 pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,y:b1,x:b0,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b6,righttrigger:b7,platform:Linux,\n"
"030000006f0e00000103000000020000,Logic3 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"05000000380700006652000025010000,Mad Catz C.T.R.L.R ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,lefttrigger:a2,righttrigger:a5,\n"
"05000000a00500003232000001000000,8Bitdo Zero GamePad,platform:Linux,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,\n"
"030000001008000001e5000010010000,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Linux,\n"
"03000000100800000300000010010000,USB Gamepad,platform:Linux,a:b2,b:b1,x:b3,y:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,\n"
"05000000ac0500003232000001000000,VR-BOX,platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,\n"
"03000000780000000600000010010000,Microntek USB Joystick,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftx:a0,lefty:a1,\n"
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,\n"
"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,\n"
"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,\n"
"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,\n"
"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,\n"
"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,\n"
"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,\n";
"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

@ -58,13 +58,16 @@
//
// 3. This notice may not be removed or altered from any source distribution.
const char* _glfwDefaultMappings =
const char* _glfwDefaultMappings[] =
{
@GLFW_GAMEPAD_MAPPINGS@
"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,\n"
"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,\n"
"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,\n"
"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,\n"
"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,\n"
"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,\n"
"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,\n";
"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,240 +0,0 @@
//========================================================================
// GLFW 3.3 Mir - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.com>
//
// 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"
#include <linux/input.h>
#include <stdlib.h>
#include <string.h>
// Create key code translation tables
//
static void createKeyTables(void)
{
int scancode;
memset(_glfw.mir.keycodes, -1, sizeof(_glfw.mir.keycodes));
memset(_glfw.mir.scancodes, -1, sizeof(_glfw.mir.scancodes));
_glfw.mir.keycodes[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
_glfw.mir.keycodes[KEY_1] = GLFW_KEY_1;
_glfw.mir.keycodes[KEY_2] = GLFW_KEY_2;
_glfw.mir.keycodes[KEY_3] = GLFW_KEY_3;
_glfw.mir.keycodes[KEY_4] = GLFW_KEY_4;
_glfw.mir.keycodes[KEY_5] = GLFW_KEY_5;
_glfw.mir.keycodes[KEY_6] = GLFW_KEY_6;
_glfw.mir.keycodes[KEY_7] = GLFW_KEY_7;
_glfw.mir.keycodes[KEY_8] = GLFW_KEY_8;
_glfw.mir.keycodes[KEY_9] = GLFW_KEY_9;
_glfw.mir.keycodes[KEY_0] = GLFW_KEY_0;
_glfw.mir.keycodes[KEY_SPACE] = GLFW_KEY_SPACE;
_glfw.mir.keycodes[KEY_MINUS] = GLFW_KEY_MINUS;
_glfw.mir.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL;
_glfw.mir.keycodes[KEY_Q] = GLFW_KEY_Q;
_glfw.mir.keycodes[KEY_W] = GLFW_KEY_W;
_glfw.mir.keycodes[KEY_E] = GLFW_KEY_E;
_glfw.mir.keycodes[KEY_R] = GLFW_KEY_R;
_glfw.mir.keycodes[KEY_T] = GLFW_KEY_T;
_glfw.mir.keycodes[KEY_Y] = GLFW_KEY_Y;
_glfw.mir.keycodes[KEY_U] = GLFW_KEY_U;
_glfw.mir.keycodes[KEY_I] = GLFW_KEY_I;
_glfw.mir.keycodes[KEY_O] = GLFW_KEY_O;
_glfw.mir.keycodes[KEY_P] = GLFW_KEY_P;
_glfw.mir.keycodes[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
_glfw.mir.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
_glfw.mir.keycodes[KEY_A] = GLFW_KEY_A;
_glfw.mir.keycodes[KEY_S] = GLFW_KEY_S;
_glfw.mir.keycodes[KEY_D] = GLFW_KEY_D;
_glfw.mir.keycodes[KEY_F] = GLFW_KEY_F;
_glfw.mir.keycodes[KEY_G] = GLFW_KEY_G;
_glfw.mir.keycodes[KEY_H] = GLFW_KEY_H;
_glfw.mir.keycodes[KEY_J] = GLFW_KEY_J;
_glfw.mir.keycodes[KEY_K] = GLFW_KEY_K;
_glfw.mir.keycodes[KEY_L] = GLFW_KEY_L;
_glfw.mir.keycodes[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
_glfw.mir.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
_glfw.mir.keycodes[KEY_Z] = GLFW_KEY_Z;
_glfw.mir.keycodes[KEY_X] = GLFW_KEY_X;
_glfw.mir.keycodes[KEY_C] = GLFW_KEY_C;
_glfw.mir.keycodes[KEY_V] = GLFW_KEY_V;
_glfw.mir.keycodes[KEY_B] = GLFW_KEY_B;
_glfw.mir.keycodes[KEY_N] = GLFW_KEY_N;
_glfw.mir.keycodes[KEY_M] = GLFW_KEY_M;
_glfw.mir.keycodes[KEY_COMMA] = GLFW_KEY_COMMA;
_glfw.mir.keycodes[KEY_DOT] = GLFW_KEY_PERIOD;
_glfw.mir.keycodes[KEY_SLASH] = GLFW_KEY_SLASH;
_glfw.mir.keycodes[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
_glfw.mir.keycodes[KEY_ESC] = GLFW_KEY_ESCAPE;
_glfw.mir.keycodes[KEY_TAB] = GLFW_KEY_TAB;
_glfw.mir.keycodes[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
_glfw.mir.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
_glfw.mir.keycodes[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
_glfw.mir.keycodes[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
_glfw.mir.keycodes[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
_glfw.mir.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
_glfw.mir.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
_glfw.mir.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
_glfw.mir.keycodes[KEY_MENU] = GLFW_KEY_MENU;
_glfw.mir.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
_glfw.mir.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
_glfw.mir.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
_glfw.mir.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
_glfw.mir.keycodes[KEY_PAUSE] = GLFW_KEY_PAUSE;
_glfw.mir.keycodes[KEY_DELETE] = GLFW_KEY_DELETE;
_glfw.mir.keycodes[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
_glfw.mir.keycodes[KEY_ENTER] = GLFW_KEY_ENTER;
_glfw.mir.keycodes[KEY_HOME] = GLFW_KEY_HOME;
_glfw.mir.keycodes[KEY_END] = GLFW_KEY_END;
_glfw.mir.keycodes[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
_glfw.mir.keycodes[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
_glfw.mir.keycodes[KEY_INSERT] = GLFW_KEY_INSERT;
_glfw.mir.keycodes[KEY_LEFT] = GLFW_KEY_LEFT;
_glfw.mir.keycodes[KEY_RIGHT] = GLFW_KEY_RIGHT;
_glfw.mir.keycodes[KEY_DOWN] = GLFW_KEY_DOWN;
_glfw.mir.keycodes[KEY_UP] = GLFW_KEY_UP;
_glfw.mir.keycodes[KEY_F1] = GLFW_KEY_F1;
_glfw.mir.keycodes[KEY_F2] = GLFW_KEY_F2;
_glfw.mir.keycodes[KEY_F3] = GLFW_KEY_F3;
_glfw.mir.keycodes[KEY_F4] = GLFW_KEY_F4;
_glfw.mir.keycodes[KEY_F5] = GLFW_KEY_F5;
_glfw.mir.keycodes[KEY_F6] = GLFW_KEY_F6;
_glfw.mir.keycodes[KEY_F7] = GLFW_KEY_F7;
_glfw.mir.keycodes[KEY_F8] = GLFW_KEY_F8;
_glfw.mir.keycodes[KEY_F9] = GLFW_KEY_F9;
_glfw.mir.keycodes[KEY_F10] = GLFW_KEY_F10;
_glfw.mir.keycodes[KEY_F11] = GLFW_KEY_F11;
_glfw.mir.keycodes[KEY_F12] = GLFW_KEY_F12;
_glfw.mir.keycodes[KEY_F13] = GLFW_KEY_F13;
_glfw.mir.keycodes[KEY_F14] = GLFW_KEY_F14;
_glfw.mir.keycodes[KEY_F15] = GLFW_KEY_F15;
_glfw.mir.keycodes[KEY_F16] = GLFW_KEY_F16;
_glfw.mir.keycodes[KEY_F17] = GLFW_KEY_F17;
_glfw.mir.keycodes[KEY_F18] = GLFW_KEY_F18;
_glfw.mir.keycodes[KEY_F19] = GLFW_KEY_F19;
_glfw.mir.keycodes[KEY_F20] = GLFW_KEY_F20;
_glfw.mir.keycodes[KEY_F21] = GLFW_KEY_F21;
_glfw.mir.keycodes[KEY_F22] = GLFW_KEY_F22;
_glfw.mir.keycodes[KEY_F23] = GLFW_KEY_F23;
_glfw.mir.keycodes[KEY_F24] = GLFW_KEY_F24;
_glfw.mir.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
_glfw.mir.keycodes[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
_glfw.mir.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
_glfw.mir.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
_glfw.mir.keycodes[KEY_KP0] = GLFW_KEY_KP_0;
_glfw.mir.keycodes[KEY_KP1] = GLFW_KEY_KP_1;
_glfw.mir.keycodes[KEY_KP2] = GLFW_KEY_KP_2;
_glfw.mir.keycodes[KEY_KP3] = GLFW_KEY_KP_3;
_glfw.mir.keycodes[KEY_KP4] = GLFW_KEY_KP_4;
_glfw.mir.keycodes[KEY_KP5] = GLFW_KEY_KP_5;
_glfw.mir.keycodes[KEY_KP6] = GLFW_KEY_KP_6;
_glfw.mir.keycodes[KEY_KP7] = GLFW_KEY_KP_7;
_glfw.mir.keycodes[KEY_KP8] = GLFW_KEY_KP_8;
_glfw.mir.keycodes[KEY_KP9] = GLFW_KEY_KP_9;
_glfw.mir.keycodes[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
_glfw.mir.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
_glfw.mir.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
for (scancode = 0; scancode < 256; scancode++)
{
if (_glfw.mir.keycodes[scancode] > 0)
_glfw.mir.scancodes[_glfw.mir.keycodes[scancode]] = scancode;
}
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformInit(void)
{
int error;
_glfw.mir.connection = mir_connect_sync(NULL, __PRETTY_FUNCTION__);
if (!mir_connection_is_valid(_glfw.mir.connection))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unable to connect to server: %s",
mir_connection_get_error_message(_glfw.mir.connection));
return GLFW_FALSE;
}
_glfw.mir.display =
mir_connection_get_egl_native_display(_glfw.mir.connection);
createKeyTables();
if (!_glfwInitJoysticksLinux())
return GLFW_FALSE;
_glfwInitTimerPOSIX();
_glfw.mir.eventQueue = calloc(1, sizeof(EventQueue));
_glfwInitEventQueueMir(_glfw.mir.eventQueue);
error = pthread_mutex_init(&_glfw.mir.eventMutex, NULL);
if (error)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Failed to create event mutex: %s",
strerror(error));
return GLFW_FALSE;
}
_glfwPollMonitorsMir();
return GLFW_TRUE;
}
void _glfwPlatformTerminate(void)
{
_glfwTerminateEGL();
_glfwTerminateJoysticksLinux();
_glfwDeleteEventQueueMir(_glfw.mir.eventQueue);
pthread_mutex_destroy(&_glfw.mir.eventMutex);
mir_connection_release(_glfw.mir.connection);
}
const char* _glfwPlatformGetVersionString(void)
{
return _GLFW_VERSION_NUMBER " Mir EGL"
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
" clock_gettime"
#else
" gettimeofday"
#endif
" evdev"
#if defined(_GLFW_BUILD_DLL)
" shared"
#endif
;
}

View File

@ -1,214 +0,0 @@
//========================================================================
// GLFW 3.3 Mir - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.com>
//
// 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"
#include <stdlib.h>
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Poll for changes in the set of connected monitors
//
void _glfwPollMonitorsMir(void)
{
int i;
MirDisplayConfig* displayConfig =
mir_connection_create_display_configuration(_glfw.mir.connection);
int numOutputs = mir_display_config_get_num_outputs(displayConfig);
for (i = 0; i < numOutputs; i++)
{
const MirOutput* output = mir_display_config_get_output(displayConfig, i);
MirOutputConnectionState state = mir_output_get_connection_state(output);
bool enabled = mir_output_is_enabled(output);
if (enabled && state == mir_output_connection_state_connected)
{
int widthMM = mir_output_get_physical_width_mm(output);
int heightMM = mir_output_get_physical_height_mm(output);
int x = mir_output_get_position_x(output);
int y = mir_output_get_position_y(output);
int id = mir_output_get_id(output);
size_t currentMode = mir_output_get_current_mode_index(output);
const char* name = mir_output_type_name(mir_output_get_type(output));
_GLFWmonitor* monitor = _glfwAllocMonitor(name,
widthMM,
heightMM);
monitor->mir.x = x;
monitor->mir.y = y;
monitor->mir.outputId = id;
monitor->mir.curMode = currentMode;
monitor->modes = _glfwPlatformGetVideoModes(monitor, &monitor->modeCount);
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
}
}
mir_display_config_release(displayConfig);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{
if (xpos)
*xpos = monitor->mir.x;
if (ypos)
*ypos = monitor->mir.y;
}
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
float* xscale, float* yscale)
{
if (xscale)
*xscale = 1.f;
if (yscale)
*yscale = 1.f;
}
static void FillInRGBBitsFromPixelFormat(GLFWvidmode* mode, const MirPixelFormat pf)
{
switch (pf)
{
case mir_pixel_format_rgb_565:
mode->redBits = 5;
mode->greenBits = 6;
mode->blueBits = 5;
break;
case mir_pixel_format_rgba_5551:
mode->redBits = 5;
mode->greenBits = 5;
mode->blueBits = 5;
break;
case mir_pixel_format_rgba_4444:
mode->redBits = 4;
mode->greenBits = 4;
mode->blueBits = 4;
break;
case mir_pixel_format_abgr_8888:
case mir_pixel_format_xbgr_8888:
case mir_pixel_format_argb_8888:
case mir_pixel_format_xrgb_8888:
case mir_pixel_format_bgr_888:
case mir_pixel_format_rgb_888:
default:
mode->redBits = 8;
mode->greenBits = 8;
mode->blueBits = 8;
break;
}
}
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
{
int i;
GLFWvidmode* modes = NULL;
MirDisplayConfig* displayConfig =
mir_connection_create_display_configuration(_glfw.mir.connection);
int numOutputs = mir_display_config_get_num_outputs(displayConfig);
for (i = 0; i < numOutputs; i++)
{
const MirOutput* output = mir_display_config_get_output(displayConfig, i);
int id = mir_output_get_id(output);
if (id != monitor->mir.outputId)
continue;
MirOutputConnectionState state = mir_output_get_connection_state(output);
bool enabled = mir_output_is_enabled(output);
// We must have been disconnected
if (!enabled || state != mir_output_connection_state_connected)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Monitor no longer connected");
return NULL;
}
int numModes = mir_output_get_num_modes(output);
modes = calloc(numModes, sizeof(GLFWvidmode));
for (*found = 0; *found < numModes; (*found)++)
{
const MirOutputMode* mode = mir_output_get_mode(output, *found);
int width = mir_output_mode_get_width(mode);
int height = mir_output_mode_get_height(mode);
double refreshRate = mir_output_mode_get_refresh_rate(mode);
MirPixelFormat currentFormat = mir_output_get_current_pixel_format(output);
modes[*found].width = width;
modes[*found].height = height;
modes[*found].refreshRate = refreshRate;
FillInRGBBitsFromPixelFormat(&modes[*found], currentFormat);
}
break;
}
mir_display_config_release(displayConfig);
return modes;
}
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
{
*mode = monitor->modes[monitor->mir.curMode];
}
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW native API //////
//////////////////////////////////////////////////////////////////////////
GLFWAPI int glfwGetMirMonitor(GLFWmonitor* handle)
{
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(0);
return monitor->mir.outputId;
}

View File

@ -1,133 +0,0 @@
//========================================================================
// GLFW 3.3 Mir - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.com>
//
// 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 <sys/queue.h>
#include <pthread.h>
#include <dlfcn.h>
#include <mir_toolkit/mir_client_library.h>
typedef VkFlags VkMirWindowCreateFlagsKHR;
typedef struct VkMirWindowCreateInfoKHR
{
VkStructureType sType;
const void* pNext;
VkMirWindowCreateFlagsKHR flags;
MirConnection* connection;
MirWindow* mirWindow;
} VkMirWindowCreateInfoKHR;
typedef VkResult (APIENTRY *PFN_vkCreateMirWindowKHR)(VkInstance,const VkMirWindowCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(VkPhysicalDevice,uint32_t,MirConnection*);
#include "posix_thread.h"
#include "posix_time.h"
#include "linux_joystick.h"
#include "xkb_unicode.h"
#include "egl_context.h"
#include "osmesa_context.h"
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle)
#define _glfw_dlsym(handle, name) dlsym(handle, name)
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->mir.nativeWindow)
#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.mir.display)
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowMir mir
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorMir mir
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryMir mir
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorMir mir
#define _GLFW_PLATFORM_CONTEXT_STATE
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
// Mir-specific Event Queue
//
typedef struct EventQueue
{
TAILQ_HEAD(, EventNode) head;
} EventQueue;
// Mir-specific per-window data
//
typedef struct _GLFWwindowMir
{
MirWindow* window;
int width;
int height;
MirEGLNativeWindowType nativeWindow;
_GLFWcursor* currentCursor;
} _GLFWwindowMir;
// Mir-specific per-monitor data
//
typedef struct _GLFWmonitorMir
{
int curMode;
int outputId;
int x;
int y;
} _GLFWmonitorMir;
// Mir-specific global data
//
typedef struct _GLFWlibraryMir
{
MirConnection* connection;
MirEGLNativeDisplayType display;
EventQueue* eventQueue;
short int keycodes[256];
short int scancodes[GLFW_KEY_LAST + 1];
pthread_mutex_t eventMutex;
pthread_cond_t eventCond;
// The window whose disabled cursor mode is active
_GLFWwindow* disabledCursorWindow;
} _GLFWlibraryMir;
// Mir-specific per-cursor data
// TODO: Only system cursors are implemented in Mir atm. Need to wait for support.
//
typedef struct _GLFWcursorMir
{
MirCursorConfiguration* conf;
MirBufferStream* customCursor;
char const* cursorName; // only needed for system cursors
} _GLFWcursorMir;
extern void _glfwPollMonitorsMir(void);
extern void _glfwInitEventQueueMir(EventQueue* queue);
extern void _glfwDeleteEventQueueMir(EventQueue* queue);

View File

@ -1,955 +0,0 @@
//========================================================================
// GLFW 3.3 Mir - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.com>
//
// 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"
#include <linux/input.h>
#include <stdlib.h>
#include <string.h>
typedef struct EventNode
{
TAILQ_ENTRY(EventNode) entries;
const MirEvent* event;
_GLFWwindow* window;
} EventNode;
static void deleteNode(EventQueue* queue, EventNode* node)
{
mir_event_unref(node->event);
free(node);
}
static GLFWbool emptyEventQueue(EventQueue* queue)
{
return queue->head.tqh_first == NULL;
}
// TODO The mir_event_ref is not supposed to be used but ... its needed
// in this case. Need to wait until we can read from an FD set up by mir
// for single threaded event handling.
static EventNode* newEventNode(const MirEvent* event, _GLFWwindow* context)
{
EventNode* newNode = calloc(1, sizeof(EventNode));
newNode->event = mir_event_ref(event);
newNode->window = context;
return newNode;
}
static void enqueueEvent(const MirEvent* event, _GLFWwindow* context)
{
pthread_mutex_lock(&_glfw.mir.eventMutex);
EventNode* newNode = newEventNode(event, context);
TAILQ_INSERT_TAIL(&_glfw.mir.eventQueue->head, newNode, entries);
pthread_cond_signal(&_glfw.mir.eventCond);
pthread_mutex_unlock(&_glfw.mir.eventMutex);
}
static EventNode* dequeueEvent(EventQueue* queue)
{
EventNode* node = NULL;
pthread_mutex_lock(&_glfw.mir.eventMutex);
node = queue->head.tqh_first;
if (node)
TAILQ_REMOVE(&queue->head, node, entries);
pthread_mutex_unlock(&_glfw.mir.eventMutex);
return node;
}
static MirPixelFormat findValidPixelFormat(void)
{
unsigned int i, validFormats, mirPixelFormats = 32;
MirPixelFormat formats[mir_pixel_formats];
mir_connection_get_available_surface_formats(_glfw.mir.connection, formats,
mirPixelFormats, &validFormats);
for (i = 0; i < validFormats; i++)
{
if (formats[i] == mir_pixel_format_abgr_8888 ||
formats[i] == mir_pixel_format_xbgr_8888 ||
formats[i] == mir_pixel_format_argb_8888 ||
formats[i] == mir_pixel_format_xrgb_8888)
{
return formats[i];
}
}
return mir_pixel_format_invalid;
}
static int mirModToGLFWMod(uint32_t mods)
{
int publicMods = 0x0;
if (mods & mir_input_event_modifier_alt)
publicMods |= GLFW_MOD_ALT;
else if (mods & mir_input_event_modifier_shift)
publicMods |= GLFW_MOD_SHIFT;
else if (mods & mir_input_event_modifier_ctrl)
publicMods |= GLFW_MOD_CONTROL;
else if (mods & mir_input_event_modifier_meta)
publicMods |= GLFW_MOD_SUPER;
return publicMods;
}
static int toGLFWKeyCode(uint32_t key)
{
if (key < sizeof(_glfw.mir.keycodes) / sizeof(_glfw.mir.keycodes[0]))
return _glfw.mir.keycodes[key];
return GLFW_KEY_UNKNOWN;
}
static void handleKeyEvent(const MirKeyboardEvent* key_event, _GLFWwindow* window)
{
const int action = mir_keyboard_event_action (key_event);
const int scan_code = mir_keyboard_event_scan_code(key_event);
const int key_code = mir_keyboard_event_key_code (key_event);
const int modifiers = mir_keyboard_event_modifiers(key_event);
const int pressed = action == mir_keyboard_action_up ? GLFW_RELEASE : GLFW_PRESS;
const int mods = mirModToGLFWMod(modifiers);
const long text = _glfwKeySym2Unicode(key_code);
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
_glfwInputKey(window, toGLFWKeyCode(scan_code), scan_code, pressed, mods);
if (text != -1)
_glfwInputChar(window, text, mods, plain);
}
static void handlePointerButton(_GLFWwindow* window,
int pressed,
const MirPointerEvent* pointer_event)
{
int mods = mir_pointer_event_modifiers(pointer_event);
const int publicMods = mirModToGLFWMod(mods);
MirPointerButton button = mir_pointer_button_primary;
static uint32_t oldButtonStates = 0;
uint32_t newButtonStates = mir_pointer_event_buttons(pointer_event);
int publicButton = GLFW_MOUSE_BUTTON_LEFT;
// XOR our old button states our new states to figure out what was added or removed
button = newButtonStates ^ oldButtonStates;
switch (button)
{
case mir_pointer_button_primary:
publicButton = GLFW_MOUSE_BUTTON_LEFT;
break;
case mir_pointer_button_secondary:
publicButton = GLFW_MOUSE_BUTTON_RIGHT;
break;
case mir_pointer_button_tertiary:
publicButton = GLFW_MOUSE_BUTTON_MIDDLE;
break;
case mir_pointer_button_forward:
// FIXME What is the forward button?
publicButton = GLFW_MOUSE_BUTTON_4;
break;
case mir_pointer_button_back:
// FIXME What is the back button?
publicButton = GLFW_MOUSE_BUTTON_5;
break;
default:
break;
}
oldButtonStates = newButtonStates;
_glfwInputMouseClick(window, publicButton, pressed, publicMods);
}
static void handlePointerMotion(_GLFWwindow* window,
const MirPointerEvent* pointer_event)
{
const int hscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll);
const int vscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll);
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
if (_glfw.mir.disabledCursorWindow != window)
return;
const int dx = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_x);
const int dy = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_y);
const int current_x = window->virtualCursorPosX;
const int current_y = window->virtualCursorPosY;
_glfwInputCursorPos(window, dx + current_x, dy + current_y);
}
else
{
const int x = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_x);
const int y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y);
_glfwInputCursorPos(window, x, y);
}
if (hscroll != 0 || vscroll != 0)
_glfwInputScroll(window, hscroll, vscroll);
}
static void handlePointerEvent(const MirPointerEvent* pointer_event,
_GLFWwindow* window)
{
int action = mir_pointer_event_action(pointer_event);
switch (action)
{
case mir_pointer_action_button_down:
handlePointerButton(window, GLFW_PRESS, pointer_event);
break;
case mir_pointer_action_button_up:
handlePointerButton(window, GLFW_RELEASE, pointer_event);
break;
case mir_pointer_action_motion:
handlePointerMotion(window, pointer_event);
break;
case mir_pointer_action_enter:
case mir_pointer_action_leave:
break;
default:
break;
}
}
static void handleInput(const MirInputEvent* input_event, _GLFWwindow* window)
{
int type = mir_input_event_get_type(input_event);
switch (type)
{
case mir_input_event_type_key:
handleKeyEvent(mir_input_event_get_keyboard_event(input_event), window);
break;
case mir_input_event_type_pointer:
handlePointerEvent(mir_input_event_get_pointer_event(input_event), window);
break;
default:
break;
}
}
static void handleEvent(const MirEvent* event, _GLFWwindow* window)
{
int type = mir_event_get_type(event);
switch (type)
{
case mir_event_type_input:
handleInput(mir_event_get_input_event(event), window);
break;
default:
break;
}
}
static void addNewEvent(MirWindow* window, const MirEvent* event, void* context)
{
enqueueEvent(event, context);
}
static GLFWbool createWindow(_GLFWwindow* window)
{
MirWindowSpec* spec;
MirBufferUsage buffer_usage = mir_buffer_usage_hardware;
MirPixelFormat pixel_format = findValidPixelFormat();
if (pixel_format == mir_pixel_format_invalid)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unable to find a correct pixel format");
return GLFW_FALSE;
}
spec = mir_create_normal_window_spec(_glfw.mir.connection,
window->mir.width,
window->mir.height);
mir_window_spec_set_pixel_format(spec, pixel_format);
mir_window_spec_set_buffer_usage(spec, buffer_usage);
window->mir.window = mir_create_window_sync(spec);
mir_window_spec_release(spec);
if (!mir_window_is_valid(window->mir.window))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unable to create window: %s",
mir_window_get_error_message(window->mir.window));
return GLFW_FALSE;
}
mir_window_set_event_handler(window->mir.window, addNewEvent, window);
return GLFW_TRUE;
}
static void setWindowConfinement(_GLFWwindow* window, MirPointerConfinementState state)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_pointer_confinement(spec, state);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
void _glfwInitEventQueueMir(EventQueue* queue)
{
TAILQ_INIT(&queue->head);
}
void _glfwDeleteEventQueueMir(EventQueue* queue)
{
if (queue)
{
EventNode* node, *node_next;
node = queue->head.tqh_first;
while (node != NULL)
{
node_next = node->entries.tqe_next;
TAILQ_REMOVE(&queue->head, node, entries);
deleteNode(queue, node);
node = node_next;
}
free(queue);
}
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformCreateWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
if (window->monitor)
{
GLFWvidmode mode;
_glfwPlatformGetVideoMode(window->monitor, &mode);
mir_window_set_state(window->mir.window, mir_window_state_fullscreen);
if (wndconfig->width > mode.width || wndconfig->height > mode.height)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Requested window size too large: %ix%i",
wndconfig->width, wndconfig->height);
return GLFW_FALSE;
}
}
window->mir.width = wndconfig->width;
window->mir.height = wndconfig->height;
window->mir.currentCursor = NULL;
if (!createWindow(window))
return GLFW_FALSE;
window->mir.nativeWindow = mir_buffer_stream_get_egl_native_window(
mir_window_get_buffer_stream(window->mir.window));
if (ctxconfig->client != GLFW_NO_API)
{
if (ctxconfig->source == GLFW_EGL_CONTEXT_API ||
ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
{
if (!_glfwInitEGL())
return GLFW_FALSE;
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
{
if (!_glfwInitOSMesa())
return GLFW_FALSE;
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
}
return GLFW_TRUE;
}
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
{
if (_glfw.mir.disabledCursorWindow == window)
_glfw.mir.disabledCursorWindow = NULL;
if (mir_window_is_valid(window->mir.window))
{
mir_window_release_sync(window->mir.window);
window->mir.window= NULL;
}
if (window->context.destroy)
window->context.destroy(window);
}
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_name(spec, title);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
int count, const GLFWimage* images)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_width (spec, width);
mir_window_spec_set_height(spec, height);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
int minwidth, int minheight,
int maxwidth, int maxheight)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_max_width (spec, maxwidth);
mir_window_spec_set_max_height(spec, maxheight);
mir_window_spec_set_min_width (spec, minwidth);
mir_window_spec_set_min_height(spec, minheight);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
int* left, int* top,
int* right, int* bottom)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
{
if (width)
*width = window->mir.width;
if (height)
*height = window->mir.height;
}
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
float* xscale, float* yscale)
{
if (xscale)
*xscale = 1.f;
if (yscale)
*yscale = 1.f;
}
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_state(spec, mir_window_state_minimized);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_state(spec, mir_window_state_restored);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_state(spec, mir_window_state_maximized);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformHideWindow(_GLFWwindow* window)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_state(spec, mir_window_state_hidden);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformShowWindow(_GLFWwindow* window)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_state(spec, mir_window_state_restored);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformFocusWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
int _glfwPlatformWindowFocused(_GLFWwindow* window)
{
return mir_window_get_focus_state(window->mir.window) == mir_window_focus_state_focused;
}
int _glfwPlatformWindowIconified(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return GLFW_FALSE;
}
int _glfwPlatformWindowVisible(_GLFWwindow* window)
{
return mir_window_get_visibility(window->mir.window) == mir_window_visibility_exposed;
}
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
{
return mir_window_get_state(window->mir.window) == mir_window_state_maximized;
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return GLFW_FALSE;
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformPollEvents(void)
{
EventNode* node = NULL;
while ((node = dequeueEvent(_glfw.mir.eventQueue)))
{
handleEvent(node->event, node->window);
deleteNode(_glfw.mir.eventQueue, node);
}
}
void _glfwPlatformWaitEvents(void)
{
pthread_mutex_lock(&_glfw.mir.eventMutex);
while (emptyEventQueue(_glfw.mir.eventQueue))
pthread_cond_wait(&_glfw.mir.eventCond, &_glfw.mir.eventMutex);
pthread_mutex_unlock(&_glfw.mir.eventMutex);
_glfwPlatformPollEvents();
}
void _glfwPlatformWaitEventsTimeout(double timeout)
{
pthread_mutex_lock(&_glfw.mir.eventMutex);
if (emptyEventQueue(_glfw.mir.eventQueue))
{
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
time.tv_sec += (long) timeout;
time.tv_nsec += (long) ((timeout - (long) timeout) * 1e9);
pthread_cond_timedwait(&_glfw.mir.eventCond, &_glfw.mir.eventMutex, &time);
}
pthread_mutex_unlock(&_glfw.mir.eventMutex);
_glfwPlatformPollEvents();
}
void _glfwPlatformPostEmptyEvent(void)
{
}
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
{
if (width)
*width = window->mir.width;
if (height)
*height = window->mir.height;
}
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
const GLFWimage* image,
int xhot, int yhot)
{
MirBufferStream* stream;
int i_w = image->width;
int i_h = image->height;
stream = mir_connection_create_buffer_stream_sync(_glfw.mir.connection,
i_w, i_h,
mir_pixel_format_argb_8888,
mir_buffer_usage_software);
cursor->mir.conf = mir_cursor_configuration_from_buffer_stream(stream, xhot, yhot);
MirGraphicsRegion region;
mir_buffer_stream_get_graphics_region(stream, &region);
unsigned char* pixels = image->pixels;
char* dest = region.vaddr;
int i;
for (i = 0; i < i_w * i_h; i++, pixels += 4)
{
unsigned int alpha = pixels[3];
*dest++ = (char)(pixels[2] * alpha / 255);
*dest++ = (char)(pixels[1] * alpha / 255);
*dest++ = (char)(pixels[0] * alpha / 255);
*dest++ = (char)alpha;
}
mir_buffer_stream_swap_buffers_sync(stream);
cursor->mir.customCursor = stream;
return GLFW_TRUE;
}
static const char* getSystemCursorName(int shape)
{
switch (shape)
{
case GLFW_ARROW_CURSOR:
return mir_arrow_cursor_name;
case GLFW_IBEAM_CURSOR:
return mir_caret_cursor_name;
case GLFW_CROSSHAIR_CURSOR:
return mir_crosshair_cursor_name;
case GLFW_HAND_CURSOR:
return mir_open_hand_cursor_name;
case GLFW_HRESIZE_CURSOR:
return mir_horizontal_resize_cursor_name;
case GLFW_VRESIZE_CURSOR:
return mir_vertical_resize_cursor_name;
}
return NULL;
}
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
{
cursor->mir.conf = NULL;
cursor->mir.customCursor = NULL;
cursor->mir.cursorName = getSystemCursorName(shape);
return cursor->mir.cursorName != NULL;
}
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
{
if (cursor->mir.conf)
mir_cursor_configuration_destroy(cursor->mir.conf);
if (cursor->mir.customCursor)
mir_buffer_stream_release_sync(cursor->mir.customCursor);
}
static void setCursorNameForWindow(MirWindow* window, char const* name)
{
MirWindowSpec* spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_cursor_name(spec, name);
mir_window_apply_spec(window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{
if (cursor)
{
window->mir.currentCursor = cursor;
if (cursor->mir.cursorName)
{
setCursorNameForWindow(window->mir.window, cursor->mir.cursorName);
}
else if (cursor->mir.conf)
{
mir_window_configure_cursor(window->mir.window, cursor->mir.conf);
}
}
else
{
setCursorNameForWindow(window->mir.window, mir_default_cursor_name);
}
}
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{
if (mode == GLFW_CURSOR_DISABLED)
{
_glfw.mir.disabledCursorWindow = window;
setWindowConfinement(window, mir_pointer_confined_to_window);
setCursorNameForWindow(window->mir.window, mir_disabled_cursor_name);
}
else
{
// If we were disabled before lets undo that!
if (_glfw.mir.disabledCursorWindow == window)
{
_glfw.mir.disabledCursorWindow = NULL;
setWindowConfinement(window, mir_pointer_unconfined);
}
if (window->cursorMode == GLFW_CURSOR_NORMAL)
{
_glfwPlatformSetCursor(window, window->mir.currentCursor);
}
else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
{
setCursorNameForWindow(window->mir.window, mir_disabled_cursor_name);
}
}
}
const char* _glfwPlatformGetScancodeName(int scancode)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return NULL;
}
int _glfwPlatformGetKeyScancode(int key)
{
return _glfw.mir.scancodes[key];
}
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return NULL;
}
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
{
if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_mir_surface)
return;
extensions[0] = "VK_KHR_surface";
extensions[1] = "VK_KHR_mir_surface";
}
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device,
uint32_t queuefamily)
{
PFN_vkGetPhysicalDeviceMirPresentationSupportKHR
vkGetPhysicalDeviceMirPresentationSupportKHR =
(PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
if (!vkGetPhysicalDeviceMirPresentationSupportKHR)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"Mir: Vulkan instance missing VK_KHR_mir_surface extension");
return GLFW_FALSE;
}
return vkGetPhysicalDeviceMirPresentationSupportKHR(device,
queuefamily,
_glfw.mir.connection);
}
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
_GLFWwindow* window,
const VkAllocationCallbacks* allocator,
VkSurfaceKHR* surface)
{
VkResult err;
VkMirWindowCreateInfoKHR sci;
PFN_vkCreateMirWindowKHR vkCreateMirWindowKHR;
vkCreateMirWindowKHR = (PFN_vkCreateMirWindowKHR)
vkGetInstanceProcAddr(instance, "vkCreateMirWindowKHR");
if (!vkCreateMirWindowKHR)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"Mir: Vulkan instance missing VK_KHR_mir_surface extension");
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
memset(&sci, 0, sizeof(sci));
sci.sType = VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR;
sci.connection = _glfw.mir.connection;
sci.mirWindow = window->mir.window;
err = vkCreateMirWindowKHR(instance, &sci, allocator, surface);
if (err)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Failed to create Vulkan surface: %s",
_glfwGetVulkanResultString(err));
}
return err;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW native API //////
//////////////////////////////////////////////////////////////////////////
GLFWAPI MirConnection* glfwGetMirDisplay(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return _glfw.mir.connection;
}
GLFWAPI MirWindow* glfwGetMirWindow(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return window->mir.window;
}

View File

@ -86,6 +86,8 @@ static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
////// GLFW event API //////
//////////////////////////////////////////////////////////////////////////
// Notifies shared code of a monitor connection or disconnection
//
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
{
if (action == GLFW_CONNECTED)
@ -113,9 +115,11 @@ void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
{
if (window->monitor == monitor)
{
int width, height;
int width, height, xoff, yoff;
_glfwPlatformGetWindowSize(window, &width, &height);
_glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0);
_glfwPlatformGetWindowFrameSize(window, &xoff, &yoff, NULL, NULL);
_glfwPlatformSetWindowPos(window, xoff, yoff);
}
}
@ -139,6 +143,9 @@ void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
_glfwFreeMonitor(monitor);
}
// Notifies shared code that a full screen window has acquired or released
// a monitor
//
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
{
monitor->window = window;
@ -149,6 +156,8 @@ void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
////// 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* monitor = calloc(1, sizeof(_GLFWmonitor));
@ -156,16 +165,20 @@ _GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
monitor->heightMM = heightMM;
if (name)
monitor->name = strdup(name);
monitor->name = _glfw_strdup(name);
return monitor;
}
// Frees a monitor object and any data associated with it
//
void _glfwFreeMonitor(_GLFWmonitor* monitor)
{
if (monitor == NULL)
return;
_glfwPlatformFreeMonitor(monitor);
_glfwFreeGammaArrays(&monitor->originalRamp);
_glfwFreeGammaArrays(&monitor->currentRamp);
@ -174,6 +187,8 @@ void _glfwFreeMonitor(_GLFWmonitor* monitor)
free(monitor);
}
// Allocates red, green and blue value arrays of the specified size
//
void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size)
{
ramp->red = calloc(size, sizeof(unsigned short));
@ -182,6 +197,8 @@ void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size)
ramp->size = size;
}
// Frees the red, green and blue value arrays and clears the struct
//
void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
{
free(ramp->red);
@ -191,6 +208,8 @@ void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
memset(ramp, 0, sizeof(GLFWgammaramp));
}
// Chooses the video mode most closely matching the desired one
//
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
const GLFWvidmode* desired)
{
@ -241,11 +260,15 @@ const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
return closest;
}
// Performs lexical comparison between two @ref GLFWvidmode structures
//
int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* 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)
{
int delta;
@ -349,6 +372,24 @@ GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
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)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
@ -404,16 +445,16 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
for (i = 0; i < 256; i++)
{
double value;
float value;
// Calculate intensity
value = i / 255.0;
value = i / 255.f;
// 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
if (value > 65535.0)
value = 65535.0;
if (value > 65535.f)
value = 65535.f;
values[i] = (unsigned short) value;
}

View File

@ -175,7 +175,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
// Info.plist for unbundled applications
// HACK: This assumes that NSOpenGLPixelFormat will remain
// a straightforward wrapper of its CGL counterpart
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 100800
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
addAttrib(kCGLPFASupportsAutomaticGraphicsSwitching);
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
}

View File

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

View File

@ -165,6 +165,11 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return GLFW_FALSE;
}
int _glfwPlatformWindowHovered(_GLFWwindow* window)
{
return GLFW_FALSE;
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{
return GLFW_FALSE;
@ -182,6 +187,15 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
{
}
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
{
return 1.f;
}
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
{
}
void _glfwPlatformShowWindow(_GLFWwindow* window)
{
}
@ -266,11 +280,11 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{
}
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
void _glfwPlatformSetClipboardString(const char* string)
{
}
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
const char* _glfwPlatformGetClipboardString(void)
{
return NULL;
}

View File

@ -37,7 +37,7 @@
#define OSMESA_CONTEXT_MINOR_VERSION 0x37
typedef void* OSMesaContext;
typedef void (*OSMESAproc)();
typedef void (*OSMESAproc)(void);
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextExt)(GLenum,GLint,GLint,GLint,OSMesaContext);
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextAttribs)(const int*,OSMesaContext);

View File

@ -54,7 +54,7 @@ GLFWbool _glfwInitVulkan(int mode)
#elif defined(_GLFW_WIN32)
_glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
#elif defined(_GLFW_COCOA)
_glfw.vk.handle = _glfw_dlopen("libMoltenVK.dylib");
_glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
#else
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
#endif
@ -136,9 +136,6 @@ GLFWbool _glfwInitVulkan(int mode)
#elif defined(_GLFW_WAYLAND)
else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
_glfw.vk.KHR_wayland_surface = GLFW_TRUE;
#elif defined(_GLFW_MIR)
else if (strcmp(ep[i].extensionName, "VK_KHR_mir_surface") == 0)
_glfw.vk.KHR_mir_surface = GLFW_TRUE;
#endif
}
@ -317,6 +314,13 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
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);
}

View File

@ -256,13 +256,21 @@ static void makeContextCurrentWGL(_GLFWwindow* window)
static void swapBuffersWGL(_GLFWwindow* window)
{
if (!window->monitor)
{
if (IsWindowsVistaOrGreater())
{
BOOL enabled;
// HACK: Use DwmFlush when desktop composition is enabled
if (_glfwIsCompositionEnabledWin32() && !window->monitor)
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
{
int count = abs(window->context.wgl.interval);
while (count--)
DwmFlush();
}
}
}
SwapBuffers(window->context.wgl.dc);
}
@ -273,10 +281,18 @@ static void swapIntervalWGL(int interval)
window->context.wgl.interval = interval;
if (!window->monitor)
{
if (IsWindowsVistaOrGreater())
{
BOOL enabled;
// HACK: Disable WGL swap interval when desktop composition is enabled to
// avoid interfering with DWM vsync
if (_glfwIsCompositionEnabledWin32() && !window->monitor)
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
interval = 0;
}
}
if (_glfw.wgl.EXT_swap_control)
_glfw.wgl.SwapIntervalEXT(interval);
@ -284,29 +300,17 @@ static void swapIntervalWGL(int interval)
static int extensionSupportedWGL(const char* extension)
{
const char* extensions;
if (_glfw.wgl.GetExtensionsStringEXT)
{
extensions = _glfw.wgl.GetExtensionsStringEXT();
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
}
const char* extensions = NULL;
if (_glfw.wgl.GetExtensionsStringARB)
{
extensions = _glfw.wgl.GetExtensionsStringARB(wglGetCurrentDC());
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
}
else if (_glfw.wgl.GetExtensionsStringEXT)
extensions = _glfw.wgl.GetExtensionsStringEXT();
if (!extensions)
return GLFW_FALSE;
return _glfwStringInExtensionString(extension, extensions);
}
static GLFWglproc getProcAddressWGL(const char* procname)
@ -329,21 +333,52 @@ static void destroyContextWGL(_GLFWwindow* window)
}
}
// Initialize WGL-specific extensions
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Initialize WGL
//
static void loadWGLExtensions(void)
GLFWbool _glfwInitWGL(void)
{
PIXELFORMATDESCRIPTOR pfd;
HGLRC rc;
HDC dc = GetDC(_glfw.win32.helperWindowHandle);;
HGLRC prc, rc;
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
// OpenGL ICD, from which we can then query WGL extensions
// NOTE: This code will accept the Microsoft GDI ICD; accelerated context
// creation failure occurs during manual pixel format enumeration
dc = GetDC(_glfw.win32.helperWindowHandle);;
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
@ -355,7 +390,7 @@ static void loadWGLExtensions(void)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to set pixel format for dummy context");
return;
return GLFW_FALSE;
}
rc = wglCreateContext(dc);
@ -363,15 +398,19 @@ static void loadWGLExtensions(void)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to create dummy context");
return;
return GLFW_FALSE;
}
pdc = wglGetCurrentDC();
prc = wglGetCurrentContext();
if (!wglMakeCurrent(dc, rc))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to make dummy context current");
wglMakeCurrent(pdc, prc);
wglDeleteContext(rc);
return;
return GLFW_FALSE;
}
// NOTE: Functions must be loaded first as they're needed to retrieve the
@ -414,43 +453,8 @@ static void loadWGLExtensions(void)
_glfw.wgl.ARB_context_flush_control =
extensionSupportedWGL("WGL_ARB_context_flush_control");
wglMakeCurrent(dc, NULL);
wglMakeCurrent(pdc, prc);
wglDeleteContext(rc);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Initialize WGL
//
GLFWbool _glfwInitWGL(void)
{
if (_glfw.wgl.instance)
return GLFW_TRUE;
_glfw.wgl.instance = LoadLibraryA("opengl32.dll");
if (!_glfw.wgl.instance)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to load opengl32.dll");
return GLFW_FALSE;
}
_glfw.wgl.CreateContext = (PFN_wglCreateContext)
GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
_glfw.wgl.DeleteContext = (PFN_wglDeleteContext)
GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
_glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress)
GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
_glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC)
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
_glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent)
GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
_glfw.wgl.ShareLists = (PFN_wglShareLists)
GetProcAddress(_glfw.wgl.instance, "wglShareLists");
return GLFW_TRUE;
}
@ -480,9 +484,6 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
PIXELFORMATDESCRIPTOR pfd;
HGLRC share = NULL;
if (!_glfw.wgl.extensionsLoaded)
loadWGLExtensions();
if (ctxconfig->share)
share = ctxconfig->share->context.wgl.handle;

View File

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

View File

@ -62,17 +62,6 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
#endif // _GLFW_BUILD_DLL
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
BOOL IsWindowsVersionOrGreater(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);
return VerifyVersionInfoW(&osvi, mask, cond);
}
// Load necessary libraries (DLLs)
//
static GLFWbool loadLibraries(void)
@ -100,6 +89,14 @@ static GLFWbool loadLibraries(void)
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");
_glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_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");
if (_glfw.win32.dinput8.instance)
@ -155,6 +152,13 @@ static GLFWbool loadLibraries(void)
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;
}
@ -179,6 +183,9 @@ static void freeLibraries(void)
if (_glfw.win32.shcore.instance)
FreeLibrary(_glfw.win32.shcore.instance);
if (_glfw.win32.ntdll.instance)
FreeLibrary(_glfw.win32.ntdll.instance);
}
// Create key code translation tables
@ -309,6 +316,7 @@ static void createKeyTables(void)
_glfw.win32.keycodes[0x053] = GLFW_KEY_KP_DECIMAL;
_glfw.win32.keycodes[0x135] = GLFW_KEY_KP_DIVIDE;
_glfw.win32.keycodes[0x11C] = GLFW_KEY_KP_ENTER;
_glfw.win32.keycodes[0x059] = GLFW_KEY_KP_EQUAL;
_glfw.win32.keycodes[0x037] = GLFW_KEY_KP_MULTIPLY;
_glfw.win32.keycodes[0x04A] = GLFW_KEY_KP_SUBTRACT;
@ -339,8 +347,8 @@ static HWND createHelperWindow(void)
return NULL;
}
// HACK: The first call to ShowWindow is ignored if the parent process
// passed along a STARTUPINFO, so clear that flag with a no-op call
// HACK: The command to the first ShowWindow call is ignored if the parent
// process passed along a STARTUPINFO, so clear that with a no-op call
ShowWindow(window, SW_HIDE);
// Register for HID device notifications
@ -351,6 +359,7 @@ static HWND createHelperWindow(void)
dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
dbi.dbcc_classguid = GUID_DEVINTERFACE_HID;
_glfw.win32.deviceNotificationHandle =
RegisterDeviceNotificationW(window,
(DEV_BROADCAST_HDR*) &dbi,
DEVICE_NOTIFY_WINDOW_HANDLE);
@ -501,6 +510,36 @@ void _glfwUpdateKeyNamesWin32(void)
}
}
// 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 embedd 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 embedd a non-default manifest
// announcing support for Windows 10 via supportedOS GUID
return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
@ -522,7 +561,9 @@ int _glfwPlatformInit(void)
createKeyTables();
_glfwUpdateKeyNamesWin32();
if (IsWindows8Point1OrGreater())
if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
else if (IsWindows8Point1OrGreater())
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
else if (IsWindowsVistaOrGreater())
SetProcessDPIAware();
@ -543,6 +584,9 @@ int _glfwPlatformInit(void)
void _glfwPlatformTerminate(void)
{
if (_glfw.win32.deviceNotificationHandle)
UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
if (_glfw.win32.helperWindowHandle)
DestroyWindow(_glfw.win32.helperWindowHandle);

View File

@ -711,9 +711,9 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
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, 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, 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);

View File

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

View File

@ -67,11 +67,6 @@
#include <xinput.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
#ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x020E
@ -103,14 +98,19 @@
#ifndef _WIN32_WINNT_WINBLUE
#define _WIN32_WINNT_WINBLUE 0x0602
#endif
#ifndef WM_GETDPISCALEDSIZE
#define WM_GETDPISCALEDSIZE 0x02e4
#endif
#ifndef USER_DEFAULT_SCREEN_DPI
#define USER_DEFAULT_SCREEN_DPI 96
#endif
#if WINVER < 0x0601
typedef struct tagCHANGEFILTERSTRUCT
typedef struct
{
DWORD cbSize;
DWORD ExtStatus;
} CHANGEFILTERSTRUCT, *PCHANGEFILTERSTRUCT;
} CHANGEFILTERSTRUCT;
#ifndef MSGFLT_ALLOW
#define MSGFLT_ALLOW 1
#endif
@ -126,16 +126,18 @@ typedef struct
HRGN hRgnBlur;
BOOL fTransitionOnMaximized;
} DWM_BLURBEHIND;
#else
#include <dwmapi.h>
#endif /*Windows Vista*/
#ifndef DPI_ENUMS_DECLARED
typedef enum PROCESS_DPI_AWARENESS
typedef enum
{
PROCESS_DPI_UNAWARE = 0,
PROCESS_SYSTEM_DPI_AWARE = 1,
PROCESS_PER_MONITOR_DPI_AWARE = 2
} PROCESS_DPI_AWARENESS;
typedef enum MONITOR_DPI_TYPE
typedef enum
{
MDT_EFFECTIVE_DPI = 0,
MDT_ANGULAR_DPI = 1,
@ -144,21 +146,32 @@ typedef enum MONITOR_DPI_TYPE
} MONITOR_DPI_TYPE;
#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
BOOL IsWindowsVersionOrGreater(WORD major, WORD minor, WORD sp);
#define IsWindowsXPOrGreater() \
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINXP), \
LOBYTE(_WIN32_WINNT_WINXP), 0)
#define IsWindowsVistaOrGreater() \
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), \
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_VISTA), \
LOBYTE(_WIN32_WINNT_VISTA), 0)
#define IsWindows7OrGreater() \
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), \
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN7), \
LOBYTE(_WIN32_WINNT_WIN7), 0)
#define IsWindows8OrGreater() \
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), \
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN8), \
LOBYTE(_WIN32_WINNT_WIN8), 0)
#define IsWindows8Point1OrGreater() \
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), \
_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
#ifndef XINPUT_CAPS_WIRELESS
#define XINPUT_CAPS_WIRELESS 0x0002
@ -209,9 +222,17 @@ typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*
// user32.dll function pointer typedefs
typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void);
typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,PCHANGEFILTERSTRUCT);
typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,CHANGEFILTERSTRUCT*);
typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND);
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
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
@ -227,6 +248,10 @@ typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,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 struct VkWin32SurfaceCreateInfoKHR
@ -246,7 +271,9 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
#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_dlclose(handle) FreeLibrary((HMODULE) handle)
@ -278,6 +305,7 @@ typedef struct _GLFWwindowWin32
GLFWbool maximized;
// Whether to enable framebuffer transparency on DWM
GLFWbool transparent;
GLFWbool scaleToMonitor;
// The last received cursor position, regardless of source
int lastCursorPosX, lastCursorPosY;
@ -289,6 +317,7 @@ typedef struct _GLFWwindowWin32
typedef struct _GLFWlibraryWin32
{
HWND helperWindowHandle;
HDEVNOTIFY deviceNotificationHandle;
DWORD foregroundLockTimeout;
int acquiredMonitorCount;
char* clipboardString;
@ -301,6 +330,7 @@ typedef struct _GLFWlibraryWin32
_GLFWwindow* disabledCursorWindow;
RAWINPUT* rawInput;
int rawInputSize;
UINT mouseTrailSize;
struct {
HINSTANCE instance;
@ -323,6 +353,10 @@ typedef struct _GLFWlibraryWin32
HINSTANCE instance;
PFN_SetProcessDPIAware SetProcessDPIAware_;
PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx_;
PFN_EnableNonClientDpiScaling EnableNonClientDpiScaling_;
PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
PFN_GetDpiForWindow GetDpiForWindow_;
PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi_;
} user32;
struct {
@ -338,6 +372,11 @@ typedef struct _GLFWlibraryWin32
PFN_GetDpiForMonitor GetDpiForMonitor_;
} shcore;
struct {
HINSTANCE instance;
PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_;
} ntdll;
} _GLFWlibraryWin32;
// Win32-specific per-monitor data
@ -348,8 +387,8 @@ typedef struct _GLFWmonitorWin32
// This size matches the static size of DISPLAY_DEVICE.DeviceName
WCHAR adapterName[32];
WCHAR displayName[32];
char publicAdapterName[64];
char publicDisplayName[64];
char publicAdapterName[32];
char publicDisplayName[32];
GLFWbool modesPruned;
GLFWbool modeChanged;
@ -393,17 +432,18 @@ typedef struct _GLFWmutexWin32
GLFWbool _glfwRegisterWindowClassWin32(void);
void _glfwUnregisterWindowClassWin32(void);
GLFWbool _glfwIsCompositionEnabledWin32(void);
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* 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 _glfwPollMonitorsWin32(void);
GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale);

View File

@ -186,14 +186,20 @@ static HICON createIcon(const GLFWimage* image,
return handle;
}
// Translate client window size to full window size according to styles
// Translate client window size to full window size according to styles and DPI
//
static void getFullWindowSize(DWORD style, DWORD exStyle,
int clientWidth, int clientHeight,
int* fullWidth, int* fullHeight)
int* fullWidth, int* fullHeight,
UINT dpi)
{
RECT rect = { 0, 0, clientWidth, clientHeight };
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
else
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
*fullWidth = rect.right - rect.left;
*fullHeight = rect.bottom - rect.top;
}
@ -203,10 +209,14 @@ static void getFullWindowSize(DWORD style, DWORD exStyle,
static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
{
int xoff, yoff;
UINT dpi = USER_DEFAULT_SCREEN_DPI;
const float ratio = (float) window->numer / (float) window->denom;
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
dpi = GetDpiForWindow(window->win32.handle);
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
0, 0, &xoff, &yoff);
0, 0, &xoff, &yoff, dpi);
if (edge == WMSZ_LEFT || edge == WMSZ_BOTTOMLEFT ||
edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT)
@ -235,26 +245,6 @@ static void centerCursor(_GLFWwindow* window)
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
}
// Returns whether the cursor is in the client area of the specified window
//
static GLFWbool cursorInClientArea(_GLFWwindow* window)
{
RECT area;
POINT pos;
if (!GetCursorPos(&pos))
return GLFW_FALSE;
if (WindowFromPoint(pos) != window->win32.handle)
return GLFW_FALSE;
GetClientRect(window->win32.handle, &area);
ClientToScreen(window->win32.handle, (POINT*) &area.left);
ClientToScreen(window->win32.handle, (POINT*) &area.right);
return PtInRect(&area, pos);
}
// Updates the cursor image according to its cursor mode
//
static void updateCursorImage(_GLFWwindow* window)
@ -286,6 +276,67 @@ static void updateClipRect(_GLFWwindow* window)
ClipCursor(NULL);
}
// Apply disabled cursor mode to a focused window
//
static void disableCursor(_GLFWwindow* window)
{
const RAWINPUTDEVICE rid = { 0x01, 0x02, 0, window->win32.handle };
_glfw.win32.disabledCursorWindow = window;
_glfwPlatformGetCursorPos(window,
&_glfw.win32.restoreCursorPosX,
&_glfw.win32.restoreCursorPosY);
updateCursorImage(window);
centerCursor(window);
updateClipRect(window);
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to register raw input device");
}
}
// Exit disabled cursor mode for the specified window
//
static void enableCursor(_GLFWwindow* window)
{
const RAWINPUTDEVICE rid = { 0x01, 0x02, RIDEV_REMOVE, NULL };
_glfw.win32.disabledCursorWindow = NULL;
updateClipRect(NULL);
_glfwPlatformSetCursorPos(window,
_glfw.win32.restoreCursorPosX,
_glfw.win32.restoreCursorPosY);
updateCursorImage(window);
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to remove raw input device");
}
}
// Returns whether the cursor is in the client area of the specified window
//
static GLFWbool cursorInClientArea(_GLFWwindow* window)
{
RECT area;
POINT pos;
if (!GetCursorPos(&pos))
return GLFW_FALSE;
if (WindowFromPoint(pos) != window->win32.handle)
return GLFW_FALSE;
GetClientRect(window->win32.handle, &area);
ClientToScreen(window->win32.handle, (POINT*) &area.left);
ClientToScreen(window->win32.handle, (POINT*) &area.right);
return PtInRect(&area, pos);
}
// Update native window styles to match attributes
//
static void updateWindowStyles(const _GLFWwindow* window)
@ -296,7 +347,16 @@ static void updateWindowStyles(const _GLFWwindow* window)
style |= getWindowStyle(window);
GetClientRect(window->win32.handle, &rect);
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, style, FALSE,
getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
AdjustWindowRectEx(&rect, style, FALSE, getWindowExStyle(window));
ClientToScreen(window->win32.handle, (POINT*) &rect.left);
ClientToScreen(window->win32.handle, (POINT*) &rect.right);
SetWindowLongW(window->win32.handle, GWL_STYLE, style);
@ -310,10 +370,12 @@ static void updateWindowStyles(const _GLFWwindow* window)
//
static void updateFramebufferTransparency(const _GLFWwindow* window)
{
BOOL enabled;
if (!IsWindowsVistaOrGreater())
return;
if (_glfwIsCompositionEnabledWin32())
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
{
HRGN region = CreateRectRgn(0, 0, -1, -1);
DWM_BLURBEHIND bb = {0};
@ -355,43 +417,24 @@ static void updateFramebufferTransparency(const _GLFWwindow* window)
}
}
// Translates a GLFW standard cursor to a resource ID
//
static LPWSTR translateCursorShape(int shape)
{
switch (shape)
{
case GLFW_ARROW_CURSOR:
return IDC_ARROW;
case GLFW_IBEAM_CURSOR:
return IDC_IBEAM;
case GLFW_CROSSHAIR_CURSOR:
return IDC_CROSS;
case GLFW_HAND_CURSOR:
return IDC_HAND;
case GLFW_HRESIZE_CURSOR:
return IDC_SIZEWE;
case GLFW_VRESIZE_CURSOR:
return IDC_SIZENS;
}
return NULL;
}
// Retrieves and translates modifier keys
//
static int getKeyMods(void)
{
int mods = 0;
if (GetKeyState(VK_SHIFT) & (1 << 31))
if (GetKeyState(VK_SHIFT) & 0x8000)
mods |= GLFW_MOD_SHIFT;
if (GetKeyState(VK_CONTROL) & (1 << 31))
if (GetKeyState(VK_CONTROL) & 0x8000)
mods |= GLFW_MOD_CONTROL;
if (GetKeyState(VK_MENU) & (1 << 31))
if (GetKeyState(VK_MENU) & 0x8000)
mods |= GLFW_MOD_ALT;
if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & (1 << 31))
if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & 0x8000)
mods |= GLFW_MOD_SUPER;
if (GetKeyState(VK_CAPITAL) & 1)
mods |= GLFW_MOD_CAPS_LOCK;
if (GetKeyState(VK_NUMLOCK) & 1)
mods |= GLFW_MOD_NUM_LOCK;
return mods;
}
@ -402,14 +445,18 @@ static int getAsyncKeyMods(void)
{
int mods = 0;
if (GetAsyncKeyState(VK_SHIFT) & (1 << 31))
if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
mods |= GLFW_MOD_SHIFT;
if (GetAsyncKeyState(VK_CONTROL) & (1 << 31))
if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
mods |= GLFW_MOD_CONTROL;
if (GetAsyncKeyState(VK_MENU) & (1 << 31))
if (GetAsyncKeyState(VK_MENU) & 0x8000)
mods |= GLFW_MOD_ALT;
if ((GetAsyncKeyState(VK_LWIN) | GetAsyncKeyState(VK_RWIN)) & (1 << 31))
if ((GetAsyncKeyState(VK_LWIN) | GetAsyncKeyState(VK_RWIN)) & 0x8000)
mods |= GLFW_MOD_SUPER;
if (GetAsyncKeyState(VK_CAPITAL) & 1)
mods |= GLFW_MOD_CAPS_LOCK;
if (GetAsyncKeyState(VK_NUMLOCK) & 1)
mods |= GLFW_MOD_NUM_LOCK;
return mods;
}
@ -463,30 +510,40 @@ static int translateKey(WPARAM wParam, LPARAM lParam)
return _glfw.win32.keycodes[HIWORD(lParam) & 0x1FF];
}
static void fitToMonitor(_GLFWwindow* window)
{
MONITORINFO mi = { sizeof(mi) };
GetMonitorInfo(window->monitor->win32.handle, &mi);
SetWindowPos(window->win32.handle, HWND_TOPMOST,
mi.rcMonitor.left,
mi.rcMonitor.top,
mi.rcMonitor.right - mi.rcMonitor.left,
mi.rcMonitor.bottom - mi.rcMonitor.top,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS);
}
// Make the specified window and its video mode active on its monitor
//
static GLFWbool acquireMonitor(_GLFWwindow* window)
static void acquireMonitor(_GLFWwindow* window)
{
GLFWvidmode mode;
GLFWbool status;
int xpos, ypos;
if (!_glfw.win32.acquiredMonitorCount)
{
SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
// HACK: When mouse trails are enabled the cursor becomes invisible when
// the OpenGL ICD switches to page flipping
if (IsWindowsXPOrGreater())
{
SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
SystemParametersInfo(SPI_SETMOUSETRAILS, 0, 0, 0);
}
}
if (!window->monitor->window)
_glfw.win32.acquiredMonitorCount++;
status = _glfwSetVideoModeWin32(window->monitor, &window->videoMode);
_glfwPlatformGetVideoMode(window->monitor, &mode);
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
SetWindowPos(window->win32.handle, HWND_TOPMOST,
xpos, ypos, mode.width, mode.height,
SWP_NOACTIVATE | SWP_NOCOPYBITS);
_glfwSetVideoModeWin32(window->monitor, &window->videoMode);
_glfwInputMonitorWindow(window->monitor, window);
return status;
}
// Remove the window and restore the original video mode
@ -498,8 +555,14 @@ static void releaseMonitor(_GLFWwindow* window)
_glfw.win32.acquiredMonitorCount--;
if (!_glfw.win32.acquiredMonitorCount)
{
SetThreadExecutionState(ES_CONTINUOUS);
// HACK: Restore mouse trail length saved in acquireMonitor
if (IsWindowsXPOrGreater())
SystemParametersInfo(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
}
_glfwInputMonitorWindow(window->monitor, NULL);
_glfwRestoreVideoModeWin32(window->monitor);
}
@ -513,9 +576,18 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (!window)
{
// This is the message handling for the hidden helper window
// and for a regular window during its initial creation
switch (uMsg)
{
case WM_NCCREATE:
{
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
EnableNonClientDpiScaling(hWnd);
break;
}
case WM_DISPLAYCHANGE:
_glfwPollMonitorsWin32();
break;
@ -568,7 +640,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (lParam == 0 && window->win32.frameAction)
{
if (window->cursorMode == GLFW_CURSOR_DISABLED)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED);
disableCursor(window);
window->win32.frameAction = GLFW_FALSE;
}
@ -586,7 +658,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
break;
if (window->cursorMode == GLFW_CURSOR_DISABLED)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED);
disableCursor(window);
return 0;
}
@ -594,7 +666,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_KILLFOCUS:
{
if (window->cursorMode == GLFW_CURSOR_DISABLED)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL);
enableCursor(window);
if (window->monitor && window->autoIconify)
_glfwPlatformIconifyWindow(window);
@ -850,10 +922,10 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_ENTERSIZEMOVE:
case WM_ENTERMENULOOP:
{
// HACK: Postpone cursor disabling while the user is moving or
// resizing the window or using the menu
// HACK: Enable the cursor while the user is moving or
// resizing the window or using the window menu
if (window->cursorMode == GLFW_CURSOR_DISABLED)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL);
enableCursor(window);
break;
}
@ -864,7 +936,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
// HACK: Disable the cursor once the user is done moving or
// resizing the window or using the menu
if (window->cursorMode == GLFW_CURSOR_DISABLED)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED);
disableCursor(window);
break;
}
@ -893,7 +965,10 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (iconified)
releaseMonitor(window);
else
{
acquireMonitor(window);
fitToMonitor(window);
}
}
window->win32.iconified = iconified;
@ -929,13 +1004,17 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_GETMINMAXINFO:
{
int xoff, yoff;
UINT dpi = USER_DEFAULT_SCREEN_DPI;
MINMAXINFO* mmi = (MINMAXINFO*) lParam;
if (window->monitor)
break;
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
dpi = GetDpiForWindow(window->win32.handle);
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
0, 0, &xoff, &yoff);
0, 0, &xoff, &yoff, dpi);
if (window->minwidth != GLFW_DONT_CARE &&
window->minheight != GLFW_DONT_CARE)
@ -951,6 +1030,22 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
mmi->ptMaxTrackSize.y = window->maxheight + yoff;
}
if (!window->decorated)
{
MONITORINFO mi;
const HMONITOR mh = MonitorFromWindow(window->win32.handle,
MONITOR_DEFAULTTONEAREST);
ZeroMemory(&mi, sizeof(mi));
mi.cbSize = sizeof(mi);
GetMonitorInfo(mh, &mi);
mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left;
mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top;
mmi->ptMaxSize.x = mi.rcWork.right - mi.rcWork.left;
mmi->ptMaxSize.y = mi.rcWork.bottom - mi.rcWork.top;
}
return 0;
}
@ -972,6 +1067,56 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
return 0;
}
case WM_GETDPISCALEDSIZE:
{
if (window->win32.scaleToMonitor)
break;
// Adjust the window size to keep the client area size constant
if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
{
RECT source = {0}, target = {0};
SIZE* size = (SIZE*) lParam;
AdjustWindowRectExForDpi(&source, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
AdjustWindowRectExForDpi(&target, getWindowStyle(window),
FALSE, getWindowExStyle(window),
LOWORD(wParam));
size->cx += (target.right - target.left) -
(source.right - source.left);
size->cy += (target.bottom - target.top) -
(source.bottom - source.top);
return TRUE;
}
break;
}
case WM_DPICHANGED:
{
const float xscale = HIWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;
const float yscale = LOWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;
// Only apply the suggested size if the OS is new enough to have
// sent a WM_GETDPISCALEDSIZE before this
if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
{
RECT* suggested = (RECT*) lParam;
SetWindowPos(window->win32.handle, HWND_TOP,
suggested->left,
suggested->top,
suggested->right - suggested->left,
suggested->bottom - suggested->top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
_glfwInputWindowContentScale(window, xscale, yscale);
break;
}
case WM_SETCURSOR:
{
if (LOWORD(lParam) == HTCLIENT)
@ -1054,7 +1199,8 @@ static int createNativeWindow(_GLFWwindow* window,
getFullWindowSize(style, exStyle,
wndconfig->width, wndconfig->height,
&fullWidth, &fullHeight);
&fullWidth, &fullHeight,
USER_DEFAULT_SCREEN_DPI);
}
wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);
@ -1093,6 +1239,40 @@ static int createNativeWindow(_GLFWwindow* window,
WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);
}
window->win32.scaleToMonitor = wndconfig->scaleToMonitor;
// Adjust window size to account for DPI scaling of the window frame and
// optionally DPI scaling of the client area
// This cannot be done until we know what monitor it was placed on
if (!window->monitor)
{
RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
if (wndconfig->scaleToMonitor)
{
float xscale, yscale;
_glfwPlatformGetWindowContentScale(window, &xscale, &yscale);
rect.right = (int) (rect.right * xscale);
rect.bottom = (int) (rect.bottom * yscale);
}
ClientToScreen(window->win32.handle, (POINT*) &rect.left);
ClientToScreen(window->win32.handle, (POINT*) &rect.right);
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
GetDpiForWindow(window->win32.handle));
}
else
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
SetWindowPos(window->win32.handle, NULL,
rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
DragAcceptFiles(window->win32.handle, TRUE);
if (fbconfig->transparent)
@ -1152,20 +1332,6 @@ void _glfwUnregisterWindowClassWin32(void)
UnregisterClassW(_GLFW_WNDCLASSNAME, GetModuleHandleW(NULL));
}
// Returns whether desktop compositing is enabled
//
GLFWbool _glfwIsCompositionEnabledWin32(void)
{
if (IsWindowsVistaOrGreater())
{
BOOL enabled;
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)))
return enabled;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
@ -1208,11 +1374,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
{
_glfwPlatformShowWindow(window);
_glfwPlatformFocusWindow(window);
if (!acquireMonitor(window))
return GLFW_FALSE;
if (wndconfig->centerCursor)
centerCursor(window);
acquireMonitor(window);
fitToMonitor(window);
}
return GLFW_TRUE;
@ -1306,8 +1469,19 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
{
RECT rect = { xpos, ypos, xpos, ypos };
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
{
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
}
SetWindowPos(window->win32.handle, NULL, rect.left, rect.top, 0, 0,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
}
@ -1328,13 +1502,27 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
if (window->monitor)
{
if (window->monitor->window == window)
{
acquireMonitor(window);
fitToMonitor(window);
}
}
else
{
RECT rect = { 0, 0, width, height };
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
{
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
}
SetWindowPos(window->win32.handle, HWND_TOP,
0, 0, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER);
@ -1389,8 +1577,18 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
_glfwPlatformGetWindowSize(window, &width, &height);
SetRect(&rect, 0, 0, width, height);
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
{
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
}
if (left)
*left = -rect.left;
@ -1427,7 +1625,7 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
void _glfwPlatformShowWindow(_GLFWwindow* window)
{
ShowWindow(window->win32.handle, SW_SHOW);
ShowWindow(window->win32.handle, SW_SHOWNA);
}
void _glfwPlatformHideWindow(_GLFWwindow* window)
@ -1458,13 +1656,27 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
if (monitor)
{
if (monitor->window == window)
{
acquireMonitor(window);
fitToMonitor(window);
}
}
else
{
RECT rect = { xpos, ypos, xpos + width, ypos + height };
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
{
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
}
SetWindowPos(window->win32.handle, HWND_TOP,
rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
@ -1481,27 +1693,27 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
if (monitor)
{
GLFWvidmode mode;
DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
MONITORINFO mi = { sizeof(mi) };
UINT flags = SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOCOPYBITS;
if (window->decorated)
{
DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
style &= ~WS_OVERLAPPEDWINDOW;
style |= getWindowStyle(window);
SetWindowLongW(window->win32.handle, GWL_STYLE, style);
flags |= SWP_FRAMECHANGED;
}
_glfwPlatformGetVideoMode(monitor, &mode);
_glfwPlatformGetMonitorPos(monitor, &xpos, &ypos);
SetWindowPos(window->win32.handle, HWND_TOPMOST,
xpos, ypos, mode.width, mode.height,
flags);
acquireMonitor(window);
GetMonitorInfo(window->monitor->win32.handle, &mi);
SetWindowPos(window->win32.handle, HWND_TOPMOST,
mi.rcMonitor.left,
mi.rcMonitor.top,
mi.rcMonitor.right - mi.rcMonitor.left,
mi.rcMonitor.bottom - mi.rcMonitor.top,
flags);
}
else
{
@ -1524,8 +1736,18 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
else
after = HWND_NOTOPMOST;
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
{
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
}
SetWindowPos(window->win32.handle, after,
rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
@ -1553,9 +1775,22 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return IsZoomed(window->win32.handle);
}
int _glfwPlatformWindowHovered(_GLFWwindow* window)
{
return cursorInClientArea(window);
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{
return window->win32.transparent && _glfwIsCompositionEnabledWin32();
BOOL enabled;
if (!window->win32.transparent)
return GLFW_FALSE;
if (!IsWindowsVistaOrGreater())
return GLFW_FALSE;
return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled;
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
@ -1575,6 +1810,39 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
}
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
{
BYTE alpha;
DWORD flags;
if ((GetWindowLongW(window->win32.handle, GWL_EXSTYLE) & WS_EX_LAYERED) &&
GetLayeredWindowAttributes(window->win32.handle, NULL, &alpha, &flags))
{
if (flags & LWA_ALPHA)
return alpha / 255.f;
}
return 1.f;
}
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
{
if (opacity < 1.f)
{
const BYTE alpha = (BYTE) (255 * opacity);
DWORD style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
style |= WS_EX_LAYERED;
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style);
SetLayeredWindowAttributes(window->win32.handle, 0, alpha, LWA_ALPHA);
}
else
{
DWORD style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
style &= ~WS_EX_LAYERED;
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style);
}
}
void _glfwPlatformPollEvents(void)
{
MSG msg;
@ -1697,39 +1965,12 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{
if (mode == GLFW_CURSOR_DISABLED)
{
const RAWINPUTDEVICE rid = { 0x01, 0x02, 0, window->win32.handle };
_glfw.win32.disabledCursorWindow = window;
_glfwPlatformGetCursorPos(window,
&_glfw.win32.restoreCursorPosX,
&_glfw.win32.restoreCursorPosY);
centerCursor(window);
updateClipRect(window);
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to register raw input device");
}
if (_glfwPlatformWindowFocused(window))
disableCursor(window);
}
else if (_glfw.win32.disabledCursorWindow == window)
{
const RAWINPUTDEVICE rid = { 0x01, 0x02, RIDEV_REMOVE, NULL };
_glfw.win32.disabledCursorWindow = NULL;
updateClipRect(NULL);
_glfwPlatformSetCursorPos(window,
_glfw.win32.restoreCursorPosX,
_glfw.win32.restoreCursorPosY);
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to remove raw input device");
}
}
if (cursorInClientArea(window))
enableCursor(window);
else if (cursorInClientArea(window))
updateCursorImage(window);
}
@ -1756,8 +1997,24 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
{
cursor->win32.handle =
CopyCursor(LoadCursorW(NULL, translateCursorShape(shape)));
LPCWSTR name = NULL;
if (shape == GLFW_ARROW_CURSOR)
name = IDC_ARROW;
else if (shape == GLFW_IBEAM_CURSOR)
name = IDC_IBEAM;
else if (shape == GLFW_CROSSHAIR_CURSOR)
name = IDC_CROSS;
else if (shape == GLFW_HAND_CURSOR)
name = IDC_HAND;
else if (shape == GLFW_HRESIZE_CURSOR)
name = IDC_SIZEWE;
else if (shape == GLFW_VRESIZE_CURSOR)
name = IDC_SIZENS;
else
return GLFW_FALSE;
cursor->win32.handle = CopyCursor(LoadCursorW(NULL, name));
if (!cursor->win32.handle)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
@ -1780,7 +2037,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
updateCursorImage(window);
}
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
void _glfwPlatformSetClipboardString(const char* string)
{
int characterCount;
HANDLE object;
@ -1823,7 +2080,7 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
CloseClipboard();
}
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
const char* _glfwPlatformGetClipboardString(void)
{
HANDLE object;
WCHAR* buffer;

View File

@ -38,6 +38,8 @@
////// GLFW event API //////
//////////////////////////////////////////////////////////////////////////
// Notifies shared code that a window has lost or received input focus
//
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
{
if (window->callbacks.focus)
@ -64,42 +66,68 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
}
}
// Notifies shared code that a window has moved
// The position is specified in client-area relative screen coordinates
//
void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
{
if (window->callbacks.pos)
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)
{
if (window->callbacks.size)
window->callbacks.size((GLFWwindow*) window, width, height);
}
// Notifies shared code that a window has been iconified or restored
//
void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
{
if (window->callbacks.iconify)
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)
{
if (window->callbacks.fbsize)
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)
{
if (window->callbacks.refresh)
window->callbacks.refresh((GLFWwindow*) window);
}
// Notifies shared code that the user wishes to close a window
//
void _glfwInputWindowCloseRequest(_GLFWwindow* window)
{
window->shouldClose = GLFW_TRUE;
@ -108,6 +136,8 @@ void _glfwInputWindowCloseRequest(_GLFWwindow* window)
window->callbacks.close((GLFWwindow*) window);
}
// Notifies shared code that a window has changed its desired monitor
//
void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor)
{
window->monitor = monitor;
@ -127,7 +157,6 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
_GLFWctxconfig ctxconfig;
_GLFWwndconfig wndconfig;
_GLFWwindow* window;
_GLFWwindow* previous;
assert(title != NULL);
assert(width >= 0);
@ -153,16 +182,6 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
wndconfig.title = title;
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))
return NULL;
@ -182,6 +201,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
window->decorated = wndconfig.decorated;
window->autoIconify = wndconfig.autoIconify;
window->floating = wndconfig.floating;
window->focusOnShow = wndconfig.focusOnShow;
window->cursorMode = GLFW_CURSOR_NORMAL;
window->minwidth = GLFW_DONT_CARE;
@ -191,36 +211,32 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
window->numer = GLFW_DONT_CARE;
window->denom = GLFW_DONT_CARE;
// Save the currently current context so it can be restored later
previous = _glfwPlatformGetTls(&_glfw.contextSlot);
if (ctxconfig.client != GLFW_NO_API)
glfwMakeContextCurrent(NULL);
// Open the actual window and create its context
if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig))
{
glfwMakeContextCurrent((GLFWwindow*) previous);
glfwDestroyWindow((GLFWwindow*) window);
return NULL;
}
if (ctxconfig.client != GLFW_NO_API)
{
window->context.makeCurrent(window);
// Retrieve the actual (as opposed to requested) context attributes
if (!_glfwRefreshContextAttribs(&ctxconfig))
if (!_glfwRefreshContextAttribs(window, &ctxconfig))
{
glfwMakeContextCurrent((GLFWwindow*) previous);
glfwDestroyWindow((GLFWwindow*) window);
return NULL;
}
// Restore the previously current context (or NULL)
glfwMakeContextCurrent((GLFWwindow*) previous);
}
if (!window->monitor)
if (window->monitor)
{
if (wndconfig.centerCursor)
{
int width, height;
_glfwPlatformGetWindowSize(window, &width, &height);
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
}
}
else
{
if (wndconfig.visible)
{
@ -252,6 +268,7 @@ void glfwDefaultWindowHints(void)
_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,
// double buffered
@ -316,7 +333,7 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_DOUBLEBUFFER:
_glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_TRANSPARENT:
case GLFW_TRANSPARENT_FRAMEBUFFER:
_glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_SAMPLES:
@ -349,15 +366,18 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_COCOA_RETINA_FRAMEBUFFER:
_glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_COCOA_FRAME_AUTOSAVE:
_glfw.hints.window.ns.frame = 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:
_glfw.hints.context.client = value;
return;
@ -396,6 +416,31 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_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)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
@ -648,6 +693,34 @@ GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle,
_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)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
@ -690,6 +763,8 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle)
return;
_glfwPlatformShowWindow(window);
if (window->focusOnShow)
_glfwPlatformFocusWindow(window);
}
@ -743,7 +818,11 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
return _glfwPlatformWindowVisible(window);
case GLFW_MAXIMIZED:
return _glfwPlatformWindowMaximized(window);
case GLFW_TRANSPARENT:
case GLFW_HOVERED:
return _glfwPlatformWindowHovered(window);
case GLFW_FOCUS_ON_SHOW:
return window->focusOnShow;
case GLFW_TRANSPARENT_FRAMEBUFFER:
return _glfwPlatformFramebufferTransparent(window);
case GLFW_RESIZABLE:
return window->resizable;
@ -819,6 +898,8 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int 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);
}
@ -977,6 +1058,17 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle
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)
{
_GLFW_REQUIRE_INIT();

View File

@ -26,14 +26,17 @@
#include "internal.h"
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <linux/input.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/timerfd.h>
#include <unistd.h>
#include <wayland-client.h>
#include <wayland-cursor.h>
static inline int min(int n1, int n2)
@ -41,6 +44,40 @@ static inline int min(int n1, int n2)
return n1 < n2 ? n1 : n2;
}
static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface,
int* which)
{
int focus;
_GLFWwindow* window = _glfw.windowListHead;
if (!which)
which = &focus;
while (window)
{
if (surface == window->wl.decorations.top.surface)
{
*which = topDecoration;
break;
}
if (surface == window->wl.decorations.left.surface)
{
*which = leftDecoration;
break;
}
if (surface == window->wl.decorations.right.surface)
{
*which = rightDecoration;
break;
}
if (surface == window->wl.decorations.bottom.surface)
{
*which = bottomDecoration;
break;
}
window = window->next;
}
return window;
}
static void pointerHandleEnter(void* data,
struct wl_pointer* pointer,
uint32_t serial,
@ -48,11 +85,25 @@ static void pointerHandleEnter(void* data,
wl_fixed_t sx,
wl_fixed_t sy)
{
_GLFWwindow* window = wl_surface_get_user_data(surface);
// Happens in the case we just destroyed the surface.
if (!surface)
return;
int focus = 0;
_GLFWwindow* window = wl_surface_get_user_data(surface);
if (!window)
{
window = findWindowFromDecorationSurface(surface, &focus);
if (!window)
return;
}
window->wl.decorations.focus = focus;
_glfw.wl.pointerSerial = serial;
_glfw.wl.pointerFocus = window;
window->wl.hovered = GLFW_TRUE;
_glfwPlatformSetCursor(window, window->wl.currentCursor);
_glfwInputCursorEnter(window, GLFW_TRUE);
}
@ -67,11 +118,57 @@ static void pointerHandleLeave(void* data,
if (!window)
return;
window->wl.hovered = GLFW_FALSE;
_glfw.wl.pointerSerial = serial;
_glfw.wl.pointerFocus = NULL;
_glfwInputCursorEnter(window, GLFW_FALSE);
}
static void setCursor(_GLFWwindow* window, const char* name)
{
struct wl_buffer* buffer;
struct wl_cursor* cursor;
struct wl_cursor_image* image;
struct wl_surface* surface = _glfw.wl.cursorSurface;
struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;
int scale = 1;
if (window->wl.scale > 1 && _glfw.wl.cursorThemeHiDPI)
{
// We only support up to scale=2 for now, since libwayland-cursor
// requires us to load a different theme for each size.
scale = 2;
theme = _glfw.wl.cursorThemeHiDPI;
}
cursor = wl_cursor_theme_get_cursor(theme, name);
if (!cursor)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Standard cursor not found");
return;
}
// TODO: handle animated cursors too.
image = cursor->images[0];
if (!image)
return;
buffer = wl_cursor_image_get_buffer(image);
if (!buffer)
return;
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
surface,
image->hotspot_x / scale,
image->hotspot_y / scale);
wl_surface_set_buffer_scale(surface, scale);
wl_surface_attach(surface, buffer, 0, 0);
wl_surface_damage(surface, 0, 0,
image->width, image->height);
wl_surface_commit(surface);
}
static void pointerHandleMotion(void* data,
struct wl_pointer* pointer,
uint32_t time,
@ -79,6 +176,7 @@ static void pointerHandleMotion(void* data,
wl_fixed_t sy)
{
_GLFWwindow* window = _glfw.wl.pointerFocus;
const char* cursorName;
if (!window)
return;
@ -91,13 +189,47 @@ static void pointerHandleMotion(void* data,
window->wl.cursorPosY = wl_fixed_to_double(sy);
}
switch (window->wl.decorations.focus)
{
case mainWindow:
_glfwInputCursorPos(window,
wl_fixed_to_double(sx),
wl_fixed_to_double(sy));
return;
case topDecoration:
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
cursorName = "n-resize";
else
cursorName = "left_ptr";
break;
case leftDecoration:
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
cursorName = "nw-resize";
else
cursorName = "w-resize";
break;
case rightDecoration:
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
cursorName = "ne-resize";
else
cursorName = "e-resize";
break;
case bottomDecoration:
if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH)
cursorName = "sw-resize";
else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH)
cursorName = "se-resize";
else
cursorName = "s-resize";
break;
default:
assert(0);
}
setCursor(window, cursorName);
}
static void pointerHandleButton(void* data,
struct wl_pointer* wl_pointer,
struct wl_pointer* pointer,
uint32_t serial,
uint32_t time,
uint32_t button,
@ -106,8 +238,76 @@ static void pointerHandleButton(void* data,
_GLFWwindow* window = _glfw.wl.pointerFocus;
int glfwButton;
// Both xdg-shell and wl_shell use the same values.
uint32_t edges = WL_SHELL_SURFACE_RESIZE_NONE;
if (!window)
return;
if (button == BTN_LEFT)
{
switch (window->wl.decorations.focus)
{
case mainWindow:
break;
case topDecoration:
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
edges = WL_SHELL_SURFACE_RESIZE_TOP;
else
{
if (window->wl.xdg.toplevel)
xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
else
wl_shell_surface_move(window->wl.shellSurface, _glfw.wl.seat, serial);
}
break;
case leftDecoration:
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
edges = WL_SHELL_SURFACE_RESIZE_TOP_LEFT;
else
edges = WL_SHELL_SURFACE_RESIZE_LEFT;
break;
case rightDecoration:
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
edges = WL_SHELL_SURFACE_RESIZE_TOP_RIGHT;
else
edges = WL_SHELL_SURFACE_RESIZE_RIGHT;
break;
case bottomDecoration:
if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH)
edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT;
else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH)
edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT;
else
edges = WL_SHELL_SURFACE_RESIZE_BOTTOM;
break;
default:
assert(0);
}
if (edges != WL_SHELL_SURFACE_RESIZE_NONE)
{
if (window->wl.xdg.toplevel)
xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat,
serial, edges);
else
wl_shell_surface_resize(window->wl.shellSurface, _glfw.wl.seat,
serial, edges);
}
}
else if (button == BTN_RIGHT)
{
if (window->wl.decorations.focus != mainWindow && window->wl.xdg.toplevel)
{
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
_glfw.wl.seat, serial,
window->wl.cursorPosX,
window->wl.cursorPosY);
return;
}
}
// Dont pass the button to the user if it was related to a decoration.
if (window->wl.decorations.focus != mainWindow)
return;
_glfw.wl.pointerSerial = serial;
@ -124,36 +324,28 @@ static void pointerHandleButton(void* data,
}
static void pointerHandleAxis(void* data,
struct wl_pointer* wl_pointer,
struct wl_pointer* pointer,
uint32_t time,
uint32_t axis,
wl_fixed_t value)
{
_GLFWwindow* window = _glfw.wl.pointerFocus;
double scrollFactor;
double x, y;
double x = 0.0, y = 0.0;
// Wayland scroll events are in pointer motion coordinate space (think two
// finger scroll). The factor 10 is commonly used to convert to "scroll
// step means 1.0.
const double scrollFactor = 1.0 / 10.0;
if (!window)
return;
/* Wayland scroll events are in pointer motion coordinate space (think
* two finger scroll). The factor 10 is commonly used to convert to
* "scroll step means 1.0. */
scrollFactor = 1.0/10.0;
assert(axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL ||
axis == WL_POINTER_AXIS_VERTICAL_SCROLL);
switch (axis)
{
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
x = wl_fixed_to_double(value) * scrollFactor;
y = 0.0;
break;
case WL_POINTER_AXIS_VERTICAL_SCROLL:
x = 0.0;
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
y = wl_fixed_to_double(value) * scrollFactor;
break;
default:
break;
}
_glfwInputScroll(window, x, y);
}
@ -174,8 +366,12 @@ static void keyboardHandleKeymap(void* data,
{
struct xkb_keymap* keymap;
struct xkb_state* state;
#ifdef HAVE_XKBCOMMON_COMPOSE_H
struct xkb_compose_table* composeTable;
struct xkb_compose_state* composeState;
#endif
char* mapStr;
const char* locale;
@ -223,6 +419,7 @@ static void keyboardHandleKeymap(void* data,
if (!locale)
locale = "C";
#ifdef HAVE_XKBCOMMON_COMPOSE_H
composeTable =
xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
XKB_COMPOSE_COMPILE_NO_FLAGS);
@ -242,6 +439,7 @@ static void keyboardHandleKeymap(void* data,
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to create XKB compose table");
}
#endif
xkb_keymap_unref(_glfw.wl.xkb.keymap);
xkb_state_unref(_glfw.wl.xkb.state);
@ -256,6 +454,10 @@ static void keyboardHandleKeymap(void* data,
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
_glfw.wl.xkb.superMask =
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
_glfw.wl.xkb.capsLockMask =
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Lock");
_glfw.wl.xkb.numLockMask =
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod2");
}
static void keyboardHandleEnter(void* data,
@ -264,7 +466,17 @@ static void keyboardHandleEnter(void* data,
struct wl_surface* surface,
struct wl_array* keys)
{
// Happens in the case we just destroyed the surface.
if (!surface)
return;
_GLFWwindow* window = wl_surface_get_user_data(surface);
if (!window)
{
window = findWindowFromDecorationSurface(surface, NULL);
if (!window)
return;
}
_glfw.wl.keyboardFocus = window;
_glfwInputWindowFocus(window, GLFW_TRUE);
@ -292,6 +504,7 @@ static int toGLFWKeyCode(uint32_t key)
return GLFW_KEY_UNKNOWN;
}
#ifdef HAVE_XKBCOMMON_COMPOSE_H
static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
{
if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
@ -311,8 +524,9 @@ static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
return sym;
}
}
#endif
static void inputChar(_GLFWwindow* window, uint32_t key)
static GLFWbool inputChar(_GLFWwindow* window, uint32_t key)
{
uint32_t code, numSyms;
long cp;
@ -324,7 +538,11 @@ static void inputChar(_GLFWwindow* window, uint32_t key)
if (numSyms == 1)
{
#ifdef HAVE_XKBCOMMON_COMPOSE_H
sym = composeSymbol(syms[0]);
#else
sym = syms[0];
#endif
cp = _glfwKeySym2Unicode(sym);
if (cp != -1)
{
@ -333,6 +551,8 @@ static void inputChar(_GLFWwindow* window, uint32_t key)
_glfwInputChar(window, cp, mods, plain);
}
}
return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, syms[0]);
}
static void keyboardHandleKey(void* data,
@ -345,6 +565,8 @@ static void keyboardHandleKey(void* data,
int keyCode;
int action;
_GLFWwindow* window = _glfw.wl.keyboardFocus;
GLFWbool shouldRepeat;
struct itimerspec timer = {};
if (!window)
return;
@ -357,7 +579,20 @@ static void keyboardHandleKey(void* data,
_glfw.wl.xkb.modifiers);
if (action == GLFW_PRESS)
inputChar(window, key);
{
shouldRepeat = inputChar(window, key);
if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0)
{
_glfw.wl.keyboardLastKey = keyCode;
_glfw.wl.keyboardLastScancode = key;
timer.it_interval.tv_sec = _glfw.wl.keyboardRepeatRate / 1000;
timer.it_interval.tv_nsec = (_glfw.wl.keyboardRepeatRate % 1000) * 1000000;
timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000;
timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000;
}
}
timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
}
static void keyboardHandleModifiers(void* data,
@ -395,15 +630,36 @@ static void keyboardHandleModifiers(void* data,
modifiers |= GLFW_MOD_SHIFT;
if (mask & _glfw.wl.xkb.superMask)
modifiers |= GLFW_MOD_SUPER;
if (mask & _glfw.wl.xkb.capsLockMask)
modifiers |= GLFW_MOD_CAPS_LOCK;
if (mask & _glfw.wl.xkb.numLockMask)
modifiers |= GLFW_MOD_NUM_LOCK;
_glfw.wl.xkb.modifiers = modifiers;
}
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
static void keyboardHandleRepeatInfo(void* data,
struct wl_keyboard* keyboard,
int32_t rate,
int32_t delay)
{
if (keyboard != _glfw.wl.keyboard)
return;
_glfw.wl.keyboardRepeatRate = rate;
_glfw.wl.keyboardRepeatDelay = delay;
}
#endif
static const struct wl_keyboard_listener keyboardListener = {
keyboardHandleKeymap,
keyboardHandleEnter,
keyboardHandleLeave,
keyboardHandleKey,
keyboardHandleModifiers,
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
keyboardHandleRepeatInfo,
#endif
};
static void seatHandleCapabilities(void* data,
@ -433,8 +689,26 @@ static void seatHandleCapabilities(void* data,
}
}
static void seatHandleName(void* data,
struct wl_seat* seat,
const char* name)
{
}
static const struct wl_seat_listener seatListener = {
seatHandleCapabilities
seatHandleCapabilities,
seatHandleName,
};
static void wmBaseHandlePing(void* data,
struct xdg_wm_base* wmBase,
uint32_t serial)
{
xdg_wm_base_pong(wmBase, serial);
}
static const struct xdg_wm_base_listener wmBaseListener = {
wmBaseHandlePing
};
static void registryHandleGlobal(void* data,
@ -450,6 +724,11 @@ static void registryHandleGlobal(void* data,
wl_registry_bind(registry, name, &wl_compositor_interface,
_glfw.wl.compositorVersion);
}
else if (strcmp(interface, "wl_subcompositor") == 0)
{
_glfw.wl.subcompositor =
wl_registry_bind(registry, name, &wl_subcompositor_interface, 1);
}
else if (strcmp(interface, "wl_shm") == 0)
{
_glfw.wl.shm =
@ -468,11 +747,31 @@ static void registryHandleGlobal(void* data,
{
if (!_glfw.wl.seat)
{
_glfw.wl.seatVersion = min(4, version);
_glfw.wl.seat =
wl_registry_bind(registry, name, &wl_seat_interface, 1);
wl_registry_bind(registry, name, &wl_seat_interface,
_glfw.wl.seatVersion);
wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL);
}
}
else if (strcmp(interface, "xdg_wm_base") == 0)
{
_glfw.wl.wmBase =
wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
xdg_wm_base_add_listener(_glfw.wl.wmBase, &wmBaseListener, NULL);
}
else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0)
{
_glfw.wl.decorationManager =
wl_registry_bind(registry, name,
&zxdg_decoration_manager_v1_interface,
1);
}
else if (strcmp(interface, "wp_viewporter") == 0)
{
_glfw.wl.viewporter =
wl_registry_bind(registry, name, &wp_viewporter_interface, 1);
}
else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0)
{
_glfw.wl.relativePointerManager =
@ -487,12 +786,31 @@ static void registryHandleGlobal(void* data,
&zwp_pointer_constraints_v1_interface,
1);
}
else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0)
{
_glfw.wl.idleInhibitManager =
wl_registry_bind(registry, name,
&zwp_idle_inhibit_manager_v1_interface,
1);
}
}
static void registryHandleGlobalRemove(void *data,
struct wl_registry *registry,
uint32_t name)
{
int i;
_GLFWmonitor* monitor;
for (i = 0; i < _glfw.monitorCount; ++i)
{
monitor = _glfw.monitors[i];
if (monitor->wl.name == name)
{
_glfwInputMonitor(monitor, GLFW_DISCONNECTED, 0);
return;
}
}
}
@ -642,6 +960,92 @@ static void createKeyTables(void)
int _glfwPlatformInit(void)
{
const char *cursorTheme;
const char *cursorSizeStr;
char *cursorSizeEnd;
long cursorSizeLong;
int cursorSize;
_glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");
if (!_glfw.wl.cursor.handle)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to open libwayland-cursor");
return GLFW_FALSE;
}
_glfw.wl.cursor.theme_load = (PFN_wl_cursor_theme_load)
_glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_load");
_glfw.wl.cursor.theme_destroy = (PFN_wl_cursor_theme_destroy)
_glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_destroy");
_glfw.wl.cursor.theme_get_cursor = (PFN_wl_cursor_theme_get_cursor)
_glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor");
_glfw.wl.cursor.image_get_buffer = (PFN_wl_cursor_image_get_buffer)
_glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_image_get_buffer");
_glfw.wl.egl.handle = _glfw_dlopen("libwayland-egl.so.1");
if (!_glfw.wl.egl.handle)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to open libwayland-egl");
return GLFW_FALSE;
}
_glfw.wl.egl.window_create = (PFN_wl_egl_window_create)
_glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_create");
_glfw.wl.egl.window_destroy = (PFN_wl_egl_window_destroy)
_glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_destroy");
_glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize)
_glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_resize");
_glfw.wl.xkb.handle = _glfw_dlopen("libxkbcommon.so.0");
if (!_glfw.wl.xkb.handle)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to open libxkbcommon");
return GLFW_FALSE;
}
_glfw.wl.xkb.context_new = (PFN_xkb_context_new)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_new");
_glfw.wl.xkb.context_unref = (PFN_xkb_context_unref)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_unref");
_glfw.wl.xkb.keymap_new_from_string = (PFN_xkb_keymap_new_from_string)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_new_from_string");
_glfw.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_unref");
_glfw.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
_glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats");
_glfw.wl.xkb.state_new = (PFN_xkb_state_new)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new");
_glfw.wl.xkb.state_unref = (PFN_xkb_state_unref)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_unref");
_glfw.wl.xkb.state_key_get_syms = (PFN_xkb_state_key_get_syms)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_syms");
_glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask");
_glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods");
#ifdef HAVE_XKBCOMMON_COMPOSE_H
_glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");
_glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_unref");
_glfw.wl.xkb.compose_state_new = (PFN_xkb_compose_state_new)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_new");
_glfw.wl.xkb.compose_state_unref = (PFN_xkb_compose_state_unref)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_unref");
_glfw.wl.xkb.compose_state_feed = (PFN_xkb_compose_state_feed)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_feed");
_glfw.wl.xkb.compose_state_get_status = (PFN_xkb_compose_state_get_status)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status");
_glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");
#endif
_glfw.wl.display = wl_display_connect(NULL);
if (!_glfw.wl.display)
{
@ -669,22 +1073,43 @@ int _glfwPlatformInit(void)
// Sync so we got all initial output events
wl_display_roundtrip(_glfw.wl.display);
#ifdef __linux__
if (!_glfwInitJoysticksLinux())
return GLFW_FALSE;
#endif
_glfwInitTimerPOSIX();
_glfw.wl.timerfd = -1;
if (_glfw.wl.seatVersion >= 4)
_glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
if (_glfw.wl.pointer && _glfw.wl.shm)
{
_glfw.wl.cursorTheme = wl_cursor_theme_load(NULL, 32, _glfw.wl.shm);
cursorTheme = getenv("XCURSOR_THEME");
cursorSizeStr = getenv("XCURSOR_SIZE");
cursorSize = 32;
if (cursorSizeStr)
{
errno = 0;
cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10);
if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX)
cursorSize = (int)cursorSizeLong;
}
_glfw.wl.cursorTheme =
wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm);
if (!_glfw.wl.cursorTheme)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Unable to load default cursor theme\n");
"Wayland: Unable to load default cursor theme");
return GLFW_FALSE;
}
// If this happens to be NULL, we just fallback to the scale=1 version.
_glfw.wl.cursorThemeHiDPI =
wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm);
_glfw.wl.cursorSurface =
wl_compositor_create_surface(_glfw.wl.compositor);
_glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
}
return GLFW_TRUE;
@ -692,24 +1117,58 @@ int _glfwPlatformInit(void)
void _glfwPlatformTerminate(void)
{
_glfwTerminateEGL();
#ifdef __linux__
_glfwTerminateJoysticksLinux();
#endif
_glfwTerminateEGL();
if (_glfw.wl.egl.handle)
{
_glfw_dlclose(_glfw.wl.egl.handle);
_glfw.wl.egl.handle = NULL;
}
#ifdef HAVE_XKBCOMMON_COMPOSE_H
if (_glfw.wl.xkb.composeState)
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
#endif
if (_glfw.wl.xkb.keymap)
xkb_keymap_unref(_glfw.wl.xkb.keymap);
if (_glfw.wl.xkb.state)
xkb_state_unref(_glfw.wl.xkb.state);
if (_glfw.wl.xkb.context)
xkb_context_unref(_glfw.wl.xkb.context);
if (_glfw.wl.xkb.handle)
{
_glfw_dlclose(_glfw.wl.xkb.handle);
_glfw.wl.xkb.handle = NULL;
}
if (_glfw.wl.cursorTheme)
wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
if (_glfw.wl.cursorThemeHiDPI)
wl_cursor_theme_destroy(_glfw.wl.cursorThemeHiDPI);
if (_glfw.wl.cursor.handle)
{
_glfw_dlclose(_glfw.wl.cursor.handle);
_glfw.wl.cursor.handle = NULL;
}
if (_glfw.wl.cursorSurface)
wl_surface_destroy(_glfw.wl.cursorSurface);
if (_glfw.wl.subcompositor)
wl_subcompositor_destroy(_glfw.wl.subcompositor);
if (_glfw.wl.compositor)
wl_compositor_destroy(_glfw.wl.compositor);
if (_glfw.wl.shm)
wl_shm_destroy(_glfw.wl.shm);
if (_glfw.wl.shell)
wl_shell_destroy(_glfw.wl.shell);
if (_glfw.wl.viewporter)
wp_viewporter_destroy(_glfw.wl.viewporter);
if (_glfw.wl.decorationManager)
zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager);
if (_glfw.wl.wmBase)
xdg_wm_base_destroy(_glfw.wl.wmBase);
if (_glfw.wl.pointer)
wl_pointer_destroy(_glfw.wl.pointer);
if (_glfw.wl.keyboard)
@ -720,6 +1179,8 @@ void _glfwPlatformTerminate(void)
zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager);
if (_glfw.wl.pointerConstraints)
zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints);
if (_glfw.wl.idleInhibitManager)
zwp_idle_inhibit_manager_v1_destroy(_glfw.wl.idleInhibitManager);
if (_glfw.wl.registry)
wl_registry_destroy(_glfw.wl.registry);
if (_glfw.wl.display)
@ -727,6 +1188,11 @@ void _glfwPlatformTerminate(void)
wl_display_flush(_glfw.wl.display);
wl_display_disconnect(_glfw.wl.display);
}
if (_glfw.wl.timerfd >= 0)
close(_glfw.wl.timerfd);
if (_glfw.wl.cursorTimerfd >= 0)
close(_glfw.wl.cursorTimerfd);
}
const char* _glfwPlatformGetVersionString(void)
@ -743,4 +1209,3 @@ const char* _glfwPlatformGetVersionString(void)
#endif
;
}

View File

@ -32,7 +32,7 @@
#include <errno.h>
static void geometry(void* data,
static void outputHandleGeometry(void* data,
struct wl_output* output,
int32_t x,
int32_t y,
@ -52,10 +52,10 @@ static void geometry(void* data,
monitor->heightMM = physicalHeight;
snprintf(name, sizeof(name), "%s %s", make, model);
monitor->name = strdup(name);
monitor->name = _glfw_strdup(name);
}
static void mode(void* data,
static void outputHandleMode(void* data,
struct wl_output* output,
uint32_t flags,
int32_t width,
@ -81,14 +81,14 @@ static void mode(void* data,
monitor->wl.currentMode = monitor->modeCount - 1;
}
static void done(void* data, struct wl_output* output)
static void outputHandleDone(void* data, struct wl_output* output)
{
struct _GLFWmonitor *monitor = data;
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
}
static void scale(void* data,
static void outputHandleScale(void* data,
struct wl_output* output,
int32_t factor)
{
@ -98,10 +98,10 @@ static void scale(void* data,
}
static const struct wl_output_listener outputListener = {
geometry,
mode,
done,
scale,
outputHandleGeometry,
outputHandleMode,
outputHandleDone,
outputHandleScale,
};
@ -136,6 +136,7 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
monitor->wl.scale = 1;
monitor->wl.output = output;
monitor->wl.name = name;
wl_output_add_listener(output, &outputListener, monitor);
}
@ -145,6 +146,12 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
{
if (monitor->wl.output)
wl_output_destroy(monitor->wl.output);
}
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{
if (xpos)
@ -180,7 +187,8 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
"Wayland: Gamma ramp getting not supported yet");
}
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor,
const GLFWgammaramp* ramp)
{
// TODO
_glfwInputError(GLFW_PLATFORM_ERROR,

View File

@ -26,7 +26,9 @@
#include <wayland-client.h>
#include <xkbcommon/xkbcommon.h>
#ifdef HAVE_XKBCOMMON_COMPOSE_H
#include <xkbcommon/xkbcommon-compose.h>
#endif
#include <dlfcn.h>
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
@ -45,13 +47,21 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
#include "posix_thread.h"
#include "posix_time.h"
#ifdef __linux__
#include "linux_joystick.h"
#else
#include "null_joystick.h"
#endif
#include "xkb_unicode.h"
#include "egl_context.h"
#include "osmesa_context.h"
#include "wayland-xdg-shell-client-protocol.h"
#include "wayland-xdg-decoration-client-protocol.h"
#include "wayland-viewporter-client-protocol.h"
#include "wayland-relative-pointer-unstable-v1-client-protocol.h"
#include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
#include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle)
@ -68,6 +78,96 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
#define _GLFW_PLATFORM_CONTEXT_STATE
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
struct wl_cursor_image {
uint32_t width;
uint32_t height;
uint32_t hotspot_x;
uint32_t hotspot_y;
uint32_t delay;
};
struct wl_cursor {
unsigned int image_count;
struct wl_cursor_image** images;
char* name;
};
typedef struct wl_cursor_theme* (* PFN_wl_cursor_theme_load)(const char*, int, struct wl_shm*);
typedef void (* PFN_wl_cursor_theme_destroy)(struct wl_cursor_theme*);
typedef struct wl_cursor* (* PFN_wl_cursor_theme_get_cursor)(struct wl_cursor_theme*, const char*);
typedef struct wl_buffer* (* PFN_wl_cursor_image_get_buffer)(struct wl_cursor_image*);
#define wl_cursor_theme_load _glfw.wl.cursor.theme_load
#define wl_cursor_theme_destroy _glfw.wl.cursor.theme_destroy
#define wl_cursor_theme_get_cursor _glfw.wl.cursor.theme_get_cursor
#define wl_cursor_image_get_buffer _glfw.wl.cursor.image_get_buffer
typedef struct wl_egl_window* (* PFN_wl_egl_window_create)(struct wl_surface*, int, int);
typedef void (* PFN_wl_egl_window_destroy)(struct wl_egl_window*);
typedef void (* PFN_wl_egl_window_resize)(struct wl_egl_window*, int, int, int, int);
#define wl_egl_window_create _glfw.wl.egl.window_create
#define wl_egl_window_destroy _glfw.wl.egl.window_destroy
#define wl_egl_window_resize _glfw.wl.egl.window_resize
typedef struct xkb_context* (* PFN_xkb_context_new)(enum xkb_context_flags);
typedef void (* PFN_xkb_context_unref)(struct xkb_context*);
typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context*, const char*, enum xkb_keymap_format, enum xkb_keymap_compile_flags);
typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*);
typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*);
typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t);
typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
typedef void (* PFN_xkb_state_unref)(struct xkb_state*);
typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component);
#define xkb_context_new _glfw.wl.xkb.context_new
#define xkb_context_unref _glfw.wl.xkb.context_unref
#define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string
#define xkb_keymap_unref _glfw.wl.xkb.keymap_unref
#define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index
#define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats
#define xkb_state_new _glfw.wl.xkb.state_new
#define xkb_state_unref _glfw.wl.xkb.state_unref
#define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms
#define xkb_state_update_mask _glfw.wl.xkb.state_update_mask
#define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods
#ifdef HAVE_XKBCOMMON_COMPOSE_H
typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags);
typedef void (* PFN_xkb_compose_state_unref)(struct xkb_compose_state*);
typedef enum xkb_compose_feed_result (* PFN_xkb_compose_state_feed)(struct xkb_compose_state*, xkb_keysym_t);
typedef enum xkb_compose_status (* PFN_xkb_compose_state_get_status)(struct xkb_compose_state*);
typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_state*);
#define xkb_compose_table_new_from_locale _glfw.wl.xkb.compose_table_new_from_locale
#define xkb_compose_table_unref _glfw.wl.xkb.compose_table_unref
#define xkb_compose_state_new _glfw.wl.xkb.compose_state_new
#define xkb_compose_state_unref _glfw.wl.xkb.compose_state_unref
#define xkb_compose_state_feed _glfw.wl.xkb.compose_state_feed
#define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status
#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
#endif
#define _GLFW_DECORATION_WIDTH 4
#define _GLFW_DECORATION_TOP 24
#define _GLFW_DECORATION_VERTICAL (_GLFW_DECORATION_TOP + _GLFW_DECORATION_WIDTH)
#define _GLFW_DECORATION_HORIZONTAL (2 * _GLFW_DECORATION_WIDTH)
typedef enum _GLFWdecorationSideWayland
{
mainWindow,
topDecoration,
leftDecoration,
rightDecoration,
bottomDecoration,
} _GLFWdecorationSideWayland;
typedef struct _GLFWdecorationWayland
{
struct wl_surface* surface;
struct wl_subsurface* subsurface;
struct wp_viewport* viewport;
} _GLFWdecorationWayland;
// Wayland-specific per-window data
//
@ -76,12 +176,19 @@ typedef struct _GLFWwindowWayland
int width, height;
GLFWbool visible;
GLFWbool maximized;
GLFWbool hovered;
GLFWbool transparent;
struct wl_surface* surface;
struct wl_egl_window* native;
struct wl_shell_surface* shellSurface;
struct wl_callback* callback;
struct {
struct xdg_surface* surface;
struct xdg_toplevel* toplevel;
struct zxdg_toplevel_decoration_v1* decoration;
} xdg;
_GLFWcursor* currentCursor;
double cursorPosX, cursorPosY;
@ -98,6 +205,19 @@ typedef struct _GLFWwindowWayland
struct zwp_relative_pointer_v1* relativePointer;
struct zwp_locked_pointer_v1* lockedPointer;
} pointerLock;
struct zwp_idle_inhibitor_v1* idleInhibitor;
// This is a hack to prevent auto-iconification on creation.
GLFWbool justCreated;
struct {
GLFWbool serverSide;
struct wl_buffer* buffer;
_GLFWdecorationWayland top, left, right, bottom;
int focus;
} decorations;
} _GLFWwindowWayland;
// Wayland-specific global data
@ -107,38 +227,97 @@ typedef struct _GLFWlibraryWayland
struct wl_display* display;
struct wl_registry* registry;
struct wl_compositor* compositor;
struct wl_subcompositor* subcompositor;
struct wl_shell* shell;
struct wl_shm* shm;
struct wl_seat* seat;
struct wl_pointer* pointer;
struct wl_keyboard* keyboard;
struct xdg_wm_base* wmBase;
struct zxdg_decoration_manager_v1* decorationManager;
struct wp_viewporter* viewporter;
struct zwp_relative_pointer_manager_v1* relativePointerManager;
struct zwp_pointer_constraints_v1* pointerConstraints;
struct zwp_idle_inhibit_manager_v1* idleInhibitManager;
int compositorVersion;
int seatVersion;
struct wl_cursor_theme* cursorTheme;
struct wl_cursor_theme* cursorThemeHiDPI;
struct wl_surface* cursorSurface;
int cursorTimerfd;
uint32_t pointerSerial;
int32_t keyboardRepeatRate;
int32_t keyboardRepeatDelay;
int keyboardLastKey;
int keyboardLastScancode;
int timerfd;
short int keycodes[256];
short int scancodes[GLFW_KEY_LAST + 1];
struct {
void* handle;
struct xkb_context* context;
struct xkb_keymap* keymap;
struct xkb_state* state;
#ifdef HAVE_XKBCOMMON_COMPOSE_H
struct xkb_compose_state* composeState;
#endif
xkb_mod_mask_t controlMask;
xkb_mod_mask_t altMask;
xkb_mod_mask_t shiftMask;
xkb_mod_mask_t superMask;
xkb_mod_mask_t capsLockMask;
xkb_mod_mask_t numLockMask;
unsigned int modifiers;
PFN_xkb_context_new context_new;
PFN_xkb_context_unref context_unref;
PFN_xkb_keymap_new_from_string keymap_new_from_string;
PFN_xkb_keymap_unref keymap_unref;
PFN_xkb_keymap_mod_get_index keymap_mod_get_index;
PFN_xkb_keymap_key_repeats keymap_key_repeats;
PFN_xkb_state_new state_new;
PFN_xkb_state_unref state_unref;
PFN_xkb_state_key_get_syms state_key_get_syms;
PFN_xkb_state_update_mask state_update_mask;
PFN_xkb_state_serialize_mods state_serialize_mods;
#ifdef HAVE_XKBCOMMON_COMPOSE_H
PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;
PFN_xkb_compose_table_unref compose_table_unref;
PFN_xkb_compose_state_new compose_state_new;
PFN_xkb_compose_state_unref compose_state_unref;
PFN_xkb_compose_state_feed compose_state_feed;
PFN_xkb_compose_state_get_status compose_state_get_status;
PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;
#endif
} xkb;
_GLFWwindow* pointerFocus;
_GLFWwindow* keyboardFocus;
struct {
void* handle;
PFN_wl_cursor_theme_load theme_load;
PFN_wl_cursor_theme_destroy theme_destroy;
PFN_wl_cursor_theme_get_cursor theme_get_cursor;
PFN_wl_cursor_image_get_buffer image_get_buffer;
} cursor;
struct {
void* handle;
PFN_wl_egl_window_create window_create;
PFN_wl_egl_window_destroy window_destroy;
PFN_wl_egl_window_resize window_resize;
} egl;
} _GLFWlibraryWayland;
// Wayland-specific per-monitor data
@ -146,6 +325,7 @@ typedef struct _GLFWlibraryWayland
typedef struct _GLFWmonitorWayland
{
struct wl_output* output;
int name;
int currentMode;
int x;
@ -158,10 +338,12 @@ typedef struct _GLFWmonitorWayland
//
typedef struct _GLFWcursorWayland
{
struct wl_cursor_image* image;
struct wl_cursor* cursor;
struct wl_cursor* cursorHiDPI;
struct wl_buffer* buffer;
int width, height;
int xhot, yhot;
int currentImage;
} _GLFWcursorWayland;

File diff suppressed because it is too large Load Diff

View File

@ -461,17 +461,17 @@ static void detectEWMH(void)
//
static GLFWbool initExtensions(void)
{
_glfw.x11.vidmode.handle = dlopen("libXxf86vm.so.1", RTLD_LAZY | RTLD_GLOBAL);
_glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1");
if (_glfw.x11.vidmode.handle)
{
_glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension)
dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension");
_glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension");
_glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp)
dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp");
_glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp");
_glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp)
dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp");
_glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp");
_glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize)
dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize");
_glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize");
_glfw.x11.vidmode.available =
XF86VidModeQueryExtension(_glfw.x11.display,
@ -479,13 +479,17 @@ static GLFWbool initExtensions(void)
&_glfw.x11.vidmode.errorBase);
}
_glfw.x11.xi.handle = dlopen("libXi.so.6", RTLD_LAZY | RTLD_GLOBAL);
#if defined(__CYGWIN__)
_glfw.x11.xi.handle = _glfw_dlopen("libXi-6.so");
#else
_glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6");
#endif
if (_glfw.x11.xi.handle)
{
_glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion)
dlsym(_glfw.x11.xi.handle, "XIQueryVersion");
_glfw_dlsym(_glfw.x11.xi.handle, "XIQueryVersion");
_glfw.x11.xi.SelectEvents = (PFN_XISelectEvents)
dlsym(_glfw.x11.xi.handle, "XISelectEvents");
_glfw_dlsym(_glfw.x11.xi.handle, "XISelectEvents");
if (XQueryExtension(_glfw.x11.display,
"XInputExtension",
@ -505,45 +509,49 @@ static GLFWbool initExtensions(void)
}
}
_glfw.x11.randr.handle = dlopen("libXrandr.so.2", RTLD_LAZY | RTLD_GLOBAL);
#if defined(__CYGWIN__)
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr-2.so");
#else
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2");
#endif
if (_glfw.x11.randr.handle)
{
_glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma)
dlsym(_glfw.x11.randr.handle, "XRRAllocGamma");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRAllocGamma");
_glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma)
dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
_glfw.x11.randr.FreeCrtcInfo = (PFN_XRRFreeCrtcInfo)
dlsym(_glfw.x11.randr.handle, "XRRFreeCrtcInfo");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeCrtcInfo");
_glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma)
dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
_glfw.x11.randr.FreeOutputInfo = (PFN_XRRFreeOutputInfo)
dlsym(_glfw.x11.randr.handle, "XRRFreeOutputInfo");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeOutputInfo");
_glfw.x11.randr.FreeScreenResources = (PFN_XRRFreeScreenResources)
dlsym(_glfw.x11.randr.handle, "XRRFreeScreenResources");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeScreenResources");
_glfw.x11.randr.GetCrtcGamma = (PFN_XRRGetCrtcGamma)
dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGamma");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGamma");
_glfw.x11.randr.GetCrtcGammaSize = (PFN_XRRGetCrtcGammaSize)
dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize");
_glfw.x11.randr.GetCrtcInfo = (PFN_XRRGetCrtcInfo)
dlsym(_glfw.x11.randr.handle, "XRRGetCrtcInfo");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcInfo");
_glfw.x11.randr.GetOutputInfo = (PFN_XRRGetOutputInfo)
dlsym(_glfw.x11.randr.handle, "XRRGetOutputInfo");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputInfo");
_glfw.x11.randr.GetOutputPrimary = (PFN_XRRGetOutputPrimary)
dlsym(_glfw.x11.randr.handle, "XRRGetOutputPrimary");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputPrimary");
_glfw.x11.randr.GetScreenResourcesCurrent = (PFN_XRRGetScreenResourcesCurrent)
dlsym(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent");
_glfw.x11.randr.QueryExtension = (PFN_XRRQueryExtension)
dlsym(_glfw.x11.randr.handle, "XRRQueryExtension");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryExtension");
_glfw.x11.randr.QueryVersion = (PFN_XRRQueryVersion)
dlsym(_glfw.x11.randr.handle, "XRRQueryVersion");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryVersion");
_glfw.x11.randr.SelectInput = (PFN_XRRSelectInput)
dlsym(_glfw.x11.randr.handle, "XRRSelectInput");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRSelectInput");
_glfw.x11.randr.SetCrtcConfig = (PFN_XRRSetCrtcConfig)
dlsym(_glfw.x11.randr.handle, "XRRSetCrtcConfig");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcConfig");
_glfw.x11.randr.SetCrtcGamma = (PFN_XRRSetCrtcGamma)
dlsym(_glfw.x11.randr.handle, "XRRSetCrtcGamma");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcGamma");
_glfw.x11.randr.UpdateConfiguration = (PFN_XRRUpdateConfiguration)
dlsym(_glfw.x11.randr.handle, "XRRUpdateConfiguration");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRUpdateConfiguration");
if (XRRQueryExtension(_glfw.x11.display,
&_glfw.x11.randr.eventBase,
@ -593,26 +601,34 @@ static GLFWbool initExtensions(void)
RROutputChangeNotifyMask);
}
_glfw.x11.xcursor.handle = dlopen("libXcursor.so.1", RTLD_LAZY | RTLD_GLOBAL);
#if defined(__CYGWIN__)
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor-1.so");
#else
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1");
#endif
if (_glfw.x11.xcursor.handle)
{
_glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate)
dlsym(_glfw.x11.xcursor.handle, "XcursorImageCreate");
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageCreate");
_glfw.x11.xcursor.ImageDestroy = (PFN_XcursorImageDestroy)
dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy");
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy");
_glfw.x11.xcursor.ImageLoadCursor = (PFN_XcursorImageLoadCursor)
dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor");
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor");
}
_glfw.x11.xinerama.handle = dlopen("libXinerama.so.1", RTLD_LAZY | RTLD_GLOBAL);
#if defined(__CYGWIN__)
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama-1.so");
#else
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1");
#endif
if (_glfw.x11.xinerama.handle)
{
_glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive)
dlsym(_glfw.x11.xinerama.handle, "XineramaIsActive");
_glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaIsActive");
_glfw.x11.xinerama.QueryExtension = (PFN_XineramaQueryExtension)
dlsym(_glfw.x11.xinerama.handle, "XineramaQueryExtension");
_glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryExtension");
_glfw.x11.xinerama.QueryScreens = (PFN_XineramaQueryScreens)
dlsym(_glfw.x11.xinerama.handle, "XineramaQueryScreens");
_glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryScreens");
if (XineramaQueryExtension(_glfw.x11.display,
&_glfw.x11.xinerama.major,
@ -644,22 +660,30 @@ static GLFWbool initExtensions(void)
}
}
_glfw.x11.x11xcb.handle = dlopen("libX11-xcb.so.1", RTLD_LAZY | RTLD_GLOBAL);
#if defined(__CYGWIN__)
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb-1.so");
#else
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1");
#endif
if (_glfw.x11.x11xcb.handle)
{
_glfw.x11.x11xcb.GetXCBConnection = (PFN_XGetXCBConnection)
dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection");
_glfw_dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection");
}
_glfw.x11.xrender.handle = dlopen("libXrender.so.1", RTLD_LAZY | RTLD_GLOBAL);
#if defined(__CYGWIN__)
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender-1.so");
#else
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1");
#endif
if (_glfw.x11.xrender.handle)
{
_glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension)
dlsym(_glfw.x11.xrender.handle, "XRenderQueryExtension");
_glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryExtension");
_glfw.x11.xrender.QueryVersion = (PFN_XRenderQueryVersion)
dlsym(_glfw.x11.xrender.handle, "XRenderQueryVersion");
_glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryVersion");
_glfw.x11.xrender.FindVisualFormat = (PFN_XRenderFindVisualFormat)
dlsym(_glfw.x11.xrender.handle, "XRenderFindVisualFormat");
_glfw_dlsym(_glfw.x11.xrender.handle, "XRenderFindVisualFormat");
if (XRenderQueryExtension(_glfw.x11.display,
&_glfw.x11.xrender.errorBase,
@ -737,9 +761,18 @@ static GLFWbool initExtensions(void)
XInternAtom(_glfw.x11.display, "_NET_WM_ICON_NAME", False);
_glfw.x11.NET_WM_BYPASS_COMPOSITOR =
XInternAtom(_glfw.x11.display, "_NET_WM_BYPASS_COMPOSITOR", False);
_glfw.x11.NET_WM_WINDOW_OPACITY =
XInternAtom(_glfw.x11.display, "_NET_WM_WINDOW_OPACITY", False);
_glfw.x11.MOTIF_WM_HINTS =
XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False);
// The compositing manager selection name contains the screen number
{
char name[32];
snprintf(name, sizeof(name), "_NET_WM_CM_S%u", _glfw.x11.screen);
_glfw.x11.NET_WM_CM_Sx = XInternAtom(_glfw.x11.display, name, False);
}
return GLFW_TRUE;
}
@ -747,8 +780,9 @@ static GLFWbool initExtensions(void)
//
static void getSystemContentScale(float* xscale, float* yscale)
{
// NOTE: Default to the display-wide DPI as we don't currently have a policy
// for which monitor a window is considered to be on
// NOTE: Fall back to the display-wide DPI instead of RandR monitor DPI if
// Xft.dpi retrieval below fails as we don't currently have an exact
// policy for which monitor a window is considered to "be on"
float xdpi = DisplayWidth(_glfw.x11.display, _glfw.x11.screen) *
25.4f / DisplayWidthMM(_glfw.x11.display, _glfw.x11.screen);
float ydpi = DisplayHeight(_glfw.x11.display, _glfw.x11.screen) *
@ -985,8 +1019,6 @@ void _glfwPlatformTerminate(void)
_glfw.x11.im = NULL;
}
_glfwTerminateEGL();
if (_glfw.x11.display)
{
XCloseDisplay(_glfw.x11.display);
@ -995,30 +1027,49 @@ void _glfwPlatformTerminate(void)
if (_glfw.x11.x11xcb.handle)
{
dlclose(_glfw.x11.x11xcb.handle);
_glfw_dlclose(_glfw.x11.x11xcb.handle);
_glfw.x11.x11xcb.handle = NULL;
}
if (_glfw.x11.xcursor.handle)
{
dlclose(_glfw.x11.xcursor.handle);
_glfw_dlclose(_glfw.x11.xcursor.handle);
_glfw.x11.xcursor.handle = NULL;
}
if (_glfw.x11.randr.handle)
{
dlclose(_glfw.x11.randr.handle);
_glfw_dlclose(_glfw.x11.randr.handle);
_glfw.x11.randr.handle = NULL;
}
if (_glfw.x11.xinerama.handle)
{
dlclose(_glfw.x11.xinerama.handle);
_glfw_dlclose(_glfw.x11.xinerama.handle);
_glfw.x11.xinerama.handle = NULL;
}
// NOTE: This needs to be done after XCloseDisplay, as libGL registers
// cleanup callbacks that get called by it
if (_glfw.x11.xrender.handle)
{
_glfw_dlclose(_glfw.x11.xrender.handle);
_glfw.x11.xrender.handle = NULL;
}
if (_glfw.x11.vidmode.handle)
{
_glfw_dlclose(_glfw.x11.vidmode.handle);
_glfw.x11.vidmode.handle = NULL;
}
if (_glfw.x11.xi.handle)
{
_glfw_dlclose(_glfw.x11.xi.handle);
_glfw.x11.xi.handle = NULL;
}
// NOTE: These need to be unloaded after XCloseDisplay, as they register
// cleanup callbacks that get called by that function
_glfwTerminateEGL();
_glfwTerminateGLX();
#if defined(__linux__)

View File

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

View File

@ -257,6 +257,8 @@ typedef struct _GLFWlibraryX11
Atom NET_WM_STATE_DEMANDS_ATTENTION;
Atom NET_WM_BYPASS_COMPOSITOR;
Atom NET_WM_FULLSCREEN_MONITORS;
Atom NET_WM_WINDOW_OPACITY;
Atom NET_WM_CM_Sx;
Atom NET_ACTIVE_WINDOW;
Atom NET_FRAME_EXTENTS;
Atom NET_REQUEST_FRAME_EXTENTS;
@ -423,7 +425,7 @@ typedef struct _GLFWcursorX11
void _glfwPollMonitorsX11(void);
GLFWbool _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor);
Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot);

View File

@ -175,29 +175,6 @@ static Bool isSelPropNewValueNotify(Display* display, XEvent* event, XPointer po
event->xproperty.atom == notification->xselection.property;
}
// Translates a GLFW standard cursor to a font cursor shape
//
static int translateCursorShape(int shape)
{
switch (shape)
{
case GLFW_ARROW_CURSOR:
return XC_left_ptr;
case GLFW_IBEAM_CURSOR:
return XC_xterm;
case GLFW_CROSSHAIR_CURSOR:
return XC_crosshair;
case GLFW_HAND_CURSOR:
return XC_hand1;
case GLFW_HRESIZE_CURSOR:
return XC_sb_h_double_arrow;
case GLFW_VRESIZE_CURSOR:
return XC_sb_v_double_arrow;
}
return 0;
}
// Translates an X event modifier state mask
//
static int translateState(int state)
@ -212,6 +189,10 @@ static int translateState(int state)
mods |= GLFW_MOD_ALT;
if (state & Mod4Mask)
mods |= GLFW_MOD_SUPER;
if (state & LockMask)
mods |= GLFW_MOD_CAPS_LOCK;
if (state & Mod2Mask)
mods |= GLFW_MOD_NUM_LOCK;
return mods;
}
@ -227,23 +208,6 @@ static int translateKey(int scancode)
return _glfw.x11.keycodes[scancode];
}
// Return the GLFW window corresponding to the specified X11 window
//
static _GLFWwindow* findWindowByHandle(Window handle)
{
_GLFWwindow* window;
if (XFindContext(_glfw.x11.display,
handle,
_glfw.x11.context,
(XPointer*) &window) != 0)
{
return NULL;
}
return window;
}
// Sends an EWMH or ICCCM event to the window manager
//
static void sendEventToWM(_GLFWwindow* window, Atom type,
@ -567,12 +531,76 @@ static void updateCursorImage(_GLFWwindow* window)
}
}
// Apply disabled cursor mode to a focused window
//
static void disableCursor(_GLFWwindow* window)
{
if (_glfw.x11.xi.available)
{
XIEventMask em;
unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 };
em.deviceid = XIAllMasterDevices;
em.mask_len = sizeof(mask);
em.mask = mask;
XISetMask(mask, XI_RawMotion);
XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
}
_glfw.x11.disabledCursorWindow = window;
_glfwPlatformGetCursorPos(window,
&_glfw.x11.restoreCursorPosX,
&_glfw.x11.restoreCursorPosY);
updateCursorImage(window);
centerCursor(window);
XGrabPointer(_glfw.x11.display, window->x11.handle, True,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync,
window->x11.handle,
_glfw.x11.hiddenCursorHandle,
CurrentTime);
}
// Exit disabled cursor mode for the specified window
//
static void enableCursor(_GLFWwindow* window)
{
if (_glfw.x11.xi.available)
{
XIEventMask em;
unsigned char mask[] = { 0 };
em.deviceid = XIAllMasterDevices;
em.mask_len = sizeof(mask);
em.mask = mask;
XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
}
_glfw.x11.disabledCursorWindow = NULL;
XUngrabPointer(_glfw.x11.display, CurrentTime);
_glfwPlatformSetCursorPos(window,
_glfw.x11.restoreCursorPosX,
_glfw.x11.restoreCursorPosY);
updateCursorImage(window);
}
// Create the X11 window (and its colormap)
//
static GLFWbool createNativeWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
Visual* visual, int depth)
{
int width = wndconfig->width;
int height = wndconfig->height;
if (wndconfig->scaleToMonitor)
{
width *= _glfw.x11.contentScaleX;
height *= _glfw.x11.contentScaleY;
}
// Create a colormap based on the visual used by the current context
window->x11.colormap = XCreateColormap(_glfw.x11.display,
_glfw.x11.root,
@ -598,7 +626,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
window->x11.handle = XCreateWindow(_glfw.x11.display,
_glfw.x11.root,
0, 0,
wndconfig->width, wndconfig->height,
width, height,
0, // Border width
depth, // Color depth
InputOutput,
@ -701,26 +729,31 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
XFree(hints);
}
updateNormalHints(window, wndconfig->width, wndconfig->height);
updateNormalHints(window, width, height);
// Set ICCCM WM_CLASS property
{
XClassHint* hint = XAllocClassHint();
if (strlen(_glfw.hints.init.x11.className) &&
strlen(_glfw.hints.init.x11.classClass))
if (strlen(wndconfig->x11.instanceName) &&
strlen(wndconfig->x11.className))
{
hint->res_name = (char*) _glfw.hints.init.x11.className;
hint->res_class = (char*) _glfw.hints.init.x11.classClass;
}
else if (strlen(wndconfig->title))
{
hint->res_name = (char*) wndconfig->title;
hint->res_class = (char*) wndconfig->title;
hint->res_name = (char*) wndconfig->x11.instanceName;
hint->res_class = (char*) wndconfig->x11.className;
}
else
{
const char* resourceName = getenv("RESOURCE_NAME");
if (resourceName && strlen(resourceName))
hint->res_name = (char*) resourceName;
else if (strlen(wndconfig->title))
hint->res_name = (char*) wndconfig->title;
else
hint->res_name = (char*) "glfw-application";
if (strlen(wndconfig->title))
hint->res_class = (char*) wndconfig->title;
else
hint->res_class = (char*) "GLFW-Application";
}
@ -1047,7 +1080,7 @@ static const char* getSelectionString(Atom selection)
if (targets[i] == XA_STRING)
*selectionString = convertLatin1toUTF8(data);
else
*selectionString = strdup(data);
*selectionString = _glfw_strdup(data);
}
XFree(data);
@ -1067,10 +1100,8 @@ static const char* getSelectionString(Atom selection)
// Make the specified window and its video mode active on its monitor
//
static GLFWbool acquireMonitor(_GLFWwindow* window)
static void acquireMonitor(_GLFWwindow* window)
{
GLFWbool status;
if (_glfw.x11.saver.count == 0)
{
// Remember old screen saver settings
@ -1088,7 +1119,7 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
if (!window->monitor->window)
_glfw.x11.saver.count++;
status = _glfwSetVideoModeX11(window->monitor, &window->videoMode);
_glfwSetVideoModeX11(window->monitor, &window->videoMode);
if (window->x11.overrideRedirect)
{
@ -1104,7 +1135,6 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
}
_glfwInputMonitorWindow(window->monitor, window);
return status;
}
// Remove the window and restore the original video mode
@ -1203,8 +1233,10 @@ static void processEvent(XEvent *event)
return;
}
window = findWindowByHandle(event->xany.window);
if (window == NULL)
if (XFindContext(_glfw.x11.display,
event->xany.window,
_glfw.x11.context,
(XPointer*) &window) != 0)
{
// This is an event for a window that has already been destroyed
return;
@ -1426,7 +1458,7 @@ static void processEvent(XEvent *event)
// HACK: This is a workaround for WMs (KWM, Fluxbox) that otherwise
// ignore the defined cursor for hidden cursor mode
if (window->cursorMode == GLFW_CURSOR_HIDDEN)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_HIDDEN);
updateCursorImage(window);
_glfwInputCursorEnter(window, GLFW_TRUE);
return;
@ -1719,7 +1751,7 @@ static void processEvent(XEvent *event)
case FocusIn:
{
if (window->cursorMode == GLFW_CURSOR_DISABLED)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED);
disableCursor(window);
if (event->xfocus.mode == NotifyGrab ||
event->xfocus.mode == NotifyUngrab)
@ -1739,7 +1771,7 @@ static void processEvent(XEvent *event)
case FocusOut:
{
if (window->cursorMode == GLFW_CURSOR_DISABLED)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL);
enableCursor(window);
if (event->xfocus.mode == NotifyGrab ||
event->xfocus.mode == NotifyUngrab)
@ -1968,11 +2000,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
{
_glfwPlatformShowWindow(window);
updateWindowMode(window);
if (!acquireMonitor(window))
return GLFW_FALSE;
if (wndconfig->centerCursor)
centerCursor(window);
acquireMonitor(window);
}
XFlush(_glfw.x11.display);
@ -2444,16 +2472,34 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return maximized;
}
int _glfwPlatformWindowHovered(_GLFWwindow* window)
{
Window w = _glfw.x11.root;
while (w)
{
Window root;
int rootX, rootY, childX, childY;
unsigned int mask;
if (!XQueryPointer(_glfw.x11.display, w,
&root, &w, &rootX, &rootY, &childX, &childY, &mask))
{
return GLFW_FALSE;
}
if (w == window->x11.handle)
return GLFW_TRUE;
}
return GLFW_FALSE;
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{
if (!window->x11.transparent)
return GLFW_FALSE;
// Check whether a compositing manager is running
char name[32];
snprintf(name, sizeof(name), "_NET_WM_CM_S%u", _glfw.x11.screen);
const Atom selection = XInternAtom(_glfw.x11.display, name, False);
return XGetSelectionOwner(_glfw.x11.display, selection) != None;
return XGetSelectionOwner(_glfw.x11.display, _glfw.x11.NET_WM_CM_Sx) != None;
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
@ -2559,6 +2605,37 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
XFlush(_glfw.x11.display);
}
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
{
float opacity = 1.f;
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.NET_WM_CM_Sx))
{
CARD32* value = NULL;
if (_glfwGetWindowPropertyX11(window->x11.handle,
_glfw.x11.NET_WM_WINDOW_OPACITY,
XA_CARDINAL,
(unsigned char**) &value))
{
opacity = (float) (*value / (double) 0xffffffffu);
}
if (value)
XFree(value);
}
return opacity;
}
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
{
const CARD32 value = (CARD32) (0xffffffffu * (double) opacity);
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32,
PropModeReplace, (unsigned char*) &value, 1);
}
void _glfwPlatformPollEvents(void)
{
_GLFWwindow* window;
@ -2566,8 +2643,9 @@ void _glfwPlatformPollEvents(void)
#if defined(__linux__)
_glfwDetectJoystickConnectionLinux();
#endif
int count = XPending(_glfw.x11.display);
while (count--)
XPending(_glfw.x11.display);
while (XQLength(_glfw.x11.display))
{
XEvent event;
XNextEvent(_glfw.x11.display, &event);
@ -2657,53 +2735,14 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{
if (mode == GLFW_CURSOR_DISABLED)
{
if (_glfw.x11.xi.available)
{
XIEventMask em;
unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 };
em.deviceid = XIAllMasterDevices;
em.mask_len = sizeof(mask);
em.mask = mask;
XISetMask(mask, XI_RawMotion);
XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
}
_glfw.x11.disabledCursorWindow = window;
_glfwPlatformGetCursorPos(window,
&_glfw.x11.restoreCursorPosX,
&_glfw.x11.restoreCursorPosY);
centerCursor(window);
XGrabPointer(_glfw.x11.display, window->x11.handle, True,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync,
window->x11.handle,
_glfw.x11.hiddenCursorHandle,
CurrentTime);
if (_glfwPlatformWindowFocused(window))
disableCursor(window);
}
else if (_glfw.x11.disabledCursorWindow == window)
{
if (_glfw.x11.xi.available)
{
XIEventMask em;
unsigned char mask[] = { 0 };
em.deviceid = XIAllMasterDevices;
em.mask_len = sizeof(mask);
em.mask = mask;
XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
}
_glfw.x11.disabledCursorWindow = NULL;
XUngrabPointer(_glfw.x11.display, CurrentTime);
_glfwPlatformSetCursorPos(window,
_glfw.x11.restoreCursorPosX,
_glfw.x11.restoreCursorPosY);
}
enableCursor(window);
else
updateCursorImage(window);
XFlush(_glfw.x11.display);
}
@ -2746,8 +2785,24 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
{
cursor->x11.handle = XCreateFontCursor(_glfw.x11.display,
translateCursorShape(shape));
int native = 0;
if (shape == GLFW_ARROW_CURSOR)
native = XC_left_ptr;
else if (shape == GLFW_IBEAM_CURSOR)
native = XC_xterm;
else if (shape == GLFW_CROSSHAIR_CURSOR)
native = XC_crosshair;
else if (shape == GLFW_HAND_CURSOR)
native = XC_hand1;
else if (shape == GLFW_HRESIZE_CURSOR)
native = XC_sb_h_double_arrow;
else if (shape == GLFW_VRESIZE_CURSOR)
native = XC_sb_v_double_arrow;
else
return GLFW_FALSE;
cursor->x11.handle = XCreateFontCursor(_glfw.x11.display, native);
if (!cursor->x11.handle)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
@ -2773,10 +2828,10 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
}
}
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
void _glfwPlatformSetClipboardString(const char* string)
{
free(_glfw.x11.clipboardString);
_glfw.x11.clipboardString = strdup(string);
_glfw.x11.clipboardString = _glfw_strdup(string);
XSetSelectionOwner(_glfw.x11.display,
_glfw.x11.CLIPBOARD,
@ -2791,7 +2846,7 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
}
}
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
const char* _glfwPlatformGetClipboardString(void)
{
return getSelectionString(_glfw.x11.CLIPBOARD);
}
@ -2968,7 +3023,7 @@ GLFWAPI void glfwSetX11SelectionString(const char* string)
_GLFW_REQUIRE_INIT();
free(_glfw.x11.primarySelectionString);
_glfw.x11.primarySelectionString = strdup(string);
_glfw.x11.primarySelectionString = _glfw_strdup(string);
XSetSelectionOwner(_glfw.x11.display,
_glfw.x11.PRIMARY,

View File

@ -32,8 +32,8 @@ add_executable(gamma WIN32 MACOSX_BUNDLE gamma.c ${GLAD})
add_executable(icon WIN32 MACOSX_BUNDLE icon.c ${GLAD})
add_executable(inputlag WIN32 MACOSX_BUNDLE inputlag.c ${GETOPT} ${GLAD})
add_executable(joysticks WIN32 MACOSX_BUNDLE joysticks.c ${GLAD})
add_executable(sharing WIN32 MACOSX_BUNDLE sharing.c ${GETOPT} ${GLAD})
add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c ${GETOPT} ${GLAD})
add_executable(opacity WIN32 MACOSX_BUNDLE opacity.c ${GLAD})
add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c ${GLAD})
add_executable(threads WIN32 MACOSX_BUNDLE threads.c ${TINYCTHREAD} ${GLAD})
add_executable(timeout WIN32 MACOSX_BUNDLE timeout.c ${GLAD})
add_executable(title WIN32 MACOSX_BUNDLE title.c ${GLAD})
@ -46,8 +46,8 @@ if (RT_LIBRARY)
target_link_libraries(threads "${RT_LIBRARY}")
endif()
set(WINDOWS_BINARIES empty gamma icon inputlag joysticks sharing tearing threads
timeout title windows)
set(WINDOWS_BINARIES empty gamma icon inputlag joysticks opacity tearing
threads timeout title windows)
set(CONSOLE_BINARIES clipboard events msaa glfwinfo iconify monitors reopen
cursor)
@ -55,7 +55,7 @@ if (VULKAN_FOUND)
add_executable(vulkan WIN32 vulkan.c ${ICON})
target_include_directories(vulkan PRIVATE "${VULKAN_INCLUDE_DIR}")
if (GLFW_VULKAN_STATIC)
target_link_libraries(vulkan "${VULKAN_STATIC_LIBRARY}" ${GLFW_VULKAN_DEPS})
target_link_libraries(vulkan "${VULKAN_STATIC_LIBRARY}")
else()
target_link_libraries(vulkan "${VULKAN_LIBRARY}")
endif()
@ -76,7 +76,7 @@ if (APPLE)
set_target_properties(gamma PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gamma")
set_target_properties(inputlag PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Input Lag")
set_target_properties(joysticks PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Joysticks")
set_target_properties(sharing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Sharing")
set_target_properties(opacity PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Opacity")
set_target_properties(tearing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Tearing")
set_target_properties(threads PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Threads")
set_target_properties(timeout PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Timeout")

View File

@ -67,7 +67,7 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
{
const char* string;
string = glfwGetClipboardString(window);
string = glfwGetClipboardString(NULL);
if (string)
printf("Clipboard contains \"%s\"\n", string);
else
@ -79,18 +79,13 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
if (mods == MODIFIER)
{
const char* string = "Hello GLFW World!";
glfwSetClipboardString(window, string);
glfwSetClipboardString(NULL, string);
printf("Setting clipboard to \"%s\"\n", string);
}
break;
}
}
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
int main(int argc, char** argv)
{
int ch;
@ -132,7 +127,6 @@ int main(int argc, char** argv)
glfwSwapInterval(1);
glfwSetKeyCallback(window, key_callback);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glClearColor(0.5f, 0.5f, 0.5f, 0);

View File

@ -244,6 +244,10 @@ static const char* get_mods_name(int mods)
strcat(name, " alt");
if (mods & GLFW_MOD_SUPER)
strcat(name, " super");
if (mods & GLFW_MOD_CAPS_LOCK)
strcat(name, " capslock-on");
if (mods & GLFW_MOD_NUM_LOCK)
strcat(name, " numlock-on");
return name;
}
@ -285,8 +289,13 @@ static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Framebuffer size: %i %i\n",
counter++, slot->number, glfwGetTime(), width, height);
}
glViewport(0, 0, width, height);
static void window_content_scale_callback(GLFWwindow* window, float xscale, float yscale)
{
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Window content scale: %0.3f %0.3f\n",
counter++, slot->number, glfwGetTime(), xscale, yscale);
}
static void window_close_callback(GLFWwindow* window)
@ -400,6 +409,15 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
printf("(( closing %s ))\n", slot->closeable ? "enabled" : "disabled");
break;
}
case GLFW_KEY_L:
{
const int state = glfwGetInputMode(window, GLFW_LOCK_KEY_MODS);
glfwSetInputMode(window, GLFW_LOCK_KEY_MODS, !state);
printf("(( lock key mods %s ))\n", !state ? "enabled" : "disabled");
break;
}
}
}
@ -586,6 +604,7 @@ int main(int argc, char** argv)
glfwSetWindowPosCallback(slots[i].window, window_pos_callback);
glfwSetWindowSizeCallback(slots[i].window, window_size_callback);
glfwSetFramebufferSizeCallback(slots[i].window, framebuffer_size_callback);
glfwSetWindowContentScaleCallback(slots[i].window, window_content_scale_callback);
glfwSetWindowCloseCallback(slots[i].window, window_close_callback);
glfwSetWindowRefreshCallback(slots[i].window, window_refresh_callback);
glfwSetWindowFocusCallback(slots[i].window, window_focus_callback);

View File

@ -38,6 +38,7 @@
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_BUTTON_TRIGGER_ON_RELEASE
#include <nuklear.h>
#define NK_GLFW_GL2_IMPLEMENTATION
@ -45,6 +46,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void error_callback(int error, const char* description)
{
@ -85,6 +87,7 @@ int main(int argc, char** argv)
{
GLFWmonitor* monitor = NULL;
GLFWwindow* window;
GLFWgammaramp orig_ramp;
struct nk_context* nk;
struct nk_font_atlas* atlas;
float gamma_value = 1.f;
@ -96,6 +99,8 @@ int main(int argc, char** argv)
monitor = glfwGetPrimaryMonitor();
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
window = glfwCreateWindow(800, 400, "Gamma Test", NULL, NULL);
if (!window)
{
@ -103,6 +108,18 @@ int main(int argc, char** argv)
exit(EXIT_FAILURE);
}
{
const GLFWgammaramp* ramp = glfwGetGammaRamp(monitor);
const size_t array_size = ramp->size * sizeof(short);
orig_ramp.size = ramp->size;
orig_ramp.red = malloc(array_size);
orig_ramp.green = malloc(array_size);
orig_ramp.blue = malloc(array_size);
memcpy(orig_ramp.red, ramp->red, array_size);
memcpy(orig_ramp.green, ramp->green, array_size);
memcpy(orig_ramp.blue, ramp->blue, array_size);
}
glfwMakeContextCurrent(window);
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
glfwSwapInterval(1);
@ -120,23 +137,27 @@ int main(int argc, char** argv)
glfwGetWindowSize(window, &width, &height);
area = nk_rect(0.f, 0.f, (float) width, (float) height);
nk_window_set_bounds(nk, "", area);
glClear(GL_COLOR_BUFFER_BIT);
nk_glfw3_new_frame();
if (nk_begin(nk, "", area, 0))
{
const GLFWgammaramp* ramp = glfwGetGammaRamp(monitor);
nk_window_set_bounds(nk, area);
const GLFWgammaramp* ramp;
nk_layout_row_dynamic(nk, 30, 2);
nk_layout_row_dynamic(nk, 30, 3);
if (nk_slider_float(nk, 0.1f, &gamma_value, 5.f, 0.1f))
glfwSetGamma(monitor, gamma_value);
nk_labelf(nk, NK_TEXT_LEFT, "%0.1f", gamma_value);
if (nk_button_label(nk, "Revert"))
glfwSetGammaRamp(monitor, &orig_ramp);
ramp = glfwGetGammaRamp(monitor);
nk_layout_row_dynamic(nk, height - 60.f, 3);
chart_ramp_array(nk, nk_rgb(255, 0, 0), ramp->size, ramp->red);
chart_ramp_array(nk, nk_rgb(0, 255, 0), ramp->size, ramp->green);
chart_ramp_array(nk, nk_rgb(0,0, 255), ramp->size, ramp->blue);
chart_ramp_array(nk, nk_rgb(0, 0, 255), ramp->size, ramp->blue);
}
nk_end(nk);
@ -146,6 +167,10 @@ int main(int argc, char** argv)
glfwWaitEventsTimeout(1.0);
}
free(orig_ramp.red);
free(orig_ramp.green);
free(orig_ramp.blue);
nk_glfw3_shutdown();
glfwTerminate();
exit(EXIT_SUCCESS);

View File

@ -127,8 +127,6 @@ static void window_size_callback(GLFWwindow* window, int width, int height)
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
printf("%0.2f Framebuffer resized to %ix%i\n", glfwGetTime(), width, height);
glViewport(0, 0, width, height);
}
static void window_focus_callback(GLFWwindow* window, int focused)

View File

@ -200,6 +200,8 @@ int main(int argc, char** argv)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
window = glfwCreateWindow(width, height, "Input lag test", monitor, NULL);
if (!window)
{

View File

@ -85,6 +85,32 @@ static void joystick_callback(int jid, int event)
glfwRequestWindowAttention(window);
}
static void drop_callback(GLFWwindow* window, int count, const char** paths)
{
int i;
for (i = 0; i < count; i++)
{
long size;
char* text;
FILE* stream = fopen(paths[i], "rb");
if (!stream)
continue;
fseek(stream, 0, SEEK_END);
size = ftell(stream);
fseek(stream, 0, SEEK_SET);
text = malloc(size + 1);
text[size] = '\0';
if (fread(text, 1, size, stream) == size)
glfwUpdateGamepadMappings(text);
free(text);
fclose(stream);
}
}
static const char* joystick_label(int jid)
{
static char label[1024];
@ -154,6 +180,8 @@ int main(void)
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
window = glfwCreateWindow(800, 600, "Joystick Test", NULL, NULL);
if (!window)
{
@ -176,6 +204,7 @@ int main(void)
}
glfwSetJoystickCallback(joystick_callback);
glfwSetDropCallback(window, drop_callback);
while (!glfwWindowShouldClose(window))
{

107
tests/opacity.c Normal file
View File

@ -0,0 +1,107 @@
//========================================================================
// Window opacity test program
// Copyright (c) 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.
//
//========================================================================
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#define NK_IMPLEMENTATION
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_STANDARD_VARARGS
#include <nuklear.h>
#define NK_GLFW_GL2_IMPLEMENTATION
#include <nuklear_glfw_gl2.h>
#include <stdio.h>
#include <stdlib.h>
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
int main(int argc, char** argv)
{
GLFWwindow* window;
struct nk_context* nk;
struct nk_font_atlas* atlas;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
window = glfwCreateWindow(400, 400, "Opacity", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
glfwSwapInterval(1);
nk = nk_glfw3_init(window, NK_GLFW3_INSTALL_CALLBACKS);
nk_glfw3_font_stash_begin(&atlas);
nk_glfw3_font_stash_end();
while (!glfwWindowShouldClose(window))
{
int width, height;
struct nk_rect area;
glfwGetWindowSize(window, &width, &height);
area = nk_rect(0.f, 0.f, (float) width, (float) height);
glClear(GL_COLOR_BUFFER_BIT);
nk_glfw3_new_frame();
if (nk_begin(nk, "", area, 0))
{
float opacity = glfwGetWindowOpacity(window);
nk_layout_row_dynamic(nk, 30, 2);
if (nk_slider_float(nk, 0.f, &opacity, 1.f, 0.001f))
glfwSetWindowOpacity(window, opacity);
nk_labelf(nk, NK_TEXT_LEFT, "%0.3f", opacity);
}
nk_end(nk);
nk_glfw3_render(NK_ANTI_ALIASING_ON);
glfwSwapBuffers(window);
glfwWaitEventsTimeout(1.0);
}
nk_glfw3_shutdown();
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -36,7 +36,6 @@
#include <math.h>
#include "linmath.h"
#include "getopt.h"
static const struct
{
@ -69,14 +68,6 @@ static int swap_tear;
static int swap_interval;
static double frame_rate;
static void usage(void)
{
printf("Usage: tearing [-h] [-f]\n");
printf("Options:\n");
printf(" -f create full screen window\n");
printf(" -h show this help\n");
}
static void update_window_title(GLFWwindow* window)
{
char title[256];
@ -101,11 +92,6 @@ static void error_callback(int error, const char* description)
fprintf(stderr, "Error: %s\n", description);
}
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action != GLFW_PRESS)
@ -138,64 +124,50 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, 1);
break;
case GLFW_KEY_F11:
case GLFW_KEY_ENTER:
{
static int x, y, width, height;
if (mods != GLFW_MOD_ALT)
return;
if (glfwGetWindowMonitor(window))
glfwSetWindowMonitor(window, NULL, x, y, width, height, 0);
else
{
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwGetWindowPos(window, &x, &y);
glfwGetWindowSize(window, &width, &height);
glfwSetWindowMonitor(window, monitor,
0, 0, mode->width, mode->height,
mode->refreshRate);
}
break;
}
}
}
int main(int argc, char** argv)
{
int ch, width, height;
unsigned long frame_count = 0;
double last_time, current_time;
int fullscreen = GLFW_FALSE;
GLFWmonitor* monitor = NULL;
GLFWwindow* window;
GLuint vertex_buffer, vertex_shader, fragment_shader, program;
GLint mvp_location, vpos_location;
while ((ch = getopt(argc, argv, "fh")) != -1)
{
switch (ch)
{
case 'h':
usage();
exit(EXIT_SUCCESS);
case 'f':
fullscreen = GLFW_TRUE;
break;
}
}
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
if (fullscreen)
{
const GLFWvidmode* mode;
monitor = glfwGetPrimaryMonitor();
mode = glfwGetVideoMode(monitor);
glfwWindowHint(GLFW_RED_BITS, mode->redBits);
glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
width = mode->width;
height = mode->height;
}
else
{
width = 640;
height = 480;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
window = glfwCreateWindow(width, height, "", monitor, NULL);
window = glfwCreateWindow(640, 480, "Tearing detector", NULL, NULL);
if (!window)
{
glfwTerminate();
@ -211,7 +183,6 @@ int main(int argc, char** argv)
swap_tear = (glfwExtensionSupported("WGL_EXT_swap_control_tear") ||
glfwExtensionSupported("GLX_EXT_swap_control_tear"));
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetKeyCallback(window, key_callback);
glGenBuffers(1, &vertex_buffer);
@ -240,9 +211,13 @@ int main(int argc, char** argv)
while (!glfwWindowShouldClose(window))
{
int width, height;
mat4x4 m, p, mvp;
float position = cosf((float) glfwGetTime() * 4.f) * 0.75f;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
mat4x4_ortho(p, -1.f, 1.f, -1.f, 1.f, 0.f, 1.f);

View File

@ -38,11 +38,6 @@ static void error_callback(int error, const char* description)
fprintf(stderr, "Error: %s\n", description);
}
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
int main(void)
{
GLFWwindow* window;
@ -63,8 +58,6 @@ int main(void)
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
glfwSwapInterval(1);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);

View File

@ -56,9 +56,10 @@ static const struct
static void usage(void)
{
printf("Usage: windows [-h] [-b]\n");
printf("Usage: windows [-h] [-b] [-f] \n");
printf("Options:\n");
printf(" -b create decorated windows\n");
printf(" -f set focus on show off for all but first window\n");
printf(" -h show this help\n");
}
@ -92,16 +93,20 @@ int main(int argc, char** argv)
{
int i, ch;
int decorated = GLFW_FALSE;
int focusOnShow = GLFW_TRUE;
int running = GLFW_TRUE;
GLFWwindow* windows[4];
while ((ch = getopt(argc, argv, "bh")) != -1)
while ((ch = getopt(argc, argv, "bfh")) != -1)
{
switch (ch)
{
case 'b':
decorated = GLFW_TRUE;
break;
case 'f':
focusOnShow = GLFW_FALSE;
break;
case 'h':
usage();
exit(EXIT_SUCCESS);
@ -122,6 +127,8 @@ int main(int argc, char** argv)
for (i = 0; i < 4; i++)
{
int left, top, right, bottom;
if (i)
glfwWindowHint(GLFW_FOCUS_ON_SHOW, focusOnShow);
windows[i] = glfwCreateWindow(200, 200, titles[i], NULL, NULL);
if (!windows[i])