mirror of
https://github.com/glfw/glfw.git
synced 2026-09-24 01:28:58 +00:00
Compare commits
388 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c702cdd1c8 | |||
| e07f0c9b6b | |||
| 35682ec3fa | |||
| f4cd470bcb | |||
| 3c9011030f | |||
| 2040309d0c | |||
| 58cc4b2c5c | |||
| b020467192 | |||
| d10463ac91 | |||
| cfb5cb8805 | |||
| 1d75b205cb | |||
| f940a97500 | |||
| ff6a8891d4 | |||
| c29e4455bb | |||
| 9bfa499d94 | |||
| 53b193a161 | |||
| e98102162f | |||
| f5d3954568 | |||
| ae53cd29ef | |||
| a678665c49 | |||
| 8a8eefa0d8 | |||
| 525ad7bfb8 | |||
| eb7c9994bf | |||
| 94c7aa0d67 | |||
| f2617a671f | |||
| 4778d02c67 | |||
| f710db6504 | |||
| 0e759c9422 | |||
| a162004a90 | |||
| ae44a28125 | |||
| 14856e8b60 | |||
| 73567ae5be | |||
| 0d5f7a9eab | |||
| a199efae44 | |||
| 14ad79f035 | |||
| f9b0dc9827 | |||
| 440e7e36f3 | |||
| 407a3e2860 | |||
| 5fbf4ddde8 | |||
| 6e69f63ffa | |||
| eb732457ea | |||
| 973bf29622 | |||
| bb3ab87a18 | |||
| d6b3a60fbc | |||
| 6c421f131d | |||
| 93186e4999 | |||
| 2c1fc13ee4 | |||
| 20b12204af | |||
| ee9dffcd66 | |||
| 370eac3c48 | |||
| 1034b6e0db | |||
| ac94014ef8 | |||
| 9f91bd6ea9 | |||
| 84077401e9 | |||
| 10c18f8124 | |||
| 09e0714284 | |||
| 7c2c7858c6 | |||
| 9da2285b14 | |||
| 6158801aeb | |||
| 3d493b60f1 | |||
| 18ee28bf82 | |||
| 5f8431d7ca | |||
| 0ee9a03b1e | |||
| c3cba58a71 | |||
| ce4672d74b | |||
| 8dab9f6ab1 | |||
| 682f1cf203 | |||
| 0e8c4ea7ce | |||
| fd72eb917e | |||
| d81946a35b | |||
| 638c4b604e | |||
| b8df6ae3c1 | |||
| df434c839a | |||
| c2858e9ed7 | |||
| 7c87948eaf | |||
| 30489c5aa1 | |||
| 390a66d2e7 | |||
| 9e6c0c747b | |||
| 8094a1c99e | |||
| bfe2d42af4 | |||
| 1a250234ea | |||
| 3169179de1 | |||
| fe9c7a01c5 | |||
| 65166858ff | |||
| b5e24676a4 | |||
| 40ab709aac | |||
| d18431338a | |||
| cc87d5ab10 | |||
| 25cf67667f | |||
| bb13275b72 | |||
| 9c513346ad | |||
| 68809869f9 | |||
| 1fe319d234 | |||
| d630684654 | |||
| 8b81a03a5a | |||
| 9903f88947 | |||
| d73ab0bd58 | |||
| 11e47f08b1 | |||
| aef4edadd0 | |||
| bf7cc2ffac | |||
| adebcc7111 | |||
| fb4f633243 | |||
| 49130ab8ec | |||
| baed2dad56 | |||
| 98990217bc | |||
| 71018b4ab5 | |||
| 79e2433eb0 | |||
| 546c99a3a3 | |||
| 7b877c4e24 | |||
| 31cbb20ba2 | |||
| f2756d0b3f | |||
| 9718675d86 | |||
| 80d181f12d | |||
| a7a70cf34d | |||
| 2867ca1e5b | |||
| a1154247fa | |||
| fcedb0be32 | |||
| bf09dba95b | |||
| 16bf872117 | |||
| 1be81a1540 | |||
| 81963967e5 | |||
| 66c0394ae1 | |||
| f308228a19 | |||
| 56ecd62f58 | |||
| 94ee10e655 | |||
| 07cc6e00da | |||
| 6d463d36fa | |||
| 95e282d5a0 | |||
| 5aeb37d1b8 | |||
| da68ec56c3 | |||
| 5d0d30db38 | |||
| 32e78aeb2e | |||
| 93e66661d3 | |||
| ac009a5f5c | |||
| 51f0cd3b51 | |||
| 019609b6cd | |||
| eed94448fd | |||
| 25b7eba4a0 | |||
| 176ab9a5d2 | |||
| f4fb25b63d | |||
| e3be6b8ae0 | |||
| 3d110d2e1b | |||
| 0b5023bc62 | |||
| 9dbc935afb | |||
| f7dc6df02c | |||
| f30acd8f74 | |||
| 16ae02ab85 | |||
| 4637c31d82 | |||
| 7f0d5e0a03 | |||
| f8668c5a9f | |||
| 1955c37c48 | |||
| d099181307 | |||
| b97039f3f5 | |||
| a368d89c94 | |||
| d80d4be030 | |||
| d8551b73f6 | |||
| 45ca8b8d19 | |||
| 58a247b26d | |||
| 2f8b71d7a1 | |||
| ce5e649d3b | |||
| 80e4922b5e | |||
| c23fca6343 | |||
| 0882fffc37 | |||
| ad9458a14c | |||
| 0d6937b33b | |||
| af866e05d2 | |||
| b4ea2d32e6 | |||
| 0c70eb8d5c | |||
| 08737bdc02 | |||
| 0d9e71fe81 | |||
| ac01da6953 | |||
| 99e72830ea | |||
| 3f852c321f | |||
| 15d102b75e | |||
| 0019f7a45e | |||
| 2d0ffd788b | |||
| e27dc50689 | |||
| b7a0f225ea | |||
| 29a75ab09d | |||
| 3ee7f8f695 | |||
| e376404d38 | |||
| 079518617c | |||
| 549308051d | |||
| 5bc1c38159 | |||
| f95c9d1bf3 | |||
| 75e44abf09 | |||
| a397195d3f | |||
| ab2247f8f3 | |||
| 5b7281bd41 | |||
| 85eda77d35 | |||
| 213dd2d0d6 | |||
| 00d2efb9ab | |||
| 4feede6dd5 | |||
| c0bc10427c | |||
| 2d8d8f5917 | |||
| 472e5fc4a9 | |||
| e55e616f1f | |||
| 50a228394f | |||
| afbd589348 | |||
| 82284b86eb | |||
| d3247a8c83 | |||
| 67c9155f3b | |||
| 8e899ccc29 | |||
| d55c57b504 | |||
| ea6c50d9e2 | |||
| 6634c47e57 | |||
| 2fa90ae19f | |||
| 2e9aff759e | |||
| 617c42b20a | |||
| 953106e74d | |||
| 07bf2b166b | |||
| 8c0512027f | |||
| be51c201dd | |||
| 57f872054c | |||
| 9bb5e880ae | |||
| 9610d68f19 | |||
| 539a728063 | |||
| 58c05ba8ee | |||
| d5de48ab53 | |||
| 99762ad7f0 | |||
| 6da26c8d6c | |||
| d2952e4e92 | |||
| 206f9ca4bc | |||
| d1a2ec4d20 | |||
| 78666204a1 | |||
| 2ca9a0979e | |||
| 5bcf9c76fd | |||
| 4dee58d480 | |||
| 32f482a6d8 | |||
| 0321bec232 | |||
| 2bb8517e9e | |||
| f4ea29cd06 | |||
| 52f7684487 | |||
| d2779aa765 | |||
| a3007b9b0e | |||
| 14a3fe0ac0 | |||
| beaeb0d4af | |||
| c48127fa9e | |||
| 372e908682 | |||
| bc7ebc1a89 | |||
| 186d03b32a | |||
| c8ea64976f | |||
| 2023095d8e | |||
| 8597002a17 | |||
| 4f7102be26 | |||
| e4e3e50867 | |||
| fa0b5e1b85 | |||
| 018ae69b33 | |||
| 244d6d7823 | |||
| d1d08ef99f | |||
| 85c6168bba | |||
| 2f5e230338 | |||
| baa9cd8968 | |||
| 412eb6a611 | |||
| 4e8e25a521 | |||
| 731ff91acd | |||
| b234e28d5d | |||
| d6fcbdc38b | |||
| f737e8ce9f | |||
| 6350641f0a | |||
| 16ddfafeaa | |||
| 4884232360 | |||
| 9457cf33d1 | |||
| 66b16f1fc1 | |||
| 2226e60944 | |||
| 9558b85f7b | |||
| c9003b5547 | |||
| 9f63a8abfa | |||
| 4ff66a7818 | |||
| 72d58d7b93 | |||
| 11c15b562d | |||
| 9b81d72c46 | |||
| b0277a129b | |||
| 120082ee3a | |||
| 6abb5cbcbb | |||
| b215a989f5 | |||
| 5fe4dfb511 | |||
| cf2eab5b4e | |||
| 55d0560746 | |||
| 1982543cd2 | |||
| aaf2800c9c | |||
| 62414bff6e | |||
| 2376d3b16a | |||
| 6a65341e14 | |||
| bff31f006e | |||
| 7410346c5c | |||
| 27a8b3c17b | |||
| 7c070f55be | |||
| 3d8aa53573 | |||
| 7c88c92778 | |||
| 21355e31db | |||
| 97dbd8b63b | |||
| 0df9cc2fc5 | |||
| e2ce3026a0 | |||
| 6a8ade99c7 | |||
| 43fc399cd1 | |||
| 5ae781586f | |||
| 798d7c6d68 | |||
| 368dec7ac7 | |||
| 12dcfd08b8 | |||
| 0e0862cfc7 | |||
| 5b306f0390 | |||
| d88347ee7d | |||
| 7a8516d296 | |||
| c50aba1335 | |||
| 6d9a58bfef | |||
| 071a049f07 | |||
| e019f7e7f2 | |||
| 315c9455d5 | |||
| 97b0c645bf | |||
| 53f46d32e2 | |||
| e9560ef021 | |||
| a44f2c0e65 | |||
| c54b5da403 | |||
| c745f434f5 | |||
| 3fa6f48ac6 | |||
| ce8fe645f4 | |||
| 79eaf49ec0 | |||
| 9950d8a319 | |||
| 4928e2bf0a | |||
| a570d0a129 | |||
| 918b4e81d2 | |||
| dd96d0ac93 | |||
| 106a617fa8 | |||
| 3817b4e1c5 | |||
| 2ba461e348 | |||
| 5352e2caa0 | |||
| 463930761b | |||
| 980f955f6c | |||
| f69829f7b4 | |||
| c3fd757b03 | |||
| 343288c1f6 | |||
| 355b46e6c5 | |||
| 366b90be1a | |||
| 77a8f103d8 | |||
| 4250725a60 | |||
| b151904316 | |||
| 558afefc04 | |||
| 21eabd3938 | |||
| 0c090a8c8b | |||
| 926d2beddb | |||
| 98bdd36231 | |||
| 8e870d4cc0 | |||
| afb5449ca4 | |||
| 5a74b5008d | |||
| 72ac5badb0 | |||
| 3af0c47c97 | |||
| a46c95c7f2 | |||
| 6801478a13 | |||
| ef5a21496c | |||
| 67a55efa27 | |||
| c5694b3013 | |||
| 466347a335 | |||
| 9cfaf0944c | |||
| bfd564f257 | |||
| 43c1910453 | |||
| 260dbf0a1d | |||
| f3e20ca437 | |||
| a2867ff6ea | |||
| 9689f7b925 | |||
| 2037b5ce39 | |||
| f4c5e6568e | |||
| 865bf67b1a | |||
| f474b6da85 | |||
| a578bc2fad | |||
| 5a11d19940 | |||
| c28778e28c | |||
| c873327fe3 | |||
| d25b427efe | |||
| 9cd378caa7 | |||
| b0258803c6 | |||
| 77eb94409c | |||
| 0735250eb1 | |||
| fa21cd13d2 | |||
| d74fffd5de | |||
| e7722af9a2 | |||
| 0cd409bd6d | |||
| 2ea7f9769a | |||
| 221451b817 | |||
| 48a795c101 | |||
| f29c963030 | |||
| dd81707992 | |||
| ec410fb6fe | |||
| 3edaa5280d | |||
| 51e415a026 | |||
| 04f559e28d | |||
| ecda05af29 | |||
| 4661315192 |
+4
-3
@@ -4,6 +4,7 @@ branches:
|
||||
- master
|
||||
skip_tags: true
|
||||
environment:
|
||||
CFLAGS: /WX
|
||||
matrix:
|
||||
- BUILD_SHARED_LIBS: ON
|
||||
- BUILD_SHARED_LIBS: OFF
|
||||
@@ -12,11 +13,11 @@ matrix:
|
||||
build_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS% ..
|
||||
- cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS% ..
|
||||
- cmake --build .
|
||||
notifications:
|
||||
- provider: Email
|
||||
to:
|
||||
- ci@glfw.org
|
||||
- on_build_failure: true
|
||||
- on_build_success: false
|
||||
on_build_failure: true
|
||||
on_build_success: false
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
*.m linguist-language=Objective-C
|
||||
+1
-1
@@ -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
|
||||
|
||||
+57
-9
@@ -4,23 +4,71 @@ branches:
|
||||
only:
|
||||
- ci
|
||||
- master
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
sudo: false
|
||||
dist: trusty
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- kubuntu-backports
|
||||
packages:
|
||||
- cmake
|
||||
env:
|
||||
- BUILD_SHARED_LIBS=ON
|
||||
- BUILD_SHARED_LIBS=OFF
|
||||
- libxrandr-dev
|
||||
- libxinerama-dev
|
||||
- libxcursor-dev
|
||||
- libxi-dev
|
||||
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 -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.12 && ./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:
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# Usage:
|
||||
# cmake -P GenerateMappings.cmake <path/to/mappings.h.in> <path/to/mappings.h>
|
||||
|
||||
set(source_url "https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt")
|
||||
set(source_path "${CMAKE_CURRENT_BINARY_DIR}/gamecontrollerdb.txt")
|
||||
set(template_path "${CMAKE_ARGV3}")
|
||||
set(target_path "${CMAKE_ARGV4}")
|
||||
|
||||
if (NOT EXISTS "${template_path}")
|
||||
message(FATAL_ERROR "Failed to find template file ${template_path}")
|
||||
endif()
|
||||
|
||||
file(DOWNLOAD "${source_url}" "${source_path}"
|
||||
STATUS download_status
|
||||
TLS_VERIFY on)
|
||||
|
||||
list(GET download_status 0 status_code)
|
||||
list(GET download_status 1 status_message)
|
||||
|
||||
if (status_code)
|
||||
message(FATAL_ERROR "Failed to download ${source_url}: ${status_message}")
|
||||
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")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
configure_file("${template_path}" "${target_path}" @ONLY NEWLINE_STYLE UNIX)
|
||||
file(REMOVE "${source_path}")
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# Find libdbus
|
||||
#
|
||||
# DBUS_INCLUDE_DIRS
|
||||
# DBUS_LIBRARY
|
||||
# DBUS_FOUND
|
||||
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
|
||||
pkg_check_modules(PC_DBUS dbus-1 QUIET)
|
||||
if (PC_DBUS_FOUND)
|
||||
set(DBUS_INCLUDE_DIRS ${PC_DBUS_INCLUDE_DIRS})
|
||||
find_library(DBUS_LIBRARY dbus-1 PATHS ${PC_DBUS_LIBRARY_DIRS})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(DBus DEFAULT_MSG DBUS_LIBRARY DBUS_INCLUDE_DIRS)
|
||||
mark_as_advanced(DBUS_INCLUDE_DIRS DBUS_LIBRARY)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
+24
-27
@@ -1,37 +1,34 @@
|
||||
# Try to find Mir on a Unix system
|
||||
# FindMir
|
||||
# -------
|
||||
# Finds the Mir library
|
||||
#
|
||||
# This will define:
|
||||
# This will will define the following variables::
|
||||
#
|
||||
# MIR_FOUND - System has Mir
|
||||
# MIR_LIBRARIES - Link these to use Mir
|
||||
# MIR_INCLUDE_DIR - Include directory for Mir
|
||||
# MIR_DEFINITIONS - Compiler switches required for using Mir
|
||||
# MIR_FOUND - the system has Mir
|
||||
# MIR_INCLUDE_DIRS - the Mir include directory
|
||||
# MIR_LIBRARIES - the Mir libraries
|
||||
# MIR_DEFINITIONS - the Mir definitions
|
||||
|
||||
if (NOT WIN32)
|
||||
|
||||
find_package (PkgConfig)
|
||||
pkg_check_modules (PKG_MIR QUIET mirclient)
|
||||
set(MIR_DEFINITIONS ${PKG_MIR_CFLAGS_OTHER})
|
||||
find_package (PkgConfig)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_check_modules (PC_MIR mirclient>=0.26.2 QUIET)
|
||||
|
||||
find_path(MIR_INCLUDE_DIR
|
||||
NAMES xkbcommon/xkbcommon.h
|
||||
HINTS ${PC_XKBCOMMON_INCLUDE_DIR} ${PC_XKBCOMMON_INCLUDE_DIRS}
|
||||
)
|
||||
find_path(MIR_INCLUDE_DIR NAMES mir_toolkit/mir_client_library.h
|
||||
PATHS ${PC_MIR_INCLUDE_DIRS})
|
||||
|
||||
find_library(MIR_LIBRARY
|
||||
NAMES mirclient
|
||||
HINTS ${PKG_MIR_LIBRARIES} ${MIR_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
set (MIR_INCLUDE_DIR ${PKG_MIR_INCLUDE_DIRS})
|
||||
set (MIR_LIBRARIES ${MIR_LIBRARY})
|
||||
find_library(MIR_LIBRARY NAMES mirclient
|
||||
PATHS ${PC_MIR_LIBRARIES} ${PC_MIR_LIBRARY_DIRS})
|
||||
|
||||
include (FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args (MIR DEFAULT_MSG
|
||||
MIR_LIBRARIES
|
||||
MIR_INCLUDE_DIR
|
||||
)
|
||||
find_package_handle_standard_args (MIR
|
||||
REQUIRED_VARS MIR_LIBRARY MIR_INCLUDE_DIR)
|
||||
|
||||
mark_as_advanced (MIR_LIBRARIES 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()
|
||||
|
||||
endif ()
|
||||
mark_as_advanced (MIR_LIBRARY MIR_INCLUDE_DIR)
|
||||
endif()
|
||||
|
||||
@@ -8,25 +8,32 @@ if (WIN32)
|
||||
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||
"$ENV{VULKAN_SDK}/Include"
|
||||
"$ENV{VK_SDK_PATH}/Include")
|
||||
if (CMAKE_CL_64)
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
find_library(VULKAN_LIBRARY NAMES vulkan-1 HINTS
|
||||
"$ENV{VULKAN_SDK}/Lib"
|
||||
"$ENV{VULKAN_SDK}/Bin"
|
||||
"$ENV{VK_SDK_PATH}/Bin")
|
||||
find_library(VULKAN_STATIC_LIBRARY NAMES vkstatic.1 HINTS
|
||||
"$ENV{VULKAN_SDK}/Lib"
|
||||
"$ENV{VULKAN_SDK}/Bin"
|
||||
"$ENV{VK_SDK_PATH}/Bin")
|
||||
else()
|
||||
find_library(VULKAN_LIBRARY NAMES vulkan-1 HINTS
|
||||
"$ENV{VULKAN_SDK}/Lib32"
|
||||
"$ENV{VULKAN_SDK}/Bin32"
|
||||
"$ENV{VK_SDK_PATH}/Bin32")
|
||||
find_library(VULKAN_STATIC_LIBRARY NAMES vkstatic.1 HINTS
|
||||
"$ENV{VULKAN_SDK}/Lib32"
|
||||
"$ENV{VULKAN_SDK}/Bin32"
|
||||
"$ENV{VK_SDK_PATH}/Bin32")
|
||||
endif()
|
||||
elseif (APPLE)
|
||||
set(CMAKE_FIND_FRAMEWORK NEVER)
|
||||
find_library(VULKAN_LIBRARY MoltenVK)
|
||||
if (VULKAN_LIBRARY)
|
||||
set(VULKAN_STATIC_LIBRARY ${VULKAN_LIBRARY})
|
||||
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||
"${VULKAN_LIBRARY}/Headers")
|
||||
endif()
|
||||
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")
|
||||
|
||||
+29
-42
@@ -1,8 +1,8 @@
|
||||
set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
project(GLFW C)
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
|
||||
|
||||
if (NOT CMAKE_VERSION VERSION_LESS "3.0")
|
||||
# Until all major package systems have moved to CMake 3,
|
||||
@@ -10,6 +10,10 @@ if (NOT CMAKE_VERSION VERSION_LESS "3.0")
|
||||
cmake_policy(SET CMP0042 OLD)
|
||||
endif()
|
||||
|
||||
if (NOT CMAKE_VERSION VERSION_LESS "3.1")
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
endif()
|
||||
|
||||
set(GLFW_VERSION_MAJOR "3")
|
||||
set(GLFW_VERSION_MINOR "3")
|
||||
set(GLFW_VERSION_PATCH "0")
|
||||
@@ -26,7 +30,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)
|
||||
@@ -36,11 +39,6 @@ if (WIN32)
|
||||
option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on hybrid systems" OFF)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
option(GLFW_USE_CHDIR "Make glfwInit chdir to Contents/Resources" ON)
|
||||
option(GLFW_USE_MENUBAR "Populate the menu bar on first window creation" ON)
|
||||
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)
|
||||
@@ -182,7 +180,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}" ${GLFW_VULKAN_DEPS})
|
||||
if (BUILD_SHARED_LIBS)
|
||||
message(WARNING "Linking Vulkan loader static library into GLFW")
|
||||
endif()
|
||||
@@ -217,6 +215,11 @@ if (UNIX AND NOT APPLE)
|
||||
list(APPEND glfw_LIBRARIES "${CMAKE_DL_LIBS}")
|
||||
list(APPEND glfw_PKG_LIBS "-l${CMAKE_DL_LIBS}")
|
||||
endif()
|
||||
|
||||
find_package(DBus)
|
||||
if (DBUS_FOUND)
|
||||
list(APPEND glfw_INCLUDE_DIRS ${DBUS_INCLUDE_DIRS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
@@ -246,38 +249,28 @@ if (_GLFW_X11)
|
||||
|
||||
# Check for XRandR (modern resolution switching and gamma control)
|
||||
if (NOT X11_Xrandr_FOUND)
|
||||
message(FATAL_ERROR "The RandR library and headers were not found")
|
||||
message(FATAL_ERROR "The RandR headers were not found")
|
||||
endif()
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIRS "${X11_Xrandr_INCLUDE_PATH}")
|
||||
list(APPEND glfw_LIBRARIES "${X11_Xrandr_LIB}")
|
||||
list(APPEND glfw_PKG_DEPS "xrandr")
|
||||
|
||||
# Check for Xinerama (legacy multi-monitor support)
|
||||
if (NOT X11_Xinerama_FOUND)
|
||||
message(FATAL_ERROR "The Xinerama library and headers were not found")
|
||||
message(FATAL_ERROR "The Xinerama headers were not found")
|
||||
endif()
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIRS "${X11_Xinerama_INCLUDE_PATH}")
|
||||
list(APPEND glfw_LIBRARIES "${X11_Xinerama_LIB}")
|
||||
list(APPEND glfw_PKG_DEPS "xinerama")
|
||||
|
||||
# Check for Xkb (X keyboard extension)
|
||||
if (NOT X11_Xkb_FOUND)
|
||||
message(FATAL_ERROR "The X keyboard extension headers were not found")
|
||||
endif()
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIR "${X11_Xkb_INCLUDE_PATH}")
|
||||
|
||||
# Check for Xcursor
|
||||
# Check for Xcursor (cursor creation from RGBA images)
|
||||
if (NOT X11_Xcursor_FOUND)
|
||||
message(FATAL_ERROR "The Xcursor libraries and headers were not found")
|
||||
message(FATAL_ERROR "The Xcursor headers were not found")
|
||||
endif()
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIR "${X11_Xcursor_INCLUDE_PATH}")
|
||||
list(APPEND glfw_LIBRARIES "${X11_Xcursor_LIB}")
|
||||
list(APPEND glfw_PKG_DEPS "xcursor")
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIRS "${X11_Xrandr_INCLUDE_PATH}"
|
||||
"${X11_Xinerama_INCLUDE_PATH}"
|
||||
"${X11_Xkb_INCLUDE_PATH}"
|
||||
"${X11_Xcursor_INCLUDE_PATH}")
|
||||
endif()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
@@ -285,21 +278,22 @@ endif()
|
||||
#--------------------------------------------------------------------
|
||||
if (_GLFW_WAYLAND)
|
||||
find_package(ECM REQUIRED NO_MODULE)
|
||||
list(APPEND CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
|
||||
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.12 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}")
|
||||
|
||||
include(CheckIncludeFiles)
|
||||
check_include_files(xkbcommon/xkbcommon-compose.h HAVE_XKBCOMMON_COMPOSE_H)
|
||||
endif()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
@@ -309,7 +303,7 @@ if (_GLFW_MIR)
|
||||
find_package(Mir REQUIRED)
|
||||
list(APPEND glfw_PKG_DEPS "mirclient")
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIRS "${MIR_INCLUDE_DIR}")
|
||||
list(APPEND glfw_INCLUDE_DIRS "${MIR_INCLUDE_DIRS}")
|
||||
list(APPEND glfw_LIBRARIES "${MIR_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}")
|
||||
|
||||
find_package(XKBCommon REQUIRED)
|
||||
@@ -331,14 +325,6 @@ endif()
|
||||
#--------------------------------------------------------------------
|
||||
if (_GLFW_COCOA)
|
||||
|
||||
if (GLFW_USE_MENUBAR)
|
||||
set(_GLFW_USE_MENUBAR 1)
|
||||
endif()
|
||||
|
||||
if (GLFW_USE_CHDIR)
|
||||
set(_GLFW_USE_CHDIR 1)
|
||||
endif()
|
||||
|
||||
list(APPEND glfw_LIBRARIES
|
||||
"-framework Cocoa"
|
||||
"-framework IOKit"
|
||||
@@ -422,6 +408,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()
|
||||
|
||||
|
||||
@@ -10,6 +10,10 @@ GLFW is an Open Source, multi-platform library for OpenGL, OpenGL ES and Vulkan
|
||||
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.
|
||||
|
||||
GLFW is licensed under the [zlib/libpng
|
||||
license](http://www.glfw.org/license.html).
|
||||
|
||||
@@ -23,45 +27,58 @@ The [version history](http://www.glfw.org/changelog.html) lists all user-visible
|
||||
changes for every release.
|
||||
|
||||
This is a development branch for version 3.3, which is _not yet described_.
|
||||
Pre-release documentation is available [here](http://www.glfw.org/docs/3.3/).
|
||||
|
||||
The `master` branch is the stable integration branch and _should_ always compile
|
||||
and run on all supported platforms, although details of newly added features may
|
||||
change until they have been included in a release. New features and many bug
|
||||
fixes live in [other branches](https://github.com/glfw/glfw/branches/all) until
|
||||
they are stable enough to merge.
|
||||
|
||||
If you are new to GLFW, you may find the
|
||||
[tutorial](http://www.glfw.org/docs/latest/quick.html) for GLFW
|
||||
3 useful. If you have used GLFW 2 in the past, there is a
|
||||
[transition guide](http://www.glfw.org/docs/latest/moving.html) for moving to
|
||||
the GLFW 3 API.
|
||||
[tutorial](http://www.glfw.org/docs/latest/quick.html) for GLFW 3 useful. If
|
||||
you have used GLFW 2 in the past, there is a [transition
|
||||
guide](http://www.glfw.org/docs/latest/moving.html) for moving to the GLFW
|
||||
3 API.
|
||||
|
||||
|
||||
## Compiling GLFW
|
||||
|
||||
GLFW itself requires only the headers and libraries for your window system. It
|
||||
does not need the headers for any context creation API (WGL, GLX, EGL, NSGL) or
|
||||
rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them.
|
||||
does not need the headers for any context creation API (WGL, GLX, EGL, NSGL,
|
||||
OSMesa) or rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them.
|
||||
|
||||
GLFW supports compilation on Windows with Visual C++ 2010 and later, MinGW and
|
||||
MinGW-w64, on macOS with Clang and on Linux and other Unix-like systems with GCC
|
||||
and Clang. It will likely compile in other environments as well, but this is
|
||||
not regularly tested.
|
||||
|
||||
There are also [pre-compiled Windows
|
||||
binaries](http://www.glfw.org/download.html) available for all compilers
|
||||
supported on that platform.
|
||||
There are [pre-compiled Windows binaries](http://www.glfw.org/download.html)
|
||||
available for all supported compilers.
|
||||
|
||||
See the [compilation guide](http://www.glfw.org/docs/latest/compile.html) in the
|
||||
documentation for more information.
|
||||
See the [compilation guide](http://www.glfw.org/docs/latest/compile.html) for
|
||||
more information about how to compile GLFW yourself.
|
||||
|
||||
|
||||
## Using GLFW
|
||||
|
||||
See the [building application guide](http://www.glfw.org/docs/latest/build.html)
|
||||
guide in the documentation for more information.
|
||||
See the [documentation](http://www.glfw.org/docs/latest/) for tutorials, guides
|
||||
and the API reference.
|
||||
|
||||
|
||||
## Contributing to GLFW
|
||||
|
||||
See the [contribution
|
||||
guide](https://github.com/glfw/glfw/blob/master/docs/CONTRIBUTING.md) for
|
||||
more information.
|
||||
|
||||
|
||||
## System requirements
|
||||
|
||||
GLFW supports Windows XP and later, OS X 10.7 Lion and later, and Linux and
|
||||
other Unix-like systems with the X Window System. Experimental implementations
|
||||
for the Wayland protocol and the Mir display server are available but not yet
|
||||
officially supported.
|
||||
GLFW supports Windows XP and later and macOS 10.7 and later. Linux and other
|
||||
Unix-like systems running the X Window System are supported even without
|
||||
a desktop environment or modern extensions, although some features require
|
||||
a running window or clipboard manager. The OSMesa backend requires Mesa 6.3.
|
||||
|
||||
See the [compatibility guide](http://www.glfw.org/docs/latest/compat.html)
|
||||
in the documentation for more information.
|
||||
@@ -71,6 +88,9 @@ in the documentation for more information.
|
||||
|
||||
GLFW itself depends only on the headers and libraries for your window system.
|
||||
|
||||
The (experimental) Wayland backend also depends on the `extra-cmake-modules`
|
||||
package, which is used to generated Wayland protocol headers.
|
||||
|
||||
The examples and test programs depend on a number of tiny libraries. These are
|
||||
located in the `deps/` directory.
|
||||
|
||||
@@ -87,40 +107,144 @@ located in the `deps/` directory.
|
||||
- [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.
|
||||
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 documentation is generated with [Doxygen](http://doxygen.org/). If CMake
|
||||
does not find Doxygen, the documentation will not be generated when you build.
|
||||
The documentation is generated with [Doxygen](http://doxygen.org/) if CMake can
|
||||
find that tool.
|
||||
|
||||
|
||||
## Reporting bugs
|
||||
|
||||
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.
|
||||
|
||||
|
||||
## Changelog
|
||||
|
||||
- Added `glfwGetError` function for querying the last error code and its
|
||||
description (#970)
|
||||
- Added `glfwUpdateGamepadMappings` function for importing gamepad mappings in
|
||||
SDL\_GameControllerDB format (#900)
|
||||
- Added `glfwJoystickIsGamepad` function for querying whether a joystick has
|
||||
a gamepad mapping (#900)
|
||||
- Added `glfwGetJoystickGUID` function for querying the SDL compatible GUID of
|
||||
a joystick (#900)
|
||||
- Added `glfwGetGamepadName` function for querying the name provided by the
|
||||
gamepad mapping (#900)
|
||||
- Added `glfwGetGamepadState` function, `GLFW_GAMEPAD_*` and `GLFWgamepadstate`
|
||||
for retrieving gamepad input state (#900)
|
||||
- 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
|
||||
scancodes for keys (#830)
|
||||
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
|
||||
receiving window maximization events (#778)
|
||||
- Added `glfwSetWindowAttrib` function for changing window attributes (#537)
|
||||
- Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#281,#850)
|
||||
- Added `glfwGetJoystickHats` function for querying joystick hats
|
||||
(#889,#906,#934)
|
||||
- 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_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_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_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_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
|
||||
- Bugfix: Calling `glfwMaximizeWindow` on a full screen window was not ignored
|
||||
- Bugfix: `GLFW_INCLUDE_VULKAN` could not be combined with the corresponding
|
||||
OpenGL and OpenGL ES header macros
|
||||
- Bugfix: `glfwGetInstanceProcAddress` returned `NULL` for
|
||||
`vkGetInstanceProcAddr` when `_GLFW_VULKAN_STATIC` was enabled
|
||||
- Bugfix: Invalid library paths were used in test and example CMake files (#930)
|
||||
- Bugfix: The scancode for synthetic key release events was always zero
|
||||
- Bugfix: The generated Doxyfile did not handle paths with spaces (#1081)
|
||||
- [Win32] Added system error strings to relevant GLFW error descriptions (#733)
|
||||
- [Win32] Moved to `WM_INPUT` for disabled cursor mode motion input (#125)
|
||||
- [Win32] Removed XInput circular deadzone from joystick axis data (#1045)
|
||||
- [Win32] Bugfix: Undecorated windows could not be iconified by the user (#861)
|
||||
- [Win32] Bugfix: Deadzone logic could underflow with some controllers (#910)
|
||||
- [Win32] Bugfix: Bitness test in `FindVulkan.cmake` was VS specific (#928)
|
||||
- [Win32] Bugfix: `glfwVulkanSupported` emitted an error on systems with
|
||||
a loader but no ICD (#916)
|
||||
- [Win32] Bugfix: Non-iconified full sreeen windows did not prevent screen
|
||||
blanking or password enabled screensavers (#851)
|
||||
- [Win32] Bugfix: Mouse capture logic lost secondary release messages (#954)
|
||||
- [Win32] Bugfix: The 32-bit Vulkan loader library static was not searched for
|
||||
- [Win32] Bugfix: Vulkan libraries have a new path as of SDK 1.0.42.0 (#956)
|
||||
- [Win32] Bugfix: Monitors with no display devices were not enumerated (#960)
|
||||
- [Win32] Bugfix: Monitor events were not emitted (#784)
|
||||
- [Win32] Bugfix: The Cygwin DLL was installed to the wrong directory (#1035)
|
||||
- [Win32] Bugfix: Normalization of axis data via XInput was incorrect (#1045)
|
||||
- [Win32] Bugfix: `glfw3native.h` would undefine a foreign `APIENTRY` (#1062)
|
||||
- [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)
|
||||
- [X11] Added support for `org.freedesktop.ScreenSaver` (#854)
|
||||
- [X11] Added support for the MIT screensaver extension (#854)
|
||||
- [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125)
|
||||
- [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading
|
||||
- [Cocoa] Added support for Vulkan window surface creation via MoltenVK (#870)
|
||||
- [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X
|
||||
- [X11] Bugfix: Dynamic X11 library loading did not use full sonames (#941)
|
||||
- [X11] Bugfix: Window creation on 64-bit would read past top of stack (#951)
|
||||
- [X11] Bugfix: XDND support had multiple non-conformance issues (#968)
|
||||
- [X11] Bugfix: The RandR monitor path was disabled despite working RandR (#972)
|
||||
- [X11] Bugfix: IM-duplicated key events would leak at low polling rates (#747)
|
||||
- [X11] Bugfix: Gamma ramp setting via RandR did not validate ramp size
|
||||
- [X11] Bugfix: Key name string encoding depended on current locale (#981,#983)
|
||||
- [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)
|
||||
- [Linux] Bugfix: `glfwInit` would fail if inotify creation failed (#833)
|
||||
- [Linux] Bugfix: `strdup` was used without any required feature macro (#1055)
|
||||
- [Cocoa] Added support for Vulkan window surface creation via
|
||||
[MoltenVK](https://moltengl.com/moltenvk/) (#870)
|
||||
- [Cocoa] Added support for loading a `MainMenu.nib` when available
|
||||
- [Cocoa] Bugfix: Disabling window aspect ratio would assert (#852)
|
||||
- [Cocoa] Bugfix: Window creation failed to set first responder (#876,#883)
|
||||
- [Cocoa] Bugfix: Removed use of deprecated `CGDisplayIOServicePort` function
|
||||
@@ -128,7 +252,28 @@ information on what to include when reporting a bug.
|
||||
- [Cocoa] Bugfix: Disabled use of deprecated `CGDisplayModeCopyPixelEncoding`
|
||||
function on macOS 10.12+
|
||||
- [Cocoa] Bugfix: Running in AppSandbox would emit warnings (#816,#882)
|
||||
- [Cocoa] Bugfix: Windows created after the first were not cascaded (#195)
|
||||
- [Cocoa] Bugfix: Leaving video mode with `glfwSetWindowMonitor` would set
|
||||
incorrect position and size (#748)
|
||||
- [Cocoa] Bugfix: Iconified full screen windows could not be restored (#848)
|
||||
- [Cocoa] Bugfix: Value range was ignored for joystick hats and buttons (#888)
|
||||
- [Cocoa] Bugfix: Full screen framebuffer was incorrectly sized for some video
|
||||
modes (#682)
|
||||
- [Cocoa] Bugfix: A string object for IME was updated non-idiomatically (#1050)
|
||||
- [Cocoa] Bugfix: A hidden or disabled cursor would become visible when a user
|
||||
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)
|
||||
- [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`
|
||||
- [GLX] Bugfix: Context creation could segfault if no GLXFBConfigs were
|
||||
available (#1040)
|
||||
- [EGL] Added support for `EGL_KHR_get_all_proc_addresses` (#871)
|
||||
- [EGL] Added support for `EGL_KHR_context_flush_control`
|
||||
- [EGL] Bugfix: The test for `EGL_RGB_BUFFER` was invalid
|
||||
|
||||
|
||||
## Contact
|
||||
@@ -154,20 +299,28 @@ GLFW exists because people around the world donated their time and lent their
|
||||
skills.
|
||||
|
||||
- Bobyshev Alexander
|
||||
- artblanc
|
||||
- arturo
|
||||
- Matt Arsenault
|
||||
- David Avedissian
|
||||
- Keith Bauer
|
||||
- John Bartholomew
|
||||
- Niklas Behrens
|
||||
- Niklas Bergström
|
||||
- Denis Bernard
|
||||
- Doug Binks
|
||||
- blanco
|
||||
- Kyle Brenneman
|
||||
- Rok Breulj
|
||||
- Martin Capitanio
|
||||
- David Carlier
|
||||
- Arturo Castro
|
||||
- Chi-kwan Chan
|
||||
- Ian Clarkson
|
||||
- Michał Cichoń
|
||||
- Lambert Clara
|
||||
- Yaron Cohen-Tal
|
||||
- Omar Cornut
|
||||
- Andrew Corrigan
|
||||
- Bailey Cosier
|
||||
- Noel Cower
|
||||
- Jason Daly
|
||||
- Jarrod Davis
|
||||
@@ -176,16 +329,23 @@ skills.
|
||||
- Michael Dickens
|
||||
- Роман Донченко
|
||||
- Mario Dorn
|
||||
- Wolfgang Draxinger
|
||||
- Jonathan Dummer
|
||||
- Ralph Eastwood
|
||||
- Fredrik Ehnbom
|
||||
- Robin Eklind
|
||||
- Siavash Eliasi
|
||||
- Felipe Ferreira
|
||||
- Michael Fogleman
|
||||
- Gerald Franz
|
||||
- Mário Freitas
|
||||
- GeO4d
|
||||
- Marcus Geelnard
|
||||
- Stephen Gowen
|
||||
- Kovid Goyal
|
||||
- Eloi Marín Gratacós
|
||||
- Stefan Gustavson
|
||||
- Jonathan Hale
|
||||
- Sylvain Hellegouarch
|
||||
- Matthew Henry
|
||||
- heromyth
|
||||
@@ -197,64 +357,83 @@ skills.
|
||||
- Erik S. V. Jansson
|
||||
- Toni Jovanoski
|
||||
- Arseny Kapoulkine
|
||||
- Cem Karan
|
||||
- Osman Keskin
|
||||
- Josh Kilmer
|
||||
- Cameron King
|
||||
- Peter Knut
|
||||
- Christoph Kubisch
|
||||
- Yuri Kunde Schlesner
|
||||
- Konstantin Käfer
|
||||
- Eric Larson
|
||||
- Robin Leffmann
|
||||
- Glenn Lewis
|
||||
- Shane Liesegang
|
||||
- Eyal Lotem
|
||||
- Дмитри Малышев
|
||||
- Martins Mozeiko
|
||||
- Tristam MacDonald
|
||||
- Hans Mackowiak
|
||||
- Дмитри Малышев
|
||||
- Zbigniew Mandziejewicz
|
||||
- Célestin Marot
|
||||
- Kyle McDonald
|
||||
- David Medlock
|
||||
- Bryce Mehring
|
||||
- Jonathan Mercier
|
||||
- Marcel Metz
|
||||
- Liam Middlebrook
|
||||
- Jonathan Miller
|
||||
- Kenneth Miller
|
||||
- Bruce Mitchener
|
||||
- Jack Moffitt
|
||||
- Jeff Molofee
|
||||
- Pierre Morel
|
||||
- Jon Morton
|
||||
- Pierre Moulon
|
||||
- Martins Mozeiko
|
||||
- Julian Møller
|
||||
- ndogxj
|
||||
- Kristian Nielsen
|
||||
- Kamil Nowakowski
|
||||
- Denis Ovod
|
||||
- Ozzy
|
||||
- Andri Pálsson
|
||||
- Peoro
|
||||
- Braden Pellett
|
||||
- Christopher Pelloux
|
||||
- Arturo J. Pérez
|
||||
- Anthony Pesch
|
||||
- Orson Peters
|
||||
- Emmanuel Gil Peyrot
|
||||
- Cyril Pichard
|
||||
- Pieroman
|
||||
- Keith Pitt
|
||||
- Stanislav Podgorskiy
|
||||
- Alexandre Pretyman
|
||||
- przemekmirek
|
||||
- Philip Rideout
|
||||
- Eddie Ringle
|
||||
- Jorge Rodriguez
|
||||
- Ed Ropple
|
||||
- Aleksey Rybalkin
|
||||
- Riku Salminen
|
||||
- Brandon Schaefer
|
||||
- Sebastian Schuberth
|
||||
- Christian Sdunek
|
||||
- Matt Sealey
|
||||
- SephiRok
|
||||
- Steve Sexton
|
||||
- Systemcluster
|
||||
- Arkady Shapkin
|
||||
- Yoshiki Shibukawa
|
||||
- Dmitri Shuralyov
|
||||
- Daniel Skorupski
|
||||
- Bradley Smith
|
||||
- Patrick Snape
|
||||
- Erlend Sogge Heggen
|
||||
- Julian Squires
|
||||
- Johannes Stein
|
||||
- Pontus Stenetorp
|
||||
- Michael Stocker
|
||||
- Justin Stoecker
|
||||
- Elviss Strazdins
|
||||
- Paul Sultana
|
||||
- Nathan Sweet
|
||||
- TTK-Bandit
|
||||
- Sergey Tikhomirov
|
||||
@@ -264,16 +443,19 @@ skills.
|
||||
- Matthew Turner
|
||||
- urraka
|
||||
- Elias Vanderstuyft
|
||||
- Stef Velzel
|
||||
- Jari Vetoniemi
|
||||
- Ricardo Vieira
|
||||
- Nicholas Vitovitch
|
||||
- Simon Voordouw
|
||||
- Corentin Wallez
|
||||
- Torsten Walluhn
|
||||
- Patrick Walton
|
||||
- Xo Wang
|
||||
- Jay Weisskopf
|
||||
- Frank Wille
|
||||
- yuriks
|
||||
- Ryogo Yoshimura
|
||||
- Andrey Zholos
|
||||
- Santi Zupancic
|
||||
- Jonas Ådahl
|
||||
- Lasse Öörni
|
||||
|
||||
Vendored
+1
-1
@@ -192,7 +192,7 @@ static inline void mat4x4_rotate(mat4x4 R, mat4x4 M, float x, float y, float z,
|
||||
vec3 u = {x, y, z};
|
||||
|
||||
if(vec3_len(u) > 1e-4) {
|
||||
mat4x4 T, C, S;
|
||||
mat4x4 T, C, S = {{0}};
|
||||
|
||||
vec3_norm(u, u);
|
||||
mat4x4_from_vec3_mul_outer(T, u, u);
|
||||
|
||||
Vendored
+3039
-1282
File diff suppressed because it is too large
Load Diff
Vendored
+41
-10
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Nuklear - v1.17 - public domain
|
||||
* Nuklear - v1.32.0 - public domain
|
||||
* no warrenty implied; use at your own risk.
|
||||
* authored from 2015-2016 by Micha Mettke
|
||||
* authored from 2015-2017 by Micha Mettke
|
||||
*/
|
||||
/*
|
||||
* ==============================================================
|
||||
@@ -24,7 +24,7 @@ NK_API void nk_glfw3_font_stash_begin(struct nk_font_atlas **atl
|
||||
NK_API void nk_glfw3_font_stash_end(void);
|
||||
|
||||
NK_API void nk_glfw3_new_frame(void);
|
||||
NK_API void nk_glfw3_render(enum nk_anti_aliasing , int max_vertex_buffer, int max_element_buffer);
|
||||
NK_API void nk_glfw3_render(enum nk_anti_aliasing);
|
||||
NK_API void nk_glfw3_shutdown(void);
|
||||
|
||||
NK_API void nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint);
|
||||
@@ -44,6 +44,12 @@ NK_API void nk_gflw3_scroll_callback(GLFWwindow *win, double xof
|
||||
#ifndef NK_GLFW_TEXT_MAX
|
||||
#define NK_GLFW_TEXT_MAX 256
|
||||
#endif
|
||||
#ifndef NK_GLFW_DOUBLE_CLICK_LO
|
||||
#define NK_GLFW_DOUBLE_CLICK_LO 0.02
|
||||
#endif
|
||||
#ifndef NK_GLFW_DOUBLE_CLICK_HI
|
||||
#define NK_GLFW_DOUBLE_CLICK_HI 0.2
|
||||
#endif
|
||||
|
||||
struct nk_glfw_device {
|
||||
struct nk_buffer cmds;
|
||||
@@ -67,7 +73,10 @@ static struct nk_glfw {
|
||||
struct nk_vec2 fb_scale;
|
||||
unsigned int text[NK_GLFW_TEXT_MAX];
|
||||
int text_len;
|
||||
float scroll;
|
||||
struct nk_vec2 scroll;
|
||||
double last_button_click;
|
||||
int is_double_click_down;
|
||||
struct nk_vec2 double_click_pos;
|
||||
} glfw;
|
||||
|
||||
NK_INTERN void
|
||||
@@ -83,7 +92,7 @@ nk_glfw3_device_upload_atlas(const void *image, int width, int height)
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_glfw3_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer)
|
||||
nk_glfw3_render(enum nk_anti_aliasing AA)
|
||||
{
|
||||
/* setup global state */
|
||||
struct nk_glfw_device *dev = &glfw.ogl;
|
||||
@@ -200,7 +209,24 @@ NK_API void
|
||||
nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff)
|
||||
{
|
||||
(void)win; (void)xoff;
|
||||
glfw.scroll += (float)yoff;
|
||||
glfw.scroll.x += (float)xoff;
|
||||
glfw.scroll.y += (float)yoff;
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_glfw3_mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
|
||||
{
|
||||
double x, y;
|
||||
if (button != GLFW_MOUSE_BUTTON_LEFT) return;
|
||||
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) {
|
||||
glfw.is_double_click_down = nk_true;
|
||||
glfw.double_click_pos = nk_vec2((float)x, (float)y);
|
||||
}
|
||||
glfw.last_button_click = glfwGetTime();
|
||||
} else glfw.is_double_click_down = nk_false;
|
||||
}
|
||||
|
||||
NK_INTERN void
|
||||
@@ -232,13 +258,17 @@ nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state init_state)
|
||||
if (init_state == NK_GLFW3_INSTALL_CALLBACKS) {
|
||||
glfwSetScrollCallback(win, nk_gflw3_scroll_callback);
|
||||
glfwSetCharCallback(win, nk_glfw3_char_callback);
|
||||
glfwSetMouseButtonCallback(win, nk_glfw3_mouse_button_callback);
|
||||
}
|
||||
|
||||
nk_init_default(&glfw.ctx, 0);
|
||||
glfw.ctx.clip.copy = nk_glfw3_clipbard_copy;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -302,7 +332,7 @@ nk_glfw3_new_frame(void)
|
||||
if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
|
||||
glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) {
|
||||
nk_input_key(ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_P) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_V) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_UNDO, glfwGetKey(win, GLFW_KEY_Z) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_REDO, glfwGetKey(win, GLFW_KEY_R) == GLFW_PRESS);
|
||||
@@ -322,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;
|
||||
}
|
||||
@@ -330,10 +360,11 @@ 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;
|
||||
glfw.scroll = 0;
|
||||
glfw.scroll = nk_vec2(0,0);
|
||||
}
|
||||
|
||||
NK_API
|
||||
|
||||
Vendored
+1
-1
@@ -53,7 +53,7 @@ extern "C"
|
||||
#define VKAPI_PTR VKAPI_CALL
|
||||
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
|
||||
#error "Vulkan isn't supported for the 'armeabi' NDK ABI"
|
||||
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && __ARM_32BIT_STATE
|
||||
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
|
||||
// On Android 32-bit ARM targets, Vulkan functions use the "hardfloat"
|
||||
// calling convention, i.e. float parameters are passed in registers. This
|
||||
// is true even if the rest of the application passes floats on the stack,
|
||||
|
||||
Vendored
+647
-7
@@ -6,7 +6,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
** Copyright (c) 2015-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.
|
||||
@@ -43,7 +43,7 @@ extern "C" {
|
||||
#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
|
||||
#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
|
||||
// Version of this file
|
||||
#define VK_HEADER_VERSION 26
|
||||
#define VK_HEADER_VERSION 39
|
||||
|
||||
|
||||
#define VK_NULL_HANDLE 0
|
||||
@@ -145,6 +145,7 @@ typedef enum VkResult {
|
||||
VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
|
||||
VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
|
||||
VK_ERROR_INVALID_SHADER_NV = -1000012000,
|
||||
VK_ERROR_OUT_OF_POOL_MEMORY_KHR = -1000069000,
|
||||
VK_RESULT_BEGIN_RANGE = VK_ERROR_FRAGMENTED_POOL,
|
||||
VK_RESULT_END_RANGE = VK_INCOMPLETE,
|
||||
VK_RESULT_RANGE_SIZE = (VK_INCOMPLETE - VK_ERROR_FRAGMENTED_POOL + 1),
|
||||
@@ -225,6 +226,28 @@ typedef enum VkStructureType {
|
||||
VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000,
|
||||
VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057001,
|
||||
VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR = 1000059000,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR = 1000059001,
|
||||
VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR = 1000059002,
|
||||
VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR = 1000059003,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR = 1000059004,
|
||||
VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR = 1000059005,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR = 1000059006,
|
||||
VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = 1000059007,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = 1000059008,
|
||||
VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000,
|
||||
VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000,
|
||||
VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000,
|
||||
VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001,
|
||||
VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX = 1000086002,
|
||||
VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX = 1000086003,
|
||||
VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX = 1000086004,
|
||||
VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX = 1000086005,
|
||||
VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT = 1000090000,
|
||||
VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT = 1000091000,
|
||||
VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT = 1000091001,
|
||||
VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT = 1000091002,
|
||||
VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT = 1000091003,
|
||||
VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||
VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO,
|
||||
VK_STRUCTURE_TYPE_RANGE_SIZE = (VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO - VK_STRUCTURE_TYPE_APPLICATION_INFO + 1),
|
||||
@@ -833,6 +856,8 @@ typedef enum VkFormatFeatureFlagBits {
|
||||
VK_FORMAT_FEATURE_BLIT_DST_BIT = 0x00000800,
|
||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000,
|
||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000,
|
||||
VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = 0x00004000,
|
||||
VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = 0x00008000,
|
||||
VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
|
||||
} VkFormatFeatureFlagBits;
|
||||
typedef VkFlags VkFormatFeatureFlags;
|
||||
@@ -856,6 +881,7 @@ typedef enum VkImageCreateFlagBits {
|
||||
VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
|
||||
VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008,
|
||||
VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010,
|
||||
VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = 0x00000020,
|
||||
VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
|
||||
} VkImageCreateFlagBits;
|
||||
typedef VkFlags VkImageCreateFlags;
|
||||
@@ -917,6 +943,7 @@ typedef enum VkPipelineStageFlagBits {
|
||||
VK_PIPELINE_STAGE_HOST_BIT = 0x00004000,
|
||||
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000,
|
||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000,
|
||||
VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX = 0x00020000,
|
||||
VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
|
||||
} VkPipelineStageFlagBits;
|
||||
typedef VkFlags VkPipelineStageFlags;
|
||||
@@ -1091,6 +1118,8 @@ typedef enum VkAccessFlagBits {
|
||||
VK_ACCESS_HOST_WRITE_BIT = 0x00004000,
|
||||
VK_ACCESS_MEMORY_READ_BIT = 0x00008000,
|
||||
VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000,
|
||||
VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX = 0x00020000,
|
||||
VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX = 0x00040000,
|
||||
VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
|
||||
} VkAccessFlagBits;
|
||||
typedef VkFlags VkAccessFlags;
|
||||
@@ -3196,6 +3225,18 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR)
|
||||
|
||||
typedef enum VkColorSpaceKHR {
|
||||
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0,
|
||||
VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT = 1000104001,
|
||||
VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104002,
|
||||
VK_COLOR_SPACE_SCRGB_LINEAR_EXT = 1000104003,
|
||||
VK_COLOR_SPACE_SCRGB_NONLINEAR_EXT = 1000104004,
|
||||
VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = 1000104005,
|
||||
VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104006,
|
||||
VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104007,
|
||||
VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104008,
|
||||
VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104009,
|
||||
VK_COLOR_SPACE_BT2020_NONLINEAR_EXT = 1000104010,
|
||||
VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011,
|
||||
VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012,
|
||||
VK_COLOR_SPACE_BEGIN_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
|
||||
VK_COLOR_SPACE_END_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
|
||||
VK_COLOR_SPACE_RANGE_SIZE_KHR = (VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR + 1),
|
||||
@@ -3731,10 +3772,140 @@ VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR(
|
||||
#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge"
|
||||
|
||||
|
||||
#define VK_KHR_get_physical_device_properties2 1
|
||||
#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 1
|
||||
#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2"
|
||||
|
||||
typedef struct VkPhysicalDeviceFeatures2KHR {
|
||||
VkStructureType sType;
|
||||
void* pNext;
|
||||
VkPhysicalDeviceFeatures features;
|
||||
} VkPhysicalDeviceFeatures2KHR;
|
||||
|
||||
typedef struct VkPhysicalDeviceProperties2KHR {
|
||||
VkStructureType sType;
|
||||
void* pNext;
|
||||
VkPhysicalDeviceProperties properties;
|
||||
} VkPhysicalDeviceProperties2KHR;
|
||||
|
||||
typedef struct VkFormatProperties2KHR {
|
||||
VkStructureType sType;
|
||||
void* pNext;
|
||||
VkFormatProperties formatProperties;
|
||||
} VkFormatProperties2KHR;
|
||||
|
||||
typedef struct VkImageFormatProperties2KHR {
|
||||
VkStructureType sType;
|
||||
void* pNext;
|
||||
VkImageFormatProperties imageFormatProperties;
|
||||
} VkImageFormatProperties2KHR;
|
||||
|
||||
typedef struct VkPhysicalDeviceImageFormatInfo2KHR {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkFormat format;
|
||||
VkImageType type;
|
||||
VkImageTiling tiling;
|
||||
VkImageUsageFlags usage;
|
||||
VkImageCreateFlags flags;
|
||||
} VkPhysicalDeviceImageFormatInfo2KHR;
|
||||
|
||||
typedef struct VkQueueFamilyProperties2KHR {
|
||||
VkStructureType sType;
|
||||
void* pNext;
|
||||
VkQueueFamilyProperties queueFamilyProperties;
|
||||
} VkQueueFamilyProperties2KHR;
|
||||
|
||||
typedef struct VkPhysicalDeviceMemoryProperties2KHR {
|
||||
VkStructureType sType;
|
||||
void* pNext;
|
||||
VkPhysicalDeviceMemoryProperties memoryProperties;
|
||||
} VkPhysicalDeviceMemoryProperties2KHR;
|
||||
|
||||
typedef struct VkSparseImageFormatProperties2KHR {
|
||||
VkStructureType sType;
|
||||
void* pNext;
|
||||
VkSparseImageFormatProperties properties;
|
||||
} VkSparseImageFormatProperties2KHR;
|
||||
|
||||
typedef struct VkPhysicalDeviceSparseImageFormatInfo2KHR {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkFormat format;
|
||||
VkImageType type;
|
||||
VkSampleCountFlagBits samples;
|
||||
VkImageUsageFlags usage;
|
||||
VkImageTiling tiling;
|
||||
} VkPhysicalDeviceSparseImageFormatInfo2KHR;
|
||||
|
||||
|
||||
typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2KHR* pFeatures);
|
||||
typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2KHR* pProperties);
|
||||
typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2KHR)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2KHR* pFormatProperties);
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2KHR* pImageFormatInfo, VkImageFormatProperties2KHR* pImageFormatProperties);
|
||||
typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2KHR* pQueueFamilyProperties);
|
||||
typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2KHR* pMemoryProperties);
|
||||
typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2KHR* pProperties);
|
||||
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2KHR(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkPhysicalDeviceFeatures2KHR* pFeatures);
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2KHR(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkPhysicalDeviceProperties2KHR* pProperties);
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2KHR(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkFormat format,
|
||||
VkFormatProperties2KHR* pFormatProperties);
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2KHR(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const VkPhysicalDeviceImageFormatInfo2KHR* pImageFormatInfo,
|
||||
VkImageFormatProperties2KHR* pImageFormatProperties);
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2KHR(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
uint32_t* pQueueFamilyPropertyCount,
|
||||
VkQueueFamilyProperties2KHR* pQueueFamilyProperties);
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2KHR(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkPhysicalDeviceMemoryProperties2KHR* pMemoryProperties);
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2KHR(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo,
|
||||
uint32_t* pPropertyCount,
|
||||
VkSparseImageFormatProperties2KHR* pProperties);
|
||||
#endif
|
||||
|
||||
#define VK_KHR_shader_draw_parameters 1
|
||||
#define VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION 1
|
||||
#define VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME "VK_KHR_shader_draw_parameters"
|
||||
|
||||
|
||||
#define VK_KHR_maintenance1 1
|
||||
#define VK_KHR_MAINTENANCE1_SPEC_VERSION 1
|
||||
#define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1"
|
||||
|
||||
typedef VkFlags VkCommandPoolTrimFlagsKHR;
|
||||
|
||||
typedef void (VKAPI_PTR *PFN_vkTrimCommandPoolKHR)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlagsKHR flags);
|
||||
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
VKAPI_ATTR void VKAPI_CALL vkTrimCommandPoolKHR(
|
||||
VkDevice device,
|
||||
VkCommandPool commandPool,
|
||||
VkCommandPoolTrimFlagsKHR flags);
|
||||
#endif
|
||||
|
||||
#define VK_EXT_debug_report 1
|
||||
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
|
||||
|
||||
#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 3
|
||||
#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 4
|
||||
#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
|
||||
#define VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
|
||||
|
||||
@@ -3769,9 +3940,13 @@ typedef enum VkDebugReportObjectTypeEXT {
|
||||
VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT = 26,
|
||||
VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT = 27,
|
||||
VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = 28,
|
||||
VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT = 29,
|
||||
VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30,
|
||||
VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT = 31,
|
||||
VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32,
|
||||
VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
|
||||
VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
|
||||
VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1),
|
||||
VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT,
|
||||
VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1),
|
||||
VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF
|
||||
} VkDebugReportObjectTypeEXT;
|
||||
|
||||
@@ -3972,8 +4147,8 @@ typedef struct VkDedicatedAllocationMemoryAllocateInfoNV {
|
||||
|
||||
|
||||
#define VK_AMD_draw_indirect_count 1
|
||||
#define VK_AMD_EXTENSION_DRAW_INDIRECT_COUNT_SPEC_VERSION 1
|
||||
#define VK_AMD_EXTENSION_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count"
|
||||
#define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 1
|
||||
#define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count"
|
||||
|
||||
typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
|
||||
typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
|
||||
@@ -3998,6 +4173,21 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountAMD(
|
||||
uint32_t stride);
|
||||
#endif
|
||||
|
||||
#define VK_AMD_negative_viewport_height 1
|
||||
#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION 1
|
||||
#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME "VK_AMD_negative_viewport_height"
|
||||
|
||||
|
||||
#define VK_AMD_gpu_shader_half_float 1
|
||||
#define VK_AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION 1
|
||||
#define VK_AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME "VK_AMD_gpu_shader_half_float"
|
||||
|
||||
|
||||
#define VK_AMD_shader_ballot 1
|
||||
#define VK_AMD_SHADER_BALLOT_SPEC_VERSION 1
|
||||
#define VK_AMD_SHADER_BALLOT_EXTENSION_NAME "VK_AMD_shader_ballot"
|
||||
|
||||
|
||||
#define VK_IMG_format_pvrtc 1
|
||||
#define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1
|
||||
#define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc"
|
||||
@@ -4116,6 +4306,456 @@ typedef struct VkWin32KeyedMutexAcquireReleaseInfoNV {
|
||||
|
||||
#endif /* VK_USE_PLATFORM_WIN32_KHR */
|
||||
|
||||
#define VK_EXT_validation_flags 1
|
||||
#define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 1
|
||||
#define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags"
|
||||
|
||||
|
||||
typedef enum VkValidationCheckEXT {
|
||||
VK_VALIDATION_CHECK_ALL_EXT = 0,
|
||||
VK_VALIDATION_CHECK_BEGIN_RANGE_EXT = VK_VALIDATION_CHECK_ALL_EXT,
|
||||
VK_VALIDATION_CHECK_END_RANGE_EXT = VK_VALIDATION_CHECK_ALL_EXT,
|
||||
VK_VALIDATION_CHECK_RANGE_SIZE_EXT = (VK_VALIDATION_CHECK_ALL_EXT - VK_VALIDATION_CHECK_ALL_EXT + 1),
|
||||
VK_VALIDATION_CHECK_MAX_ENUM_EXT = 0x7FFFFFFF
|
||||
} VkValidationCheckEXT;
|
||||
|
||||
typedef struct VkValidationFlagsEXT {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
uint32_t disabledValidationCheckCount;
|
||||
VkValidationCheckEXT* pDisabledValidationChecks;
|
||||
} VkValidationFlagsEXT;
|
||||
|
||||
|
||||
|
||||
#ifdef VK_USE_PLATFORM_VI_NN
|
||||
#define VK_NN_vi_surface 1
|
||||
#define VK_NN_VI_SURFACE_SPEC_VERSION 1
|
||||
#define VK_NN_VI_SURFACE_EXTENSION_NAME "VK_NN_vi_surface"
|
||||
|
||||
typedef VkFlags VkViSurfaceCreateFlagsNN;
|
||||
|
||||
typedef struct VkViSurfaceCreateInfoNN {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkViSurfaceCreateFlagsNN flags;
|
||||
void* window;
|
||||
} VkViSurfaceCreateInfoNN;
|
||||
|
||||
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateViSurfaceNN)(VkInstance instance, const VkViSurfaceCreateInfoNN* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
|
||||
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateViSurfaceNN(
|
||||
VkInstance instance,
|
||||
const VkViSurfaceCreateInfoNN* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkSurfaceKHR* pSurface);
|
||||
#endif
|
||||
#endif /* VK_USE_PLATFORM_VI_NN */
|
||||
|
||||
#define VK_EXT_shader_subgroup_ballot 1
|
||||
#define VK_EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION 1
|
||||
#define VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME "VK_EXT_shader_subgroup_ballot"
|
||||
|
||||
|
||||
#define VK_EXT_shader_subgroup_vote 1
|
||||
#define VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION 1
|
||||
#define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote"
|
||||
|
||||
|
||||
#define VK_NVX_device_generated_commands 1
|
||||
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkObjectTableNVX)
|
||||
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNVX)
|
||||
|
||||
#define VK_NVX_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 1
|
||||
#define VK_NVX_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NVX_device_generated_commands"
|
||||
|
||||
|
||||
typedef enum VkIndirectCommandsTokenTypeNVX {
|
||||
VK_INDIRECT_COMMANDS_TOKEN_PIPELINE_NVX = 0,
|
||||
VK_INDIRECT_COMMANDS_TOKEN_DESCRIPTOR_SET_NVX = 1,
|
||||
VK_INDIRECT_COMMANDS_TOKEN_INDEX_BUFFER_NVX = 2,
|
||||
VK_INDIRECT_COMMANDS_TOKEN_VERTEX_BUFFER_NVX = 3,
|
||||
VK_INDIRECT_COMMANDS_TOKEN_PUSH_CONSTANT_NVX = 4,
|
||||
VK_INDIRECT_COMMANDS_TOKEN_DRAW_INDEXED_NVX = 5,
|
||||
VK_INDIRECT_COMMANDS_TOKEN_DRAW_NVX = 6,
|
||||
VK_INDIRECT_COMMANDS_TOKEN_DISPATCH_NVX = 7,
|
||||
VK_INDIRECT_COMMANDS_TOKEN_TYPE_BEGIN_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_PIPELINE_NVX,
|
||||
VK_INDIRECT_COMMANDS_TOKEN_TYPE_END_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_DISPATCH_NVX,
|
||||
VK_INDIRECT_COMMANDS_TOKEN_TYPE_RANGE_SIZE_NVX = (VK_INDIRECT_COMMANDS_TOKEN_DISPATCH_NVX - VK_INDIRECT_COMMANDS_TOKEN_PIPELINE_NVX + 1),
|
||||
VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF
|
||||
} VkIndirectCommandsTokenTypeNVX;
|
||||
|
||||
typedef enum VkObjectEntryTypeNVX {
|
||||
VK_OBJECT_ENTRY_DESCRIPTOR_SET_NVX = 0,
|
||||
VK_OBJECT_ENTRY_PIPELINE_NVX = 1,
|
||||
VK_OBJECT_ENTRY_INDEX_BUFFER_NVX = 2,
|
||||
VK_OBJECT_ENTRY_VERTEX_BUFFER_NVX = 3,
|
||||
VK_OBJECT_ENTRY_PUSH_CONSTANT_NVX = 4,
|
||||
VK_OBJECT_ENTRY_TYPE_BEGIN_RANGE_NVX = VK_OBJECT_ENTRY_DESCRIPTOR_SET_NVX,
|
||||
VK_OBJECT_ENTRY_TYPE_END_RANGE_NVX = VK_OBJECT_ENTRY_PUSH_CONSTANT_NVX,
|
||||
VK_OBJECT_ENTRY_TYPE_RANGE_SIZE_NVX = (VK_OBJECT_ENTRY_PUSH_CONSTANT_NVX - VK_OBJECT_ENTRY_DESCRIPTOR_SET_NVX + 1),
|
||||
VK_OBJECT_ENTRY_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF
|
||||
} VkObjectEntryTypeNVX;
|
||||
|
||||
|
||||
typedef enum VkIndirectCommandsLayoutUsageFlagBitsNVX {
|
||||
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX = 0x00000001,
|
||||
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX = 0x00000002,
|
||||
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX = 0x00000004,
|
||||
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX = 0x00000008,
|
||||
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF
|
||||
} VkIndirectCommandsLayoutUsageFlagBitsNVX;
|
||||
typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNVX;
|
||||
|
||||
typedef enum VkObjectEntryUsageFlagBitsNVX {
|
||||
VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX = 0x00000001,
|
||||
VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX = 0x00000002,
|
||||
VK_OBJECT_ENTRY_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF
|
||||
} VkObjectEntryUsageFlagBitsNVX;
|
||||
typedef VkFlags VkObjectEntryUsageFlagsNVX;
|
||||
|
||||
typedef struct VkDeviceGeneratedCommandsFeaturesNVX {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkBool32 computeBindingPointSupport;
|
||||
} VkDeviceGeneratedCommandsFeaturesNVX;
|
||||
|
||||
typedef struct VkDeviceGeneratedCommandsLimitsNVX {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
uint32_t maxIndirectCommandsLayoutTokenCount;
|
||||
uint32_t maxObjectEntryCounts;
|
||||
uint32_t minSequenceCountBufferOffsetAlignment;
|
||||
uint32_t minSequenceIndexBufferOffsetAlignment;
|
||||
uint32_t minCommandsTokenBufferOffsetAlignment;
|
||||
} VkDeviceGeneratedCommandsLimitsNVX;
|
||||
|
||||
typedef struct VkIndirectCommandsTokenNVX {
|
||||
VkIndirectCommandsTokenTypeNVX tokenType;
|
||||
VkBuffer buffer;
|
||||
VkDeviceSize offset;
|
||||
} VkIndirectCommandsTokenNVX;
|
||||
|
||||
typedef struct VkIndirectCommandsLayoutTokenNVX {
|
||||
VkIndirectCommandsTokenTypeNVX tokenType;
|
||||
uint32_t bindingUnit;
|
||||
uint32_t dynamicCount;
|
||||
uint32_t divisor;
|
||||
} VkIndirectCommandsLayoutTokenNVX;
|
||||
|
||||
typedef struct VkIndirectCommandsLayoutCreateInfoNVX {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkPipelineBindPoint pipelineBindPoint;
|
||||
VkIndirectCommandsLayoutUsageFlagsNVX flags;
|
||||
uint32_t tokenCount;
|
||||
const VkIndirectCommandsLayoutTokenNVX* pTokens;
|
||||
} VkIndirectCommandsLayoutCreateInfoNVX;
|
||||
|
||||
typedef struct VkCmdProcessCommandsInfoNVX {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkObjectTableNVX objectTable;
|
||||
VkIndirectCommandsLayoutNVX indirectCommandsLayout;
|
||||
uint32_t indirectCommandsTokenCount;
|
||||
const VkIndirectCommandsTokenNVX* pIndirectCommandsTokens;
|
||||
uint32_t maxSequencesCount;
|
||||
VkCommandBuffer targetCommandBuffer;
|
||||
VkBuffer sequencesCountBuffer;
|
||||
VkDeviceSize sequencesCountOffset;
|
||||
VkBuffer sequencesIndexBuffer;
|
||||
VkDeviceSize sequencesIndexOffset;
|
||||
} VkCmdProcessCommandsInfoNVX;
|
||||
|
||||
typedef struct VkCmdReserveSpaceForCommandsInfoNVX {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkObjectTableNVX objectTable;
|
||||
VkIndirectCommandsLayoutNVX indirectCommandsLayout;
|
||||
uint32_t maxSequencesCount;
|
||||
} VkCmdReserveSpaceForCommandsInfoNVX;
|
||||
|
||||
typedef struct VkObjectTableCreateInfoNVX {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
uint32_t objectCount;
|
||||
const VkObjectEntryTypeNVX* pObjectEntryTypes;
|
||||
const uint32_t* pObjectEntryCounts;
|
||||
const VkObjectEntryUsageFlagsNVX* pObjectEntryUsageFlags;
|
||||
uint32_t maxUniformBuffersPerDescriptor;
|
||||
uint32_t maxStorageBuffersPerDescriptor;
|
||||
uint32_t maxStorageImagesPerDescriptor;
|
||||
uint32_t maxSampledImagesPerDescriptor;
|
||||
uint32_t maxPipelineLayouts;
|
||||
} VkObjectTableCreateInfoNVX;
|
||||
|
||||
typedef struct VkObjectTableEntryNVX {
|
||||
VkObjectEntryTypeNVX type;
|
||||
VkObjectEntryUsageFlagsNVX flags;
|
||||
} VkObjectTableEntryNVX;
|
||||
|
||||
typedef struct VkObjectTablePipelineEntryNVX {
|
||||
VkObjectEntryTypeNVX type;
|
||||
VkObjectEntryUsageFlagsNVX flags;
|
||||
VkPipeline pipeline;
|
||||
} VkObjectTablePipelineEntryNVX;
|
||||
|
||||
typedef struct VkObjectTableDescriptorSetEntryNVX {
|
||||
VkObjectEntryTypeNVX type;
|
||||
VkObjectEntryUsageFlagsNVX flags;
|
||||
VkPipelineLayout pipelineLayout;
|
||||
VkDescriptorSet descriptorSet;
|
||||
} VkObjectTableDescriptorSetEntryNVX;
|
||||
|
||||
typedef struct VkObjectTableVertexBufferEntryNVX {
|
||||
VkObjectEntryTypeNVX type;
|
||||
VkObjectEntryUsageFlagsNVX flags;
|
||||
VkBuffer buffer;
|
||||
} VkObjectTableVertexBufferEntryNVX;
|
||||
|
||||
typedef struct VkObjectTableIndexBufferEntryNVX {
|
||||
VkObjectEntryTypeNVX type;
|
||||
VkObjectEntryUsageFlagsNVX flags;
|
||||
VkBuffer buffer;
|
||||
VkIndexType indexType;
|
||||
} VkObjectTableIndexBufferEntryNVX;
|
||||
|
||||
typedef struct VkObjectTablePushConstantEntryNVX {
|
||||
VkObjectEntryTypeNVX type;
|
||||
VkObjectEntryUsageFlagsNVX flags;
|
||||
VkPipelineLayout pipelineLayout;
|
||||
VkShaderStageFlags stageFlags;
|
||||
} VkObjectTablePushConstantEntryNVX;
|
||||
|
||||
|
||||
typedef void (VKAPI_PTR *PFN_vkCmdProcessCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo);
|
||||
typedef void (VKAPI_PTR *PFN_vkCmdReserveSpaceForCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo);
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNVX)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout);
|
||||
typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNVX)(VkDevice device, VkIndirectCommandsLayoutNVX indirectCommandsLayout, const VkAllocationCallbacks* pAllocator);
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateObjectTableNVX)(VkDevice device, const VkObjectTableCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkObjectTableNVX* pObjectTable);
|
||||
typedef void (VKAPI_PTR *PFN_vkDestroyObjectTableNVX)(VkDevice device, VkObjectTableNVX objectTable, const VkAllocationCallbacks* pAllocator);
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkRegisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectTableEntryNVX* const* ppObjectTableEntries, const uint32_t* pObjectIndices);
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkUnregisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectEntryTypeNVX* pObjectEntryTypes, const uint32_t* pObjectIndices);
|
||||
typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX)(VkPhysicalDevice physicalDevice, VkDeviceGeneratedCommandsFeaturesNVX* pFeatures, VkDeviceGeneratedCommandsLimitsNVX* pLimits);
|
||||
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
VKAPI_ATTR void VKAPI_CALL vkCmdProcessCommandsNVX(
|
||||
VkCommandBuffer commandBuffer,
|
||||
const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo);
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL vkCmdReserveSpaceForCommandsNVX(
|
||||
VkCommandBuffer commandBuffer,
|
||||
const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo);
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNVX(
|
||||
VkDevice device,
|
||||
const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout);
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNVX(
|
||||
VkDevice device,
|
||||
VkIndirectCommandsLayoutNVX indirectCommandsLayout,
|
||||
const VkAllocationCallbacks* pAllocator);
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateObjectTableNVX(
|
||||
VkDevice device,
|
||||
const VkObjectTableCreateInfoNVX* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkObjectTableNVX* pObjectTable);
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL vkDestroyObjectTableNVX(
|
||||
VkDevice device,
|
||||
VkObjectTableNVX objectTable,
|
||||
const VkAllocationCallbacks* pAllocator);
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkRegisterObjectsNVX(
|
||||
VkDevice device,
|
||||
VkObjectTableNVX objectTable,
|
||||
uint32_t objectCount,
|
||||
const VkObjectTableEntryNVX* const* ppObjectTableEntries,
|
||||
const uint32_t* pObjectIndices);
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkUnregisterObjectsNVX(
|
||||
VkDevice device,
|
||||
VkObjectTableNVX objectTable,
|
||||
uint32_t objectCount,
|
||||
const VkObjectEntryTypeNVX* pObjectEntryTypes,
|
||||
const uint32_t* pObjectIndices);
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkDeviceGeneratedCommandsFeaturesNVX* pFeatures,
|
||||
VkDeviceGeneratedCommandsLimitsNVX* pLimits);
|
||||
#endif
|
||||
|
||||
#define VK_EXT_direct_mode_display 1
|
||||
#define VK_EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION 1
|
||||
#define VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME "VK_EXT_direct_mode_display"
|
||||
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkReleaseDisplayEXT)(VkPhysicalDevice physicalDevice, VkDisplayKHR display);
|
||||
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkReleaseDisplayEXT(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkDisplayKHR display);
|
||||
#endif
|
||||
|
||||
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
|
||||
#define VK_EXT_acquire_xlib_display 1
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
|
||||
#define VK_EXT_ACQUIRE_XLIB_DISPLAY_SPEC_VERSION 1
|
||||
#define VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_xlib_display"
|
||||
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkAcquireXlibDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, VkDisplayKHR display);
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkGetRandROutputDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, RROutput rrOutput, VkDisplayKHR* pDisplay);
|
||||
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkAcquireXlibDisplayEXT(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
Display* dpy,
|
||||
VkDisplayKHR display);
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetRandROutputDisplayEXT(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
Display* dpy,
|
||||
RROutput rrOutput,
|
||||
VkDisplayKHR* pDisplay);
|
||||
#endif
|
||||
#endif /* VK_USE_PLATFORM_XLIB_XRANDR_EXT */
|
||||
|
||||
#define VK_EXT_display_surface_counter 1
|
||||
#define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1
|
||||
#define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter"
|
||||
|
||||
|
||||
typedef enum VkSurfaceCounterFlagBitsEXT {
|
||||
VK_SURFACE_COUNTER_VBLANK_EXT = 0x00000001,
|
||||
VK_SURFACE_COUNTER_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
|
||||
} VkSurfaceCounterFlagBitsEXT;
|
||||
typedef VkFlags VkSurfaceCounterFlagsEXT;
|
||||
|
||||
typedef struct VkSurfaceCapabilities2EXT {
|
||||
VkStructureType sType;
|
||||
void* pNext;
|
||||
uint32_t minImageCount;
|
||||
uint32_t maxImageCount;
|
||||
VkExtent2D currentExtent;
|
||||
VkExtent2D minImageExtent;
|
||||
VkExtent2D maxImageExtent;
|
||||
uint32_t maxImageArrayLayers;
|
||||
VkSurfaceTransformFlagsKHR supportedTransforms;
|
||||
VkSurfaceTransformFlagBitsKHR currentTransform;
|
||||
VkCompositeAlphaFlagsKHR supportedCompositeAlpha;
|
||||
VkImageUsageFlags supportedUsageFlags;
|
||||
VkSurfaceCounterFlagsEXT supportedSurfaceCounters;
|
||||
} VkSurfaceCapabilities2EXT;
|
||||
|
||||
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT* pSurfaceCapabilities);
|
||||
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2EXT(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkSurfaceKHR surface,
|
||||
VkSurfaceCapabilities2EXT* pSurfaceCapabilities);
|
||||
#endif
|
||||
|
||||
#define VK_EXT_display_control 1
|
||||
#define VK_EXT_DISPLAY_CONTROL_SPEC_VERSION 1
|
||||
#define VK_EXT_DISPLAY_CONTROL_EXTENSION_NAME "VK_EXT_display_control"
|
||||
|
||||
|
||||
typedef enum VkDisplayPowerStateEXT {
|
||||
VK_DISPLAY_POWER_STATE_OFF_EXT = 0,
|
||||
VK_DISPLAY_POWER_STATE_SUSPEND_EXT = 1,
|
||||
VK_DISPLAY_POWER_STATE_ON_EXT = 2,
|
||||
VK_DISPLAY_POWER_STATE_BEGIN_RANGE_EXT = VK_DISPLAY_POWER_STATE_OFF_EXT,
|
||||
VK_DISPLAY_POWER_STATE_END_RANGE_EXT = VK_DISPLAY_POWER_STATE_ON_EXT,
|
||||
VK_DISPLAY_POWER_STATE_RANGE_SIZE_EXT = (VK_DISPLAY_POWER_STATE_ON_EXT - VK_DISPLAY_POWER_STATE_OFF_EXT + 1),
|
||||
VK_DISPLAY_POWER_STATE_MAX_ENUM_EXT = 0x7FFFFFFF
|
||||
} VkDisplayPowerStateEXT;
|
||||
|
||||
typedef enum VkDeviceEventTypeEXT {
|
||||
VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT = 0,
|
||||
VK_DEVICE_EVENT_TYPE_BEGIN_RANGE_EXT = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT,
|
||||
VK_DEVICE_EVENT_TYPE_END_RANGE_EXT = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT,
|
||||
VK_DEVICE_EVENT_TYPE_RANGE_SIZE_EXT = (VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT - VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT + 1),
|
||||
VK_DEVICE_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF
|
||||
} VkDeviceEventTypeEXT;
|
||||
|
||||
typedef enum VkDisplayEventTypeEXT {
|
||||
VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT = 0,
|
||||
VK_DISPLAY_EVENT_TYPE_BEGIN_RANGE_EXT = VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT,
|
||||
VK_DISPLAY_EVENT_TYPE_END_RANGE_EXT = VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT,
|
||||
VK_DISPLAY_EVENT_TYPE_RANGE_SIZE_EXT = (VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT - VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT + 1),
|
||||
VK_DISPLAY_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF
|
||||
} VkDisplayEventTypeEXT;
|
||||
|
||||
typedef struct VkDisplayPowerInfoEXT {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkDisplayPowerStateEXT powerState;
|
||||
} VkDisplayPowerInfoEXT;
|
||||
|
||||
typedef struct VkDeviceEventInfoEXT {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkDeviceEventTypeEXT deviceEvent;
|
||||
} VkDeviceEventInfoEXT;
|
||||
|
||||
typedef struct VkDisplayEventInfoEXT {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkDisplayEventTypeEXT displayEvent;
|
||||
} VkDisplayEventInfoEXT;
|
||||
|
||||
typedef struct VkSwapchainCounterCreateInfoEXT {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkSurfaceCounterFlagsEXT surfaceCounters;
|
||||
} VkSwapchainCounterCreateInfoEXT;
|
||||
|
||||
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkDisplayPowerControlEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayPowerInfoEXT* pDisplayPowerInfo);
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkRegisterDeviceEventEXT)(VkDevice device, const VkDeviceEventInfoEXT* pDeviceEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence);
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkRegisterDisplayEventEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayEventInfoEXT* pDisplayEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence);
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainCounterEXT)(VkDevice device, VkSwapchainKHR swapchain, VkSurfaceCounterFlagBitsEXT counter, uint64_t* pCounterValue);
|
||||
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkDisplayPowerControlEXT(
|
||||
VkDevice device,
|
||||
VkDisplayKHR display,
|
||||
const VkDisplayPowerInfoEXT* pDisplayPowerInfo);
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDeviceEventEXT(
|
||||
VkDevice device,
|
||||
const VkDeviceEventInfoEXT* pDeviceEventInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkFence* pFence);
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDisplayEventEXT(
|
||||
VkDevice device,
|
||||
VkDisplayKHR display,
|
||||
const VkDisplayEventInfoEXT* pDisplayEventInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkFence* pFence);
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainCounterEXT(
|
||||
VkDevice device,
|
||||
VkSwapchainKHR swapchain,
|
||||
VkSurfaceCounterFlagBitsEXT counter,
|
||||
uint64_t* pCounterValue);
|
||||
#endif
|
||||
|
||||
#define VK_EXT_swapchain_colorspace 1
|
||||
#define VK_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 1
|
||||
#define VK_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+3
-6
@@ -14,14 +14,11 @@ 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}/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} ${arg}")
|
||||
set(GLFW_DOCS_SOURCES "${GLFW_DOCS_SOURCES} \\\n\"${arg}\"")
|
||||
endforeach()
|
||||
|
||||
configure_file(Doxyfile.in Doxyfile @ONLY)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
- [Reporting a segfault or other crash bug](#reporting-a-segfault-or-other-crash-bug)
|
||||
- [Reporting a context creation bug](#reporting-a-context-creation-bug)
|
||||
- [Reporting a monitor or video mode bug](#reporting-a-monitor-or-video-mode-bug)
|
||||
- [Reporting an input or event bug](#reporting-an-input-or-event-bug)
|
||||
- [Reporting a window, input or event bug](#reporting-a-window-input-or-event-bug)
|
||||
- [Reporting some other library bug](#reporting-some-other-library-bug)
|
||||
- [Reporting a documentation bug](#reporting-a-documentation-bug)
|
||||
- [Reporting a website bug](#reporting-a-website-bug)
|
||||
@@ -42,15 +42,36 @@ doesn't, that might be a separate bug.
|
||||
If GLFW is crashing or triggering asserts, make sure that all your object
|
||||
handles and other pointers are valid.
|
||||
|
||||
For bugs where it makes sense, a [Short, Self Contained, Correct (Compilable),
|
||||
Example](http://www.sscce.org/) is absolutely invaluable. Just put it inline in
|
||||
the body text. Note that if the bug is reproducible with one of the test
|
||||
programs that come with GLFW, just mention that instead.
|
||||
For bugs where it makes sense, a short, self contained example is absolutely
|
||||
invaluable. Just put it inline in the body text. Note that if the bug is
|
||||
reproducible with one of the test programs that come with GLFW, just mention
|
||||
that instead.
|
||||
|
||||
__Don't worry about adding too much information__. Unimportant information can
|
||||
be abbreviated or removed later, but missing information can stall bug fixing,
|
||||
especially when your schedule doesn't align with that of the maintainer.
|
||||
|
||||
__Please provide text as text, not as images__. This includes code, error
|
||||
messages and any other text. Text in images cannot be found by other users
|
||||
searching for the same problem and may have to be re-typed by maintainers when
|
||||
debugging.
|
||||
|
||||
You don't need to manually indent your code or other text to quote it with
|
||||
GitHub Markdown; just surround it with triple backticks:
|
||||
|
||||
```
|
||||
Some quoted text.
|
||||
```
|
||||
|
||||
You can also add syntax highlighting by appending the common file extension:
|
||||
|
||||
```c
|
||||
int five(void)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
```
|
||||
|
||||
There are issue labels for both platforms and GPU manufacturers, so there is no
|
||||
need to mention these in the subject line. If you do, it will be removed when
|
||||
the issue is labeled.
|
||||
@@ -139,6 +160,9 @@ Always include the __operating system name and version__ (e.g. `Windows
|
||||
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
||||
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
|
||||
|
||||
If you are running your program in a virtual machine, please mention this and
|
||||
include the __VM name and version__ (e.g. `VirtualBox 5.1`).
|
||||
|
||||
Please also include the __GLFW version string__ (`3.2.0 X11 EGL clock_gettime
|
||||
/dev/js`), as described
|
||||
[here](http://www.glfw.org/docs/latest/intro.html#intro_version_string), the
|
||||
@@ -178,6 +202,9 @@ Always include the __operating system name and version__ (e.g. `Windows
|
||||
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
||||
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
|
||||
|
||||
If you are running your program in a virtual machine, please mention this and
|
||||
include the __VM name and version__ (e.g. `VirtualBox 5.1`).
|
||||
|
||||
Please also include any __error messages__ provided to your application via the
|
||||
[error
|
||||
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
|
||||
@@ -195,12 +222,12 @@ monitors output:
|
||||
```
|
||||
|
||||
|
||||
### Reporting an input or event bug
|
||||
### Reporting a window, input or event bug
|
||||
|
||||
__Note:__ The exact ordering of related window events will sometimes differ.
|
||||
|
||||
__Note:__ Window moving and resizing (by the user) will block the main thread on some
|
||||
platforms. This is not a bug. Set a [refresh
|
||||
__Note:__ Window moving and resizing (by the user) will block the main thread on
|
||||
some platforms. This is not a bug. Set a [refresh
|
||||
callback](http://www.glfw.org/docs/latest/window.html#window_refresh) if you
|
||||
want to keep the window contents updated during a move or size operation.
|
||||
|
||||
@@ -215,12 +242,20 @@ Always include the __operating system name and version__ (e.g. `Windows
|
||||
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
||||
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
|
||||
|
||||
If you are running your program in a virtual machine, please mention this and
|
||||
include the __VM name and version__ (e.g. `VirtualBox 5.1`).
|
||||
|
||||
Please also include any __error messages__ provided to your application via the
|
||||
[error
|
||||
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
|
||||
if relevant, the __output of `events`__ when reporting this kind of bug. If
|
||||
this tool doesn't run on the machine, mention this instead.
|
||||
|
||||
__X11:__ If possible, please include what desktop environment (e.g. GNOME,
|
||||
Unity, KDE) and/or window manager (e.g. Openbox, dwm, Window Maker) you are
|
||||
running. If the bug is related to keyboard input, please include any input
|
||||
method (e.g. ibus, SCIM) you are using.
|
||||
|
||||
|
||||
#### Quick template
|
||||
|
||||
@@ -301,6 +336,9 @@ other bugs and features to work on.
|
||||
If the patch fixes a bug introduced after the last release, it should not get
|
||||
a change log entry.
|
||||
|
||||
If you haven't already, read the excellent article [How to Write a Git Commit
|
||||
Message](https://chris.beams.io/posts/git-commit/).
|
||||
|
||||
|
||||
## Contributing a feature
|
||||
|
||||
@@ -309,6 +347,10 @@ did not write the code yourself, you must explain where it came from and under
|
||||
what license. Even code using the same license as GLFW may not be copied
|
||||
without attribution.
|
||||
|
||||
__Note:__ If you haven't already implemented the feature, check first if there
|
||||
already is an open issue for it and if it's already being developed in an
|
||||
[experimental branch](https://github.com/glfw/glfw/branches/all).
|
||||
|
||||
__There is no preferred patch size__. A one character change is just as welcome
|
||||
as one adding a thousand line one, if that is the appropriate size for the
|
||||
feature.
|
||||
@@ -334,6 +376,9 @@ If it adds a new OpenGL, OpenGL ES or Vulkan option or extension, support
|
||||
for it must be added to `tests/glfwinfo.c` and the behavior of the library when
|
||||
the extension is missing documented in `docs/compat.dox`.
|
||||
|
||||
If you haven't already, read the excellent article [How to Write a Git Commit
|
||||
Message](https://chris.beams.io/posts/git-commit/).
|
||||
|
||||
Features will not be rejected because they don't include all the above parts,
|
||||
but please keep in mind that maintainer time is finite and that there are many
|
||||
other features and bugs to work on.
|
||||
+10
-9
@@ -52,7 +52,7 @@ PROJECT_LOGO =
|
||||
# If a relative path is entered, it will be relative to the location
|
||||
# where doxygen was started. If left blank the current directory will be used.
|
||||
|
||||
OUTPUT_DIRECTORY = @GLFW_BINARY_DIR@/docs
|
||||
OUTPUT_DIRECTORY = "@GLFW_BINARY_DIR@/docs"
|
||||
|
||||
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
|
||||
# 4096 sub-directories (in 2 levels) under the output directory of each output
|
||||
@@ -204,7 +204,8 @@ ALIASES = "thread_safety=@par Thread safety\n" \
|
||||
"x11=__X11:__" \
|
||||
"wayland=__Wayland:__" \
|
||||
"win32=__Windows:__" \
|
||||
"macos=__macOS:__"
|
||||
"macos=__macOS:__" \
|
||||
"linux=__Linux:__"
|
||||
|
||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
||||
# A mapping has the form "name=value". For example adding
|
||||
@@ -475,7 +476,7 @@ SORT_MEMBER_DOCS = NO
|
||||
# by member name. If set to NO (the default) the members will appear in
|
||||
# declaration order.
|
||||
|
||||
SORT_BRIEF_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
|
||||
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
|
||||
# will sort the (brief and detailed) documentation of class members so that
|
||||
@@ -650,7 +651,7 @@ WARN_FORMAT = "$file:$line: $text"
|
||||
# and error messages should be written. If left blank the output is written
|
||||
# to stderr.
|
||||
|
||||
WARN_LOGFILE = @GLFW_BINARY_DIR@/docs/warnings.txt
|
||||
WARN_LOGFILE = "@GLFW_BINARY_DIR@/docs/warnings.txt"
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
@@ -721,7 +722,7 @@ EXCLUDE_SYMBOLS = APIENTRY GLFWAPI
|
||||
# directories that contain example code fragments that are included (see
|
||||
# the \include command).
|
||||
|
||||
EXAMPLE_PATH = @GLFW_SOURCE_DIR@/examples
|
||||
EXAMPLE_PATH = "@GLFW_SOURCE_DIR@/examples"
|
||||
|
||||
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
|
||||
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
@@ -897,13 +898,13 @@ HTML_FILE_EXTENSION = .html
|
||||
# have to redo this when upgrading to a newer version of doxygen or when
|
||||
# changing the value of configuration settings such as GENERATE_TREEVIEW!
|
||||
|
||||
HTML_HEADER = @GLFW_SOURCE_DIR@/docs/header.html
|
||||
HTML_HEADER = "@GLFW_SOURCE_DIR@/docs/header.html"
|
||||
|
||||
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
|
||||
# each generated HTML page. If it is left blank doxygen will generate a
|
||||
# standard footer.
|
||||
|
||||
HTML_FOOTER = @GLFW_SOURCE_DIR@/docs/footer.html
|
||||
HTML_FOOTER = "@GLFW_SOURCE_DIR@/docs/footer.html"
|
||||
|
||||
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
|
||||
# style sheet that is used by each HTML page. It can be used to
|
||||
@@ -922,7 +923,7 @@ HTML_STYLESHEET =
|
||||
# robust against future updates. Doxygen will copy the style sheet file to
|
||||
# the output directory.
|
||||
|
||||
HTML_EXTRA_STYLESHEET = @GLFW_SOURCE_DIR@/docs/extra.css
|
||||
HTML_EXTRA_STYLESHEET = "@GLFW_SOURCE_DIR@/docs/extra.css"
|
||||
|
||||
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
|
||||
# other source files which should be copied to the HTML output directory. Note
|
||||
@@ -931,7 +932,7 @@ HTML_EXTRA_STYLESHEET = @GLFW_SOURCE_DIR@/docs/extra.css
|
||||
# files. In the HTML_STYLESHEET file, use the file name only. Also note that
|
||||
# the files will be copied as-is; there are no commands or markers available.
|
||||
|
||||
HTML_EXTRA_FILES = @GLFW_SOURCE_DIR@/docs/spaces.svg
|
||||
HTML_EXTRA_FILES = "@GLFW_SOURCE_DIR@/docs/spaces.svg"
|
||||
|
||||
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
|
||||
# Doxygen will adjust the colors in the style sheet and background images
|
||||
|
||||
+53
-24
@@ -15,27 +15,27 @@ specific compiler of your chosen development environment. The compilation
|
||||
and linking process should be explained in your C programming material and in
|
||||
the documentation for your development environment.
|
||||
|
||||
|
||||
@section build_include Including the GLFW header file
|
||||
|
||||
In the source files of your application where you use OpenGL or GLFW, you should
|
||||
include the GLFW header file, i.e.:
|
||||
You should include the GLFW header in the source files where you use OpenGL or
|
||||
GLFW.
|
||||
|
||||
@code
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
The GLFW header declares the GLFW API and by default also includes the OpenGL
|
||||
header of your development environment, which in turn defines all the constants,
|
||||
types and function prototypes of the OpenGL API.
|
||||
This header declares the GLFW API and by default also includes the OpenGL header
|
||||
from your development environment. See below for how to control this.
|
||||
|
||||
The GLFW header also defines everything necessary for your OpenGL header to
|
||||
function. For example, under Windows you are normally required to include
|
||||
`windows.h` before the OpenGL header, which would pollute your code namespace
|
||||
with the entire Win32 API.
|
||||
The GLFW header also defines any platform-specific macros needed by your OpenGL
|
||||
header, so it can be included without needing any window system headers.
|
||||
|
||||
Instead, the GLFW header takes care of this for you, not by including
|
||||
`windows.h`, but by duplicating only the very few necessary parts of it. It
|
||||
does this only when needed, so if `windows.h` _is_ included, the GLFW header
|
||||
For example, under Windows you are normally required to include `windows.h`
|
||||
before the OpenGL header, which would bring in the whole Win32 API. The GLFW
|
||||
header duplicates the small number of macros needed.
|
||||
|
||||
It does this only when needed, so if `windows.h` _is_ included, the GLFW header
|
||||
does not try to redefine those symbols. The reverse is not true, i.e.
|
||||
`windows.h` cannot cope if any of its symbols have already been defined.
|
||||
|
||||
@@ -49,8 +49,21 @@ In other words:
|
||||
|
||||
If you are using an OpenGL extension loading library such as
|
||||
[glad](https://github.com/Dav1dde/glad), the extension loader header should
|
||||
either be included _before_ the GLFW one, or the @ref GLFW_INCLUDE_NONE macro
|
||||
(described below) should be defined.
|
||||
be included _before_ the GLFW one.
|
||||
|
||||
@code
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
Alternatively the @ref GLFW_INCLUDE_NONE macro (described below) can be used to
|
||||
prevent the GLFW header from including the OpenGL header.
|
||||
|
||||
@code
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <glad/glad.h>
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection build_macros GLFW header option macros
|
||||
@@ -86,6 +99,10 @@ __GLFW_INCLUDE_ES3__ makes the GLFW header include the OpenGL ES 3.0
|
||||
__GLFW_INCLUDE_ES31__ makes the GLFW header include the OpenGL ES 3.1
|
||||
`GLES3/gl31.h` header instead of the regular OpenGL header.
|
||||
|
||||
@anchor GLFW_INCLUDE_ES32
|
||||
__GLFW_INCLUDE_ES31__ makes the GLFW header include the OpenGL ES 3.2
|
||||
`GLES3/gl32.h` header instead of the regular OpenGL header.
|
||||
|
||||
@anchor GLFW_INCLUDE_NONE
|
||||
__GLFW_INCLUDE_NONE__ makes the GLFW header not include any OpenGL or OpenGL ES
|
||||
API header. This is useful in combination with an extension loading library.
|
||||
@@ -166,8 +183,8 @@ This section is about using CMake to compile and link GLFW along with your
|
||||
application. If you want to use an installed binary instead, see @ref
|
||||
build_link_cmake_package.
|
||||
|
||||
With just a few changes to your `CMakeLists.txt` you can have the GLFW source
|
||||
tree built along with your application.
|
||||
With a few changes to your `CMakeLists.txt` you can have the GLFW source tree
|
||||
built along with your application.
|
||||
|
||||
When including GLFW as part of your build, you probably don't want to build the
|
||||
GLFW tests, examples and documentation. To disable these, set the corresponding
|
||||
@@ -222,7 +239,8 @@ target_link_libraries(myapp ${OPENGL_glu_LIBRARY})
|
||||
@endcode
|
||||
|
||||
@note GLU has been deprecated and should not be used in new code, but some
|
||||
legacy code requires it.
|
||||
legacy code requires it. See the [section on GLU](@ref moving_glu) in the
|
||||
transition guide for suggested replacements.
|
||||
|
||||
|
||||
@subsection build_link_cmake_package With CMake and installed GLFW binaries
|
||||
@@ -231,13 +249,22 @@ This section is about using CMake to link GLFW after it has been built and
|
||||
installed. If you want to build it along with your application instead, see
|
||||
@ref build_link_cmake_source.
|
||||
|
||||
With just a few changes to your `CMakeLists.txt`, you can locate the package and
|
||||
With a few changes to your `CMakeLists.txt` you can locate the package and
|
||||
target files generated when GLFW is installed.
|
||||
|
||||
@code{.cmake}
|
||||
find_package(glfw3 3.3 REQUIRED)
|
||||
@endcode
|
||||
|
||||
Once GLFW has been added to the project, link against it with the `glfw` target.
|
||||
This adds all link-time dependencies of GLFW as it is currently configured,
|
||||
the include directory for the GLFW header and, when applicable, the @ref
|
||||
GLFW_DLL macro.
|
||||
|
||||
@code{.cmake}
|
||||
target_link_libraries(myapp glfw)
|
||||
@endcode
|
||||
|
||||
Note that the dependencies do not include OpenGL or GLU, as GLFW loads any
|
||||
OpenGL, OpenGL ES or Vulkan libraries it needs at runtime and does not use GLU.
|
||||
If your application calls OpenGL directly, instead of using a modern
|
||||
@@ -265,7 +292,8 @@ target_link_libraries(myapp ${OPENGL_glu_LIBRARY})
|
||||
@endcode
|
||||
|
||||
@note GLU has been deprecated and should not be used in new code, but some
|
||||
legacy code requires it.
|
||||
legacy code requires it. See the [section on GLU](@ref moving_glu) in the
|
||||
transition guide for suggested replacements.
|
||||
|
||||
|
||||
@subsection build_link_pkgconfig With makefiles and pkg-config on Unix
|
||||
@@ -284,8 +312,8 @@ GLFW library may look like this:
|
||||
cc `pkg-config --cflags glfw3` -o myprog myprog.c `pkg-config --static --libs glfw3`
|
||||
@endcode
|
||||
|
||||
If you are using the shared version of the GLFW library, simply omit the
|
||||
`--static` flag.
|
||||
If you are using the shared version of the GLFW library, omit the `--static`
|
||||
flag.
|
||||
|
||||
@code{.sh}
|
||||
cc `pkg-config --cflags glfw3` -o myprog myprog.c `pkg-config --libs glfw3`
|
||||
@@ -309,7 +337,8 @@ cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --libs glfw3 g
|
||||
@endcode
|
||||
|
||||
@note GLU has been deprecated and should not be used in new code, but some
|
||||
legacy code requires it.
|
||||
legacy code requires it. See the [section on GLU](@ref moving_glu) in the
|
||||
transition guide for suggested replacements.
|
||||
|
||||
If you are using the static version of the GLFW library, make sure you don't
|
||||
link statically against GLU.
|
||||
@@ -321,8 +350,8 @@ cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --static --lib
|
||||
|
||||
@subsection build_link_xcode With Xcode on macOS
|
||||
|
||||
If you are using the dynamic library version of GLFW, simply add it to the
|
||||
project dependencies.
|
||||
If you are using the dynamic library version of GLFW, add it to the project
|
||||
dependencies.
|
||||
|
||||
If you are using the static library version of GLFW, add it and the Cocoa,
|
||||
OpenGL, IOKit and CoreVideo frameworks to the project as dependencies. They can
|
||||
|
||||
+60
-9
@@ -76,6 +76,56 @@ GLFW uses the Xkb extension and detectable auto-repeat to provide keyboard
|
||||
input. If the running X server does not support this extension, a non-Xkb
|
||||
fallback path is used.
|
||||
|
||||
GLFW uses the XInput2 extension to provide raw, non-accelerated mouse motion
|
||||
when the cursor is disabled. If the running X server does not support this
|
||||
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` 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.
|
||||
|
||||
|
||||
@section compat_glx GLX extensions
|
||||
|
||||
@@ -160,21 +210,21 @@ extensions to provide support for sRGB framebuffers. Where both of these
|
||||
extension are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect.
|
||||
|
||||
|
||||
@section compat_osx OpenGL 3.2 and later on macOS
|
||||
@section compat_osx OpenGL on macOS
|
||||
|
||||
Support for OpenGL 3.2 and above was introduced with OS X 10.7 and even then
|
||||
only forward-compatible, core profile contexts are supported. Support for
|
||||
OpenGL 4.1 was introduced with OS X 10.9, also limited to forward-compatible,
|
||||
core profile contexts. There is also still no mechanism for requesting debug
|
||||
contexts. Versions of Mac OS X earlier than 10.7 support at most OpenGL
|
||||
version 2.1.
|
||||
contexts or no-error contexts. Versions of Mac OS X earlier than 10.7 support
|
||||
at most OpenGL version 2.1.
|
||||
|
||||
Because of this, on OS X 10.7 and later, the `GLFW_CONTEXT_VERSION_MAJOR` and
|
||||
`GLFW_CONTEXT_VERSION_MINOR` hints will cause @ref glfwCreateWindow to fail if
|
||||
given version 3.0 or 3.1, the `GLFW_OPENGL_FORWARD_COMPAT` hint must be set to
|
||||
given version 3.0 or 3.1. The `GLFW_OPENGL_FORWARD_COMPAT` hint must be set to
|
||||
`GLFW_TRUE` and the `GLFW_OPENGL_PROFILE` hint must be set to
|
||||
`GLFW_OPENGL_CORE_PROFILE` when creating OpenGL 3.2 and later contexts and the
|
||||
`GLFW_OPENGL_DEBUG_CONTEXT` hint is ignored.
|
||||
`GLFW_OPENGL_CORE_PROFILE` when creating OpenGL 3.2 and later contexts. The
|
||||
`GLFW_OPENGL_DEBUG_CONTEXT` and `GLFW_CONTEXT_NO_ERROR` hints are ignored.
|
||||
|
||||
Also, on Mac OS X 10.6 and below, the `GLFW_CONTEXT_VERSION_MAJOR` and
|
||||
`GLFW_CONTEXT_VERSION_MINOR` hints will fail if given a version above 2.1,
|
||||
@@ -187,9 +237,10 @@ a non-default value will cause @ref glfwCreateWindow to fail and the
|
||||
|
||||
By default, GLFW uses the standard system-wide Vulkan loader to access the
|
||||
Vulkan API on all platforms except macOS. This is installed by both graphics
|
||||
drivers and Vulkan SDKs. If the loader is not found, @ref glfwVulkanSupported
|
||||
will return `GLFW_FALSE` and all other Vulkan-related functions will fail with
|
||||
an @ref GLFW_API_UNAVAILABLE error.
|
||||
drivers and Vulkan SDKs. If either the loader or at least one minimally
|
||||
functional ICD is missing, @ref glfwVulkanSupported will return `GLFW_FALSE` and
|
||||
all other Vulkan-related functions will fail with an @ref GLFW_API_UNAVAILABLE
|
||||
error.
|
||||
|
||||
|
||||
@section compat_wsi Vulkan WSI extensions
|
||||
|
||||
+28
-27
@@ -13,7 +13,7 @@ build applications that use GLFW, see @ref build_guide.
|
||||
GLFW uses [CMake](http://www.cmake.org/) to generate project files or makefiles
|
||||
for a particular development environment. If you are on a Unix-like system such
|
||||
as Linux or FreeBSD or have a package system like Fink, MacPorts, Cygwin or
|
||||
Homebrew, you can simply install its CMake package. If not, you can download
|
||||
Homebrew, you can install its CMake package. If not, you can download
|
||||
installers for Windows and macOS from the
|
||||
[CMake website](http://www.cmake.org/).
|
||||
|
||||
@@ -33,9 +33,9 @@ below.
|
||||
|
||||
@subsubsection compile_deps_msvc Dependencies for Visual C++ on Windows
|
||||
|
||||
The Microsoft Platform SDK that is installed along with Visual C++ already
|
||||
contains all the necessary headers, link libraries and tools except for CMake.
|
||||
Move on to @ref compile_generate.
|
||||
The Windows SDK bundled with Visual C++ already contains all the necessary
|
||||
headers, link libraries and tools except for CMake. Move on to @ref
|
||||
compile_generate.
|
||||
|
||||
|
||||
@subsubsection compile_deps_mingw Dependencies for MinGW or MinGW-w64 on Windows
|
||||
@@ -88,10 +88,24 @@ Once you have Xcode installed, move on to @ref compile_generate.
|
||||
|
||||
@subsubsection compile_deps_x11 Dependencies for Linux and X11
|
||||
|
||||
To compile GLFW for X11, you need to have the X11 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 `xorg-dev`
|
||||
package, which pulls in all X.org header packages.
|
||||
To compile GLFW for X11, you need to have the X11 and libdbus development
|
||||
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 `xorg-dev` and `libdbus-1-dev` packages. The `xorg-dev`
|
||||
package in turn pulls in all X.org header packages.
|
||||
|
||||
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.
|
||||
@@ -219,17 +233,6 @@ __GLFW_VULKAN_STATIC__ determines whether to use the Vulkan loader linked
|
||||
statically into the application.
|
||||
|
||||
|
||||
@subsubsection compile_options_osx macOS specific CMake options
|
||||
|
||||
@anchor GLFW_USE_CHDIR
|
||||
__GLFW_USE_CHDIR__ determines whether @ref glfwInit changes the current
|
||||
directory of bundled applications to the `Contents/Resources` directory.
|
||||
|
||||
@anchor GLFW_USE_MENUBAR
|
||||
__GLFW_USE_MENUBAR__ determines whether the first call to @ref glfwCreateWindow
|
||||
sets up a minimal menu bar.
|
||||
|
||||
|
||||
@subsubsection compile_options_win32 Windows specific CMake options
|
||||
|
||||
@anchor USE_MSVC_RUNTIME_LIBRARY_DLL
|
||||
@@ -276,19 +279,17 @@ If you are linking the Vulkan loader statically into your application then you
|
||||
must also define @b _GLFW_VULKAN_STATIC. Otherwise, GLFW will attempt to use the
|
||||
external version.
|
||||
|
||||
If you are using a custom name for the Vulkan, EGL, GLX, OSMesa, OpenGL, GLESv1
|
||||
or GLESv2 library, you can override the default names by defining those you need
|
||||
of @b _GLFW_VULKAN_LIBRARY, @b _GLFW_EGL_LIBRARY, @b _GLFW_GLX_LIBRARY, @b
|
||||
_GLFW_OSMESA_LIBRARY, @b _GLFW_OPENGL_LIBRARY, @b _GLFW_GLESV1_LIBRARY and @b
|
||||
_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)
|
||||
|
||||
If you are using the Cocoa window creation API, the following options are
|
||||
available:
|
||||
|
||||
- @b _GLFW_USE_CHDIR to `chdir` to the `Resources` subdirectory of the
|
||||
application bundle during @ref glfwInit (recommended)
|
||||
- @b _GLFW_USE_MENUBAR to create and populate the menu bar when the first window
|
||||
is created (recommended)
|
||||
|
||||
@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
|
||||
applied to the GLFW sources.
|
||||
|
||||
+8
-7
@@ -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 simple object sharing test program called `sharing`.
|
||||
GLFW comes with a barebones object sharing example program called `sharing`.
|
||||
|
||||
|
||||
@subsection context_offscreen Offscreen contexts
|
||||
@@ -84,10 +84,9 @@ objects are recommended for rendering with such contexts.
|
||||
You should still [process events](@ref events) as long as you have at least one
|
||||
window, even if none of them are visible.
|
||||
|
||||
@macos The first time a window is created the menu bar is populated with
|
||||
common commands like Hide, Quit and About. This is not desirable for example
|
||||
when writing a command-line only application. The menu bar setup can be
|
||||
disabled with a [compile-time option](@ref compile_options_osx).
|
||||
@macos The first time a window is created the menu bar is created. This is not
|
||||
desirable for example when writing a command-line only application. Menu bar
|
||||
creation can be disabled with the @ref GLFW_COCOA_MENUBAR init hint.
|
||||
|
||||
|
||||
@subsection context_less Windows without contexts
|
||||
@@ -104,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
|
||||
@@ -127,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
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+55
-11
@@ -76,8 +76,34 @@
|
||||
border:2px solid desaturate(darken(@base-color, 10%), 20%);
|
||||
}
|
||||
|
||||
.sm-dox,.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted,.sm-dox ul a:hover {
|
||||
background:none;
|
||||
text-shadow:none;
|
||||
}
|
||||
|
||||
#navrow1,#navrow2,#navrow3,#navrow4,.tablist a,.tablist a:visited,.tablist a:hover,.tablist li,.tablist li.current a,.memdoc,dl.reflist dd,div.toc li,.ah,span.lineno,span.lineno a,span.lineno a:hover,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,.doxtable code {
|
||||
.sm-dox a span.sub-arrow {
|
||||
border-color:@navbar-link-color transparent transparent transparent;
|
||||
}
|
||||
|
||||
.sm-dox a span.sub-arrow:active,.sm-dox a span.sub-arrow:focus,.sm-dox a span.sub-arrow:hover,.sm-dox a:hover span.sub-arrow {
|
||||
border-color:@default-link-color transparent transparent transparent;
|
||||
}
|
||||
|
||||
.sm-dox ul a span.sub-arrow:active,.sm-dox ul a span.sub-arrow:focus,.sm-dox ul a span.sub-arrow:hover,.sm-dox ul a:hover span.sub-arrow {
|
||||
border-color:transparent transparent transparent @default-link-color;
|
||||
}
|
||||
|
||||
.sm-dox ul a:hover {
|
||||
background:@header-footer-link-color;
|
||||
text-shadow:none;
|
||||
}
|
||||
|
||||
.sm-dox ul.sm-nowrap a {
|
||||
color:@default-text-color;
|
||||
text-shadow:none;
|
||||
}
|
||||
|
||||
#main-nav,#main-menu,#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li,.memdoc,dl.reflist dd,div.toc li,.ah,span.lineno,span.lineno a,span.lineno a:hover,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,.doxtable code {
|
||||
background:none;
|
||||
}
|
||||
|
||||
@@ -85,7 +111,7 @@
|
||||
border:none;
|
||||
}
|
||||
|
||||
.tablist a,.tablist a:visited,.tablist a:hover,.tablist li,.tablist li.current a,.reflist dt a.el,.levels span,.directory .levels span {
|
||||
#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li,.reflist dt a.el,.levels span,.directory .levels span {
|
||||
text-shadow:none;
|
||||
}
|
||||
|
||||
@@ -183,28 +209,45 @@ address.footer {
|
||||
background:@header-footer-link-color;
|
||||
}
|
||||
|
||||
#navrow1,#navrow2,#navrow3,#navrow4 {
|
||||
#main-nav {
|
||||
max-width:960px;
|
||||
min-width:800px;
|
||||
margin:0 auto;
|
||||
font-size:13px;
|
||||
}
|
||||
|
||||
#main-menu {
|
||||
max-width:920px;
|
||||
min-width:800px;
|
||||
margin:0 auto;
|
||||
font-size:13px;
|
||||
}
|
||||
|
||||
.tablist {
|
||||
.memtitle {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.memproto,.memname {
|
||||
font-weight:bold;
|
||||
text-shadow:none;
|
||||
}
|
||||
|
||||
#main-menu {
|
||||
height:36px;
|
||||
display:block;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.tablist a,.tablist a:visited,.tablist a:hover,.tablist li,.tablist li.current a {
|
||||
#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li {
|
||||
color:@navbar-link-color;
|
||||
}
|
||||
|
||||
.tablist li.current a {
|
||||
background:linear-gradient(to bottom,@tab-background-color2 0%,@tab-background-color1 100%);
|
||||
box-shadow:inset 0 0 32px @tab-background-color1;
|
||||
text-shadow:0 -1px 1px darken(@tab-background-color1, 15%);
|
||||
color:@tab-text-color;
|
||||
#main-menu li ul.sm-nowrap li a {
|
||||
color:@default-text-color;
|
||||
}
|
||||
|
||||
#main-menu li ul.sm-nowrap li a:hover {
|
||||
color:@default-link-color;
|
||||
}
|
||||
|
||||
.contents {
|
||||
@@ -222,6 +265,7 @@ table.doxtable th,dl.reflist dt {
|
||||
background:linear-gradient(to bottom,@table-background-color2 0%,@table-background-color1 100%);
|
||||
box-shadow:inset 0 0 32px @table-background-color1;
|
||||
text-shadow:0 -1px 1px darken(@table-background-color1, 15%);
|
||||
text-align:left;
|
||||
color:@table-text-color;
|
||||
}
|
||||
|
||||
@@ -285,7 +329,7 @@ table.doxtable {
|
||||
border-radius:4px;
|
||||
}
|
||||
|
||||
a,a:hover,a:visited,a:visited:hover,.contents a:visited,.el,a.el:visited,#glfwhome:hover,.tablist a:hover,span.lineno a:hover {
|
||||
a,a:hover,a:visited,a:visited:hover,.contents a:visited,.el,a.el:visited,#glfwhome:hover,#main-menu a:hover,span.lineno a:hover {
|
||||
color:@default-link-color;
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ $extrastylesheet
|
||||
<ul class="glfwnavbar">
|
||||
<li><a href="http://www.glfw.org/documentation.html">Documentation</a></li>
|
||||
<li><a href="http://www.glfw.org/download.html">Download</a></li>
|
||||
<li><a href="http://www.glfw.org/media.html">Media</a></li>
|
||||
<li><a href="http://www.glfw.org/community.html">Community</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
+292
-52
@@ -145,7 +145,9 @@ per-window state arrays that can be polled with @ref glfwGetKey.
|
||||
@code
|
||||
int state = glfwGetKey(window, GLFW_KEY_E);
|
||||
if (state == GLFW_PRESS)
|
||||
{
|
||||
activate_airship();
|
||||
}
|
||||
@endcode
|
||||
|
||||
The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
|
||||
@@ -153,6 +155,7 @@ The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
|
||||
This function only returns cached key event state. It does not poll the
|
||||
system for the current physical state of the key.
|
||||
|
||||
@anchor GLFW_STICKY_KEYS
|
||||
Whenever you poll state, you risk missing the state change you are looking for.
|
||||
If a pressed key is released again before you poll its state, you will have
|
||||
missed the key press. The recommended solution for this is to use a
|
||||
@@ -167,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, 1);
|
||||
@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).
|
||||
|
||||
@@ -178,15 +194,12 @@ GLFW supports text input in the form of a stream of
|
||||
operating system text input system. Unlike key input, text input obeys keyboard
|
||||
layouts and modifier keys and supports composing characters using
|
||||
[dead keys](https://en.wikipedia.org/wiki/Dead_key). Once received, you can
|
||||
encode the code points into
|
||||
[UTF-8](https://en.wikipedia.org/wiki/UTF-8) or any other encoding you prefer.
|
||||
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](https://en.wikipedia.org/wiki/UTF-32).
|
||||
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);
|
||||
@@ -202,23 +215,6 @@ void character_callback(GLFWwindow* window, unsigned int codepoint)
|
||||
}
|
||||
@endcode
|
||||
|
||||
If you wish to receive even those Unicode code points generated with modifier
|
||||
key combinations that a plain text field would ignore, or just 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
|
||||
|
||||
@@ -271,8 +267,9 @@ glfwGetCursorPos(window, &xpos, &ypos);
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection cursor_mode Cursor modes
|
||||
@subsection cursor_mode Cursor mode
|
||||
|
||||
@anchor GLFW_CURSOR
|
||||
The `GLFW_CURSOR` input mode provides several cursor modes for special forms of
|
||||
mouse motion input. By default, the cursor mode is `GLFW_CURSOR_NORMAL`,
|
||||
meaning the regular arrow cursor (or another cursor set with @ref glfwSetCursor)
|
||||
@@ -295,8 +292,8 @@ is provided normally via both the cursor position callback and through polling.
|
||||
other features of GLFW. It is not supported and will not work as robustly as
|
||||
`GLFW_CURSOR_DISABLED`.
|
||||
|
||||
If you just wish the cursor to become hidden when it is over a window, set
|
||||
the cursor mode to `GLFW_CURSOR_HIDDEN`.
|
||||
If you only wish the cursor to become hidden when it is over a window but still
|
||||
want it to behave normally, set the cursor mode to `GLFW_CURSOR_HIDDEN`.
|
||||
|
||||
@code
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||
@@ -342,8 +339,8 @@ If cursor creation fails, `NULL` will be returned, so it is necessary to check
|
||||
the return value.
|
||||
|
||||
The image data is 32-bit, little-endian, non-premultiplied RGBA, i.e. eight bits
|
||||
per channel. The pixels are arranged canonically as sequential rows, starting
|
||||
from the top-left corner.
|
||||
per channel with the red channel first. The pixels are arranged canonically as
|
||||
sequential rows, starting from the top-left corner.
|
||||
|
||||
|
||||
@subsubsection cursor_standard Standard cursor creation
|
||||
@@ -367,8 +364,10 @@ When a cursor is no longer needed, destroy it with @ref glfwDestroyCursor.
|
||||
glfwDestroyCursor(cursor);
|
||||
@endcode
|
||||
|
||||
Cursor destruction always succeeds. All cursors remaining when @ref
|
||||
glfwTerminate is called are destroyed as well.
|
||||
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.
|
||||
|
||||
|
||||
@subsubsection cursor_set Cursor setting
|
||||
@@ -385,14 +384,14 @@ to `GLFW_CURSOR_NORMAL`.
|
||||
|
||||
A single cursor may be set for any number of windows.
|
||||
|
||||
To remove a cursor from a window, set the cursor of that window to `NULL`.
|
||||
To revert to the default cursor, set the cursor of that window to `NULL`.
|
||||
|
||||
@code
|
||||
glfwSetCursor(window, NULL);
|
||||
@endcode
|
||||
|
||||
When a cursor is destroyed, it is removed from any window where it is set. This
|
||||
does not affect the cursor modes of those windows.
|
||||
When a cursor is destroyed, any window that has it set will revert to the
|
||||
default cursor. This does not affect the cursor mode.
|
||||
|
||||
|
||||
@subsection cursor_enter Cursor enter/leave events
|
||||
@@ -420,6 +419,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
|
||||
|
||||
@@ -449,7 +458,9 @@ per-window state arrays that can be polled with @ref glfwGetMouseButton.
|
||||
@code
|
||||
int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
|
||||
if (state == GLFW_PRESS)
|
||||
{
|
||||
upgrade_cow();
|
||||
}
|
||||
@endcode
|
||||
|
||||
The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
|
||||
@@ -457,6 +468,7 @@ The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
|
||||
This function only returns cached mouse button event state. It does not poll
|
||||
the system for the current state of the mouse button.
|
||||
|
||||
@anchor GLFW_STICKY_MOUSE_BUTTONS
|
||||
Whenever you poll state, you risk missing the state change you are looking for.
|
||||
If a pressed mouse button is released again before you poll its state, you will have
|
||||
missed the button press. The recommended solution for this is to use a
|
||||
@@ -494,28 +506,34 @@ void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
}
|
||||
@endcode
|
||||
|
||||
A simple mouse wheel, being vertical, provides offsets along the Y-axis.
|
||||
A normal mouse wheel, being vertical, provides offsets along the Y-axis.
|
||||
|
||||
|
||||
@section joystick Joystick input
|
||||
|
||||
The joystick functions expose connected joysticks and controllers, with both
|
||||
referred to as joysticks. It supports up to sixteen joysticks, ranging from
|
||||
`GLFW_JOYSTICK_1`, `GLFW_JOYSTICK_2` up to `GLFW_JOYSTICK_LAST`. You can test
|
||||
whether a [joystick](@ref joysticks) is present with @ref glfwJoystickPresent.
|
||||
`GLFW_JOYSTICK_1`, `GLFW_JOYSTICK_2` up to and including `GLFW_JOYSTICK_16` or
|
||||
`GLFW_JOYSTICK_LAST`. You can test whether a [joystick](@ref joysticks) is
|
||||
present with @ref glfwJoystickPresent.
|
||||
|
||||
@code
|
||||
int present = glfwJoystickPresent(GLFW_JOYSTICK_1);
|
||||
@endcode
|
||||
|
||||
When GLFW is initialized, detected joysticks are added to to the beginning of
|
||||
the array, starting with `GLFW_JOYSTICK_1`. Once a joystick is detected, it
|
||||
keeps its assigned index until it is disconnected, so as joysticks are connected
|
||||
and disconnected, they will become spread out.
|
||||
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.
|
||||
|
||||
Joystick state is updated as needed when a joystick function is called and does
|
||||
not require a window to be created or @ref glfwPollEvents or @ref glfwWaitEvents
|
||||
to be called.
|
||||
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
|
||||
disconnected, there may appear gaps in the IDs.
|
||||
|
||||
Joystick axis, button and hat state is updated when polled and does not require
|
||||
a window to be created or events to be processed. However, if you want joystick
|
||||
connection and disconnection events reliably delivered to the
|
||||
[joystick callback](@ref joystick_event) then you must
|
||||
[process events](@ref events).
|
||||
|
||||
To see all the properties of all connected joysticks in real-time, run the
|
||||
`joysticks` test program.
|
||||
@@ -529,7 +547,7 @@ returned array.
|
||||
|
||||
@code
|
||||
int count;
|
||||
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &count);
|
||||
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_5, &count);
|
||||
@endcode
|
||||
|
||||
Each element in the returned array is a value between -1.0 and 1.0.
|
||||
@@ -543,11 +561,55 @@ returned array.
|
||||
|
||||
@code
|
||||
int count;
|
||||
const unsigned char* axes = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &count);
|
||||
const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_3, &count);
|
||||
@endcode
|
||||
|
||||
Each element in the returned array is either `GLFW_PRESS` or `GLFW_RELEASE`.
|
||||
|
||||
For backward compatibility with earlier versions that did not have @ref
|
||||
glfwGetJoystickHats, the button array by default also includes all hats. See
|
||||
the reference documentation for @ref glfwGetJoystickButtons for details.
|
||||
|
||||
|
||||
@subsection joystick_hat Joystick hat states
|
||||
|
||||
The states of all hats are returned by @ref glfwGetJoystickHats. See the
|
||||
reference documentation for the lifetime of the returned array.
|
||||
|
||||
@code
|
||||
int count;
|
||||
const unsigned char* hats = glfwGetJoystickHats(GLFW_JOYSTICK_7, &count);
|
||||
@endcode
|
||||
|
||||
Each element in the returned array is one of the following:
|
||||
|
||||
Name | Value
|
||||
--------------------- | --------------------------------
|
||||
`GLFW_HAT_CENTERED` | 0
|
||||
`GLFW_HAT_UP` | 1
|
||||
`GLFW_HAT_RIGHT` | 2
|
||||
`GLFW_HAT_DOWN` | 4
|
||||
`GLFW_HAT_LEFT` | 8
|
||||
`GLFW_HAT_RIGHT_UP` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_UP`
|
||||
`GLFW_HAT_RIGHT_DOWN` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_DOWN`
|
||||
`GLFW_HAT_LEFT_UP` | `GLFW_HAT_LEFT` \| `GLFW_HAT_UP`
|
||||
`GLFW_HAT_LEFT_DOWN` | `GLFW_HAT_LEFT` \| `GLFW_HAT_DOWN`
|
||||
|
||||
The diagonal directions are bitwise combinations of the primary (up, right, down
|
||||
and left) directions and you can test for these individually by ANDing it with
|
||||
the corresponding direction.
|
||||
|
||||
@code
|
||||
if (hats[2] & GLFW_HAT_RIGHT)
|
||||
{
|
||||
// State of hat 2 could be right-up, right or right-down
|
||||
}
|
||||
@endcode
|
||||
|
||||
For backward compatibility with earlier versions that did not have @ref
|
||||
glfwGetJoystickHats, all hats are by default also included in the button array.
|
||||
See the reference documentation for @ref glfwGetJoystickButtons for details.
|
||||
|
||||
|
||||
@subsection joystick_name Joystick name
|
||||
|
||||
@@ -556,7 +618,7 @@ glfwGetJoystickName. See the reference documentation for the lifetime of the
|
||||
returned string.
|
||||
|
||||
@code
|
||||
const char* name = glfwGetJoystickName(GLFW_JOYSTICK_1);
|
||||
const char* name = glfwGetJoystickName(GLFW_JOYSTICK_4);
|
||||
@endcode
|
||||
|
||||
Joystick names are not guaranteed to be unique. Two joysticks of the same model
|
||||
@@ -564,6 +626,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
|
||||
@@ -590,6 +663,175 @@ void joystick_callback(int jid, int event)
|
||||
}
|
||||
@endcode
|
||||
|
||||
For joystick connection and disconnection events to be delivered on all
|
||||
platforms, you need to call one of the [event processing](@ref events)
|
||||
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
|
||||
|
||||
The joystick functions provide unlabeled axes, buttons and hats, with no
|
||||
indication of where they are located on the device. Their order may also vary
|
||||
between platforms even with the same device.
|
||||
|
||||
To solve this problem the SDL community crowdsourced the
|
||||
[SDL_GameControllerDB](https://github.com/gabomdq/SDL_GameControllerDB) project,
|
||||
a database of mappings from many different devices to an Xbox-like gamepad.
|
||||
|
||||
GLFW supports this mapping format and contains a copy of the mappings
|
||||
available at the time of release. See @ref gamepad_mapping for how to update
|
||||
this at runtime. Mappings will be assigned to joysticks automatically any time
|
||||
a joystick is connected or the mappings are updated.
|
||||
|
||||
You can check whether a joystick is both present and has a gamepad mapping with
|
||||
@ref glfwJoystickIsGamepad.
|
||||
|
||||
@code
|
||||
if (glfwJoystickIsGamepad(GLFW_JOYSTICK_2))
|
||||
{
|
||||
// Use as gamepad
|
||||
}
|
||||
@endcode
|
||||
|
||||
If you are only interested in gamepad input you can use this function instead of
|
||||
@ref glfwJoystickPresent.
|
||||
|
||||
You can query the human-readable name provided by the gamepad mapping with @ref
|
||||
glfwGetGamepadName. This may or may not be the same as the
|
||||
[joystick name](@ref joystick_name).
|
||||
|
||||
@code
|
||||
const char* name = glfwGetGamepadName(GLFW_JOYSTICK_7);
|
||||
@endcode
|
||||
|
||||
To retrieve the gamepad state of a joystick, call @ref glfwGetGamepadState.
|
||||
|
||||
@code
|
||||
GLFWgamepadstate state;
|
||||
|
||||
if (glfwGetGamepadState(GLFW_JOYSTICK_3, &state))
|
||||
{
|
||||
if (state.buttons[GLFW_GAMEPAD_BUTTON_A])
|
||||
{
|
||||
input_jump();
|
||||
}
|
||||
|
||||
input_speed(state.axes[GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER]);
|
||||
}
|
||||
@endcode
|
||||
|
||||
The @ref GLFWgamepadstate struct has two arrays; one for button states and one
|
||||
for axis states. The values for each button and axis are the same as for the
|
||||
@ref glfwGetJoystickButtons and @ref glfwGetJoystickAxes functions, i.e.
|
||||
`GLFW_PRESS` or `GLFW_RELEASE` for buttons and -1.0 to 1.0 inclusive for axes.
|
||||
|
||||
The sizes of the arrays and the positions within each array are fixed.
|
||||
|
||||
The [button indices](@ref gamepad_buttons) are `GLFW_GAMEPAD_BUTTON_A`,
|
||||
`GLFW_GAMEPAD_BUTTON_B`, `GLFW_GAMEPAD_BUTTON_X`, `GLFW_GAMEPAD_BUTTON_Y`,
|
||||
`GLFW_GAMEPAD_BUTTON_LEFT_BUMPER`, `GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER`,
|
||||
`GLFW_GAMEPAD_BUTTON_BACK`, `GLFW_GAMEPAD_BUTTON_START`,
|
||||
`GLFW_GAMEPAD_BUTTON_GUIDE`, `GLFW_GAMEPAD_BUTTON_LEFT_THUMB`,
|
||||
`GLFW_GAMEPAD_BUTTON_RIGHT_THUMB`, `GLFW_GAMEPAD_BUTTON_DPAD_UP`,
|
||||
`GLFW_GAMEPAD_BUTTON_DPAD_RIGHT`, `GLFW_GAMEPAD_BUTTON_DPAD_DOWN` and
|
||||
`GLFW_GAMEPAD_BUTTON_DPAD_LEFT`.
|
||||
|
||||
For those who prefer, there are also the `GLFW_GAMEPAD_BUTTON_CROSS`,
|
||||
`GLFW_GAMEPAD_BUTTON_CIRCLE`, `GLFW_GAMEPAD_BUTTON_SQUARE` and
|
||||
`GLFW_GAMEPAD_BUTTON_TRIANGLE` aliases for the A, B, X and Y button indices.
|
||||
|
||||
The [axis indices](@ref gamepad_axes) are `GLFW_GAMEPAD_AXIS_LEFT_X`,
|
||||
`GLFW_GAMEPAD_AXIS_LEFT_Y`, `GLFW_GAMEPAD_AXIS_RIGHT_X`,
|
||||
`GLFW_GAMEPAD_AXIS_RIGHT_Y`, `GLFW_GAMEPAD_AXIS_LEFT_TRIGGER` and
|
||||
`GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER`.
|
||||
|
||||
The `GLFW_GAMEPAD_BUTTON_LAST` and `GLFW_GAMEPAD_AXIS_LAST` constants equal
|
||||
the largest available index for each array.
|
||||
|
||||
|
||||
@subsection gamepad_mapping Gamepad mappings
|
||||
|
||||
GLFW contains a copy of the mappings available in
|
||||
[SDL_GameControllerDB](https://github.com/gabomdq/SDL_GameControllerDB) at the
|
||||
time of release. Newer ones can be added at runtime with @ref
|
||||
glfwUpdateGamepadMappings.
|
||||
|
||||
@code
|
||||
const char* mappings = load_file_contents("gamecontrollerdb.txt");
|
||||
|
||||
glfwUpdateGamepadMappings(mappings);
|
||||
@endcode
|
||||
|
||||
This function supports everything from single lines up to and including the
|
||||
unmodified contents of the whole `gamecontrollerdb.txt` file.
|
||||
|
||||
Below is a description of the mapping format. Please keep in mind that __this
|
||||
description is not authoritative__. The format is defined by the SDL and
|
||||
SDL_GameControllerDB projects and their documentation and code takes precedence.
|
||||
|
||||
Each mapping is a single line of comma-separated values describing the GUID,
|
||||
name and layout of the gamepad. Lines that do not begin with a hexadecimal
|
||||
digit are ignored.
|
||||
|
||||
The first value is always the gamepad GUID, a 32 character long hexadecimal
|
||||
string that typically identifies its make, model, revision and the type of
|
||||
connection to the computer. When this information is not available, the GUID is
|
||||
generated using the gamepad name. GLFW uses the SDL 2.0.5+ GUID format but can
|
||||
convert from the older formats.
|
||||
|
||||
The second value is always the human-readable name of the gamepad.
|
||||
|
||||
All subsequent values are in the form `<field>:<value>` and describe the layout
|
||||
of the mapping. These fields may not all be present and may occur in any order.
|
||||
|
||||
The button fields are `a`, `b`, `c`, `d`, `back`, `start`, `guide`, `dpup`,
|
||||
`dpright`, `dpdown`, `dpleft`, `leftshoulder`, `rightshoulder`, `leftstick` and
|
||||
`rightstick`.
|
||||
|
||||
The axis fields are `leftx`, `lefty`, `rightx`, `righty`, `lefttrigger` and
|
||||
`righttrigger`.
|
||||
|
||||
The value of an axis or button field can be a joystick button, a joystick axis,
|
||||
a hat bitmask or empty. Joystick buttons are specified as `bN`, for example
|
||||
`b2` for the third button. Joystick axes are specified as `aN`, for example
|
||||
`a7` for the eighth button. Joystick hat bit masks are specified as `hN.N`, for
|
||||
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.
|
||||
|
||||
There is also the special `platform` field that specifies which platform the
|
||||
mapping is valid for. Possible values are `Windows`, `Mac OS X` and `Linux`.
|
||||
|
||||
Below is an example of what a gamepad mapping might look like. It is the
|
||||
one built into GLFW for Xbox controllers accessed via the XInput API on Windows.
|
||||
This example has been broken into several lines to fit on the page, but real
|
||||
gamepad mappings must be a single line.
|
||||
|
||||
@code{.unparsed}
|
||||
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,
|
||||
@endcode
|
||||
|
||||
@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
|
||||
|
||||
@@ -634,9 +876,11 @@ 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);
|
||||
}
|
||||
@endcode
|
||||
|
||||
If the clipboard is empty or if its contents could not be converted, `NULL` is
|
||||
@@ -646,13 +890,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
|
||||
|
||||
|
||||
+8
-9
@@ -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`
|
||||
|
||||
*/
|
||||
|
||||
+142
-60
@@ -30,7 +30,9 @@ successfully initialized, and only from the main thread.
|
||||
|
||||
- @ref glfwGetVersion
|
||||
- @ref glfwGetVersionString
|
||||
- @ref glfwGetError
|
||||
- @ref glfwSetErrorCallback
|
||||
- @ref glfwInitHint
|
||||
- @ref glfwInit
|
||||
- @ref glfwTerminate
|
||||
|
||||
@@ -52,13 +54,61 @@ if (!glfwInit())
|
||||
|
||||
If any part of initialization fails, any parts that succeeded are terminated as
|
||||
if @ref glfwTerminate had been called. The library only needs to be initialized
|
||||
once and additional calls to an already initialized library will simply return
|
||||
once and additional calls to an already initialized library will return
|
||||
`GLFW_TRUE` immediately.
|
||||
|
||||
Once the library has been successfully initialized, it should be terminated
|
||||
before the application exits. Modern systems are very good at freeing resources
|
||||
allocated by programs that simply exit, but GLFW sometimes has to change global
|
||||
system settings and these might not be restored without termination.
|
||||
allocated by programs that exit, but GLFW sometimes has to change global system
|
||||
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. Hints are set with @ref glfwInitHint.
|
||||
|
||||
@code
|
||||
glfwInitHint(GLFW_JOYSTICK_HAT_BUTTONS, GLFW_FALSE);
|
||||
@endcode
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@subsubsection init_hints_shared Shared init hints
|
||||
|
||||
@anchor GLFW_JOYSTICK_HAT_BUTTONS
|
||||
__GLFW_JOYSTICK_HAT_BUTTONS__ specifies whether to also expose joystick hats as
|
||||
buttons, for compatibility with earlier versions of GLFW that did not have @ref
|
||||
glfwGetJoystickHats. Set this with @ref glfwInitHint.
|
||||
|
||||
|
||||
@subsubsection init_hints_osx macOS specific init hints
|
||||
|
||||
@anchor GLFW_COCOA_CHDIR_RESOURCES
|
||||
__GLFW_COCOA_CHDIR_RESOURCES__ specifies whether to set the current directory to
|
||||
the application to the `Contents/Resources` subdirectory of the application's
|
||||
bundle, if present. Set this with @ref glfwInitHint.
|
||||
|
||||
@anchor GLFW_COCOA_MENUBAR
|
||||
__GLFW_COCOA_MENUBAR__ specifies whether to create a basic menu bar, either from
|
||||
a nib or manually, when the first window is created, which is when AppKit is
|
||||
initialized. Set this with @ref glfwInitHint.
|
||||
|
||||
|
||||
@subsubsection init_hints_values Supported and default values
|
||||
|
||||
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`
|
||||
|
||||
|
||||
@subsection intro_init_terminate Terminating GLFW
|
||||
@@ -83,41 +133,76 @@ immediately.
|
||||
@section error_handling Error handling
|
||||
|
||||
Some GLFW functions have return values that indicate an error, but this is often
|
||||
not very helpful when trying to figure out _why_ the error occurred. Some
|
||||
functions also return otherwise valid values on error. Finally, far from all
|
||||
GLFW functions have return values.
|
||||
not very helpful when trying to figure out what happened or why it occurred.
|
||||
Other functions have no return value reserved for errors, so error notification
|
||||
needs a separate channel. Finally, far from all GLFW functions have return
|
||||
values.
|
||||
|
||||
This is where the error callback comes in. This callback is called whenever an
|
||||
error occurs. It is set with @ref glfwSetErrorCallback, a function that may be
|
||||
called regardless of whether GLFW is initialized.
|
||||
The last [error code](@ref errors) for the calling thread can be queried at any
|
||||
time with @ref glfwGetError.
|
||||
|
||||
@code
|
||||
glfwSetErrorCallback(error_callback);
|
||||
int code = glfwGetError(NULL);
|
||||
|
||||
if (code != GLFW_NO_ERROR)
|
||||
handle_error(code);
|
||||
@endcode
|
||||
|
||||
The error callback receives a human-readable description of the error and (when
|
||||
possible) its cause. The description encoded as UTF-8. The callback is also
|
||||
provided with an [error code](@ref errors).
|
||||
|
||||
@code
|
||||
void error_callback(int error, const char* description)
|
||||
{
|
||||
puts(description);
|
||||
}
|
||||
@endcode
|
||||
If no error has occurred since the last call, @ref GLFW_NO_ERROR (zero) is
|
||||
returned. The error is cleared before the function returns.
|
||||
|
||||
The error code indicates the general category of the error. Some error codes,
|
||||
such as @ref GLFW_NOT_INITIALIZED has only a single meaning, whereas others like
|
||||
@ref GLFW_PLATFORM_ERROR are used for many different errors.
|
||||
|
||||
The description string is only valid until the error callback returns, as it may
|
||||
have been generated specifically for that error. This lets GLFW provide much
|
||||
more specific error descriptions but means you must make a copy if you want to
|
||||
keep the description string.
|
||||
GLFW often has more information about an error than its general category. You
|
||||
can retrieve a UTF-8 encoded human-readable description along with the error
|
||||
code. If no error has occurred since the last call, the description is set to
|
||||
`NULL`.
|
||||
|
||||
@note Relying on erroneous behavior is not forward compatible. In other words,
|
||||
do not rely on a currently invalid call to generate a specific error, as that
|
||||
same call may in future versions generate a different error or become valid.
|
||||
@code
|
||||
const char* description;
|
||||
int code = glfwGetError(&description);
|
||||
|
||||
if (description)
|
||||
display_error_message(code, description);
|
||||
@endcode
|
||||
|
||||
The retrieved description string is only valid until the next error occurs.
|
||||
This means you must make a copy of it if you want to keep it.
|
||||
|
||||
You can also set an error callback, which will be called each time an error
|
||||
occurs. It is set with @ref glfwSetErrorCallback.
|
||||
|
||||
@code
|
||||
glfwSetErrorCallback(error_callback);
|
||||
@endcode
|
||||
|
||||
The error callback receives the same error code and human-readable description
|
||||
returned by @ref glfwGetError.
|
||||
|
||||
@code
|
||||
void error_callback(int code, const char* description)
|
||||
{
|
||||
display_error_message(code, description);
|
||||
}
|
||||
@endcode
|
||||
|
||||
The error callback is called after the error is stored, so calling @ref
|
||||
glfwGetError from within the error callback returns the same values as the
|
||||
callback argument.
|
||||
|
||||
The description string passed to the callback is only valid until the error
|
||||
callback returns. This means you must make a copy of it if you want to keep it.
|
||||
|
||||
__Reported errors are never fatal.__ As long as GLFW was successfully
|
||||
initialized, it will remain initialized and in a safe state until terminated
|
||||
regardless of how many errors occur. If an error occurs during initialization
|
||||
that causes @ref glfwInit to fail, any part of the library that was initialized
|
||||
will be safely terminated.
|
||||
|
||||
Do not rely on a currently invalid call to generate a specific error, as in the
|
||||
future that same call may generate a different error or become valid.
|
||||
|
||||
|
||||
@section coordinate_systems Coordinate systems
|
||||
@@ -188,14 +273,10 @@ releases.
|
||||
|
||||
@subsection reentrancy Reentrancy
|
||||
|
||||
GLFW event processing and object creation and destruction are not reentrant.
|
||||
This means that the following functions must not be called from any callback
|
||||
function:
|
||||
GLFW event processing and object destruction are not reentrant. This means that
|
||||
the following functions must not be called from any callback function:
|
||||
|
||||
- @ref glfwCreateWindow
|
||||
- @ref glfwDestroyWindow
|
||||
- @ref glfwCreateCursor
|
||||
- @ref glfwCreateStandardCursor
|
||||
- @ref glfwDestroyCursor
|
||||
- @ref glfwPollEvents
|
||||
- @ref glfwWaitEvents
|
||||
@@ -208,35 +289,39 @@ functions not on this list will not be made non-reentrant.
|
||||
|
||||
@subsection thread_safety Thread safety
|
||||
|
||||
Most GLFW functions must only be called from the main thread, but some may be
|
||||
called from any thread. However, no GLFW function may be called from any thread
|
||||
but the main thread until GLFW has been successfully initialized, including
|
||||
functions that may called before initialization.
|
||||
Most GLFW functions must only be called from the main thread (the thread that
|
||||
calls main), but some may be called from any thread once the library has been
|
||||
initialized. Before initialization the whole library is thread-unsafe.
|
||||
|
||||
The reference documentation for every GLFW function states whether it is limited
|
||||
to the main thread.
|
||||
|
||||
Initialization and termination, event processing and the creation and
|
||||
destruction of windows, contexts and cursors are all limited to the main thread
|
||||
due to limitations of one or several platforms.
|
||||
Initialization, termination, event processing and the creation and
|
||||
destruction of windows, cursors and OpenGL and OpenGL ES contexts are all
|
||||
restricted to the main thread due to limitations of one or several platforms.
|
||||
|
||||
Because event processing must be performed on the main thread, all callbacks
|
||||
except for the error callback will only be called on that thread. The error
|
||||
callback may be called on any thread, as any GLFW function may generate errors.
|
||||
|
||||
The posting of empty events may be done from any thread. The window user
|
||||
pointer and close flag may also be accessed and modified from any thread, but
|
||||
this is not synchronized by GLFW. The following window related functions may
|
||||
be called from any thread:
|
||||
The error code and description may be queried from any thread.
|
||||
|
||||
- @ref glfwGetError
|
||||
|
||||
Empty events may be posted from any thread.
|
||||
|
||||
- @ref glfwPostEmptyEvent
|
||||
|
||||
The window user pointer and close flag may be read and written from any thread,
|
||||
but this is not synchronized by GLFW.
|
||||
|
||||
- @ref glfwGetWindowUserPointer
|
||||
- @ref glfwSetWindowUserPointer
|
||||
- @ref glfwWindowShouldClose
|
||||
- @ref glfwSetWindowShouldClose
|
||||
|
||||
Rendering may be done on any thread. The following context related functions
|
||||
may be called from any thread:
|
||||
These functions for working with OpenGL and OpenGL ES contexts may be called
|
||||
from any thread, but the window object is not synchronized by GLFW.
|
||||
|
||||
- @ref glfwMakeContextCurrent
|
||||
- @ref glfwGetCurrentContext
|
||||
@@ -245,27 +330,23 @@ may be called from any thread:
|
||||
- @ref glfwExtensionSupported
|
||||
- @ref glfwGetProcAddress
|
||||
|
||||
The raw timer may be queried from any thread. The following raw timer related
|
||||
functions may be called from any thread:
|
||||
The raw timer functions may be called from any thread.
|
||||
|
||||
- @ref glfwGetTimerFrequency
|
||||
- @ref glfwGetTimerValue
|
||||
|
||||
The regular timer may be used from any thread, but the reading and writing of
|
||||
the timer offset is not synchronized by GLFW. The following timer related
|
||||
functions may be called from any thread:
|
||||
The regular timer may be used from any thread, but reading and writing the timer
|
||||
offset is not synchronized by GLFW.
|
||||
|
||||
- @ref glfwGetTime
|
||||
- @ref glfwSetTime
|
||||
|
||||
Library version information may be queried from any thread. The following
|
||||
version related functions may be called from any thread:
|
||||
Library version information may be queried from any thread.
|
||||
|
||||
- @ref glfwGetVersion
|
||||
- @ref glfwGetVersionString
|
||||
|
||||
Vulkan objects may be created and information queried from any thread. The
|
||||
following Vulkan related functions may be called from any thread:
|
||||
All Vulkan related functions may be called from any thread.
|
||||
|
||||
- @ref glfwVulkanSupported
|
||||
- @ref glfwGetRequiredInstanceExtensions
|
||||
@@ -273,9 +354,9 @@ following Vulkan related functions may be called from any thread:
|
||||
- @ref glfwGetPhysicalDevicePresentationSupport
|
||||
- @ref glfwCreateWindowSurface
|
||||
|
||||
GLFW uses no synchronization objects internally except for thread-local storage
|
||||
to keep track of the current context for each thread. Synchronization is left
|
||||
to the application.
|
||||
GLFW uses synchronization objects internally only to manage the per-thread
|
||||
context and error states. Additional synchronization is left to the
|
||||
application.
|
||||
|
||||
Functions that may currently be called from any thread will always remain so,
|
||||
but functions that are currently limited to the main thread may be updated to
|
||||
@@ -297,8 +378,9 @@ Undocumented behavior, i.e. behavior that is not described in the documentation,
|
||||
may change at any time until it is documented.
|
||||
|
||||
If the reference documentation and the implementation differ, the reference
|
||||
documentation is correct and the implementation will be fixed in the next
|
||||
release.
|
||||
documentation will almost always take precedence and the implementation will be
|
||||
fixed in the next release. The reference documentation will also take
|
||||
precedence over anything stated in a guide.
|
||||
|
||||
|
||||
@subsection event_order Event order
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ GLFW is a free, Open Source, multi-platform library for OpenGL, OpenGL ES and
|
||||
Vulkan application development. It provides a simple, platform-independent API
|
||||
for creating windows, contexts and surfaces, reading input, handling events, etc.
|
||||
|
||||
See @ref news_33 for release highlights or the
|
||||
See @ref news_33 for highlights or the
|
||||
[version history](http://www.glfw.org/changelog.html) for details.
|
||||
|
||||
@ref quick_guide is a guide for users new to GLFW. It takes you through how to
|
||||
|
||||
+41
-11
@@ -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
|
||||
@@ -131,17 +133,34 @@ current _resolution_, i.e. the width and height of its current
|
||||
[video mode](@ref monitor_modes).
|
||||
|
||||
@code
|
||||
int widthMM, heightMM;
|
||||
glfwGetMonitorPhysicalSize(monitor, &widthMM, &heightMM);
|
||||
int width_mm, height_mm;
|
||||
glfwGetMonitorPhysicalSize(monitor, &width_mm, &height_mm);
|
||||
@endcode
|
||||
|
||||
This can, for example, be used together with the current video mode to calculate
|
||||
the DPI of a monitor.
|
||||
While this can be used to calculate the raw DPI of a monitor, this is often not
|
||||
useful. Instead use the [monitor content scale](@ref monitor_scale) and
|
||||
[window content scale](@ref window_scale) to scale your content.
|
||||
|
||||
|
||||
@subsection monitor_scale Content scale
|
||||
|
||||
The content scale for a monitor can be retrieved with @ref
|
||||
glfwGetMonitorContentScale.
|
||||
|
||||
@code
|
||||
const double dpi = mode->width / (widthMM / 25.4);
|
||||
float xscale, yscale;
|
||||
glfwGetMonitorContentScale(monitor, &xscale, &yscale);
|
||||
@endcode
|
||||
|
||||
The content scale is the ratio between the current DPI and the platform's
|
||||
default DPI. If you scale all pixel dimensions by this scale then your content
|
||||
should appear at an appropriate size. This is especially important for text and
|
||||
any UI elements.
|
||||
|
||||
The content scale may depend on both the monitor resolution and pixel density
|
||||
and on user settings. It may be very different from the raw DPI calculated from
|
||||
the physical size and current resolution.
|
||||
|
||||
|
||||
@subsection monitor_pos Virtual position
|
||||
|
||||
@@ -170,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
|
||||
@@ -195,8 +225,8 @@ glfwSetGammaRamp(monitor, &ramp);
|
||||
The gamma ramp data is copied before the function returns, so there is no need
|
||||
to keep it around once the ramp has been set.
|
||||
|
||||
@note It is recommended to use gamma ramps of size 256, as that is the size
|
||||
supported by all graphics cards on all platforms.
|
||||
It is recommended that your gamma ramp have the same size as the current gamma
|
||||
ramp for that monitor.
|
||||
|
||||
The current gamma ramp for a monitor is returned by @ref glfwGetGammaRamp. See
|
||||
the reference documentation for the lifetime of the returned structure.
|
||||
|
||||
+8
-1
@@ -221,7 +221,7 @@ GLFW 2, windows and contexts created with GLFW 3 will never be destroyed unless
|
||||
you choose them to be. Each window now has a close flag that is set to
|
||||
`GLFW_TRUE` when the user attempts to close that window. By default, nothing else
|
||||
happens and the window stays visible. It is then up to you to either destroy
|
||||
the window, take some other action or simply ignore the request.
|
||||
the window, take some other action or ignore the request.
|
||||
|
||||
You can query the close flag at any time with @ref glfwWindowShouldClose and set
|
||||
it at any time with @ref glfwSetWindowShouldClose.
|
||||
@@ -447,6 +447,13 @@ defining @ref GLFW_INCLUDE_GLU before the inclusion of the GLFW header.
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
There are many libraries that offer replacements for the functionality offered
|
||||
by GLU. For the matrix helper functions, see math libraries like
|
||||
[GLM](https://github.com/g-truc/glm) (for C++),
|
||||
[linmath.h](https://github.com/datenwolf/linmath.h) (for C) and others. For the
|
||||
tessellation functions, see for example
|
||||
[libtess2](https://github.com/memononen/libtess2).
|
||||
|
||||
|
||||
@section moving_tables Name change tables
|
||||
|
||||
|
||||
+137
-11
@@ -1,19 +1,50 @@
|
||||
/*!
|
||||
|
||||
@page news New features
|
||||
@page news Release notes
|
||||
|
||||
@section news_33 Release notes for 3.3
|
||||
|
||||
|
||||
@subsection news_33_geterror Error query
|
||||
|
||||
GLFW now supports querying the last error code for the calling thread and its
|
||||
human-readable description with @ref glfwGetError.
|
||||
|
||||
@see @ref error_handling
|
||||
|
||||
|
||||
@subsection news_33_gamepad SDL_GameControllerDB support and gamepad input
|
||||
|
||||
GLFW now supports remapping of gamepads and controllers to a 360-like controller
|
||||
layout with @ref glfwJoystickIsGamepad, @ref glfwGetJoystickGUID, @ref
|
||||
glfwGetGamepadName, @ref glfwGetGamepadState and @ref glfwUpdateGamepadMappings,
|
||||
and the input state struct @ref GLFWgamepadstate.
|
||||
|
||||
@sa @ref gamepad
|
||||
|
||||
|
||||
@subsection news_33_attention User attention request
|
||||
|
||||
GLFW now supports requesting user attention to a specific window (on macOS to
|
||||
the application as a whole) with @ref glfwRequestWindowAttention.
|
||||
|
||||
@see @ref window_attention
|
||||
|
||||
@section news_33 New features in 3.3
|
||||
|
||||
@subsection news_33_maximize Window maximization callback
|
||||
|
||||
GLFW now supports window maximization notifications with @ref
|
||||
glfwSetWindowMaximizeCallback.
|
||||
GLFW now supports notifying the application that the window has been maximized
|
||||
@ref glfwSetWindowMaximizeCallback.
|
||||
|
||||
@see @ref window_maximize
|
||||
|
||||
|
||||
@subsection news_33_keyscancode Platform-specific key scancode query
|
||||
|
||||
GLFW now supports querying the platform dependent scancode of any key with
|
||||
@ref glfwGetKeyScancode.
|
||||
GLFW now supports querying the platform dependent scancode of any physical key
|
||||
with @ref glfwGetKeyScancode.
|
||||
|
||||
@see @ref input_key
|
||||
|
||||
|
||||
@subsection news_33_setwindowattrib Support for updating window attributes
|
||||
@@ -24,20 +55,115 @@ GLFW now supports changing the [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
|
||||
[GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) attributes for existing
|
||||
windows with @ref glfwSetWindowAttrib.
|
||||
|
||||
@see @ref window_attribs
|
||||
|
||||
|
||||
@subsection news_33_contentscale Content scale queries for DPI-aware rendering
|
||||
|
||||
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 glfwSetWindowCloseCallback.
|
||||
|
||||
@see @ref window_scale
|
||||
|
||||
|
||||
@subsection news_33_inithint Support for initialization hints
|
||||
|
||||
GLFW now supports setting library initialization hints with @ref glfwInitHint.
|
||||
These must be set before initialization to take effect.
|
||||
|
||||
@see @ref init_hints
|
||||
|
||||
|
||||
@subsection news_33_platformhints Support for platform specific hints
|
||||
|
||||
GLFW now supports platform specific init and window hints to control system
|
||||
features that are only available on a single platform.
|
||||
|
||||
@see @ref init_hints_osx
|
||||
@see @ref window_hints_osx
|
||||
|
||||
|
||||
@subsection news_33_joyhats Support for joystick hats
|
||||
|
||||
GLFW now supports querying the hats (or POVs or D-pads) of a joystick with @ref
|
||||
glfwGetJoystickHats. Hats are by default also exposed as buttons, but this can
|
||||
be disabled with the @ref GLFW_JOYSTICK_HAT_BUTTONS init hint.
|
||||
|
||||
@see @ref joystick_hat
|
||||
|
||||
|
||||
@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_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
|
||||
|
||||
GLFW now supports controlling whether the cursor is centered over newly created
|
||||
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
|
||||
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/).
|
||||
|
||||
@see @ref vulkan_guide
|
||||
|
||||
|
||||
@subsection news_33_osmesa OSMesa backend for headless software rendering
|
||||
|
||||
GLFW now supports headless context creation and software rendering via OSMesa,
|
||||
intended for automated testing. This backend does not provide input.
|
||||
GLFW now supports creating offscreen OpenGL contexts using
|
||||
[OSMesa](https://www.mesa3d.org/osmesa.html) by setting
|
||||
[GLFW_CONTEXT_CREATION_API](@ref GLFW_CONTEXT_CREATION_API_hint) to
|
||||
`GLFW_OSMESA_CONTEXT_API`.
|
||||
|
||||
There is also a new null backend that uses OSMesa as its native context
|
||||
creation API, intended for automated testing. This backend does not provide
|
||||
input.
|
||||
|
||||
|
||||
@section news_32 New features in 3.2
|
||||
@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
|
||||
access functions @ref glfwGetX11SelectionString and @ref
|
||||
glfwSetX11SelectionString.
|
||||
|
||||
|
||||
@section news_32 Release notes for 3.2
|
||||
|
||||
|
||||
@subsection news_32_vulkan Support for Vulkan
|
||||
@@ -128,7 +254,7 @@ GLFW now supports being used as a
|
||||
easy linking with the library and its dependencies.
|
||||
|
||||
|
||||
@section news_31 New features in 3.1
|
||||
@section news_31 Release notes for 3.1
|
||||
|
||||
These are the release highlights. For a full list of changes see the
|
||||
[version history](http://www.glfw.org/changelog.html).
|
||||
@@ -239,7 +365,7 @@ GLFW now has an _experimental_ Mir display server backend that can be selected
|
||||
on Linux with a CMake option.
|
||||
|
||||
|
||||
@section news_30 New features in 3.0
|
||||
@section news_30 Release notes for 3.0
|
||||
|
||||
These are the release highlights. For a full list of changes see the
|
||||
[version history](http://www.glfw.org/changelog.html).
|
||||
|
||||
+5
-7
@@ -69,7 +69,7 @@ if (!glfwInit())
|
||||
}
|
||||
@endcode
|
||||
|
||||
Note that `GLFW_TRUE` and `GLFW_FALSE` are and will always be just one and zero.
|
||||
Note that `GLFW_TRUE` and `GLFW_FALSE` are and will always be one and zero.
|
||||
|
||||
When you are done using GLFW, typically just before the application exits, you
|
||||
need to terminate GLFW.
|
||||
@@ -86,14 +86,12 @@ functions that require it.
|
||||
@subsection quick_capture_error Setting an error callback
|
||||
|
||||
Most events are reported through callbacks, whether it's a key being pressed,
|
||||
a GLFW window being moved, or an error occurring. Callbacks are simply
|
||||
C functions (or C++ static methods) that are called by GLFW with arguments
|
||||
describing the event.
|
||||
a GLFW window being moved, or an error occurring. Callbacks are C functions (or
|
||||
C++ static methods) that are called by GLFW with arguments describing the event.
|
||||
|
||||
In case a GLFW function fails, an error is reported to the GLFW error callback.
|
||||
You can receive these reports with an error callback. This function must have
|
||||
the signature below. This simple error callback just prints the error
|
||||
description to `stderr`.
|
||||
the signature below but may do anything permitted in other callbacks.
|
||||
|
||||
@code
|
||||
void error_callback(int error, const char* description)
|
||||
@@ -249,7 +247,7 @@ You can also set a framebuffer size callback using @ref
|
||||
glfwSetFramebufferSizeCallback and be notified when the size changes.
|
||||
|
||||
Actual rendering with OpenGL is outside the scope of this tutorial, but there
|
||||
are [many](https://open.gl/) [excellent](http://learnopengl.com/)
|
||||
are [many](https://open.gl/) [excellent](https://learnopengl.com/)
|
||||
[tutorial](http://openglbook.com/) [sites](http://ogldev.atspace.co.uk/) that
|
||||
teach modern OpenGL. Some of them use GLFW to create the context and window
|
||||
while others use GLUT or SDL, but remember that OpenGL itself always works the
|
||||
|
||||
+23
-15
@@ -20,6 +20,11 @@ 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.
|
||||
|
||||
@@ -34,19 +39,18 @@ 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). 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.
|
||||
Unix-like systems and `libMoltenVK.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.
|
||||
|
||||
The @ref GLFW_VULKAN_STATIC CMake option makes GLFW link directly against the
|
||||
static form. Not linking against the Vulkan loader will then be a compile-time
|
||||
error.
|
||||
static library form. Not linking against the Vulkan loader will then be
|
||||
a compile-time error.
|
||||
|
||||
@macos MoltenVK only provides the static library form of the Vulkan loader, but
|
||||
GLFW is able to find it without @ref GLFW_VULKAN_STATIC as long as it is linked
|
||||
into any of the binaries already loaded into the process. As it is a static
|
||||
library, you must also link against its dependencies: the `Cocoa`, `Metal` and
|
||||
`QuartzCore` frameworks and the `libc++` library.
|
||||
@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.
|
||||
|
||||
|
||||
@section vulkan_include Including the Vulkan and GLFW header files
|
||||
@@ -81,7 +85,7 @@ section. The canonical desktop loader library exports all Vulkan core and
|
||||
Khronos extension functions, allowing them to be called directly.
|
||||
|
||||
If you are loading the Vulkan loader dynamically instead of linking directly
|
||||
against it, you can check for the availability of a loader with @ref
|
||||
against it, you can check for the availability of a loader and ICD with @ref
|
||||
glfwVulkanSupported.
|
||||
|
||||
@code
|
||||
@@ -91,11 +95,11 @@ if (glfwVulkanSupported())
|
||||
}
|
||||
@endcode
|
||||
|
||||
This function returns `GLFW_TRUE` if the Vulkan loader was found. This check is
|
||||
performed by @ref glfwInit.
|
||||
This function returns `GLFW_TRUE` if the Vulkan loader and any minimally
|
||||
functional ICD was found.
|
||||
|
||||
If no loader was found, calling any other Vulkan related GLFW function will
|
||||
generate a @ref GLFW_API_UNAVAILABLE error.
|
||||
If if one or both were not found, calling any other Vulkan related GLFW function
|
||||
will generate a @ref GLFW_API_UNAVAILABLE error.
|
||||
|
||||
|
||||
@subsection vulkan_proc Querying Vulkan function pointers
|
||||
@@ -226,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.
|
||||
|
||||
|
||||
+262
-52
@@ -77,7 +77,7 @@ GLFWvidmode.blueBits | @ref GLFW_BLUE_BITS hint
|
||||
GLFWvidmode.refreshRate | @ref GLFW_REFRESH_RATE hint
|
||||
|
||||
Once you have a full screen window, you can change its resolution, refresh rate
|
||||
and monitor with @ref glfwSetWindowMonitor. If you just need change its
|
||||
and monitor with @ref glfwSetWindowMonitor. If you only need change its
|
||||
resolution you can also call @ref glfwSetWindowSize. In all cases, the new
|
||||
video mode will be selected the same way as the video mode chosen by @ref
|
||||
glfwCreateWindow. If the window has an OpenGL or OpenGL ES context, it will be
|
||||
@@ -87,7 +87,10 @@ By default, the original video mode of the monitor will be restored and the
|
||||
window iconified if it loses input focus, to allow the user to switch back to
|
||||
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 windows with full screen windows.
|
||||
wish to simultaneously cover multiple monitors with full screen windows.
|
||||
|
||||
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
|
||||
@@ -96,7 +99,7 @@ If the closest match for the desired video mode is the current one, the video
|
||||
mode will not be changed, making window creation faster and application
|
||||
switching much smoother. This is sometimes called _windowed full screen_ or
|
||||
_borderless full screen_ window and counts as a full screen window. To create
|
||||
such a window, simply request the current video mode.
|
||||
such a window, request the current video mode.
|
||||
|
||||
@code
|
||||
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
|
||||
@@ -143,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 simply ignore them. Setting these hints requires no platform specific
|
||||
headers or calls.
|
||||
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
|
||||
@@ -179,38 +184,55 @@ context, but are ignored when requesting an OpenGL ES context:
|
||||
@anchor GLFW_RESIZABLE_hint
|
||||
__GLFW_RESIZABLE__ specifies whether the windowed mode window will be resizable
|
||||
_by the user_. The window will still be resizable using the @ref
|
||||
glfwSetWindowSize function. This hint is ignored for full screen and
|
||||
undecorated windows.
|
||||
glfwSetWindowSize function. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
|
||||
This hint is ignored for full screen and undecorated windows.
|
||||
|
||||
@anchor GLFW_VISIBLE_hint
|
||||
__GLFW_VISIBLE__ specifies whether the windowed mode window will be initially
|
||||
visible. This hint is ignored for full screen windows.
|
||||
visible. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This hint is
|
||||
ignored for full screen windows.
|
||||
|
||||
@anchor GLFW_DECORATED_hint
|
||||
__GLFW_DECORATED__ specifies whether the windowed mode window will have window
|
||||
decorations such as a border, a close widget, etc. An undecorated window will
|
||||
not be resizable by the user but will still allow the user to generate close
|
||||
events on some platforms. This hint is ignored for full screen windows.
|
||||
events on some platforms. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
|
||||
This hint is ignored for full screen windows.
|
||||
|
||||
@anchor GLFW_FOCUSED_hint
|
||||
__GLFW_FOCUSED__ specifies whether the windowed mode window will be given input
|
||||
focus when created. This hint is ignored for full screen and initially hidden
|
||||
windows.
|
||||
focus when created. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This
|
||||
hint is ignored for full screen and initially hidden windows.
|
||||
|
||||
@anchor GLFW_AUTO_ICONIFY_hint
|
||||
__GLFW_AUTO_ICONIFY__ specifies whether the full screen window will
|
||||
automatically iconify and restore the previous video mode on input focus loss.
|
||||
This hint is ignored for windowed mode windows.
|
||||
Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This hint is ignored for
|
||||
windowed mode windows.
|
||||
|
||||
@anchor GLFW_FLOATING_hint
|
||||
__GLFW_FLOATING__ specifies whether the windowed mode window will be floating
|
||||
above other regular windows, also called topmost or always-on-top. This is
|
||||
intended primarily for debugging purposes and cannot be used to implement proper
|
||||
full screen windows. This hint is ignored for full screen windows.
|
||||
full screen windows. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This
|
||||
hint is ignored for full screen windows.
|
||||
|
||||
@anchor GLFW_MAXIMIZED_hint
|
||||
__GLFW_MAXIMIZED__ specifies whether the windowed mode window will be maximized
|
||||
when created. This hint is ignored for full screen windows.
|
||||
when created. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This hint is
|
||||
ignored for full screen windows.
|
||||
|
||||
@anchor GLFW_CENTER_CURSOR_hint
|
||||
__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_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`.
|
||||
|
||||
|
||||
@subsubsection window_hints_fb Framebuffer related hints
|
||||
@@ -248,8 +270,8 @@ Auxiliary buffers are a legacy OpenGL feature and should not be used in new
|
||||
code.
|
||||
|
||||
@anchor GLFW_STEREO
|
||||
__GLFW_STEREO__ specifies whether to use OpenGL stereoscopic rendering. This is
|
||||
a hard constraint.
|
||||
__GLFW_STEREO__ specifies whether to use OpenGL stereoscopic rendering.
|
||||
Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This is a hard constraint.
|
||||
|
||||
@anchor GLFW_SAMPLES
|
||||
__GLFW_SAMPLES__ specifies the desired number of samples to use for
|
||||
@@ -258,14 +280,21 @@ the application has no preference.
|
||||
|
||||
@anchor GLFW_SRGB_CAPABLE
|
||||
__GLFW_SRGB_CAPABLE__ specifies whether the framebuffer should be sRGB capable.
|
||||
If supported, a created OpenGL context will support the `GL_FRAMEBUFFER_SRGB`
|
||||
enable, also called `GL_FRAMEBUFFER_SRGB_EXT`) for controlling sRGB rendering
|
||||
and a created OpenGL ES context will always have sRGB rendering enabled.
|
||||
Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
|
||||
|
||||
@par
|
||||
__OpenGL:__ If enabled and supported by the system, the `GL_FRAMEBUFFER_SRGB`
|
||||
enable will control sRGB rendering. By default, sRGB rendering will be
|
||||
disabled.
|
||||
|
||||
@par
|
||||
__OpenGL ES:__ If enabled and supported by the system, the context will always
|
||||
have sRGB rendering enabled.
|
||||
|
||||
@anchor GLFW_DOUBLEBUFFER
|
||||
__GLFW_DOUBLEBUFFER__ specifies whether the framebuffer should be double
|
||||
buffered. You nearly always want to use double buffering. This is a hard
|
||||
constraint.
|
||||
constraint. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
|
||||
|
||||
|
||||
@subsubsection window_hints_mtr Monitor related hints
|
||||
@@ -285,9 +314,9 @@ This is a hard constraint.
|
||||
|
||||
@anchor GLFW_CONTEXT_CREATION_API_hint
|
||||
__GLFW_CONTEXT_CREATION_API__ specifies which context creation API to use to
|
||||
create the context. Possible values are `GLFW_NATIVE_CONTEXT_API` and
|
||||
`GLFW_EGL_CONTEXT_API`. This is a hard constraint. If no client API is
|
||||
requested, this hint is ignored.
|
||||
create the context. Possible values are `GLFW_NATIVE_CONTEXT_API`,
|
||||
`GLFW_EGL_CONTEXT_API` and `GLFW_OSMESA_CONTEXT_API`. This is a hard
|
||||
constraint. If no client API is requested, this hint is ignored.
|
||||
|
||||
@par
|
||||
@macos The EGL API is not available on this platform and requests to use it
|
||||
@@ -297,6 +326,12 @@ will fail.
|
||||
__Wayland, Mir:__ The EGL API _is_ the native context creation API, so this hint
|
||||
will have no effect.
|
||||
|
||||
@par
|
||||
__OSMesa:__ As its name implies, an OpenGL context created with OSMesa does not
|
||||
update the window contents when its buffers are swapped. Use OpenGL functions
|
||||
or the OSMesa native access functions @ref glfwGetOSMesaColorBuffer and @ref
|
||||
glfwGetOSMesaDepthBuffer to retrieve the framebuffer contents.
|
||||
|
||||
@note An OpenGL extension loader library that assumes it knows which context
|
||||
creation API is used on a given platform may fail if you change this hint. This
|
||||
can be resolved by having it load via @ref glfwGetProcAddress, which always uses
|
||||
@@ -312,6 +347,9 @@ __GLFW_CONTEXT_VERSION_MAJOR__ and __GLFW_CONTEXT_VERSION_MINOR__ specify the
|
||||
client API version that the created context must be compatible with. The exact
|
||||
behavior of these hints depend on the requested client API.
|
||||
|
||||
@note Do not confuse these hints with `GLFW_VERSION_MAJOR` and
|
||||
`GLFW_VERSION_MINOR`, which provide the API version of the GLFW header.
|
||||
|
||||
@par
|
||||
__OpenGL:__ These hints are not hard constraints, but creation will fail if the
|
||||
OpenGL version of the created context is less than the one requested. It is
|
||||
@@ -351,7 +389,8 @@ Forward-compatibility is described in detail in the
|
||||
@anchor GLFW_OPENGL_DEBUG_CONTEXT_hint
|
||||
__GLFW_OPENGL_DEBUG_CONTEXT__ specifies whether to create a debug OpenGL
|
||||
context, which may have additional error and performance issue reporting
|
||||
functionality. If OpenGL ES is requested, this hint is ignored.
|
||||
functionality. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. If OpenGL ES
|
||||
is requested, this hint is ignored.
|
||||
|
||||
@anchor GLFW_OPENGL_PROFILE_hint
|
||||
__GLFW_OPENGL_PROFILE__ specifies which OpenGL profile to create the context
|
||||
@@ -388,28 +427,53 @@ extension.
|
||||
|
||||
@anchor GLFW_CONTEXT_NO_ERROR_hint
|
||||
__GLFW_CONTEXT_NO_ERROR__ specifies whether errors should be generated by the
|
||||
context. If enabled, situations that would have generated errors instead cause
|
||||
undefined behavior.
|
||||
context. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. If enabled,
|
||||
situations that would have generated errors instead cause undefined behavior.
|
||||
|
||||
@par
|
||||
The no error mode for OpenGL and OpenGL ES is described in detail by the
|
||||
[GL_KHR_no_error](https://www.opengl.org/registry/specs/KHR/no_error.txt)
|
||||
extension.
|
||||
|
||||
@note This hint is experimental in its current state. There are currently
|
||||
(October 2015) no corresponding WGL or GLX extensions. That makes this hint
|
||||
a [hard constraint](@ref window_hints_hard) for those backends, as creation will
|
||||
fail if unsupported context flags are requested. Once the extensions are
|
||||
available, they will be required and creation of `GL_KHR_no_error` contexts may
|
||||
fail on early drivers where this flag is supported without those extensions
|
||||
being listed.
|
||||
|
||||
|
||||
@subsubsection window_hints_osx macOS specific hints
|
||||
@subsubsection window_hints_osx macOS specific window hints
|
||||
|
||||
@anchor GLFW_COCOA_RETINA_FRAMEBUFFER_hint
|
||||
__GLFW_COCOA_RETINA_FRAMEBUFFER__ specifies whether to use full resolution
|
||||
framebuffers on Retina displays. This is ignored on other platforms.
|
||||
framebuffers on Retina displays. 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
|
||||
Switching, i.e. to allow the system to choose the integrated GPU for the OpenGL
|
||||
context and move it between GPUs if necessary or whether to force it to always
|
||||
run on the discrete GPU. This only affects systems with both integrated and
|
||||
discrete GPUs. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This is
|
||||
ignored on other platforms.
|
||||
|
||||
@par
|
||||
Simpler programs and tools may want to enable this to save power, while games
|
||||
and other applications performing advanced rendering will want to leave it
|
||||
disabled.
|
||||
|
||||
@par
|
||||
A bundled application that wishes to participate in Automatic Graphics Switching
|
||||
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
|
||||
@@ -423,6 +487,8 @@ GLFW_FOCUSED | `GLFW_TRUE` | `GLFW_TRUE` or `GL
|
||||
GLFW_AUTO_ICONIFY | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
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_FRAMEBUFFER | `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`
|
||||
@@ -440,7 +506,7 @@ GLFW_STEREO | `GLFW_FALSE` | `GLFW_TRUE` or `GL
|
||||
GLFW_SRGB_CAPABLE | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
GLFW_DOUBLEBUFFER | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
GLFW_CLIENT_API | `GLFW_OPENGL_API` | `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API`
|
||||
GLFW_CONTEXT_CREATION_API | `GLFW_NATIVE_CONTEXT_API` | `GLFW_NATIVE_CONTEXT_API` or `GLFW_EGL_CONTEXT_API`
|
||||
GLFW_CONTEXT_CREATION_API | `GLFW_NATIVE_CONTEXT_API` | `GLFW_NATIVE_CONTEXT_API`, `GLFW_EGL_CONTEXT_API` or `GLFW_OSMESA_CONTEXT_API`
|
||||
GLFW_CONTEXT_VERSION_MAJOR | 1 | Any valid major version number of the chosen client API
|
||||
GLFW_CONTEXT_VERSION_MINOR | 0 | Any valid minor version number of the chosen client API
|
||||
GLFW_CONTEXT_ROBUSTNESS | `GLFW_NO_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS`, `GLFW_NO_RESET_NOTIFICATION` or `GLFW_LOSE_CONTEXT_ON_RESET`
|
||||
@@ -449,6 +515,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_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
|
||||
@@ -461,7 +531,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.
|
||||
|
||||
@@ -525,15 +595,15 @@ window's desired video mode. The video mode most closely matching the new
|
||||
desired video mode is set immediately. The window is resized to fit the
|
||||
resolution of the set video mode.
|
||||
|
||||
If you wish to be notified when a window is resized, whether by the user or
|
||||
the system, set a size callback.
|
||||
If you wish to be notified when a window is resized, whether by the user, the
|
||||
system or your own code, set a size callback.
|
||||
|
||||
@code
|
||||
glfwSetWindowSizeCallback(window, window_size_callback);
|
||||
@endcode
|
||||
|
||||
The callback function receives the new size, in screen coordinates, of the
|
||||
client area of the window when it is resized.
|
||||
client area of the window when the window is resized.
|
||||
|
||||
@code
|
||||
void window_size_callback(GLFWwindow* window, int width, int height)
|
||||
@@ -606,6 +676,43 @@ The size of a framebuffer may change independently of the size of a window, for
|
||||
example if the window is dragged between a regular monitor and a high-DPI one.
|
||||
|
||||
|
||||
@subsection window_scale Window content scale
|
||||
|
||||
The content scale for a window can be retrieved with @ref
|
||||
glfwGetWindowContentScale.
|
||||
|
||||
@code
|
||||
float xscale, yscale;
|
||||
glfwGetWindowContentScale(window, &xscale, &yscale);
|
||||
@endcode
|
||||
|
||||
The content scale of a window is the ratio between the current DPI and the
|
||||
platform's default DPI. If you scale all pixel dimensions by this scale then
|
||||
your content should appear at an appropriate size. This is especially important
|
||||
for text and any UI elements.
|
||||
|
||||
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
|
||||
|
||||
|
||||
@subsection window_sizelimits Window size limits
|
||||
|
||||
The minimum and maximum size of the client area of a windowed mode window can be
|
||||
@@ -637,7 +744,7 @@ glfwSetWindowAspectRatio(window, 16, 9);
|
||||
|
||||
The aspect ratio is specified as a numerator and denominator, corresponding to
|
||||
the width and height, respectively. If you want a window to maintain its
|
||||
current aspect ratio, simply use its current size as the ratio.
|
||||
current aspect ratio, use its current size as the ratio.
|
||||
|
||||
@code
|
||||
int width, height;
|
||||
@@ -663,15 +770,15 @@ The window system may put limitations on window placement.
|
||||
glfwSetWindowPos(window, 100, 100);
|
||||
@endcode
|
||||
|
||||
If you wish to be notified when a window is moved, whether by the user, system
|
||||
or your own code, set a position callback.
|
||||
If you wish to be notified when a window is moved, whether by the user, the
|
||||
system or your own code, set a position callback.
|
||||
|
||||
@code
|
||||
glfwSetWindowPosCallback(window, window_pos_callback);
|
||||
@endcode
|
||||
|
||||
The callback function receives the new position of the upper-left corner of the
|
||||
client area when the window is moved.
|
||||
The callback function receives the new position, in screen coordinates, of the
|
||||
upper-left corner of the client area when the window is moved.
|
||||
|
||||
@code
|
||||
void window_pos_callback(GLFWwindow* window, int xpos, int ypos)
|
||||
@@ -728,6 +835,10 @@ images[1] = load_icon("my_icon_small.png");
|
||||
glfwSetWindowIcon(window, 2, images);
|
||||
@endcode
|
||||
|
||||
The image data is 32-bit, little-endian, non-premultiplied RGBA, i.e. eight bits
|
||||
per channel with the red channel first. The pixels are arranged canonically as
|
||||
sequential rows, starting from the top-left corner.
|
||||
|
||||
To revert to the default window icon, pass in an empty image array.
|
||||
|
||||
@code
|
||||
@@ -927,6 +1038,10 @@ glfwFocusWindow.
|
||||
glfwFocusWindow(window);
|
||||
@endcode
|
||||
|
||||
Keep in mind that it can be very disruptive to the user when a window is forced
|
||||
to the top. For a less disruptive way of getting the user's attention, see
|
||||
[attention requests](@ref window_attention).
|
||||
|
||||
If you wish to be notified when a window gains or loses input focus, whether by
|
||||
the user, system or your own code, set a focus callback.
|
||||
|
||||
@@ -965,6 +1080,20 @@ glfwWindowHint(GLFW_FOCUSED, GLFW_FALSE);
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection window_attention Window attention request
|
||||
|
||||
If you wish to notify the user of an event without interrupting, you can request
|
||||
attention with @ref glfwRequestWindowAttention.
|
||||
|
||||
@code
|
||||
glfwRequestWindowAttention(window);
|
||||
@endcode
|
||||
|
||||
The system will highlight the specified window, or on platforms where this is
|
||||
not supported, the application as a whole. Once the user has given it
|
||||
attention, the system will automatically end the request.
|
||||
|
||||
|
||||
@subsection window_refresh Window damage and refresh
|
||||
|
||||
If you wish to be notified when the contents of a window is damaged and needs
|
||||
@@ -990,6 +1119,66 @@ window contents are saved off-screen, this callback might only be called when
|
||||
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_FRAMEBUFFER](@ref GLFW_TRANSPARENT_FRAMEBUFFER_hint)
|
||||
window hint.
|
||||
|
||||
@code
|
||||
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
|
||||
@endcode
|
||||
|
||||
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_FRAMEBUFFER](@ref GLFW_TRANSPARENT_FRAMEBUFFER_attrib)
|
||||
window attribute.
|
||||
|
||||
@code
|
||||
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
|
||||
|
||||
Windows have a number of attributes that can be returned using @ref
|
||||
@@ -1031,6 +1220,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.
|
||||
@@ -1059,6 +1253,12 @@ 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_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.
|
||||
|
||||
|
||||
@subsubsection window_attribs_ctx Context related attributes
|
||||
|
||||
@@ -1068,8 +1268,8 @@ either `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API`.
|
||||
|
||||
@anchor GLFW_CONTEXT_CREATION_API_attrib
|
||||
__GLFW_CONTEXT_CREATION_API__ indicates the context creation API used to create
|
||||
the window's context; either `GLFW_NATIVE_CONTEXT_API` or
|
||||
`GLFW_EGL_CONTEXT_API`.
|
||||
the window's context; either `GLFW_NATIVE_CONTEXT_API`, `GLFW_EGL_CONTEXT_API`
|
||||
or `GLFW_OSMESA_CONTEXT_API`.
|
||||
|
||||
@anchor GLFW_CONTEXT_VERSION_MAJOR_attrib
|
||||
@anchor GLFW_CONTEXT_VERSION_MINOR_attrib
|
||||
@@ -1078,6 +1278,10 @@ __GLFW_CONTEXT_VERSION_MAJOR__, __GLFW_CONTEXT_VERSION_MINOR__ and
|
||||
__GLFW_CONTEXT_REVISION__ indicate the client API version of the window's
|
||||
context.
|
||||
|
||||
@note Do not confuse these attributes with `GLFW_VERSION_MAJOR`,
|
||||
`GLFW_VERSION_MINOR` and `GLFW_VERSION_REVISION` which provide the API version
|
||||
of the GLFW header.
|
||||
|
||||
@anchor GLFW_OPENGL_FORWARD_COMPAT_attrib
|
||||
__GLFW_OPENGL_FORWARD_COMPAT__ is `GLFW_TRUE` if the window's context is an
|
||||
OpenGL forward-compatible one, or `GLFW_FALSE` otherwise.
|
||||
@@ -1165,4 +1369,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.
|
||||
|
||||
*/
|
||||
|
||||
@@ -3,7 +3,7 @@ link_libraries(glfw)
|
||||
|
||||
include_directories(${glfw_INCLUDE_DIRS} "${GLFW_SOURCE_DIR}/deps")
|
||||
|
||||
if (BUILD_SHARED_LIBS)
|
||||
if (MATH_LIBRARY)
|
||||
link_libraries("${MATH_LIBRARY}")
|
||||
endif()
|
||||
|
||||
@@ -35,13 +35,17 @@ 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})
|
||||
|
||||
target_link_libraries(particles "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}")
|
||||
target_link_libraries(particles "${CMAKE_THREAD_LIBS_INIT}")
|
||||
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
|
||||
@@ -58,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")
|
||||
|
||||
@@ -172,6 +172,7 @@ static GLfloat angle = 0.f;
|
||||
/* OpenGL draw function & timing */
|
||||
static void draw(void)
|
||||
{
|
||||
glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glPushMatrix();
|
||||
@@ -311,6 +312,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_DEPTH_BITS, 16);
|
||||
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
|
||||
|
||||
window = glfwCreateWindow( 300, 300, "Gears", NULL, NULL );
|
||||
if (!window)
|
||||
|
||||
@@ -87,6 +87,8 @@ int main(void)
|
||||
|
||||
glfwSetErrorCallback(error_callback);
|
||||
|
||||
glfwInitHint(GLFW_COCOA_MENUBAR, GLFW_FALSE);
|
||||
|
||||
if (!glfwInit())
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
|
||||
@@ -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++)
|
||||
+1025
-152
File diff suppressed because it is too large
Load Diff
@@ -45,6 +45,7 @@ extern "C" {
|
||||
* more information.
|
||||
*/
|
||||
/*! @defgroup native Native access
|
||||
* @brief Functions related to accessing native handles.
|
||||
*
|
||||
* **By using the native access functions you assert that you know what you're
|
||||
* doing and how to fix problems caused by using them. If you don't, you
|
||||
@@ -85,7 +86,10 @@ extern "C" {
|
||||
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
|
||||
// example to allow applications to correctly declare a GL_ARB_debug_output
|
||||
// callback) but windows.h assumes no one will define APIENTRY before it does
|
||||
#undef APIENTRY
|
||||
#if defined(GLFW_APIENTRY_DEFINED)
|
||||
#undef APIENTRY
|
||||
#undef GLFW_APIENTRY_DEFINED
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_COCOA)
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
@@ -288,6 +292,56 @@ GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
|
||||
|
||||
/*! @brief Sets the current primary selection to the specified string.
|
||||
*
|
||||
* @param[in] string A UTF-8 encoded string.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @pointer_lifetime The specified string is copied before this function
|
||||
* returns.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref clipboard
|
||||
* @sa glfwGetX11SelectionString
|
||||
* @sa glfwSetClipboardString
|
||||
*
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI void glfwSetX11SelectionString(const char* string);
|
||||
|
||||
/*! @brief Returns the contents of the current primary selection as a string.
|
||||
*
|
||||
* If the selection is empty or if its contents cannot be converted, `NULL`
|
||||
* is returned and a @ref GLFW_FORMAT_UNAVAILABLE error is generated.
|
||||
*
|
||||
* @return The contents of the selection as a UTF-8 encoded string, or `NULL`
|
||||
* if an [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @pointer_lifetime The returned string is allocated and freed by GLFW. You
|
||||
* should not free it yourself. It is valid until the next call to @ref
|
||||
* glfwGetX11SelectionString or @ref glfwSetX11SelectionString, or until the
|
||||
* library is terminated.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref clipboard
|
||||
* @sa glfwSetX11SelectionString
|
||||
* @sa glfwGetClipboardString
|
||||
*
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI const char* glfwGetX11SelectionString(void);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||
@@ -393,9 +447,9 @@ GLFWAPI MirConnection* glfwGetMirDisplay(void);
|
||||
*/
|
||||
GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor);
|
||||
|
||||
/*! @brief Returns the `MirSurface*` of the specified window.
|
||||
/*! @brief Returns the `MirWindow*` of the specified window.
|
||||
*
|
||||
* @return The `MirSurface*` of the specified window, or `NULL` if an
|
||||
* @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
|
||||
@@ -405,7 +459,7 @@ GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor);
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window);
|
||||
GLFWAPI MirWindow* glfwGetMirWindow(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_EGL)
|
||||
|
||||
+62
-30
@@ -1,5 +1,5 @@
|
||||
|
||||
set(common_HEADERS internal.h
|
||||
set(common_HEADERS internal.h mappings.h
|
||||
"${GLFW_BINARY_DIR}/src/glfw_config.h"
|
||||
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h"
|
||||
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h")
|
||||
@@ -7,50 +7,66 @@ set(common_SOURCES context.c init.c input.c monitor.c vulkan.c window.c)
|
||||
|
||||
if (_GLFW_COCOA)
|
||||
set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h cocoa_joystick.h
|
||||
posix_tls.h nsgl_context.h)
|
||||
posix_thread.h nsgl_context.h egl_context.h osmesa_context.h)
|
||||
set(glfw_SOURCES ${common_SOURCES} cocoa_init.m cocoa_joystick.m
|
||||
cocoa_monitor.m cocoa_window.m cocoa_time.c posix_tls.c
|
||||
nsgl_context.m)
|
||||
cocoa_monitor.m cocoa_window.m cocoa_time.c posix_thread.c
|
||||
nsgl_context.m egl_context.c osmesa_context.c)
|
||||
elseif (_GLFW_WIN32)
|
||||
set(glfw_HEADERS ${common_HEADERS} win32_platform.h win32_joystick.h
|
||||
wgl_context.h egl_context.h)
|
||||
wgl_context.h egl_context.h osmesa_context.h)
|
||||
set(glfw_SOURCES ${common_SOURCES} win32_init.c win32_joystick.c
|
||||
win32_monitor.c win32_time.c win32_tls.c win32_window.c
|
||||
wgl_context.c egl_context.c)
|
||||
win32_monitor.c win32_time.c win32_thread.c win32_window.c
|
||||
wgl_context.c egl_context.c osmesa_context.c)
|
||||
elseif (_GLFW_X11)
|
||||
set(glfw_HEADERS ${common_HEADERS} x11_platform.h xkb_unicode.h
|
||||
linux_joystick.h posix_time.h posix_tls.h glx_context.h
|
||||
egl_context.h)
|
||||
set(glfw_HEADERS ${common_HEADERS} x11_platform.h xkb_unicode.h posix_time.h
|
||||
posix_thread.h glx_context.h egl_context.h osmesa_context.h)
|
||||
set(glfw_SOURCES ${common_SOURCES} x11_init.c x11_monitor.c x11_window.c
|
||||
xkb_unicode.c linux_joystick.c posix_time.c posix_tls.c
|
||||
glx_context.c egl_context.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
|
||||
posix_time.h posix_tls.h xkb_unicode.h egl_context.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_tls.c xkb_unicode.c
|
||||
egl_context.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/relative-pointer/relative-pointer-unstable-v1.xml
|
||||
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/xdg-shell/xdg-shell.xml"
|
||||
BASENAME xdg-shell)
|
||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
||||
PROTOCOL
|
||||
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml"
|
||||
BASENAME relative-pointer-unstable-v1)
|
||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
||||
PROTOCOL
|
||||
${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml
|
||||
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml"
|
||||
BASENAME pointer-constraints-unstable-v1)
|
||||
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_MIR)
|
||||
set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
|
||||
posix_time.h posix_tls.h xkb_unicode.h egl_context.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_tls.c xkb_unicode.c
|
||||
egl_context.c)
|
||||
linux_joystick.c posix_time.c posix_thread.c xkb_unicode.c
|
||||
egl_context.c osmesa_context.c)
|
||||
elseif (_GLFW_OSMESA)
|
||||
set(glfw_HEADERS ${common_HEADERS} osmesa_platform.h
|
||||
posix_time.h posix_tls.h osmesa_context.h)
|
||||
set(glfw_SOURCES ${common_SOURCES} osmesa_init.c osmesa_monitor.c
|
||||
osmesa_window.c posix_time.c posix_tls.c
|
||||
osmesa_context.c)
|
||||
set(glfw_HEADERS ${common_HEADERS} null_platform.h null_joystick.h
|
||||
posix_time.h posix_thread.h osmesa_context.h)
|
||||
set(glfw_SOURCES ${common_SOURCES} null_init.c null_monitor.c null_window.c
|
||||
null_joystick.c posix_time.c posix_thread.c osmesa_context.c)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
@@ -58,6 +74,18 @@ if (APPLE)
|
||||
set_source_files_properties(${glfw_SOURCES} PROPERTIES LANGUAGE C)
|
||||
endif()
|
||||
|
||||
# Make GCC and Clang warn about declarations that VS 2010 and 2012 won't accept
|
||||
# for all source files that VS will build
|
||||
if (${CMAKE_C_COMPILER_ID} STREQUAL GNU OR ${CMAKE_C_COMPILER_ID} STREQUAL Clang)
|
||||
if (WIN32)
|
||||
set(windows_SOURCES ${glfw_SOURCES})
|
||||
else()
|
||||
set(windows_SOURCES ${common_SOURCES})
|
||||
endif()
|
||||
set_source_files_properties(${windows_SOURCES} PROPERTIES
|
||||
COMPILE_FLAGS -Wdeclaration-after-statement)
|
||||
endif()
|
||||
|
||||
add_library(glfw ${glfw_SOURCES} ${glfw_HEADERS})
|
||||
set_target_properties(glfw PROPERTIES
|
||||
OUTPUT_NAME ${GLFW_LIB_NAME}
|
||||
@@ -66,10 +94,10 @@ set_target_properties(glfw PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
FOLDER "GLFW3")
|
||||
|
||||
target_compile_definitions(glfw PRIVATE -D_GLFW_USE_CONFIG_H)
|
||||
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>)
|
||||
"$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>")
|
||||
target_include_directories(glfw PRIVATE
|
||||
"${GLFW_SOURCE_DIR}/src"
|
||||
"${GLFW_BINARY_DIR}/src"
|
||||
@@ -110,7 +138,7 @@ if (BUILD_SHARED_LIBS)
|
||||
target_compile_options(glfw PRIVATE "-fvisibility=hidden")
|
||||
endif()
|
||||
|
||||
target_compile_definitions(glfw INTERFACE -DGLFW_DLL)
|
||||
target_compile_definitions(glfw INTERFACE GLFW_DLL)
|
||||
target_link_libraries(glfw PRIVATE ${glfw_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(glfw INTERFACE ${glfw_LIBRARIES})
|
||||
@@ -121,6 +149,10 @@ if (MSVC)
|
||||
endif()
|
||||
|
||||
if (GLFW_INSTALL)
|
||||
install(TARGETS glfw EXPORT glfwTargets DESTINATION lib${LIB_SUFFIX})
|
||||
install(TARGETS glfw
|
||||
EXPORT glfwTargets
|
||||
RUNTIME DESTINATION "bin"
|
||||
ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
|
||||
LIBRARY DESTINATION "lib${LIB_SUFFIX}")
|
||||
endif()
|
||||
|
||||
|
||||
+9
-24
@@ -28,8 +28,6 @@
|
||||
#include <sys/param.h> // For MAXPATHLEN
|
||||
|
||||
|
||||
#if defined(_GLFW_USE_CHDIR)
|
||||
|
||||
// Change to our application bundle's resources directory, if present
|
||||
//
|
||||
static void changeToResourcesDirectory(void)
|
||||
@@ -66,8 +64,6 @@ static void changeToResourcesDirectory(void)
|
||||
chdir(resourcesPath);
|
||||
}
|
||||
|
||||
#endif /* _GLFW_USE_CHDIR */
|
||||
|
||||
// Create key code translation tables
|
||||
//
|
||||
static void createKeyTables(void)
|
||||
@@ -219,8 +215,9 @@ static GLFWbool updateUnicodeDataNS(void)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.ns.unicodeData = TISGetInputSourceProperty(_glfw.ns.inputSource,
|
||||
kTISPropertyUnicodeKeyLayoutData);
|
||||
_glfw.ns.unicodeData =
|
||||
TISGetInputSourceProperty(_glfw.ns.inputSource,
|
||||
kTISPropertyUnicodeKeyLayoutData);
|
||||
if (!_glfw.ns.unicodeData)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
@@ -236,7 +233,8 @@ static GLFWbool updateUnicodeDataNS(void)
|
||||
static GLFWbool initializeTIS(void)
|
||||
{
|
||||
// This works only because Cocoa has already loaded it properly
|
||||
_glfw.ns.tis.bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
|
||||
_glfw.ns.tis.bundle =
|
||||
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
|
||||
if (!_glfw.ns.tis.bundle)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
@@ -294,6 +292,9 @@ int _glfwPlatformInit(void)
|
||||
{
|
||||
_glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
if (_glfw.hints.init.ns.chdir)
|
||||
changeToResourcesDirectory();
|
||||
|
||||
_glfw.ns.listener = [[GLFWLayoutListener alloc] init];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:_glfw.ns.listener
|
||||
@@ -301,10 +302,6 @@ int _glfwPlatformInit(void)
|
||||
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
||||
object:nil];
|
||||
|
||||
#if defined(_GLFW_USE_CHDIR)
|
||||
changeToResourcesDirectory();
|
||||
#endif
|
||||
|
||||
createKeyTables();
|
||||
|
||||
_glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
@@ -316,12 +313,10 @@ int _glfwPlatformInit(void)
|
||||
if (!initializeTIS())
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
||||
return GLFW_FALSE;
|
||||
|
||||
_glfwInitTimerNS();
|
||||
_glfwInitJoysticksNS();
|
||||
|
||||
_glfwPollMonitorsNS();
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
@@ -359,14 +354,10 @@ void _glfwPlatformTerminate(void)
|
||||
_glfw.ns.listener = nil;
|
||||
}
|
||||
|
||||
[_glfw.ns.cursor release];
|
||||
_glfw.ns.cursor = nil;
|
||||
|
||||
free(_glfw.ns.clipboardString);
|
||||
|
||||
_glfwTerminateNSGL();
|
||||
_glfwTerminateJoysticksNS();
|
||||
_glfwTerminateThreadLocalStoragePOSIX();
|
||||
|
||||
[_glfw.ns.autoreleasePool release];
|
||||
_glfw.ns.autoreleasePool = nil;
|
||||
@@ -375,12 +366,6 @@ void _glfwPlatformTerminate(void)
|
||||
const char* _glfwPlatformGetVersionString(void)
|
||||
{
|
||||
return _GLFW_VERSION_NUMBER " Cocoa NSGL"
|
||||
#if defined(_GLFW_USE_CHDIR)
|
||||
" chdir"
|
||||
#endif
|
||||
#if defined(_GLFW_USE_MENUBAR)
|
||||
" menubar"
|
||||
#endif
|
||||
#if defined(_GLFW_BUILD_DLL)
|
||||
" dynamic"
|
||||
#endif
|
||||
|
||||
+7
-17
@@ -24,37 +24,27 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_cocoa_joystick_h_
|
||||
#define _glfw3_cocoa_joystick_h_
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/IOCFPlugIn.h>
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
#include <IOKit/hid/IOHIDKeys.h>
|
||||
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
|
||||
_GLFWjoystickNS ns_js[GLFW_JOYSTICK_LAST + 1]
|
||||
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickNS ns
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE
|
||||
|
||||
#define _GLFW_PLATFORM_MAPPING_NAME "Mac OS X"
|
||||
|
||||
// Cocoa-specific per-joystick data
|
||||
//
|
||||
typedef struct _GLFWjoystickNS
|
||||
{
|
||||
GLFWbool present;
|
||||
char name[256];
|
||||
|
||||
IOHIDDeviceRef deviceRef;
|
||||
|
||||
CFMutableArrayRef axisElements;
|
||||
CFMutableArrayRef buttonElements;
|
||||
CFMutableArrayRef hatElements;
|
||||
|
||||
float* axes;
|
||||
unsigned char* buttons;
|
||||
IOHIDDeviceRef device;
|
||||
CFMutableArrayRef axes;
|
||||
CFMutableArrayRef buttons;
|
||||
CFMutableArrayRef hats;
|
||||
} _GLFWjoystickNS;
|
||||
|
||||
|
||||
void _glfwInitJoysticksNS(void);
|
||||
void _glfwTerminateJoysticksNS(void);
|
||||
|
||||
#endif // _glfw3_cocoa_joystick_h_
|
||||
|
||||
+311
-360
@@ -42,42 +42,167 @@
|
||||
//
|
||||
typedef struct _GLFWjoyelementNS
|
||||
{
|
||||
IOHIDElementRef elementRef;
|
||||
|
||||
long min;
|
||||
long max;
|
||||
|
||||
long minReport;
|
||||
long maxReport;
|
||||
IOHIDElementRef native;
|
||||
uint32_t usage;
|
||||
int index;
|
||||
long minimum;
|
||||
long maximum;
|
||||
|
||||
} _GLFWjoyelementNS;
|
||||
|
||||
|
||||
static void getElementsCFArrayHandler(const void* value, void* parameter);
|
||||
|
||||
// Adds an element to the specified joystick
|
||||
// Returns the value of the specified element of the specified joystick
|
||||
//
|
||||
static void addJoystickElement(_GLFWjoystickNS* js,
|
||||
IOHIDElementRef elementRef)
|
||||
static long getElementValue(_GLFWjoystick* js, _GLFWjoyelementNS* element)
|
||||
{
|
||||
IOHIDElementType elementType;
|
||||
long usagePage, usage;
|
||||
CFMutableArrayRef elementsArray = NULL;
|
||||
IOHIDValueRef valueRef;
|
||||
long value = 0;
|
||||
|
||||
elementType = IOHIDElementGetType(elementRef);
|
||||
usagePage = IOHIDElementGetUsagePage(elementRef);
|
||||
usage = IOHIDElementGetUsage(elementRef);
|
||||
|
||||
if ((elementType != kIOHIDElementTypeInput_Axis) &&
|
||||
(elementType != kIOHIDElementTypeInput_Button) &&
|
||||
(elementType != kIOHIDElementTypeInput_Misc))
|
||||
if (js->ns.device)
|
||||
{
|
||||
return;
|
||||
if (IOHIDDeviceGetValue(js->ns.device,
|
||||
element->native,
|
||||
&valueRef) == kIOReturnSuccess)
|
||||
{
|
||||
value = IOHIDValueGetIntegerValue(valueRef);
|
||||
}
|
||||
}
|
||||
|
||||
switch (usagePage)
|
||||
return value;
|
||||
}
|
||||
|
||||
// Comparison function for matching the SDL element order
|
||||
//
|
||||
static CFComparisonResult compareElements(const void* fp,
|
||||
const void* sp,
|
||||
void* user)
|
||||
{
|
||||
const _GLFWjoyelementNS* fe = fp;
|
||||
const _GLFWjoyelementNS* se = sp;
|
||||
if (fe->usage < se->usage)
|
||||
return kCFCompareLessThan;
|
||||
if (fe->usage > se->usage)
|
||||
return kCFCompareGreaterThan;
|
||||
if (fe->index < se->index)
|
||||
return kCFCompareLessThan;
|
||||
if (fe->index > se->index)
|
||||
return kCFCompareGreaterThan;
|
||||
return kCFCompareEqualTo;
|
||||
}
|
||||
|
||||
// Removes the specified joystick
|
||||
//
|
||||
static void closeJoystick(_GLFWjoystick* js)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!js->present)
|
||||
return;
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->ns.axes); i++)
|
||||
free((void*) CFArrayGetValueAtIndex(js->ns.axes, i));
|
||||
CFRelease(js->ns.axes);
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++)
|
||||
free((void*) CFArrayGetValueAtIndex(js->ns.buttons, i));
|
||||
CFRelease(js->ns.buttons);
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
|
||||
free((void*) CFArrayGetValueAtIndex(js->ns.hats, i));
|
||||
CFRelease(js->ns.hats);
|
||||
|
||||
_glfwFreeJoystick(js);
|
||||
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
||||
}
|
||||
|
||||
// Callback for user-initiated joystick addition
|
||||
//
|
||||
static void matchCallback(void* context,
|
||||
IOReturn result,
|
||||
void* sender,
|
||||
IOHIDDeviceRef device)
|
||||
{
|
||||
int jid;
|
||||
char name[256];
|
||||
char guid[33];
|
||||
CFIndex i;
|
||||
CFTypeRef property;
|
||||
uint32_t vendor = 0, product = 0, version = 0;
|
||||
_GLFWjoystick* js;
|
||||
CFMutableArrayRef axes, buttons, hats;
|
||||
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
case kHIDPage_GenericDesktop:
|
||||
if (_glfw.joysticks[jid].ns.device == device)
|
||||
return;
|
||||
}
|
||||
|
||||
axes = CFArrayCreateMutable(NULL, 0, NULL);
|
||||
buttons = CFArrayCreateMutable(NULL, 0, NULL);
|
||||
hats = CFArrayCreateMutable(NULL, 0, NULL);
|
||||
|
||||
property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
|
||||
if (property)
|
||||
{
|
||||
CFStringGetCString(property,
|
||||
name,
|
||||
sizeof(name),
|
||||
kCFStringEncodingUTF8);
|
||||
}
|
||||
else
|
||||
strncpy(name, "Unknown", sizeof(name));
|
||||
|
||||
property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey));
|
||||
if (property)
|
||||
CFNumberGetValue(property, kCFNumberSInt32Type, &vendor);
|
||||
|
||||
property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey));
|
||||
if (property)
|
||||
CFNumberGetValue(property, kCFNumberSInt32Type, &product);
|
||||
|
||||
property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVersionNumberKey));
|
||||
if (property)
|
||||
CFNumberGetValue(property, kCFNumberSInt32Type, &version);
|
||||
|
||||
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
||||
if (vendor && product)
|
||||
{
|
||||
sprintf(guid, "03000000%02x%02x0000%02x%02x0000%02x%02x0000",
|
||||
(uint8_t) vendor, (uint8_t) (vendor >> 8),
|
||||
(uint8_t) product, (uint8_t) (product >> 8),
|
||||
(uint8_t) version, (uint8_t) (version >> 8));
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
|
||||
name[0], name[1], name[2], name[3],
|
||||
name[4], name[5], name[6], name[7],
|
||||
name[8], name[9], name[10]);
|
||||
}
|
||||
|
||||
CFArrayRef elements =
|
||||
IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(elements); i++)
|
||||
{
|
||||
IOHIDElementRef native = (IOHIDElementRef)
|
||||
CFArrayGetValueAtIndex(elements, i);
|
||||
if (CFGetTypeID(native) != IOHIDElementGetTypeID())
|
||||
continue;
|
||||
|
||||
const IOHIDElementType type = IOHIDElementGetType(native);
|
||||
if ((type != kIOHIDElementTypeInput_Axis) &&
|
||||
(type != kIOHIDElementTypeInput_Button) &&
|
||||
(type != kIOHIDElementTypeInput_Misc))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
CFMutableArrayRef target = NULL;
|
||||
|
||||
const uint32_t usage = IOHIDElementGetUsage(native);
|
||||
const uint32_t page = IOHIDElementGetUsagePage(native);
|
||||
if (page == kHIDPage_GenericDesktop)
|
||||
{
|
||||
switch (usage)
|
||||
{
|
||||
@@ -90,241 +215,48 @@ static void addJoystickElement(_GLFWjoystickNS* js,
|
||||
case kHIDUsage_GD_Slider:
|
||||
case kHIDUsage_GD_Dial:
|
||||
case kHIDUsage_GD_Wheel:
|
||||
elementsArray = js->axisElements;
|
||||
target = axes;
|
||||
break;
|
||||
case kHIDUsage_GD_Hatswitch:
|
||||
elementsArray = js->hatElements;
|
||||
target = hats;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else if (page == kHIDPage_Button)
|
||||
target = buttons;
|
||||
|
||||
case kHIDPage_Button:
|
||||
elementsArray = js->buttonElements;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (elementsArray)
|
||||
{
|
||||
_GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));
|
||||
|
||||
CFArrayAppendValue(elementsArray, element);
|
||||
|
||||
element->elementRef = elementRef;
|
||||
|
||||
element->minReport = IOHIDElementGetLogicalMin(elementRef);
|
||||
element->maxReport = IOHIDElementGetLogicalMax(elementRef);
|
||||
}
|
||||
}
|
||||
|
||||
// Adds an element to the specified joystick
|
||||
//
|
||||
static void getElementsCFArrayHandler(const void* value, void* parameter)
|
||||
{
|
||||
if (CFGetTypeID(value) == IOHIDElementGetTypeID())
|
||||
{
|
||||
addJoystickElement((_GLFWjoystickNS*) parameter,
|
||||
(IOHIDElementRef) value);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the value of the specified element of the specified joystick
|
||||
//
|
||||
static long getElementValue(_GLFWjoystickNS* js, _GLFWjoyelementNS* element)
|
||||
{
|
||||
IOReturn result = kIOReturnSuccess;
|
||||
IOHIDValueRef valueRef;
|
||||
long value = 0;
|
||||
|
||||
if (js && element && js->deviceRef)
|
||||
{
|
||||
result = IOHIDDeviceGetValue(js->deviceRef,
|
||||
element->elementRef,
|
||||
&valueRef);
|
||||
|
||||
if (kIOReturnSuccess == result)
|
||||
if (target)
|
||||
{
|
||||
value = IOHIDValueGetIntegerValue(valueRef);
|
||||
|
||||
// Record min and max for auto calibration
|
||||
if (value < element->minReport)
|
||||
element->minReport = value;
|
||||
if (value > element->maxReport)
|
||||
element->maxReport = value;
|
||||
_GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));
|
||||
element->native = native;
|
||||
element->usage = usage;
|
||||
element->index = (int) CFArrayGetCount(target);
|
||||
element->minimum = IOHIDElementGetLogicalMin(native);
|
||||
element->maximum = IOHIDElementGetLogicalMax(native);
|
||||
CFArrayAppendValue(target, element);
|
||||
}
|
||||
}
|
||||
|
||||
// Auto user scale
|
||||
return value;
|
||||
}
|
||||
CFRelease(elements);
|
||||
|
||||
// Removes the specified joystick
|
||||
//
|
||||
static void removeJoystick(_GLFWjoystickNS* js)
|
||||
{
|
||||
int i;
|
||||
CFArraySortValues(axes, CFRangeMake(0, CFArrayGetCount(axes)),
|
||||
compareElements, NULL);
|
||||
CFArraySortValues(buttons, CFRangeMake(0, CFArrayGetCount(buttons)),
|
||||
compareElements, NULL);
|
||||
CFArraySortValues(hats, CFRangeMake(0, CFArrayGetCount(hats)),
|
||||
compareElements, NULL);
|
||||
|
||||
if (!js->present)
|
||||
return;
|
||||
js = _glfwAllocJoystick(name, guid,
|
||||
(int) CFArrayGetCount(axes),
|
||||
(int) CFArrayGetCount(buttons),
|
||||
(int) CFArrayGetCount(hats));
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->axisElements); i++)
|
||||
free((void*) CFArrayGetValueAtIndex(js->axisElements, i));
|
||||
CFArrayRemoveAllValues(js->axisElements);
|
||||
CFRelease(js->axisElements);
|
||||
js->ns.device = device;
|
||||
js->ns.axes = axes;
|
||||
js->ns.buttons = buttons;
|
||||
js->ns.hats = hats;
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->buttonElements); i++)
|
||||
free((void*) CFArrayGetValueAtIndex(js->buttonElements, i));
|
||||
CFArrayRemoveAllValues(js->buttonElements);
|
||||
CFRelease(js->buttonElements);
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->hatElements); i++)
|
||||
free((void*) CFArrayGetValueAtIndex(js->hatElements, i));
|
||||
CFArrayRemoveAllValues(js->hatElements);
|
||||
CFRelease(js->hatElements);
|
||||
|
||||
free(js->axes);
|
||||
free(js->buttons);
|
||||
|
||||
memset(js, 0, sizeof(_GLFWjoystickNS));
|
||||
|
||||
_glfwInputJoystickChange(js - _glfw.ns_js, GLFW_DISCONNECTED);
|
||||
}
|
||||
|
||||
// Polls for joystick axis events and updates GLFW state
|
||||
//
|
||||
static GLFWbool pollJoystickAxisEvents(_GLFWjoystickNS* js)
|
||||
{
|
||||
CFIndex i;
|
||||
|
||||
if (!js->present)
|
||||
return GLFW_FALSE;
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->axisElements); i++)
|
||||
{
|
||||
_GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
|
||||
CFArrayGetValueAtIndex(js->axisElements, i);
|
||||
|
||||
long value = getElementValue(js, axis);
|
||||
long readScale = axis->maxReport - axis->minReport;
|
||||
|
||||
if (readScale == 0)
|
||||
js->axes[i] = value;
|
||||
else
|
||||
js->axes[i] = (2.f * (value - axis->minReport) / readScale) - 1.f;
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
// Polls for joystick button events and updates GLFW state
|
||||
//
|
||||
static GLFWbool pollJoystickButtonEvents(_GLFWjoystickNS* js)
|
||||
{
|
||||
CFIndex i;
|
||||
int buttonIndex = 0;
|
||||
|
||||
if (!js->present)
|
||||
return GLFW_FALSE;
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->buttonElements); i++)
|
||||
{
|
||||
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
|
||||
CFArrayGetValueAtIndex(js->buttonElements, i);
|
||||
|
||||
if (getElementValue(js, button))
|
||||
js->buttons[buttonIndex++] = GLFW_PRESS;
|
||||
else
|
||||
js->buttons[buttonIndex++] = GLFW_RELEASE;
|
||||
}
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->hatElements); i++)
|
||||
{
|
||||
_GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
|
||||
CFArrayGetValueAtIndex(js->hatElements, i);
|
||||
|
||||
// Bit fields of button presses for each direction, including nil
|
||||
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
||||
|
||||
long j, value = getElementValue(js, hat);
|
||||
if (value < 0 || value > 8)
|
||||
value = 8;
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
if (directions[value] & (1 << j))
|
||||
js->buttons[buttonIndex++] = GLFW_PRESS;
|
||||
else
|
||||
js->buttons[buttonIndex++] = GLFW_RELEASE;
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
// Callback for user-initiated joystick addition
|
||||
//
|
||||
static void matchCallback(void* context,
|
||||
IOReturn result,
|
||||
void* sender,
|
||||
IOHIDDeviceRef deviceRef)
|
||||
{
|
||||
_GLFWjoystickNS* js;
|
||||
int jid;
|
||||
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (_glfw.ns_js[jid].present && _glfw.ns_js[jid].deviceRef == deviceRef)
|
||||
return;
|
||||
}
|
||||
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (!_glfw.ns_js[jid].present)
|
||||
break;
|
||||
}
|
||||
|
||||
if (jid > GLFW_JOYSTICK_LAST)
|
||||
return;
|
||||
|
||||
js = _glfw.ns_js + jid;
|
||||
js->present = GLFW_TRUE;
|
||||
js->deviceRef = deviceRef;
|
||||
|
||||
CFStringRef name = IOHIDDeviceGetProperty(deviceRef,
|
||||
CFSTR(kIOHIDProductKey));
|
||||
if (name)
|
||||
{
|
||||
CFStringGetCString(name,
|
||||
js->name,
|
||||
sizeof(js->name),
|
||||
kCFStringEncodingUTF8);
|
||||
}
|
||||
else
|
||||
strncpy(js->name, "Unknown", sizeof(js->name));
|
||||
|
||||
js->axisElements = CFArrayCreateMutable(NULL, 0, NULL);
|
||||
js->buttonElements = CFArrayCreateMutable(NULL, 0, NULL);
|
||||
js->hatElements = CFArrayCreateMutable(NULL, 0, NULL);
|
||||
|
||||
CFArrayRef arrayRef = IOHIDDeviceCopyMatchingElements(deviceRef,
|
||||
NULL,
|
||||
kIOHIDOptionsTypeNone);
|
||||
CFRange range = { 0, CFArrayGetCount(arrayRef) };
|
||||
CFArrayApplyFunction(arrayRef,
|
||||
range,
|
||||
getElementsCFArrayHandler,
|
||||
(void*) js);
|
||||
|
||||
CFRelease(arrayRef);
|
||||
|
||||
js->axes = calloc(CFArrayGetCount(js->axisElements), sizeof(float));
|
||||
js->buttons = calloc(CFArrayGetCount(js->buttonElements) +
|
||||
CFArrayGetCount(js->hatElements) * 4, 1);
|
||||
|
||||
_glfwInputJoystickChange(jid, GLFW_CONNECTED);
|
||||
_glfwInputJoystick(js, GLFW_CONNECTED);
|
||||
}
|
||||
|
||||
// Callback for user-initiated joystick removal
|
||||
@@ -332,60 +264,20 @@ static void matchCallback(void* context,
|
||||
static void removeCallback(void* context,
|
||||
IOReturn result,
|
||||
void* sender,
|
||||
IOHIDDeviceRef deviceRef)
|
||||
IOHIDDeviceRef device)
|
||||
{
|
||||
int jid;
|
||||
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (_glfw.ns_js[jid].deviceRef == deviceRef)
|
||||
if (_glfw.joysticks[jid].ns.device == device)
|
||||
{
|
||||
removeJoystick(_glfw.ns_js + jid);
|
||||
closeJoystick(_glfw.joysticks + jid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a dictionary to match against devices with the specified usage page
|
||||
// and usage
|
||||
//
|
||||
static CFMutableDictionaryRef createMatchingDictionary(long usagePage,
|
||||
long usage)
|
||||
{
|
||||
CFMutableDictionaryRef result =
|
||||
CFDictionaryCreateMutable(kCFAllocatorDefault,
|
||||
0,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
if (result)
|
||||
{
|
||||
CFNumberRef pageRef = CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberLongType,
|
||||
&usagePage);
|
||||
if (pageRef)
|
||||
{
|
||||
CFDictionarySetValue(result,
|
||||
CFSTR(kIOHIDDeviceUsagePageKey),
|
||||
pageRef);
|
||||
CFRelease(pageRef);
|
||||
|
||||
CFNumberRef usageRef = CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberLongType,
|
||||
&usage);
|
||||
if (usageRef)
|
||||
{
|
||||
CFDictionarySetValue(result,
|
||||
CFSTR(kIOHIDDeviceUsageKey),
|
||||
usageRef);
|
||||
CFRelease(usageRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
@@ -395,56 +287,73 @@ static CFMutableDictionaryRef createMatchingDictionary(long usagePage,
|
||||
//
|
||||
void _glfwInitJoysticksNS(void)
|
||||
{
|
||||
CFMutableArrayRef matchingCFArrayRef;
|
||||
CFMutableArrayRef matching;
|
||||
const long usages[] =
|
||||
{
|
||||
kHIDUsage_GD_Joystick,
|
||||
kHIDUsage_GD_GamePad,
|
||||
kHIDUsage_GD_MultiAxisController
|
||||
};
|
||||
|
||||
_glfw.ns.hidManager = IOHIDManagerCreate(kCFAllocatorDefault,
|
||||
kIOHIDOptionsTypeNone);
|
||||
|
||||
matchingCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault,
|
||||
0,
|
||||
&kCFTypeArrayCallBacks);
|
||||
if (matchingCFArrayRef)
|
||||
matching = CFArrayCreateMutable(kCFAllocatorDefault,
|
||||
0,
|
||||
&kCFTypeArrayCallBacks);
|
||||
if (!matching)
|
||||
{
|
||||
CFDictionaryRef matchingCFDictRef =
|
||||
createMatchingDictionary(kHIDPage_GenericDesktop,
|
||||
kHIDUsage_GD_Joystick);
|
||||
if (matchingCFDictRef)
|
||||
{
|
||||
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
|
||||
CFRelease(matchingCFDictRef);
|
||||
}
|
||||
|
||||
matchingCFDictRef = createMatchingDictionary(kHIDPage_GenericDesktop,
|
||||
kHIDUsage_GD_GamePad);
|
||||
if (matchingCFDictRef)
|
||||
{
|
||||
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
|
||||
CFRelease(matchingCFDictRef);
|
||||
}
|
||||
|
||||
matchingCFDictRef =
|
||||
createMatchingDictionary(kHIDPage_GenericDesktop,
|
||||
kHIDUsage_GD_MultiAxisController);
|
||||
if (matchingCFDictRef)
|
||||
{
|
||||
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
|
||||
CFRelease(matchingCFDictRef);
|
||||
}
|
||||
|
||||
IOHIDManagerSetDeviceMatchingMultiple(_glfw.ns.hidManager,
|
||||
matchingCFArrayRef);
|
||||
CFRelease(matchingCFArrayRef);
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create array");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < sizeof(usages) / sizeof(long); i++)
|
||||
{
|
||||
const long page = kHIDPage_GenericDesktop;
|
||||
|
||||
CFMutableDictionaryRef dict =
|
||||
CFDictionaryCreateMutable(kCFAllocatorDefault,
|
||||
0,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
if (!dict)
|
||||
continue;
|
||||
|
||||
CFNumberRef pageRef = CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberLongType,
|
||||
&page);
|
||||
CFNumberRef usageRef = CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberLongType,
|
||||
&usages[i]);
|
||||
if (pageRef && usageRef)
|
||||
{
|
||||
CFDictionarySetValue(dict,
|
||||
CFSTR(kIOHIDDeviceUsagePageKey),
|
||||
pageRef);
|
||||
CFDictionarySetValue(dict,
|
||||
CFSTR(kIOHIDDeviceUsageKey),
|
||||
usageRef);
|
||||
CFArrayAppendValue(matching, dict);
|
||||
}
|
||||
|
||||
if (pageRef)
|
||||
CFRelease(pageRef);
|
||||
if (usageRef)
|
||||
CFRelease(usageRef);
|
||||
|
||||
CFRelease(dict);
|
||||
}
|
||||
|
||||
IOHIDManagerSetDeviceMatchingMultiple(_glfw.ns.hidManager, matching);
|
||||
CFRelease(matching);
|
||||
|
||||
IOHIDManagerRegisterDeviceMatchingCallback(_glfw.ns.hidManager,
|
||||
&matchCallback, NULL);
|
||||
IOHIDManagerRegisterDeviceRemovalCallback(_glfw.ns.hidManager,
|
||||
&removeCallback, NULL);
|
||||
|
||||
IOHIDManagerScheduleWithRunLoop(_glfw.ns.hidManager,
|
||||
CFRunLoopGetMain(),
|
||||
kCFRunLoopDefaultMode);
|
||||
|
||||
IOHIDManagerOpen(_glfw.ns.hidManager, kIOHIDOptionsTypeNone);
|
||||
|
||||
// Execute the run loop once in order to register any initially-attached
|
||||
@@ -458,11 +367,8 @@ void _glfwTerminateJoysticksNS(void)
|
||||
{
|
||||
int jid;
|
||||
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
_GLFWjoystickNS* js = _glfw.ns_js + jid;
|
||||
removeJoystick(js);
|
||||
}
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
closeJoystick(_glfw.joysticks + jid);
|
||||
|
||||
CFRelease(_glfw.ns.hidManager);
|
||||
_glfw.ns.hidManager = NULL;
|
||||
@@ -473,39 +379,84 @@ void _glfwTerminateJoysticksNS(void)
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformJoystickPresent(int jid)
|
||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
{
|
||||
_GLFWjoystickNS* js = _glfw.ns_js + jid;
|
||||
if (mode & _GLFW_POLL_AXES)
|
||||
{
|
||||
CFIndex i;
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->ns.axes); i++)
|
||||
{
|
||||
_GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
|
||||
CFArrayGetValueAtIndex(js->ns.axes, i);
|
||||
|
||||
const long raw = getElementValue(js, axis);
|
||||
// Perform auto calibration
|
||||
if (raw < axis->minimum)
|
||||
axis->minimum = raw;
|
||||
if (raw > axis->maximum)
|
||||
axis->maximum = raw;
|
||||
|
||||
const long delta = axis->maximum - axis->minimum;
|
||||
if (delta == 0)
|
||||
_glfwInputJoystickAxis(js, (int) i, 0.f);
|
||||
else
|
||||
{
|
||||
const float value = (2.f * (raw - axis->minimum) / delta) - 1.f;
|
||||
_glfwInputJoystickAxis(js, (int) i, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mode & _GLFW_POLL_BUTTONS)
|
||||
{
|
||||
CFIndex i;
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++)
|
||||
{
|
||||
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
|
||||
CFArrayGetValueAtIndex(js->ns.buttons, i);
|
||||
const char value = getElementValue(js, button) - button->minimum;
|
||||
_glfwInputJoystickButton(js, (int) i, value);
|
||||
}
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
|
||||
{
|
||||
const int states[9] =
|
||||
{
|
||||
GLFW_HAT_UP,
|
||||
GLFW_HAT_RIGHT_UP,
|
||||
GLFW_HAT_RIGHT,
|
||||
GLFW_HAT_RIGHT_DOWN,
|
||||
GLFW_HAT_DOWN,
|
||||
GLFW_HAT_LEFT_DOWN,
|
||||
GLFW_HAT_LEFT,
|
||||
GLFW_HAT_LEFT_UP,
|
||||
GLFW_HAT_CENTERED
|
||||
};
|
||||
|
||||
_GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
|
||||
CFArrayGetValueAtIndex(js->ns.hats, i);
|
||||
long state = getElementValue(js, hat) - hat->minimum;
|
||||
if (state < 0 || state > 8)
|
||||
state = 8;
|
||||
|
||||
_glfwInputJoystickHat(js, (int) i, states[state]);
|
||||
}
|
||||
}
|
||||
|
||||
return js->present;
|
||||
}
|
||||
|
||||
const float* _glfwPlatformGetJoystickAxes(int jid, int* count)
|
||||
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
||||
{
|
||||
_GLFWjoystickNS* js = _glfw.ns_js + jid;
|
||||
if (!pollJoystickAxisEvents(js))
|
||||
return NULL;
|
||||
|
||||
*count = (int) CFArrayGetCount(js->axisElements);
|
||||
return js->axes;
|
||||
}
|
||||
|
||||
const unsigned char* _glfwPlatformGetJoystickButtons(int jid, int* count)
|
||||
{
|
||||
_GLFWjoystickNS* js = _glfw.ns_js + jid;
|
||||
if (!pollJoystickButtonEvents(js))
|
||||
return NULL;
|
||||
|
||||
*count = (int) CFArrayGetCount(js->buttonElements) +
|
||||
(int) CFArrayGetCount(js->hatElements) * 4;
|
||||
return js->buttons;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetJoystickName(int jid)
|
||||
{
|
||||
_GLFWjoystickNS* js = _glfw.ns_js + jid;
|
||||
if (!js->present)
|
||||
return NULL;
|
||||
|
||||
return js->name;
|
||||
if ((strncmp(guid + 4, "000000000000", 12) == 0) &&
|
||||
(strncmp(guid + 20, "000000000000", 12) == 0))
|
||||
{
|
||||
char original[33];
|
||||
strcpy(original, guid);
|
||||
sprintf(guid, "03000000%.4s0000%.4s000000000000",
|
||||
original, original + 16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+131
-71
@@ -48,14 +48,14 @@ static char* getDisplayName(CGDirectDisplayID displayID)
|
||||
IOServiceMatching("IODisplayConnect"),
|
||||
&it) != 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Failed to get display service port iterator");
|
||||
return 0;
|
||||
// This may happen if a desktop Mac is running headless
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((service = IOIteratorNext(it)) != 0)
|
||||
{
|
||||
info = IODisplayCreateInfoDictionary(service, kIODisplayOnlyPreferredName);
|
||||
info = IODisplayCreateInfoDictionary(service,
|
||||
kIODisplayOnlyPreferredName);
|
||||
|
||||
CFNumberRef vendorIDRef =
|
||||
CFDictionaryGetValue(info, CFSTR(kDisplayVendorID));
|
||||
@@ -99,8 +99,6 @@ static char* getDisplayName(CGDirectDisplayID displayID)
|
||||
(const void**) &nameRef))
|
||||
{
|
||||
// This may happen if a desktop Mac is running headless
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Failed to retrieve display name");
|
||||
CFRelease(info);
|
||||
return NULL;
|
||||
}
|
||||
@@ -128,7 +126,7 @@ static GLFWbool modeIsGood(CGDisplayModeRef mode)
|
||||
if (flags & kDisplayModeStretchedFlag)
|
||||
return GLFW_FALSE;
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101200
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
||||
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
|
||||
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) &&
|
||||
CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
|
||||
@@ -159,7 +157,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
|
||||
result.refreshRate = (int) (time.timeScale / (double) time.timeValue);
|
||||
}
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101200
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
||||
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
|
||||
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0)
|
||||
{
|
||||
@@ -175,7 +173,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
|
||||
result.blueBits = 8;
|
||||
}
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101200
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
||||
CFRelease(format);
|
||||
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
|
||||
return result;
|
||||
@@ -188,7 +186,13 @@ static CGDisplayFadeReservationToken beginFadeReservation(void)
|
||||
CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken;
|
||||
|
||||
if (CGAcquireDisplayFadeReservation(5, &token) == kCGErrorSuccess)
|
||||
CGDisplayFade(token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
|
||||
{
|
||||
CGDisplayFade(token, 0.3,
|
||||
kCGDisplayBlendNormal,
|
||||
kCGDisplayBlendSolidColor,
|
||||
0.0, 0.0, 0.0,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
@@ -199,7 +203,11 @@ static void endFadeReservation(CGDisplayFadeReservationToken token)
|
||||
{
|
||||
if (token != kCGDisplayFadeReservationInvalidToken)
|
||||
{
|
||||
CGDisplayFade(token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
|
||||
CGDisplayFade(token, 0.5,
|
||||
kCGDisplayBlendSolidColor,
|
||||
kCGDisplayBlendNormal,
|
||||
0.0, 0.0, 0.0,
|
||||
FALSE);
|
||||
CGReleaseDisplayFadeReservation(token);
|
||||
}
|
||||
}
|
||||
@@ -209,9 +217,77 @@ static void endFadeReservation(CGDisplayFadeReservationToken token)
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Poll for changes in the set of connected monitors
|
||||
//
|
||||
void _glfwPollMonitorsNS(void)
|
||||
{
|
||||
uint32_t i, j, displayCount, disconnectedCount;
|
||||
CGDirectDisplayID* displays;
|
||||
_GLFWmonitor** disconnected = NULL;
|
||||
|
||||
CGGetOnlineDisplayList(0, NULL, &displayCount);
|
||||
displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
||||
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
||||
|
||||
for (i = 0; i < _glfw.monitorCount; i++)
|
||||
_glfw.monitors[i]->ns.screen = nil;
|
||||
|
||||
disconnectedCount = _glfw.monitorCount;
|
||||
if (disconnectedCount)
|
||||
{
|
||||
disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
|
||||
memcpy(disconnected,
|
||||
_glfw.monitors,
|
||||
_glfw.monitorCount * sizeof(_GLFWmonitor*));
|
||||
}
|
||||
|
||||
for (i = 0; i < displayCount; i++)
|
||||
{
|
||||
_GLFWmonitor* monitor;
|
||||
const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]);
|
||||
|
||||
if (CGDisplayIsAsleep(displays[i]))
|
||||
continue;
|
||||
|
||||
for (j = 0; j < disconnectedCount; j++)
|
||||
{
|
||||
// HACK: Compare unit numbers instead of display IDs to work around
|
||||
// display replacement on machines with automatic graphics
|
||||
// switching
|
||||
if (disconnected[j] && disconnected[j]->ns.unitNumber == unitNumber)
|
||||
{
|
||||
disconnected[j] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const CGSize size = CGDisplayScreenSize(displays[i]);
|
||||
char* name = getDisplayName(displays[i]);
|
||||
if (!name)
|
||||
name = _glfw_strdup("Unknown");
|
||||
|
||||
monitor = _glfwAllocMonitor(name, size.width, size.height);
|
||||
monitor->ns.displayID = displays[i];
|
||||
monitor->ns.unitNumber = unitNumber;
|
||||
|
||||
free(name);
|
||||
|
||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
||||
}
|
||||
|
||||
for (i = 0; i < disconnectedCount; i++)
|
||||
{
|
||||
if (disconnected[i])
|
||||
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
|
||||
}
|
||||
|
||||
free(disconnected);
|
||||
free(displays);
|
||||
}
|
||||
|
||||
// Change the current video mode
|
||||
//
|
||||
GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
||||
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
||||
{
|
||||
CFArrayRef modes;
|
||||
CFIndex count, i;
|
||||
@@ -223,7 +299,7 @@ GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
||||
best = _glfwChooseVideoMode(monitor, desired);
|
||||
_glfwPlatformGetVideoMode(monitor, ¤t);
|
||||
if (_glfwCompareVideoModes(¤t, best) == 0)
|
||||
return GLFW_TRUE;
|
||||
return;
|
||||
|
||||
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
|
||||
|
||||
@@ -256,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
|
||||
@@ -288,55 +355,6 @@ void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor)
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
||||
{
|
||||
uint32_t i, found = 0, displayCount;
|
||||
_GLFWmonitor** monitors;
|
||||
CGDirectDisplayID* displays;
|
||||
|
||||
*count = 0;
|
||||
|
||||
CGGetOnlineDisplayList(0, NULL, &displayCount);
|
||||
displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
||||
monitors = calloc(displayCount, sizeof(_GLFWmonitor*));
|
||||
|
||||
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
||||
|
||||
for (i = 0; i < displayCount; i++)
|
||||
{
|
||||
_GLFWmonitor* monitor;
|
||||
|
||||
if (CGDisplayIsAsleep(displays[i]))
|
||||
continue;
|
||||
|
||||
const CGSize size = CGDisplayScreenSize(displays[i]);
|
||||
char* name = getDisplayName(displays[i]);
|
||||
if (!name)
|
||||
name = strdup("Unknown");
|
||||
|
||||
monitor = _glfwAllocMonitor(name, size.width, size.height);
|
||||
monitor->ns.displayID = displays[i];
|
||||
monitor->ns.unitNumber = CGDisplayUnitNumber(displays[i]);
|
||||
|
||||
free(name);
|
||||
|
||||
found++;
|
||||
monitors[found - 1] = monitor;
|
||||
}
|
||||
|
||||
free(displays);
|
||||
|
||||
*count = found;
|
||||
return monitors;
|
||||
}
|
||||
|
||||
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
|
||||
{
|
||||
// HACK: Compare unit numbers instead of display IDs to work around display
|
||||
// replacement on machines with automatic graphics switching
|
||||
return first->ns.unitNumber == second->ns.unitNumber;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
{
|
||||
const CGRect bounds = CGDisplayBounds(monitor->ns.displayID);
|
||||
@@ -347,6 +365,48 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
*ypos = (int) bounds.origin.y;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||
float* xscale, float* yscale)
|
||||
{
|
||||
if (!monitor->ns.screen)
|
||||
{
|
||||
NSUInteger i;
|
||||
NSArray* screens = [NSScreen screens];
|
||||
|
||||
for (i = 0; i < [screens count]; i++)
|
||||
{
|
||||
NSScreen* screen = [screens objectAtIndex:i];
|
||||
NSNumber* displayID =
|
||||
[[screen deviceDescription] objectForKey:@"NSScreenNumber"];
|
||||
|
||||
// HACK: Compare unit numbers instead of display IDs to work around
|
||||
// display replacement on machines with automatic graphics
|
||||
// switching
|
||||
if (monitor->ns.unitNumber ==
|
||||
CGDisplayUnitNumber([displayID unsignedIntValue]))
|
||||
{
|
||||
monitor->ns.screen = screen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == [screens count])
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Failed to find a screen for monitor");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const NSRect points = [monitor->ns.screen frame];
|
||||
const NSRect pixels = [monitor->ns.screen convertRectToBacking:points];
|
||||
|
||||
if (xscale)
|
||||
*xscale = (float) (pixels.size.width / points.size.width);
|
||||
if (yscale)
|
||||
*yscale = (float) (pixels.size.height / points.size.height);
|
||||
}
|
||||
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||
{
|
||||
CFArrayRef modes;
|
||||
|
||||
+19
-13
@@ -24,9 +24,6 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_cocoa_platform_h_
|
||||
#define _glfw3_cocoa_platform_h_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
@@ -51,23 +48,25 @@ typedef struct VkMacOSSurfaceCreateInfoMVK
|
||||
|
||||
typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||
|
||||
#include "posix_tls.h"
|
||||
#include "posix_thread.h"
|
||||
#include "cocoa_joystick.h"
|
||||
#include "nsgl_context.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->ns.view)
|
||||
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS ns
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS ns
|
||||
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeNS ns_time
|
||||
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerNS ns
|
||||
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorNS ns
|
||||
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorNS ns
|
||||
|
||||
#define _GLFW_EGL_CONTEXT_STATE
|
||||
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE
|
||||
|
||||
// HIToolbox.framework pointer typedefs
|
||||
#define kTISPropertyUnicodeKeyLayoutData _glfw.ns.tis.kPropertyUnicodeKeyLayoutData
|
||||
typedef TISInputSourceRef (*PFN_TISCopyCurrentKeyboardLayoutInputSource)(void);
|
||||
@@ -89,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
|
||||
@@ -103,7 +107,7 @@ typedef struct _GLFWlibraryNS
|
||||
CGEventSourceRef eventSource;
|
||||
id delegate;
|
||||
id autoreleasePool;
|
||||
id cursor;
|
||||
GLFWbool cursorHidden;
|
||||
TISInputSourceRef inputSource;
|
||||
IOHIDManagerRef hidManager;
|
||||
id unicodeData;
|
||||
@@ -113,6 +117,7 @@ typedef struct _GLFWlibraryNS
|
||||
short int keycodes[256];
|
||||
short int scancodes[GLFW_KEY_LAST + 1];
|
||||
char* clipboardString;
|
||||
CGPoint cascadePoint;
|
||||
// Where to place the cursor when re-enabled
|
||||
double restoreCursorPosX, restoreCursorPosY;
|
||||
// The window whose disabled cursor mode is active
|
||||
@@ -135,6 +140,7 @@ typedef struct _GLFWmonitorNS
|
||||
CGDirectDisplayID displayID;
|
||||
CGDisplayModeRef previousMode;
|
||||
uint32_t unitNumber;
|
||||
id screen;
|
||||
|
||||
} _GLFWmonitorNS;
|
||||
|
||||
@@ -148,16 +154,16 @@ typedef struct _GLFWcursorNS
|
||||
|
||||
// Cocoa-specific global timer data
|
||||
//
|
||||
typedef struct _GLFWtimeNS
|
||||
typedef struct _GLFWtimerNS
|
||||
{
|
||||
uint64_t frequency;
|
||||
|
||||
} _GLFWtimeNS;
|
||||
} _GLFWtimerNS;
|
||||
|
||||
|
||||
void _glfwInitTimerNS(void);
|
||||
|
||||
GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||
void _glfwPollMonitorsNS(void);
|
||||
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
|
||||
|
||||
#endif // _glfw3_cocoa_platform_h_
|
||||
|
||||
+2
-2
@@ -40,7 +40,7 @@ void _glfwInitTimerNS(void)
|
||||
mach_timebase_info_data_t info;
|
||||
mach_timebase_info(&info);
|
||||
|
||||
_glfw.ns_time.frequency = (info.denom * 1e9) / info.numer;
|
||||
_glfw.timer.ns.frequency = (info.denom * 1e9) / info.numer;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,6 @@ uint64_t _glfwPlatformGetTimerValue(void)
|
||||
|
||||
uint64_t _glfwPlatformGetTimerFrequency(void)
|
||||
{
|
||||
return _glfw.ns_time.frequency;
|
||||
return _glfw.timer.ns.frequency;
|
||||
}
|
||||
|
||||
|
||||
+277
-142
@@ -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
|
||||
@@ -50,29 +51,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
// Returns the specified standard cursor
|
||||
//
|
||||
static NSCursor* getStandardCursor(int shape)
|
||||
{
|
||||
switch (shape)
|
||||
{
|
||||
case GLFW_ARROW_CURSOR:
|
||||
return [NSCursor arrowCursor];
|
||||
case GLFW_IBEAM_CURSOR:
|
||||
return [NSCursor IBeamCursor];
|
||||
case GLFW_CROSSHAIR_CURSOR:
|
||||
return [NSCursor crosshairCursor];
|
||||
case GLFW_HAND_CURSOR:
|
||||
return [NSCursor pointingHandCursor];
|
||||
case GLFW_HRESIZE_CURSOR:
|
||||
return [NSCursor resizeLeftRightCursor];
|
||||
case GLFW_VRESIZE_CURSOR:
|
||||
return [NSCursor resizeUpDownCursor];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Returns the style mask corresponding to the window settings
|
||||
//
|
||||
static NSUInteger getStyleMask(_GLFWwindow* window)
|
||||
@@ -111,19 +89,43 @@ static GLFWbool cursorInClientArea(_GLFWwindow* window)
|
||||
return [window->ns.view mouse:pos inRect:[window->ns.view frame]];
|
||||
}
|
||||
|
||||
// Hides the cursor if not already hidden
|
||||
//
|
||||
static void hideCursor(_GLFWwindow* window)
|
||||
{
|
||||
if (!_glfw.ns.cursorHidden)
|
||||
{
|
||||
[NSCursor hide];
|
||||
_glfw.ns.cursorHidden = GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Shows the cursor if not already shown
|
||||
//
|
||||
static void showCursor(_GLFWwindow* window)
|
||||
{
|
||||
if (_glfw.ns.cursorHidden)
|
||||
{
|
||||
[NSCursor unhide];
|
||||
_glfw.ns.cursorHidden = GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Updates the cursor image according to its cursor mode
|
||||
//
|
||||
static void updateCursorImage(_GLFWwindow* window)
|
||||
{
|
||||
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
||||
{
|
||||
showCursor(window);
|
||||
|
||||
if (window->cursor)
|
||||
[(NSCursor*) window->cursor->ns.object set];
|
||||
else
|
||||
[[NSCursor arrowCursor] set];
|
||||
}
|
||||
else
|
||||
[(NSCursor*) _glfw.ns.cursor set];
|
||||
hideCursor(window);
|
||||
}
|
||||
|
||||
// Transforms the specified y-coordinate between the CG display and NS screen
|
||||
@@ -136,9 +138,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),
|
||||
@@ -147,8 +149,7 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
|
||||
|
||||
[window->ns.object setFrame:frame display:YES];
|
||||
|
||||
_glfwInputMonitorWindowChange(window->monitor, window);
|
||||
return status;
|
||||
_glfwInputMonitorWindow(window->monitor, window);
|
||||
}
|
||||
|
||||
// Remove the window and restore the original video mode
|
||||
@@ -158,7 +159,7 @@ static void releaseMonitor(_GLFWwindow* window)
|
||||
if (window->monitor->window != window)
|
||||
return;
|
||||
|
||||
_glfwInputMonitorWindowChange(window->monitor, NULL);
|
||||
_glfwInputMonitorWindow(window->monitor, NULL);
|
||||
_glfwRestoreVideoModeNS(window->monitor);
|
||||
}
|
||||
|
||||
@@ -176,6 +177,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;
|
||||
}
|
||||
@@ -227,13 +230,13 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
_GLFWwindow* window;
|
||||
}
|
||||
|
||||
- (id)initWithGlfwWindow:(_GLFWwindow *)initWindow;
|
||||
- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow;
|
||||
|
||||
@end
|
||||
|
||||
@implementation GLFWWindowDelegate
|
||||
|
||||
- (id)initWithGlfwWindow:(_GLFWwindow *)initWindow
|
||||
- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
@@ -266,8 +269,21 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
const NSRect contentRect = [window->ns.view frame];
|
||||
const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
|
||||
|
||||
_glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
|
||||
_glfwInputWindowSize(window, contentRect.size.width, contentRect.size.height);
|
||||
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
|
||||
@@ -340,7 +356,15 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
|
||||
- (void)applicationDidChangeScreenParameters:(NSNotification *) notification
|
||||
{
|
||||
_glfwInputMonitorChange();
|
||||
_GLFWwindow* window;
|
||||
|
||||
for (window = _glfw.windowListHead; window; window = window->next)
|
||||
{
|
||||
if (window->context.client != GLFW_NO_API)
|
||||
[window->context.nsgl.object update];
|
||||
}
|
||||
|
||||
_glfwPollMonitorsNS();
|
||||
}
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)notification
|
||||
@@ -372,27 +396,13 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
NSMutableAttributedString* markedText;
|
||||
}
|
||||
|
||||
- (id)initWithGlfwWindow:(_GLFWwindow *)initWindow;
|
||||
- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow;
|
||||
|
||||
@end
|
||||
|
||||
@implementation GLFWContentView
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
if (self == [GLFWContentView class])
|
||||
{
|
||||
if (_glfw.ns.cursor == nil)
|
||||
{
|
||||
NSImage* data = [[NSImage alloc] initWithSize:NSMakeSize(16, 16)];
|
||||
_glfw.ns.cursor = [[NSCursor alloc] initWithImage:data
|
||||
hotSpot:NSZeroPoint];
|
||||
[data release];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (id)initWithGlfwWindow:(_GLFWwindow *)initWindow
|
||||
- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
@@ -418,7 +428,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
|
||||
- (BOOL)isOpaque
|
||||
{
|
||||
return YES;
|
||||
return [window->ns.object isOpaque];
|
||||
}
|
||||
|
||||
- (BOOL)canBecomeKeyView
|
||||
@@ -438,7 +448,10 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
|
||||
- (id)makeBackingLayer
|
||||
{
|
||||
return window->ns.layer;
|
||||
if (window->ns.layer)
|
||||
return window->ns.layer;
|
||||
|
||||
return [super makeBackingLayer];
|
||||
}
|
||||
|
||||
- (void)cursorUpdate:(NSEvent *)event
|
||||
@@ -534,11 +547,17 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
|
||||
- (void)mouseExited:(NSEvent *)event
|
||||
{
|
||||
if (window->cursorMode == GLFW_CURSOR_HIDDEN)
|
||||
showCursor(window);
|
||||
|
||||
_glfwInputCursorEnter(window, GLFW_FALSE);
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(NSEvent *)event
|
||||
{
|
||||
if (window->cursorMode == GLFW_CURSOR_HIDDEN)
|
||||
hideCursor(window);
|
||||
|
||||
_glfwInputCursorEnter(window, GLFW_TRUE);
|
||||
}
|
||||
|
||||
@@ -547,7 +566,23 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
const NSRect contentRect = [window->ns.view frame];
|
||||
const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
|
||||
|
||||
_glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)drawRect:(NSRect)rect
|
||||
@@ -663,17 +698,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]);
|
||||
@@ -710,10 +745,11 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
selectedRange:(NSRange)selectedRange
|
||||
replacementRange:(NSRange)replacementRange
|
||||
{
|
||||
[markedText release];
|
||||
if ([string isKindOfClass:[NSAttributedString class]])
|
||||
[markedText initWithAttributedString:string];
|
||||
markedText = [[NSMutableAttributedString alloc] initWithAttributedString:string];
|
||||
else
|
||||
[markedText initWithString:string];
|
||||
markedText = [[NSMutableAttributedString alloc] initWithString:string];
|
||||
}
|
||||
|
||||
- (void)unmarkText
|
||||
@@ -792,6 +828,11 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)canBecomeMainWindow
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -800,6 +841,10 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
@interface GLFWApplication : NSApplication
|
||||
{
|
||||
NSArray* nibObjects;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation GLFWApplication
|
||||
@@ -824,53 +869,58 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
- (void)doNothing:(id)object
|
||||
{
|
||||
}
|
||||
|
||||
- (void)loadMainMenu
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 100800
|
||||
[[NSBundle mainBundle] loadNibNamed:@"MainMenu"
|
||||
owner:NSApp
|
||||
topLevelObjects:&nibObjects];
|
||||
#else
|
||||
[[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:NSApp];
|
||||
#endif
|
||||
}
|
||||
@end
|
||||
|
||||
#if defined(_GLFW_USE_MENUBAR)
|
||||
|
||||
// Try to figure out what the calling application is called
|
||||
// Set up the menu bar (manually)
|
||||
// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
|
||||
// could go away at any moment, lots of stuff that really should be
|
||||
// localize(d|able), etc. Add a nib to save us this horror.
|
||||
//
|
||||
static NSString* findAppName(void)
|
||||
static void createMenuBar(void)
|
||||
{
|
||||
size_t i;
|
||||
NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
|
||||
|
||||
// Keys to search for as potential application names
|
||||
NSString* GLFWNameKeys[] =
|
||||
NSString* appName = nil;
|
||||
NSDictionary* bundleInfo = [[NSBundle mainBundle] infoDictionary];
|
||||
NSString* nameKeys[] =
|
||||
{
|
||||
@"CFBundleDisplayName",
|
||||
@"CFBundleName",
|
||||
@"CFBundleExecutable",
|
||||
};
|
||||
|
||||
for (i = 0; i < sizeof(GLFWNameKeys) / sizeof(GLFWNameKeys[0]); i++)
|
||||
// Try to figure out what the calling application is called
|
||||
|
||||
for (i = 0; i < sizeof(nameKeys) / sizeof(nameKeys[0]); i++)
|
||||
{
|
||||
id name = [infoDictionary objectForKey:GLFWNameKeys[i]];
|
||||
id name = [bundleInfo objectForKey:nameKeys[i]];
|
||||
if (name &&
|
||||
[name isKindOfClass:[NSString class]] &&
|
||||
![name isEqualToString:@""])
|
||||
{
|
||||
return name;
|
||||
appName = name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char** progname = _NSGetProgname();
|
||||
if (progname && *progname)
|
||||
return [NSString stringWithUTF8String:*progname];
|
||||
|
||||
// Really shouldn't get here
|
||||
return @"GLFW Application";
|
||||
}
|
||||
|
||||
// Set up the menu bar (manually)
|
||||
// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
|
||||
// could go away at any moment, lots of stuff that really should be
|
||||
// localize(d|able), etc. Loading a nib would save us this horror, but that
|
||||
// doesn't seem like a good thing to require of GLFW users.
|
||||
//
|
||||
static void createMenuBar(void)
|
||||
{
|
||||
NSString* appName = findAppName();
|
||||
if (!appName)
|
||||
{
|
||||
char** progname = _NSGetProgname();
|
||||
if (progname && *progname)
|
||||
appName = [NSString stringWithUTF8String:*progname];
|
||||
else
|
||||
appName = @"GLFW Application";
|
||||
}
|
||||
|
||||
NSMenu* bar = [[NSMenu alloc] init];
|
||||
[NSApp setMainMenu:bar];
|
||||
@@ -937,8 +987,6 @@ static void createMenuBar(void)
|
||||
[NSApp performSelector:setAppleMenuSelector withObject:appMenu];
|
||||
}
|
||||
|
||||
#endif /* _GLFW_USE_MENUBAR */
|
||||
|
||||
// Initialize the Cocoa Application Kit
|
||||
//
|
||||
static GLFWbool initializeAppKit(void)
|
||||
@@ -954,15 +1002,20 @@ static GLFWbool initializeAppKit(void)
|
||||
toTarget:NSApp
|
||||
withObject:nil];
|
||||
|
||||
// In case we are unbundled, make us a proper UI application
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
if (_glfw.hints.init.ns.menubar)
|
||||
{
|
||||
// In case we are unbundled, make us a proper UI application
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
|
||||
#if defined(_GLFW_USE_MENUBAR)
|
||||
// Menu bar setup must go between sharedApplication above and
|
||||
// finishLaunching below, in order to properly emulate the behavior
|
||||
// of NSApplicationMain
|
||||
createMenuBar();
|
||||
#endif
|
||||
// Menu bar setup must go between sharedApplication above and
|
||||
// finishLaunching below, in order to properly emulate the behavior
|
||||
// of NSApplicationMain
|
||||
|
||||
if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
|
||||
[NSApp loadMainMenu];
|
||||
else
|
||||
createMenuBar();
|
||||
}
|
||||
|
||||
// There can only be one application delegate, but we allocate it the
|
||||
// first time a window is created to keep all window code in this file
|
||||
@@ -977,13 +1030,21 @@ static GLFWbool initializeAppKit(void)
|
||||
[NSApp setDelegate:_glfw.ns.delegate];
|
||||
[NSApp run];
|
||||
|
||||
// Press and Hold prevents some keys from emitting repeated characters
|
||||
NSDictionary* defaults =
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],
|
||||
@"ApplePressAndHoldEnabled",
|
||||
nil];
|
||||
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
// Create the Cocoa window
|
||||
//
|
||||
static GLFWbool createNativeWindow(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig)
|
||||
const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
window->ns.delegate = [[GLFWWindowDelegate alloc] initWithGlfwWindow:window];
|
||||
if (window->ns.delegate == nil)
|
||||
@@ -1025,9 +1086,17 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
||||
else
|
||||
{
|
||||
[window->ns.object center];
|
||||
_glfw.ns.cascadePoint =
|
||||
NSPointToCGPoint([window->ns.object cascadeTopLeftFromPoint:
|
||||
NSPointFromCGPoint(_glfw.ns.cascadePoint)]);
|
||||
|
||||
if (wndconfig->resizable)
|
||||
[window->ns.object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
|
||||
{
|
||||
const NSWindowCollectionBehavior behavior =
|
||||
NSWindowCollectionBehaviorFullScreenPrimary |
|
||||
NSWindowCollectionBehaviorManaged;
|
||||
[window->ns.object setCollectionBehavior:behavior];
|
||||
}
|
||||
|
||||
if (wndconfig->floating)
|
||||
[window->ns.object setLevel:NSFloatingWindowLevel];
|
||||
@@ -1036,11 +1105,20 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
||||
[window->ns.object zoom:nil];
|
||||
}
|
||||
|
||||
if (strlen(wndconfig->ns.frameName))
|
||||
[window->ns.object setFrameAutosaveName:[NSString stringWithUTF8String:wndconfig->ns.frameName]];
|
||||
|
||||
window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
|
||||
|
||||
if (wndconfig->ns.retina)
|
||||
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
|
||||
|
||||
if (fbconfig->transparent)
|
||||
{
|
||||
[window->ns.object setOpaque:NO];
|
||||
[window->ns.object setBackgroundColor:[NSColor clearColor]];
|
||||
}
|
||||
|
||||
[window->ns.object setContentView:window->ns.view];
|
||||
[window->ns.object makeFirstResponder:window->ns.view];
|
||||
[window->ns.object setTitle:[NSString stringWithUTF8String:wndconfig->title]];
|
||||
@@ -1048,6 +1126,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;
|
||||
}
|
||||
|
||||
@@ -1064,7 +1145,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
if (!initializeAppKit())
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!createNativeWindow(window, wndconfig))
|
||||
if (!createNativeWindow(window, wndconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (ctxconfig->client != GLFW_NO_API)
|
||||
@@ -1076,10 +1157,19 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
if (!_glfwCreateContextNSGL(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
else
|
||||
else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Cocoa: EGL not available");
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwInitEGL())
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
||||
{
|
||||
if (!_glfwInitOSMesa())
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1087,10 +1177,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
{
|
||||
_glfwPlatformShowWindow(window);
|
||||
_glfwPlatformFocusWindow(window);
|
||||
if (!acquireMonitor(window))
|
||||
return GLFW_FALSE;
|
||||
|
||||
centerCursor(window);
|
||||
acquireMonitor(window);
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
@@ -1125,7 +1212,11 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
|
||||
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char *title)
|
||||
{
|
||||
[window->ns.object setTitle:[NSString stringWithUTF8String:title]];
|
||||
NSString* string = [NSString stringWithUTF8String:title];
|
||||
[window->ns.object setTitle:string];
|
||||
// HACK: Set the miniwindow title explicitly as setTitle: doesn't update it
|
||||
// if the window lacks NSWindowStyleMaskTitled
|
||||
[window->ns.object setMiniwindowTitle:string];
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
||||
@@ -1227,6 +1318,18 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||
*bottom = contentRect.origin.y - frameRect.origin.y;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
||||
float* xscale, float* yscale)
|
||||
{
|
||||
const NSRect points = [window->ns.view frame];
|
||||
const NSRect pixels = [window->ns.view convertRectToBacking:points];
|
||||
|
||||
if (xscale)
|
||||
*xscale = (float) (pixels.size.width / points.size.width);
|
||||
if (yscale)
|
||||
*yscale = (float) (pixels.size.height / points.size.height);
|
||||
}
|
||||
|
||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||
{
|
||||
[window->ns.object miniaturize:nil];
|
||||
@@ -1256,6 +1359,11 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||
[window->ns.object orderOut:nil];
|
||||
}
|
||||
|
||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||
{
|
||||
[NSApp requestUserAttention:NSInformationalRequest];
|
||||
}
|
||||
|
||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||
{
|
||||
// Make us the active application
|
||||
@@ -1297,34 +1405,17 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
if (window->monitor)
|
||||
releaseMonitor(window);
|
||||
|
||||
_glfwInputWindowMonitorChange(window, monitor);
|
||||
_glfwInputWindowMonitor(window, monitor);
|
||||
|
||||
// HACK: Allow the state cached in Cocoa to catch up to reality
|
||||
// TODO: Solve this in a less terrible way
|
||||
_glfwPlatformPollEvents();
|
||||
|
||||
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];
|
||||
@@ -1334,6 +1425,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)
|
||||
{
|
||||
@@ -1361,6 +1458,9 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
[window->ns.object setLevel:NSNormalWindowLevel];
|
||||
|
||||
[window->ns.object setHasShadow:YES];
|
||||
// HACK: Clearing NSWindowStyleMaskTitled resets and disables the window
|
||||
// title property but the miniwindow title property is unaffected
|
||||
[window->ns.object setTitle:[window->ns.object miniwindowTitle]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1384,6 +1484,25 @@ 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];
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
[window->ns.object setStyleMask:getStyleMask(window)];
|
||||
@@ -1403,6 +1522,16 @@ 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)
|
||||
{
|
||||
for (;;)
|
||||
@@ -1525,14 +1654,8 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
||||
updateCursorImage(window);
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetKeyName(int key, int scancode)
|
||||
const char* _glfwPlatformGetScancodeName(int scancode)
|
||||
{
|
||||
if (key != GLFW_KEY_UNKNOWN)
|
||||
scancode = _glfw.ns.scancodes[key];
|
||||
|
||||
if (!_glfwIsPrintable(_glfw.ns.keycodes[scancode]))
|
||||
return NULL;
|
||||
|
||||
UInt32 deadKeyState = 0;
|
||||
UniChar characters[8];
|
||||
UniCharCount characterCount = 0;
|
||||
@@ -1620,7 +1743,19 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||
if (!initializeAppKit())
|
||||
return GLFW_FALSE;
|
||||
|
||||
cursor->ns.object = getStandardCursor(shape);
|
||||
if (shape == GLFW_ARROW_CURSOR)
|
||||
cursor->ns.object = [NSCursor arrowCursor];
|
||||
else if (shape == GLFW_IBEAM_CURSOR)
|
||||
cursor->ns.object = [NSCursor IBeamCursor];
|
||||
else if (shape == GLFW_CROSSHAIR_CURSOR)
|
||||
cursor->ns.object = [NSCursor crosshairCursor];
|
||||
else if (shape == GLFW_HAND_CURSOR)
|
||||
cursor->ns.object = [NSCursor pointingHandCursor];
|
||||
else if (shape == GLFW_HRESIZE_CURSOR)
|
||||
cursor->ns.object = [NSCursor resizeLeftRightCursor];
|
||||
else if (shape == GLFW_VRESIZE_CURSOR)
|
||||
cursor->ns.object = [NSCursor resizeUpDownCursor];
|
||||
|
||||
if (!cursor->ns.object)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
@@ -1644,7 +1779,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];
|
||||
|
||||
@@ -1654,7 +1789,7 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
|
||||
forType:NSStringPboardType];
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
const char* _glfwPlatformGetClipboardString(void)
|
||||
{
|
||||
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
|
||||
|
||||
@@ -1674,7 +1809,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;
|
||||
}
|
||||
|
||||
+60
-22
@@ -38,13 +38,30 @@
|
||||
////// 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_EGL_CONTEXT_API &&
|
||||
ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid context creation API %i",
|
||||
"Invalid context creation API 0x%08X",
|
||||
ctxconfig->source);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
@@ -54,7 +71,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
ctxconfig->client != GLFW_OPENGL_ES_API)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid client API %i",
|
||||
"Invalid client API 0x%08X",
|
||||
ctxconfig->client);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
@@ -84,7 +101,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid OpenGL profile %i",
|
||||
"Invalid OpenGL profile 0x%08X",
|
||||
ctxconfig->profile);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
@@ -133,7 +150,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid context robustness mode %i",
|
||||
"Invalid context robustness mode 0x%08X",
|
||||
ctxconfig->robustness);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
@@ -145,7 +162,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid context release behavior %i",
|
||||
"Invalid context release behavior 0x%08X",
|
||||
ctxconfig->release);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
@@ -154,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)
|
||||
@@ -207,6 +226,9 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
|
||||
// not important to us here, so we count them as one
|
||||
missing++;
|
||||
}
|
||||
|
||||
if (desired->transparent != current->transparent)
|
||||
missing++;
|
||||
}
|
||||
|
||||
// These polynomials make many small channel size differences matter
|
||||
@@ -317,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[] =
|
||||
{
|
||||
@@ -330,11 +355,12 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
||||
NULL
|
||||
};
|
||||
|
||||
window = _glfwPlatformGetCurrentContext();
|
||||
|
||||
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)
|
||||
@@ -342,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;
|
||||
}
|
||||
|
||||
@@ -359,6 +386,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
||||
"OpenGL ES version string retrieval is broken");
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
@@ -390,6 +418,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
||||
"No version found in OpenGL ES version string");
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
@@ -419,6 +448,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
||||
window->context.major, window->context.minor);
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
@@ -434,6 +464,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Entry point retrieval is broken");
|
||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
@@ -540,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;
|
||||
@@ -577,13 +611,14 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions
|
||||
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
_GLFWwindow* previous = _glfwPlatformGetCurrentContext();
|
||||
_GLFWwindow* previous = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -600,7 +635,7 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
|
||||
GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
return (GLFWwindow*) _glfwPlatformGetCurrentContext();
|
||||
return _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
|
||||
@@ -612,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;
|
||||
}
|
||||
|
||||
@@ -625,10 +661,11 @@ GLFWAPI void glfwSwapInterval(int interval)
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
window = _glfwPlatformGetCurrentContext();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -638,21 +675,21 @@ GLFWAPI void glfwSwapInterval(int interval)
|
||||
GLFWAPI int glfwExtensionSupported(const char* extension)
|
||||
{
|
||||
_GLFWwindow* window;
|
||||
|
||||
assert(extension != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
|
||||
window = _glfwPlatformGetCurrentContext();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -708,10 +745,11 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
window = _glfwPlatformGetCurrentContext();
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
+80
-43
@@ -113,7 +113,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
||||
_GLFWfbconfig* u = usableConfigs + usableCount;
|
||||
|
||||
// Only consider RGB(A) EGLConfigs
|
||||
if (!(getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) & EGL_RGB_BUFFER))
|
||||
if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
|
||||
continue;
|
||||
|
||||
// Only consider window EGLConfigs
|
||||
@@ -121,9 +121,25 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
||||
continue;
|
||||
|
||||
#if defined(_GLFW_X11)
|
||||
XVisualInfo vi = {0};
|
||||
|
||||
// Only consider EGLConfigs with associated Visuals
|
||||
if (!getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID))
|
||||
vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
|
||||
if (!vi.visualid)
|
||||
continue;
|
||||
|
||||
if (desired->transparent)
|
||||
{
|
||||
int count;
|
||||
XVisualInfo* vis = XGetVisualInfo(_glfw.x11.display,
|
||||
VisualIDMask, &vi,
|
||||
&count);
|
||||
if (vis)
|
||||
{
|
||||
u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
|
||||
XFree(vis);
|
||||
}
|
||||
}
|
||||
#endif // _GLFW_X11
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
@@ -199,12 +215,12 @@ static void makeContextCurrentEGL(_GLFWwindow* window)
|
||||
}
|
||||
}
|
||||
|
||||
_glfwPlatformSetCurrentContext(window);
|
||||
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||
}
|
||||
|
||||
static void swapBuffersEGL(_GLFWwindow* window)
|
||||
{
|
||||
if (window != _glfwPlatformGetCurrentContext())
|
||||
if (window != _glfwPlatformGetTls(&_glfw.contextSlot))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGL: The context must be current on the calling thread when swapping buffers");
|
||||
@@ -233,7 +249,7 @@ static int extensionSupportedEGL(const char* extension)
|
||||
|
||||
static GLFWglproc getProcAddressEGL(const char* procname)
|
||||
{
|
||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
||||
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
|
||||
if (window->context.egl.client)
|
||||
{
|
||||
@@ -286,11 +302,15 @@ GLFWbool _glfwInitEGL(void)
|
||||
int i;
|
||||
const char* sonames[] =
|
||||
{
|
||||
#if defined(_GLFW_WIN32)
|
||||
#if defined(_GLFW_EGL_LIBRARY)
|
||||
_GLFW_EGL_LIBRARY,
|
||||
#elif defined(_GLFW_WIN32)
|
||||
"libEGL.dll",
|
||||
"EGL.dll",
|
||||
#elif defined(_GLFW_COCOA)
|
||||
"libEGL.dylib",
|
||||
#elif defined(__CYGWIN__)
|
||||
"libEGL-1.so",
|
||||
#else
|
||||
"libEGL.so.1",
|
||||
#endif
|
||||
@@ -401,6 +421,8 @@ GLFWbool _glfwInitEGL(void)
|
||||
extensionSupportedEGL("EGL_KHR_gl_colorspace");
|
||||
_glfw.egl.KHR_get_all_proc_addresses =
|
||||
extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
|
||||
_glfw.egl.KHR_context_flush_control =
|
||||
extensionSupportedEGL("EGL_KHR_context_flush_control");
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
@@ -422,11 +444,11 @@ void _glfwTerminateEGL(void)
|
||||
}
|
||||
}
|
||||
|
||||
#define setEGLattrib(attribName, attribValue) \
|
||||
#define setAttrib(a, v) \
|
||||
{ \
|
||||
attribs[index++] = attribName; \
|
||||
attribs[index++] = attribValue; \
|
||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
attribs[index++] = a; \
|
||||
attribs[index++] = v; \
|
||||
}
|
||||
|
||||
// Create the OpenGL or OpenGL ES context
|
||||
@@ -438,6 +460,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
EGLint attribs[40];
|
||||
EGLConfig config;
|
||||
EGLContext share = NULL;
|
||||
int index = 0;
|
||||
|
||||
if (!_glfw.egl.display)
|
||||
{
|
||||
@@ -478,7 +501,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
|
||||
if (_glfw.egl.KHR_create_context)
|
||||
{
|
||||
int index = 0, mask = 0, flags = 0;
|
||||
int mask = 0, flags = 0;
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
{
|
||||
@@ -489,12 +512,6 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
|
||||
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
||||
mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
|
||||
|
||||
if (_glfw.egl.KHR_create_context_no_error)
|
||||
{
|
||||
if (ctxconfig->noerror)
|
||||
flags |= EGL_CONTEXT_OPENGL_NO_ERROR_KHR;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctxconfig->debug)
|
||||
@@ -504,44 +521,57 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
{
|
||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||
{
|
||||
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||
EGL_NO_RESET_NOTIFICATION_KHR);
|
||||
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||
EGL_NO_RESET_NOTIFICATION_KHR);
|
||||
}
|
||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||
{
|
||||
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||
EGL_LOSE_CONTEXT_ON_RESET_KHR);
|
||||
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||
EGL_LOSE_CONTEXT_ON_RESET_KHR);
|
||||
}
|
||||
|
||||
flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
|
||||
}
|
||||
|
||||
if (ctxconfig->noerror)
|
||||
{
|
||||
if (_glfw.egl.KHR_create_context_no_error)
|
||||
setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
|
||||
}
|
||||
|
||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||
{
|
||||
setEGLattrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
|
||||
setEGLattrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
|
||||
setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
|
||||
setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
|
||||
}
|
||||
|
||||
if (mask)
|
||||
setEGLattrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
|
||||
setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
|
||||
|
||||
if (flags)
|
||||
setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags);
|
||||
|
||||
setEGLattrib(EGL_NONE, EGL_NONE);
|
||||
setAttrib(EGL_CONTEXT_FLAGS_KHR, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
|
||||
|
||||
setEGLattrib(EGL_NONE, EGL_NONE);
|
||||
setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
|
||||
}
|
||||
|
||||
// Context release behaviors (GL_KHR_context_flush_control) are not yet
|
||||
// supported on EGL but are not a hard constraint, so ignore and continue
|
||||
if (_glfw.egl.KHR_context_flush_control)
|
||||
{
|
||||
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||
{
|
||||
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||
EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
|
||||
}
|
||||
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||
{
|
||||
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||
EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
|
||||
}
|
||||
}
|
||||
|
||||
setAttrib(EGL_NONE, EGL_NONE);
|
||||
|
||||
window->context.egl.handle = eglCreateContext(_glfw.egl.display,
|
||||
config, share, attribs);
|
||||
@@ -561,12 +591,10 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
if (fbconfig->sRGB)
|
||||
{
|
||||
if (_glfw.egl.KHR_gl_colorspace)
|
||||
{
|
||||
setEGLattrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
||||
}
|
||||
setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
||||
}
|
||||
|
||||
setEGLattrib(EGL_NONE, EGL_NONE);
|
||||
setAttrib(EGL_NONE, EGL_NONE);
|
||||
}
|
||||
|
||||
window->context.egl.surface =
|
||||
@@ -591,7 +619,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
const char** sonames;
|
||||
const char* es1sonames[] =
|
||||
{
|
||||
#if defined(_GLFW_WIN32)
|
||||
#if defined(_GLFW_GLESV1_LIBRARY)
|
||||
_GLFW_GLESV1_LIBRARY,
|
||||
#elif defined(_GLFW_WIN32)
|
||||
"GLESv1_CM.dll",
|
||||
"libGLES_CM.dll",
|
||||
#elif defined(_GLFW_COCOA)
|
||||
@@ -604,11 +634,15 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
};
|
||||
const char* es2sonames[] =
|
||||
{
|
||||
#if defined(_GLFW_WIN32)
|
||||
#if defined(_GLFW_GLESV2_LIBRARY)
|
||||
_GLFW_GLESV2_LIBRARY,
|
||||
#elif defined(_GLFW_WIN32)
|
||||
"GLESv2.dll",
|
||||
"libGLESv2.dll",
|
||||
#elif defined(_GLFW_COCOA)
|
||||
"libGLESv2.dylib",
|
||||
#elif defined(__CYGWIN__)
|
||||
"libGLESv2-2.so",
|
||||
#else
|
||||
"libGLESv2.so.2",
|
||||
#endif
|
||||
@@ -616,7 +650,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
};
|
||||
const char* glsonames[] =
|
||||
{
|
||||
#if defined(_GLFW_WIN32)
|
||||
#if defined(_GLFW_OPENGL_LIBRARY)
|
||||
_GLFW_OPENGL_LIBRARY,
|
||||
#elif defined(_GLFW_WIN32)
|
||||
#elif defined(_GLFW_COCOA)
|
||||
#else
|
||||
"libGL.so.1",
|
||||
@@ -664,12 +700,13 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
#undef setEGLattrib
|
||||
#undef setAttrib
|
||||
|
||||
// Returns the Visual and depth of the chosen EGLConfig
|
||||
//
|
||||
#if defined(_GLFW_X11)
|
||||
GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig,
|
||||
GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig,
|
||||
Visual** visual, int* depth)
|
||||
{
|
||||
|
||||
+10
-5
@@ -25,15 +25,16 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_egl_context_h_
|
||||
#define _glfw3_egl_context_h_
|
||||
|
||||
#if defined(_GLFW_USE_EGLPLATFORM_H)
|
||||
#include <EGL/eglplatform.h>
|
||||
#elif defined(_GLFW_WIN32)
|
||||
#define EGLAPIENTRY __stdcall
|
||||
typedef HDC EGLNativeDisplayType;
|
||||
typedef HWND EGLNativeWindowType;
|
||||
#elif defined(_GLFW_COCOA)
|
||||
#define EGLAPIENTRY
|
||||
typedef void* EGLNativeDisplayType;
|
||||
typedef id EGLNativeWindowType;
|
||||
#elif defined(_GLFW_X11)
|
||||
#define EGLAPIENTRY
|
||||
typedef Display* EGLNativeDisplayType;
|
||||
@@ -106,6 +107,9 @@ typedef MirEGLNativeWindowType EGLNativeWindowType;
|
||||
#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3
|
||||
#define EGL_GL_COLORSPACE_KHR 0x309d
|
||||
#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
|
||||
#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
|
||||
#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
|
||||
#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
|
||||
|
||||
typedef int EGLint;
|
||||
typedef unsigned int EGLBoolean;
|
||||
@@ -177,6 +181,7 @@ typedef struct _GLFWlibraryEGL
|
||||
GLFWbool KHR_create_context_no_error;
|
||||
GLFWbool KHR_gl_colorspace;
|
||||
GLFWbool KHR_get_all_proc_addresses;
|
||||
GLFWbool KHR_context_flush_control;
|
||||
|
||||
void* handle;
|
||||
|
||||
@@ -206,9 +211,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig);
|
||||
#if defined(_GLFW_X11)
|
||||
GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig,
|
||||
GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig,
|
||||
Visual** visual, int* depth);
|
||||
#endif /*_GLFW_X11*/
|
||||
|
||||
#endif // _glfw3_egl_context_h_
|
||||
|
||||
@@ -55,8 +55,6 @@
|
||||
// Define this to 1 to force use of high-performance GPU on hybrid systems
|
||||
#cmakedefine _GLFW_USE_HYBRID_HPG
|
||||
|
||||
// Define this to 1 if glfwInit should change the current directory
|
||||
#cmakedefine _GLFW_USE_CHDIR
|
||||
// Define this to 1 if glfwCreateWindow should populate the menu bar
|
||||
#cmakedefine _GLFW_USE_MENUBAR
|
||||
// Define this to 1 if xkbcommon supports the compose key
|
||||
#cmakedefine HAVE_XKBCOMMON_COMPOSE_H
|
||||
|
||||
|
||||
+67
-46
@@ -47,7 +47,8 @@ static int getGLXFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
|
||||
|
||||
// Return the GLXFBConfig most closely matching the specified hints
|
||||
//
|
||||
static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result)
|
||||
static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
|
||||
GLXFBConfig* result)
|
||||
{
|
||||
GLXFBConfig* nativeConfigs;
|
||||
_GLFWfbconfig* usableConfigs;
|
||||
@@ -59,12 +60,12 @@ static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* res
|
||||
// HACK: This is a (hopefully temporary) workaround for Chromium
|
||||
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
|
||||
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
|
||||
if (strcmp(vendor, "Chromium") == 0)
|
||||
if (vendor && strcmp(vendor, "Chromium") == 0)
|
||||
trustWindowBit = GLFW_FALSE;
|
||||
|
||||
nativeConfigs =
|
||||
glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
|
||||
if (!nativeCount)
|
||||
if (!nativeConfigs || !nativeCount)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
|
||||
return GLFW_FALSE;
|
||||
@@ -89,6 +90,16 @@ static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* res
|
||||
continue;
|
||||
}
|
||||
|
||||
if (desired->transparent)
|
||||
{
|
||||
XVisualInfo* vi = glXGetVisualFromFBConfig(_glfw.x11.display, n);
|
||||
if (vi)
|
||||
{
|
||||
u->transparent = _glfwIsVisualTransparentX11(vi->visual);
|
||||
XFree(vi);
|
||||
}
|
||||
}
|
||||
|
||||
u->redBits = getGLXFBConfigAttrib(n, GLX_RED_SIZE);
|
||||
u->greenBits = getGLXFBConfigAttrib(n, GLX_GREEN_SIZE);
|
||||
u->blueBits = getGLXFBConfigAttrib(n, GLX_BLUE_SIZE);
|
||||
@@ -165,7 +176,7 @@ static void makeContextCurrentGLX(_GLFWwindow* window)
|
||||
}
|
||||
}
|
||||
|
||||
_glfwPlatformSetCurrentContext(window);
|
||||
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||
}
|
||||
|
||||
static void swapBuffersGLX(_GLFWwindow* window)
|
||||
@@ -175,7 +186,7 @@ static void swapBuffersGLX(_GLFWwindow* window)
|
||||
|
||||
static void swapIntervalGLX(int interval)
|
||||
{
|
||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
||||
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
|
||||
if (_glfw.glx.EXT_swap_control)
|
||||
{
|
||||
@@ -212,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
|
||||
@@ -244,7 +255,9 @@ GLFWbool _glfwInitGLX(void)
|
||||
int i;
|
||||
const char* sonames[] =
|
||||
{
|
||||
#if defined(__CYGWIN__)
|
||||
#if defined(_GLFW_GLX_LIBRARY)
|
||||
_GLFW_GLX_LIBRARY,
|
||||
#elif defined(__CYGWIN__)
|
||||
"libGL-1.so",
|
||||
#else
|
||||
"libGL.so.1",
|
||||
@@ -258,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;
|
||||
}
|
||||
@@ -270,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 ||
|
||||
@@ -397,6 +410,9 @@ GLFWbool _glfwInitGLX(void)
|
||||
if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))
|
||||
_glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE;
|
||||
|
||||
if (extensionSupportedGLX("GLX_ARB_create_context_no_error"))
|
||||
_glfw.glx.ARB_create_context_no_error = GLFW_TRUE;
|
||||
|
||||
if (extensionSupportedGLX("GLX_ARB_context_flush_control"))
|
||||
_glfw.glx.ARB_context_flush_control = GLFW_TRUE;
|
||||
|
||||
@@ -412,16 +428,16 @@ void _glfwTerminateGLX(void)
|
||||
|
||||
if (_glfw.glx.handle)
|
||||
{
|
||||
dlclose(_glfw.glx.handle);
|
||||
_glfw_dlclose(_glfw.glx.handle);
|
||||
_glfw.glx.handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define setGLXattrib(attribName, attribValue) \
|
||||
#define setAttrib(a, v) \
|
||||
{ \
|
||||
attribs[index++] = attribName; \
|
||||
attribs[index++] = attribValue; \
|
||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
attribs[index++] = a; \
|
||||
attribs[index++] = v; \
|
||||
}
|
||||
|
||||
// Create the OpenGL or OpenGL ES context
|
||||
@@ -498,8 +514,6 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
|
||||
if (ctxconfig->debug)
|
||||
flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
|
||||
if (ctxconfig->noerror)
|
||||
flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;
|
||||
|
||||
if (ctxconfig->robustness)
|
||||
{
|
||||
@@ -507,13 +521,13 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
{
|
||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||
{
|
||||
setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
GLX_NO_RESET_NOTIFICATION_ARB);
|
||||
setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
GLX_NO_RESET_NOTIFICATION_ARB);
|
||||
}
|
||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||
{
|
||||
setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
GLX_LOSE_CONTEXT_ON_RESET_ARB);
|
||||
setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
GLX_LOSE_CONTEXT_ON_RESET_ARB);
|
||||
}
|
||||
|
||||
flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
|
||||
@@ -526,33 +540,39 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
{
|
||||
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||
{
|
||||
setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||
setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||
}
|
||||
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||
{
|
||||
setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
||||
setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ctxconfig->noerror)
|
||||
{
|
||||
if (_glfw.glx.ARB_create_context_no_error)
|
||||
setAttrib(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
|
||||
}
|
||||
|
||||
// NOTE: Only request an explicitly versioned context when necessary, as
|
||||
// explicitly requesting version 1.0 does not always return the
|
||||
// highest version supported by the driver
|
||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||
{
|
||||
setGLXattrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||
setGLXattrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||
setAttrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||
setAttrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||
}
|
||||
|
||||
if (mask)
|
||||
setGLXattrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||
setAttrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||
|
||||
if (flags)
|
||||
setGLXattrib(GLX_CONTEXT_FLAGS_ARB, flags);
|
||||
setAttrib(GLX_CONTEXT_FLAGS_ARB, flags);
|
||||
|
||||
setGLXattrib(None, None);
|
||||
setAttrib(None, None);
|
||||
|
||||
window->context.glx.handle =
|
||||
_glfw.glx.CreateContextAttribsARB(_glfw.x11.display,
|
||||
@@ -609,11 +629,12 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
#undef setGLXattrib
|
||||
#undef setAttrib
|
||||
|
||||
// Returns the Visual and depth of the chosen GLXFBConfig
|
||||
//
|
||||
GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig,
|
||||
GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig,
|
||||
Visual** visual, int* depth)
|
||||
{
|
||||
@@ -636,7 +657,7 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig,
|
||||
}
|
||||
|
||||
*visual = result->visual;
|
||||
*depth = result->depth;
|
||||
*depth = result->depth;
|
||||
|
||||
XFree(result);
|
||||
return GLFW_TRUE;
|
||||
|
||||
+4
-6
@@ -25,9 +25,6 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_glx_context_h_
|
||||
#define _glfw3_glx_context_h_
|
||||
|
||||
#define GLX_VENDOR 1
|
||||
#define GLX_RGBA_BIT 0x00000001
|
||||
#define GLX_WINDOW_BIT 0x00000001
|
||||
@@ -67,6 +64,7 @@
|
||||
#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
|
||||
#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
|
||||
#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
|
||||
#define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
|
||||
|
||||
typedef XID GLXWindow;
|
||||
typedef XID GLXDrawable;
|
||||
@@ -165,19 +163,19 @@ typedef struct _GLFWlibraryGLX
|
||||
GLFWbool ARB_create_context_profile;
|
||||
GLFWbool ARB_create_context_robustness;
|
||||
GLFWbool EXT_create_context_es2_profile;
|
||||
GLFWbool ARB_create_context_no_error;
|
||||
GLFWbool ARB_context_flush_control;
|
||||
|
||||
} _GLFWlibraryGLX;
|
||||
|
||||
|
||||
GLFWbool _glfwInitGLX(void);
|
||||
void _glfwTerminateGLX(void);
|
||||
GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig);
|
||||
void _glfwDestroyContextGLX(_GLFWwindow* window);
|
||||
GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig,
|
||||
GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig,
|
||||
Visual** visual, int* depth);
|
||||
|
||||
#endif // _glfw3_glx_context_h_
|
||||
|
||||
+206
-84
@@ -26,33 +26,42 @@
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
#include "mappings.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
// The three 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
|
||||
// These are documented in internal.h
|
||||
//
|
||||
GLFWbool _glfwInitialized = GLFW_FALSE;
|
||||
_GLFWlibrary _glfw;
|
||||
_GLFWlibrary _glfw = { GLFW_FALSE };
|
||||
|
||||
// This is outside of _glfw so it can be initialized and usable before
|
||||
// glfwInit is called, which lets that function report errors
|
||||
// These are outside of _glfw so they can be used before initialization and
|
||||
// after termination
|
||||
//
|
||||
static GLFWerrorfun _glfwErrorCallback = NULL;
|
||||
|
||||
static _GLFWerror _glfwMainThreadError;
|
||||
static GLFWerrorfun _glfwErrorCallback;
|
||||
static _GLFWinitconfig _glfwInitHints =
|
||||
{
|
||||
GLFW_TRUE, // hat buttons
|
||||
{
|
||||
GLFW_TRUE, // macOS menu bar
|
||||
GLFW_TRUE // macOS bundle chdir
|
||||
}
|
||||
};
|
||||
|
||||
// Returns a generic string representation of the specified error
|
||||
//
|
||||
static const char* getErrorString(int error)
|
||||
static const char* getErrorString(int code)
|
||||
{
|
||||
switch (error)
|
||||
switch (code)
|
||||
{
|
||||
case GLFW_NOT_INITIALIZED:
|
||||
return "The GLFW library is not initialized";
|
||||
@@ -69,7 +78,7 @@ static const char* getErrorString(int error)
|
||||
case GLFW_VERSION_UNAVAILABLE:
|
||||
return "The requested API version is unavailable";
|
||||
case GLFW_PLATFORM_ERROR:
|
||||
return "A platform-specific error occurred";
|
||||
return "An undocumented platform-specific error occurred";
|
||||
case GLFW_FORMAT_UNAVAILABLE:
|
||||
return "The requested format is unavailable";
|
||||
case GLFW_NO_WINDOW_CONTEXT:
|
||||
@@ -79,75 +88,12 @@ static const char* getErrorString(int error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW event API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwInputError(int error, const char* format, ...)
|
||||
{
|
||||
if (_glfwErrorCallback)
|
||||
{
|
||||
char buffer[8192];
|
||||
const char* description;
|
||||
|
||||
if (format)
|
||||
{
|
||||
int count;
|
||||
va_list vl;
|
||||
|
||||
va_start(vl, format);
|
||||
count = vsnprintf(buffer, sizeof(buffer), format, vl);
|
||||
va_end(vl);
|
||||
|
||||
if (count < 0)
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
|
||||
description = buffer;
|
||||
}
|
||||
else
|
||||
description = getErrorString(error);
|
||||
|
||||
_glfwErrorCallback(error, description);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW public API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWAPI int glfwInit(void)
|
||||
{
|
||||
if (_glfwInitialized)
|
||||
return GLFW_TRUE;
|
||||
|
||||
memset(&_glfw, 0, sizeof(_glfw));
|
||||
|
||||
if (!_glfwPlatformInit())
|
||||
{
|
||||
_glfwPlatformTerminate();
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
|
||||
_glfwInitialized = GLFW_TRUE;
|
||||
|
||||
_glfw.timerOffset = _glfwPlatformGetTimerValue();
|
||||
|
||||
// Not all window hints have zero as their default value
|
||||
glfwDefaultWindowHints();
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwTerminate(void)
|
||||
// Terminate the library
|
||||
//
|
||||
static void terminate(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!_glfwInitialized)
|
||||
return;
|
||||
|
||||
memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
|
||||
|
||||
while (_glfw.windowListHead)
|
||||
@@ -161,28 +107,180 @@ GLFWAPI void glfwTerminate(void)
|
||||
_GLFWmonitor* monitor = _glfw.monitors[i];
|
||||
if (monitor->originalRamp.size)
|
||||
_glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
|
||||
_glfwFreeMonitor(monitor);
|
||||
}
|
||||
|
||||
_glfwTerminateVulkan();
|
||||
|
||||
_glfwFreeMonitors(_glfw.monitors, _glfw.monitorCount);
|
||||
free(_glfw.monitors);
|
||||
_glfw.monitors = NULL;
|
||||
_glfw.monitorCount = 0;
|
||||
|
||||
free(_glfw.mappings);
|
||||
_glfw.mappings = NULL;
|
||||
_glfw.mappingCount = 0;
|
||||
|
||||
_glfwTerminateVulkan();
|
||||
_glfwPlatformTerminate();
|
||||
|
||||
_glfw.initialized = GLFW_FALSE;
|
||||
|
||||
while (_glfw.errorListHead)
|
||||
{
|
||||
_GLFWerror* error = _glfw.errorListHead;
|
||||
_glfw.errorListHead = error->next;
|
||||
free(error);
|
||||
}
|
||||
|
||||
_glfwPlatformDestroyTls(&_glfw.contextSlot);
|
||||
_glfwPlatformDestroyTls(&_glfw.errorSlot);
|
||||
_glfwPlatformDestroyMutex(&_glfw.errorLock);
|
||||
|
||||
memset(&_glfw, 0, sizeof(_glfw));
|
||||
_glfwInitialized = GLFW_FALSE;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* _glfw_strdup(const char* source)
|
||||
{
|
||||
const size_t length = strlen(source);
|
||||
char* result = calloc(length + 1, 1);
|
||||
strcpy(result, source);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW event API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Notifies shared code of an error
|
||||
//
|
||||
void _glfwInputError(int code, const char* format, ...)
|
||||
{
|
||||
_GLFWerror* error;
|
||||
char description[_GLFW_MESSAGE_SIZE];
|
||||
|
||||
if (format)
|
||||
{
|
||||
va_list vl;
|
||||
|
||||
va_start(vl, format);
|
||||
vsnprintf(description, sizeof(description), format, vl);
|
||||
va_end(vl);
|
||||
|
||||
description[sizeof(description) - 1] = '\0';
|
||||
}
|
||||
else
|
||||
strcpy(description, getErrorString(code));
|
||||
|
||||
if (_glfw.initialized)
|
||||
{
|
||||
error = _glfwPlatformGetTls(&_glfw.errorSlot);
|
||||
if (!error)
|
||||
{
|
||||
error = calloc(1, sizeof(_GLFWerror));
|
||||
_glfwPlatformSetTls(&_glfw.errorSlot, error);
|
||||
_glfwPlatformLockMutex(&_glfw.errorLock);
|
||||
error->next = _glfw.errorListHead;
|
||||
_glfw.errorListHead = error;
|
||||
_glfwPlatformUnlockMutex(&_glfw.errorLock);
|
||||
}
|
||||
}
|
||||
else
|
||||
error = &_glfwMainThreadError;
|
||||
|
||||
error->code = code;
|
||||
strcpy(error->description, description);
|
||||
|
||||
if (_glfwErrorCallback)
|
||||
_glfwErrorCallback(code, description);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW public API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWAPI int glfwInit(void)
|
||||
{
|
||||
if (_glfw.initialized)
|
||||
return GLFW_TRUE;
|
||||
|
||||
memset(&_glfw, 0, sizeof(_glfw));
|
||||
_glfw.hints.init = _glfwInitHints;
|
||||
|
||||
if (!_glfwPlatformInit())
|
||||
{
|
||||
terminate();
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
|
||||
!_glfwPlatformCreateTls(&_glfw.errorSlot) ||
|
||||
!_glfwPlatformCreateTls(&_glfw.contextSlot))
|
||||
{
|
||||
terminate();
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
|
||||
|
||||
_glfw.initialized = GLFW_TRUE;
|
||||
_glfw.timer.offset = _glfwPlatformGetTimerValue();
|
||||
|
||||
glfwDefaultWindowHints();
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; _glfwDefaultMappings[i]; i++)
|
||||
{
|
||||
if (!glfwUpdateGamepadMappings(_glfwDefaultMappings[i]))
|
||||
{
|
||||
terminate();
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwTerminate(void)
|
||||
{
|
||||
if (!_glfw.initialized)
|
||||
return;
|
||||
|
||||
terminate();
|
||||
}
|
||||
|
||||
GLFWAPI void glfwInitHint(int hint, int value)
|
||||
{
|
||||
switch (hint)
|
||||
{
|
||||
case GLFW_JOYSTICK_HAT_BUTTONS:
|
||||
_glfwInitHints.hatButtons = value;
|
||||
return;
|
||||
case GLFW_COCOA_CHDIR_RESOURCES:
|
||||
_glfwInitHints.ns.chdir = value;
|
||||
return;
|
||||
case GLFW_COCOA_MENUBAR:
|
||||
_glfwInitHints.ns.menubar = value;
|
||||
return;
|
||||
}
|
||||
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid init hint 0x%08X", hint);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
|
||||
{
|
||||
if (major != NULL)
|
||||
*major = GLFW_VERSION_MAJOR;
|
||||
|
||||
if (minor != NULL)
|
||||
*minor = GLFW_VERSION_MINOR;
|
||||
|
||||
if (rev != NULL)
|
||||
*rev = GLFW_VERSION_REVISION;
|
||||
}
|
||||
@@ -192,6 +290,30 @@ GLFWAPI const char* glfwGetVersionString(void)
|
||||
return _glfwPlatformGetVersionString();
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetError(const char** description)
|
||||
{
|
||||
_GLFWerror* error;
|
||||
int code = GLFW_NO_ERROR;
|
||||
|
||||
if (description)
|
||||
*description = NULL;
|
||||
|
||||
if (_glfw.initialized)
|
||||
error = _glfwPlatformGetTls(&_glfw.errorSlot);
|
||||
else
|
||||
error = &_glfwMainThreadError;
|
||||
|
||||
if (error)
|
||||
{
|
||||
code = error->code;
|
||||
error->code = GLFW_NO_ERROR;
|
||||
if (description && code)
|
||||
*description = error->description;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
|
||||
{
|
||||
_GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
|
||||
|
||||
+729
-93
File diff suppressed because it is too large
Load Diff
+251
-578
File diff suppressed because it is too large
Load Diff
+274
-181
@@ -27,9 +27,6 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <linux/joystick.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/inotify.h>
|
||||
@@ -40,129 +37,225 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#endif // __linux__
|
||||
|
||||
#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)
|
||||
{
|
||||
_glfwInputJoystickButton(js,
|
||||
js->linjs.keyMap[code - BTN_MISC],
|
||||
value ? GLFW_PRESS : GLFW_RELEASE);
|
||||
}
|
||||
|
||||
// Apply an EV_ABS event to the specified joystick
|
||||
//
|
||||
static void handleAbsEvent(_GLFWjoystick* js, int code, int value)
|
||||
{
|
||||
const int index = js->linjs.absMap[code];
|
||||
|
||||
if (code >= ABS_HAT0X && code <= ABS_HAT3Y)
|
||||
{
|
||||
static const char stateMap[3][3] =
|
||||
{
|
||||
{ GLFW_HAT_CENTERED, GLFW_HAT_UP, GLFW_HAT_DOWN },
|
||||
{ GLFW_HAT_LEFT, GLFW_HAT_LEFT_UP, GLFW_HAT_LEFT_DOWN },
|
||||
{ GLFW_HAT_RIGHT, GLFW_HAT_RIGHT_UP, GLFW_HAT_RIGHT_DOWN },
|
||||
};
|
||||
|
||||
const int hat = (code - ABS_HAT0X) / 2;
|
||||
const int axis = (code - ABS_HAT0X) % 2;
|
||||
int* state = js->linjs.hats[hat];
|
||||
|
||||
// NOTE: Looking at several input drivers, it seems all hat events use
|
||||
// -1 for left / up, 0 for centered and 1 for right / down
|
||||
if (value == 0)
|
||||
state[axis] = 0;
|
||||
else if (value < 0)
|
||||
state[axis] = 1;
|
||||
else if (value > 0)
|
||||
state[axis] = 2;
|
||||
|
||||
_glfwInputJoystickHat(js, index, stateMap[state[0]][state[1]]);
|
||||
}
|
||||
else
|
||||
{
|
||||
const struct input_absinfo* info = &js->linjs.absInfo[code];
|
||||
float normalized = value;
|
||||
|
||||
const int range = info->maximum - info->minimum;
|
||||
if (range)
|
||||
{
|
||||
// Normalize to 0.0 -> 1.0
|
||||
normalized = (normalized - info->minimum) / range;
|
||||
// Normalize to -1.0 -> 1.0
|
||||
normalized = normalized * 2.0f - 1.0f;
|
||||
}
|
||||
|
||||
_glfwInputJoystickAxis(js, index, normalized);
|
||||
}
|
||||
}
|
||||
|
||||
// Poll state of absolute axes
|
||||
//
|
||||
static void pollAbsState(_GLFWjoystick* js)
|
||||
{
|
||||
int code;
|
||||
|
||||
for (code = 0; code < ABS_CNT; code++)
|
||||
{
|
||||
if (js->linjs.absMap[code] < 0)
|
||||
continue;
|
||||
|
||||
struct input_absinfo* info = &js->linjs.absInfo[code];
|
||||
|
||||
if (ioctl(js->linjs.fd, EVIOCGABS(code), info) < 0)
|
||||
continue;
|
||||
|
||||
handleAbsEvent(js, code, info->value);
|
||||
}
|
||||
}
|
||||
|
||||
#define isBitSet(bit, arr) (arr[(bit) / 8] & (1 << ((bit) % 8)))
|
||||
|
||||
// Attempt to open the specified joystick device
|
||||
//
|
||||
#if defined(__linux__)
|
||||
static GLFWbool openJoystickDevice(const char* path)
|
||||
{
|
||||
char axisCount, buttonCount;
|
||||
int jid, code;
|
||||
char name[256] = "";
|
||||
int jid, fd, version;
|
||||
_GLFWjoystickLinux* js;
|
||||
char guid[33] = "";
|
||||
char evBits[(EV_CNT + 7) / 8] = {0};
|
||||
char keyBits[(KEY_CNT + 7) / 8] = {0};
|
||||
char absBits[(ABS_CNT + 7) / 8] = {0};
|
||||
int axisCount = 0, buttonCount = 0, hatCount = 0;
|
||||
struct input_id id;
|
||||
_GLFWjoystickLinux linjs = {0};
|
||||
_GLFWjoystick* js = NULL;
|
||||
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (!_glfw.linux_js.js[jid].present)
|
||||
if (!_glfw.joysticks[jid].present)
|
||||
continue;
|
||||
|
||||
if (strcmp(_glfw.linux_js.js[jid].path, path) == 0)
|
||||
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (!_glfw.linux_js.js[jid].present)
|
||||
break;
|
||||
}
|
||||
|
||||
if (jid > GLFW_JOYSTICK_LAST)
|
||||
linjs.fd = open(path, O_RDONLY | O_NONBLOCK);
|
||||
if (linjs.fd == -1)
|
||||
return GLFW_FALSE;
|
||||
|
||||
fd = open(path, O_RDONLY | O_NONBLOCK);
|
||||
if (fd == -1)
|
||||
return GLFW_FALSE;
|
||||
|
||||
// Verify that the joystick driver version is at least 1.0
|
||||
ioctl(fd, JSIOCGVERSION, &version);
|
||||
if (version < 0x010000)
|
||||
if (ioctl(linjs.fd, EVIOCGBIT(0, sizeof(evBits)), evBits) < 0 ||
|
||||
ioctl(linjs.fd, EVIOCGBIT(EV_KEY, sizeof(keyBits)), keyBits) < 0 ||
|
||||
ioctl(linjs.fd, EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits) < 0 ||
|
||||
ioctl(linjs.fd, EVIOCGID, &id) < 0)
|
||||
{
|
||||
// It's an old 0.x interface (we don't support it)
|
||||
close(fd);
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Linux: Failed to query input device: %s",
|
||||
strerror(errno));
|
||||
close(linjs.fd);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0)
|
||||
// Ensure this device supports the events expected of a joystick
|
||||
if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits))
|
||||
{
|
||||
close(linjs.fd);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0)
|
||||
strncpy(name, "Unknown", sizeof(name));
|
||||
|
||||
js = _glfw.linux_js.js + jid;
|
||||
js->present = GLFW_TRUE;
|
||||
js->name = strdup(name);
|
||||
js->path = strdup(path);
|
||||
js->fd = fd;
|
||||
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
||||
if (id.vendor && id.product && id.version)
|
||||
{
|
||||
sprintf(guid, "%02x%02x0000%02x%02x0000%02x%02x0000%02x%02x0000",
|
||||
id.bustype & 0xff, id.bustype >> 8,
|
||||
id.vendor & 0xff, id.vendor >> 8,
|
||||
id.product & 0xff, id.product >> 8,
|
||||
id.version & 0xff, id.version >> 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(guid, "%02x%02x0000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
|
||||
id.bustype & 0xff, id.bustype >> 8,
|
||||
name[0], name[1], name[2], name[3],
|
||||
name[4], name[5], name[6], name[7],
|
||||
name[8], name[9], name[10]);
|
||||
}
|
||||
|
||||
ioctl(fd, JSIOCGAXES, &axisCount);
|
||||
js->axisCount = (int) axisCount;
|
||||
js->axes = calloc(axisCount, sizeof(float));
|
||||
for (code = BTN_MISC; code < KEY_CNT; code++)
|
||||
{
|
||||
if (!isBitSet(code, keyBits))
|
||||
continue;
|
||||
|
||||
ioctl(fd, JSIOCGBUTTONS, &buttonCount);
|
||||
js->buttonCount = (int) buttonCount;
|
||||
js->buttons = calloc(buttonCount, 1);
|
||||
linjs.keyMap[code - BTN_MISC] = buttonCount;
|
||||
buttonCount++;
|
||||
}
|
||||
|
||||
_glfwInputJoystickChange(jid, GLFW_CONNECTED);
|
||||
for (code = 0; code < ABS_CNT; code++)
|
||||
{
|
||||
linjs.absMap[code] = -1;
|
||||
if (!isBitSet(code, absBits))
|
||||
continue;
|
||||
|
||||
if (code >= ABS_HAT0X && code <= ABS_HAT3Y)
|
||||
{
|
||||
linjs.absMap[code] = hatCount;
|
||||
hatCount++;
|
||||
// Skip the Y axis
|
||||
code++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ioctl(linjs.fd, EVIOCGABS(code), &linjs.absInfo[code]) < 0)
|
||||
continue;
|
||||
|
||||
linjs.absMap[code] = axisCount;
|
||||
axisCount++;
|
||||
}
|
||||
}
|
||||
|
||||
js = _glfwAllocJoystick(name, guid, axisCount, buttonCount, hatCount);
|
||||
if (!js)
|
||||
{
|
||||
close(linjs.fd);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
strncpy(linjs.path, path, sizeof(linjs.path));
|
||||
memcpy(&js->linjs, &linjs, sizeof(linjs));
|
||||
|
||||
pollAbsState(js);
|
||||
|
||||
_glfwInputJoystick(js, GLFW_CONNECTED);
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
#endif // __linux__
|
||||
|
||||
// Polls for and processes events the specified joystick
|
||||
#undef isBitSet
|
||||
|
||||
// Frees all resources associated with the specified joystick
|
||||
//
|
||||
static GLFWbool pollJoystickEvents(_GLFWjoystickLinux* js)
|
||||
static void closeJoystick(_GLFWjoystick* js)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
_glfwPollJoystickEvents();
|
||||
|
||||
if (!js->present)
|
||||
return GLFW_FALSE;
|
||||
|
||||
// Read all queued events (non-blocking)
|
||||
for (;;)
|
||||
{
|
||||
struct js_event e;
|
||||
|
||||
errno = 0;
|
||||
if (read(js->fd, &e, sizeof(e)) < 0)
|
||||
{
|
||||
// Reset the joystick slot if the device was disconnected
|
||||
if (errno == ENODEV)
|
||||
{
|
||||
free(js->axes);
|
||||
free(js->buttons);
|
||||
free(js->name);
|
||||
free(js->path);
|
||||
|
||||
memset(js, 0, sizeof(_GLFWjoystickLinux));
|
||||
|
||||
_glfwInputJoystickChange(js - _glfw.linux_js.js,
|
||||
GLFW_DISCONNECTED);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Clear the initial-state bit
|
||||
e.type &= ~JS_EVENT_INIT;
|
||||
|
||||
if (e.type == JS_EVENT_AXIS)
|
||||
js->axes[e.number] = (float) e.value / 32767.0f;
|
||||
else if (e.type == JS_EVENT_BUTTON)
|
||||
js->buttons[e.number] = e.value ? GLFW_PRESS : GLFW_RELEASE;
|
||||
}
|
||||
#endif // __linux__
|
||||
return js->present;
|
||||
close(js->linjs.fd);
|
||||
_glfwFreeJoystick(js);
|
||||
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
||||
}
|
||||
|
||||
// Lexically compare joysticks by name; used by qsort
|
||||
//
|
||||
#if defined(__linux__)
|
||||
static int compareJoysticks(const void* fp, const void* sp)
|
||||
{
|
||||
const _GLFWjoystickLinux* fj = fp;
|
||||
const _GLFWjoystickLinux* sj = sp;
|
||||
return strcmp(fj->path, sj->path);
|
||||
const _GLFWjoystick* fj = fp;
|
||||
const _GLFWjoystick* sj = sp;
|
||||
return strcmp(fj->linjs.path, sj->linjs.path);
|
||||
}
|
||||
#endif // __linux__
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -173,36 +266,24 @@ static int compareJoysticks(const void* fp, const void* sp)
|
||||
//
|
||||
GLFWbool _glfwInitJoysticksLinux(void)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
DIR* dir;
|
||||
int count = 0;
|
||||
const char* dirname = "/dev/input";
|
||||
|
||||
_glfw.linux_js.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||
if (_glfw.linux_js.inotify == -1)
|
||||
_glfw.linjs.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||
if (_glfw.linjs.inotify > 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Linux: Failed to initialize inotify: %s",
|
||||
strerror(errno));
|
||||
return GLFW_FALSE;
|
||||
// HACK: Register for IN_ATTRIB to get notified when udev is done
|
||||
// This works well in practice but the true way is libudev
|
||||
|
||||
_glfw.linjs.watch = inotify_add_watch(_glfw.linjs.inotify,
|
||||
dirname,
|
||||
IN_CREATE | IN_ATTRIB | IN_DELETE);
|
||||
}
|
||||
|
||||
// HACK: Register for IN_ATTRIB as well to get notified when udev is done
|
||||
// This works well in practice but the true way is libudev
|
||||
// Continue without device connection notifications if inotify fails
|
||||
|
||||
_glfw.linux_js.watch = inotify_add_watch(_glfw.linux_js.inotify,
|
||||
dirname,
|
||||
IN_CREATE | IN_ATTRIB);
|
||||
if (_glfw.linux_js.watch == -1)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Linux: Failed to watch for joystick connections in %s: %s",
|
||||
dirname,
|
||||
strerror(errno));
|
||||
// Continue without device connection notifications
|
||||
}
|
||||
|
||||
if (regcomp(&_glfw.linux_js.regex, "^js[0-9]\\+$", 0) != 0)
|
||||
if (regcomp(&_glfw.linjs.regex, "^event[0-9]\\+$", 0) != 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
|
||||
return GLFW_FALSE;
|
||||
@@ -215,31 +296,25 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
||||
|
||||
while ((entry = readdir(dir)))
|
||||
{
|
||||
char path[20];
|
||||
regmatch_t match;
|
||||
|
||||
if (regexec(&_glfw.linux_js.regex, entry->d_name, 1, &match, 0) != 0)
|
||||
if (regexec(&_glfw.linjs.regex, entry->d_name, 1, &match, 0) != 0)
|
||||
continue;
|
||||
|
||||
char path[PATH_MAX];
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
|
||||
|
||||
if (openJoystickDevice(path))
|
||||
count++;
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Linux: Failed to open joystick device directory %s: %s",
|
||||
dirname,
|
||||
strerror(errno));
|
||||
// Continue with no joysticks detected
|
||||
}
|
||||
|
||||
qsort(_glfw.linux_js.js, count, sizeof(_GLFWjoystickLinux), compareJoysticks);
|
||||
#endif // __linux__
|
||||
// Continue with no joysticks if enumeration fails
|
||||
|
||||
qsort(_glfw.joysticks, count, sizeof(_GLFWjoystick), compareJoysticks);
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
@@ -247,56 +322,65 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
||||
//
|
||||
void _glfwTerminateJoysticksLinux(void)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
int i;
|
||||
int jid;
|
||||
|
||||
for (i = 0; i <= GLFW_JOYSTICK_LAST; i++)
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (_glfw.linux_js.js[i].present)
|
||||
{
|
||||
close(_glfw.linux_js.js[i].fd);
|
||||
free(_glfw.linux_js.js[i].axes);
|
||||
free(_glfw.linux_js.js[i].buttons);
|
||||
free(_glfw.linux_js.js[i].name);
|
||||
free(_glfw.linux_js.js[i].path);
|
||||
}
|
||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||
if (js->present)
|
||||
closeJoystick(js);
|
||||
}
|
||||
|
||||
regfree(&_glfw.linux_js.regex);
|
||||
regfree(&_glfw.linjs.regex);
|
||||
|
||||
if (_glfw.linux_js.inotify > 0)
|
||||
if (_glfw.linjs.inotify > 0)
|
||||
{
|
||||
if (_glfw.linux_js.watch > 0)
|
||||
inotify_rm_watch(_glfw.linux_js.inotify, _glfw.linux_js.watch);
|
||||
if (_glfw.linjs.watch > 0)
|
||||
inotify_rm_watch(_glfw.linjs.inotify, _glfw.linjs.watch);
|
||||
|
||||
close(_glfw.linux_js.inotify);
|
||||
close(_glfw.linjs.inotify);
|
||||
}
|
||||
#endif // __linux__
|
||||
}
|
||||
|
||||
void _glfwPollJoystickEvents(void)
|
||||
void _glfwDetectJoystickConnectionLinux(void)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
ssize_t offset = 0;
|
||||
char buffer[16384];
|
||||
|
||||
const ssize_t size = read(_glfw.linux_js.inotify, buffer, sizeof(buffer));
|
||||
if (_glfw.linjs.inotify <= 0)
|
||||
return;
|
||||
|
||||
const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer));
|
||||
|
||||
while (size > offset)
|
||||
{
|
||||
regmatch_t match;
|
||||
const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
|
||||
|
||||
if (regexec(&_glfw.linux_js.regex, e->name, 1, &match, 0) == 0)
|
||||
{
|
||||
char path[20];
|
||||
snprintf(path, sizeof(path), "/dev/input/%s", e->name);
|
||||
openJoystickDevice(path);
|
||||
}
|
||||
|
||||
offset += sizeof(struct inotify_event) + e->len;
|
||||
|
||||
if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) != 0)
|
||||
continue;
|
||||
|
||||
char path[PATH_MAX];
|
||||
snprintf(path, sizeof(path), "/dev/input/%s", e->name);
|
||||
|
||||
if (e->mask & (IN_CREATE | IN_ATTRIB))
|
||||
openJoystickDevice(path);
|
||||
else if (e->mask & IN_DELETE)
|
||||
{
|
||||
int jid;
|
||||
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
|
||||
{
|
||||
closeJoystick(_glfw.joysticks + jid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -304,38 +388,47 @@ void _glfwPollJoystickEvents(void)
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformJoystickPresent(int jid)
|
||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
{
|
||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + jid;
|
||||
return pollJoystickEvents(js);
|
||||
// Read all queued events (non-blocking)
|
||||
for (;;)
|
||||
{
|
||||
struct input_event e;
|
||||
|
||||
errno = 0;
|
||||
if (read(js->linjs.fd, &e, sizeof(e)) < 0)
|
||||
{
|
||||
// Reset the joystick slot if the device was disconnected
|
||||
if (errno == ENODEV)
|
||||
closeJoystick(js);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (e.type == EV_SYN)
|
||||
{
|
||||
if (e.code == SYN_DROPPED)
|
||||
_glfw.linjs.dropped = GLFW_TRUE;
|
||||
else if (e.code == SYN_REPORT)
|
||||
{
|
||||
_glfw.linjs.dropped = GLFW_FALSE;
|
||||
pollAbsState(js);
|
||||
}
|
||||
}
|
||||
|
||||
if (_glfw.linjs.dropped)
|
||||
continue;
|
||||
|
||||
if (e.type == EV_KEY)
|
||||
handleKeyEvent(js, e.code, e.value);
|
||||
else if (e.type == EV_ABS)
|
||||
handleAbsEvent(js, e.code, e.value);
|
||||
}
|
||||
|
||||
return js->present;
|
||||
}
|
||||
|
||||
const float* _glfwPlatformGetJoystickAxes(int jid, int* count)
|
||||
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
||||
{
|
||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + jid;
|
||||
if (!pollJoystickEvents(js))
|
||||
return NULL;
|
||||
|
||||
*count = js->axisCount;
|
||||
return js->axes;
|
||||
}
|
||||
|
||||
const unsigned char* _glfwPlatformGetJoystickButtons(int jid, int* count)
|
||||
{
|
||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + jid;
|
||||
if (!pollJoystickEvents(js))
|
||||
return NULL;
|
||||
|
||||
*count = js->buttonCount;
|
||||
return js->buttons;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetJoystickName(int jid)
|
||||
{
|
||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + jid;
|
||||
if (!pollJoystickEvents(js))
|
||||
return NULL;
|
||||
|
||||
return js->name;
|
||||
}
|
||||
|
||||
|
||||
+18
-24
@@ -24,45 +24,39 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_linux_joystick_h_
|
||||
#define _glfw3_linux_joystick_h_
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/limits.h>
|
||||
#include <regex.h>
|
||||
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWjoylistLinux linux_js
|
||||
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickLinux linjs
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWlibraryLinux linjs
|
||||
|
||||
#define _GLFW_PLATFORM_MAPPING_NAME "Linux"
|
||||
|
||||
// Linux-specific joystick data
|
||||
//
|
||||
typedef struct _GLFWjoystickLinux
|
||||
{
|
||||
GLFWbool present;
|
||||
int fd;
|
||||
float* axes;
|
||||
int axisCount;
|
||||
unsigned char* buttons;
|
||||
int buttonCount;
|
||||
char* name;
|
||||
char* path;
|
||||
int fd;
|
||||
char path[PATH_MAX];
|
||||
int keyMap[KEY_CNT - BTN_MISC];
|
||||
int absMap[ABS_CNT];
|
||||
struct input_absinfo absInfo[ABS_CNT];
|
||||
int hats[4][2];
|
||||
} _GLFWjoystickLinux;
|
||||
|
||||
// Linux-specific joystick API data
|
||||
//
|
||||
typedef struct _GLFWjoylistLinux
|
||||
typedef struct _GLFWlibraryLinux
|
||||
{
|
||||
_GLFWjoystickLinux js[GLFW_JOYSTICK_LAST + 1];
|
||||
|
||||
#if defined(__linux__)
|
||||
int inotify;
|
||||
int watch;
|
||||
regex_t regex;
|
||||
#endif /*__linux__*/
|
||||
} _GLFWjoylistLinux;
|
||||
int inotify;
|
||||
int watch;
|
||||
regex_t regex;
|
||||
GLFWbool dropped;
|
||||
} _GLFWlibraryLinux;
|
||||
|
||||
|
||||
GLFWbool _glfwInitJoysticksLinux(void);
|
||||
void _glfwTerminateJoysticksLinux(void);
|
||||
void _glfwDetectJoystickConnectionLinux(void);
|
||||
|
||||
void _glfwPollJoystickEvents(void);
|
||||
|
||||
#endif // _glfw3_linux_joystick_h_
|
||||
|
||||
+478
@@ -0,0 +1,478 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
// As mappings.h.in, this file is used by CMake to produce the mappings.h
|
||||
// header file. If you are adding a GLFW specific gamepad mapping, this is
|
||||
// where to put it.
|
||||
//========================================================================
|
||||
// As mappings.h, this provides all pre-defined gamepad mappings, including
|
||||
// all available in SDL_GameControllerDB. Do not edit this file. Any gamepad
|
||||
// mappings not specific to GLFW should be submitted to SDL_GameControllerDB.
|
||||
// This file can be re-generated from mappings.h.in and the upstream
|
||||
// gamecontrollerdb.txt with the GenerateMappings.cmake script.
|
||||
//========================================================================
|
||||
|
||||
// All gamepad mappings not labeled GLFW are copied from the
|
||||
// SDL_GameControllerDB project under the following license:
|
||||
//
|
||||
// Simple DirectMedia Layer
|
||||
// Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the
|
||||
// use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
const char* _glfwDefaultMappings[] =
|
||||
{
|
||||
"03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,",
|
||||
"03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",
|
||||
"03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",
|
||||
"03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,",
|
||||
"03000000a00500003232000000000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,",
|
||||
"030000008f0e00001200000000000000,Acme,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,",
|
||||
"03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows,",
|
||||
"030000006b1400000055000000000000,bigben ps3padstreetnew,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
|
||||
"0300000066f700000500000000000000,BrutalLegendTest,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows,",
|
||||
"03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
|
||||
"030000005e0400008e02000000000000,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
|
||||
"03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows,",
|
||||
"03000000a306000022f6000000000000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000791d00000103000000000000,Dual Box WII,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
|
||||
"030000004f04000023b3000000000000,Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000341a00000108000000000000,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
|
||||
"030000000d0f00008500000000000000,Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00008400000000000000,Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00008800000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00008700000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"78696e70757403000000000000000000,Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows,",
|
||||
"03000000790000000600000000000000,G-Shark GS-GP702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,",
|
||||
"03000000260900002625000000000000,Gamecube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows,",
|
||||
"030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000280400000140000000000000,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000ffff00000000000000000000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
|
||||
"03000000451300000010000000000000,Generic USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
|
||||
"03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00004900000000000000,Hatsune Miku Sho Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000d81400000862000000000000,HitBox Edition Cthulhu+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00005f00000000000000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00005e00000000000000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00004000000000000000,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00006e00000000000000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00006600000000000000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f0000ee00000000000000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00004d00000000000000,HORIPAD3 A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000250900000017000000000000,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows,",
|
||||
"030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Windows,",
|
||||
"03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
|
||||
"03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
|
||||
"03000000830500006020000000000000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Windows,",
|
||||
"03000000b50700001403000000000000,IMPACT BLACK,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
|
||||
"030000006f0e00002401000000000000,INJUSTICE FightStick for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000491900000204000000000000,Ipega PG-9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",
|
||||
"030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows,",
|
||||
"030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000006d04000018c2000000000000,Logitech F510 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000006d04000019c2000000000000,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000380700005032000000000000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000380700005082000000000000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000380700008433000000000000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000380700008483000000000000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b6,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000380700008134000000000000,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000380700008184000000000000,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000380700008532000000000000,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000380700003888000000000000,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000380700001888000000000000,MadCatz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
|
||||
"03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000008305000031b0000000000000,MaxfireBlaze3,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
|
||||
"03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows,",
|
||||
"03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000008f0e00001030000000000000,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows,",
|
||||
"0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,",
|
||||
"03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Windows,",
|
||||
"03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,",
|
||||
"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
|
||||
"030000004b120000014d000000000000,NYKO AIRFLO,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,leftx:h0.6,lefty:h0.12,rightshoulder:b5,rightstick:a2,righttrigger:b7,rightx:h0.9,righty:h0.4,start:b9,x:b2,y:b3,platform:Windows,",
|
||||
"03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,",
|
||||
"03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
|
||||
"03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000008f0e00007530000000000000,PS (R) Gamepad,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000e30500009605000000000000,PS to USB convert cable,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,",
|
||||
"03000000100800000100000000000000,PS1 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
|
||||
"03000000100800000300000000000000,PS2 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
|
||||
"03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,",
|
||||
"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,",
|
||||
"03000000250900000500000000000000,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,",
|
||||
"03000000100000008200000000000000,PS360+ v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000300f00000011000000000000,QanBa Arcade JoyStick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows,",
|
||||
"03000000300f00001611000000000000,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,",
|
||||
"03000000222c00000020000000000000,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000300f00001210000000000000,QanBa Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,",
|
||||
"03000000341a00000104000000000000,QanBa Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows,",
|
||||
"03000000222c00000223000000000000,Qanba Obsidian Arcade Joystick PS3 Mode,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000222c00000023000000000000,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
|
||||
"030000000d0f00001100000000000000,REAL ARCADE PRO.3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00008b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00008a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00006b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00006a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00007000000000000000,REAL ARCADE PRO.4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00002200000000000000,REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00005c00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000000d0f00005b00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000790000001100000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,",
|
||||
"0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,",
|
||||
"0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,",
|
||||
"030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000006f0e00001e01000000000000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000004f04000003d0000000000000,run'n'drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000a306000023f6000000000000,Saitek Cyborg V.1 Game pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000300f00001201000000000000,Saitek Dual Analog Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
|
||||
"03000000a30600000cff000000000000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,x:b0,y:b1,platform:Windows,",
|
||||
"03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000300f00001001000000000000,Saitek P480 Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
|
||||
"03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows,",
|
||||
"03000000300f00001101000000000000,saitek rumble pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
|
||||
"0300000000050000289b000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000341a00000208000000000000,SL-6555-SBK,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,",
|
||||
"030000008f0e00000800000000000000,SpeedLink Strike FX Wireless,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
|
||||
"03000000ff1100003133000000000000,SVEN X-PAD,a:b2,b:b3,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a4,start:b5,x:b0,y:b1,platform:Windows,",
|
||||
"03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
|
||||
"03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
|
||||
"030000004f04000015b3000000000000,Thrustmaster Dual Analog 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,",
|
||||
"030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows,",
|
||||
"030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,",
|
||||
"03000000666600000488000000000000,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,",
|
||||
"03000000d90400000200000000000000,TwinShock PS2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
|
||||
"03000000380700006652000000000000,UnKnown,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000632500002305000000000000,USB Vibration Joystick (BM),a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
|
||||
"03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||
"03000000450c00002043000000000000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
|
||||
"03000000172700004431000000000000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,",
|
||||
"03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
|
||||
"03000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",
|
||||
"03000000022000000090000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",
|
||||
"03000000102800000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,",
|
||||
"03000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,",
|
||||
"030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X,",
|
||||
"03000000a306000022f6000001030000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"03000000790000000600000000000000,G-Shark GP-702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Mac OS X,",
|
||||
"03000000ad1b000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,",
|
||||
"030000000d0f00005f00000000010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000000d0f00005e00000000010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000000d0f00005f00000000000000,HORI Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000000d0f00005e00000000000000,HORI Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000000d0f00004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000000d0f00006e00000000010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000000d0f00006600000000010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000000d0f00006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000008f0e00001330000011010000,HuiJia SNES Controller,a:b4,b:b2,back:b16,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b12,rightshoulder:b14,start:b18,x:b6,y:b0,platform:Mac OS X,",
|
||||
"03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,",
|
||||
"03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,",
|
||||
"030000006d04000016c2000000020000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000006d04000016c2000000030000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000006d04000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000006d04000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000006d0400001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||
"030000006d04000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"03000000380700005032000000010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"03000000380700005082000000010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X,",
|
||||
"03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,",
|
||||
"03000000d8140000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Mac OS X,",
|
||||
"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,",
|
||||
"030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X,",
|
||||
"030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,",
|
||||
"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,",
|
||||
"030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||
"03000000321500000010000000010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||
"03000000790000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
|
||||
"03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
|
||||
"030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X,",
|
||||
"03000000b40400000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X,",
|
||||
"030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,",
|
||||
"030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"030000005e0400008e02000001000000,Steam Virtual GamePad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||
"03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X,",
|
||||
"03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,",
|
||||
"03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,",
|
||||
"03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,",
|
||||
"03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,",
|
||||
"030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X,",
|
||||
"030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X,",
|
||||
"03000000bd12000015d0000000010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
|
||||
"03000000bd12000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
|
||||
"03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X,",
|
||||
"050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X,",
|
||||
"050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X,",
|
||||
"030000005e0400008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||
"03000000c6240000045d000000000000,Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||
"030000005e040000e302000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||
"030000005e040000d102000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||
"030000005e040000dd02000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||
"030000005e040000e002000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,",
|
||||
"030000005e040000fd02000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,",
|
||||
"030000005e040000ea02000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||
"030000005e040000e002000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,",
|
||||
"03000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,",
|
||||
"03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||
"05000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
|
||||
"03000000022000000090000011010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
|
||||
"05000000c82d00002038000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
|
||||
"03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
|
||||
"05000000c82d00003028000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,",
|
||||
"05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,",
|
||||
"05000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,",
|
||||
"05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,",
|
||||
"030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,",
|
||||
"03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,",
|
||||
"03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",
|
||||
"03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000a306000022f6000011010000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000b40400000a01000000010000,CYPRESS USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,",
|
||||
"03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux,",
|
||||
"030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
|
||||
"030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000006f0e00001304000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:a0,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:a3,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000006f0e00001f01000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000280400000140000000010000,Gravis GamePad Pro USB ,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000008f0e00000610000000010000,GreenAsia Electronics 4Axes 12Keys GamePad ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux,",
|
||||
"030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,",
|
||||
"030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
|
||||
"0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
|
||||
"06000000adde0000efbe000002010000,Hidromancer Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux,",
|
||||
"03000000c9110000f055000011010000,HJC Game GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
|
||||
"030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux,",
|
||||
"030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000000d0f00006a00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000000d0f00006b00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000000d0f00005f00000011010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000000d0f00005e00000011010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000000d0f00006e00000011010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000000d0f00006600000011010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000000d0f00006700000001010000,HORIPAD ONE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000008f0e00001330000010010000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Linux,",
|
||||
"03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,",
|
||||
"050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,",
|
||||
"03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux,",
|
||||
"030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux,",
|
||||
"03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,",
|
||||
"03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
|
||||
"030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000006d04000016c2000011010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000006d04000015c2000010010000,Logitech Logitech Extreme 3D,a:b0,b:b4,back:b6,guide:b8,leftshoulder:b9,leftstick:h0.8,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:h0.2,start:b7,x:b2,y:b5,platform:Linux,",
|
||||
"030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux,",
|
||||
"05000000380700006652000025010000,Mad Catz C.T.R.L.R ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000380700005032000011010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000380700005082000011010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000380700008034000011010000,Mad Catz fightstick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000380700008084000011010000,Mad Catz fightstick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000380700008433000011010000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000380700008483000011010000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller (SFIV),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
|
||||
"03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000380700003888000010010000,MadCatz PC USB Wired Stick 8838,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000780000000600000010010000,Microntek USB Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,",
|
||||
"030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000005e0400008e02000062230000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000005e040000d102000001010000,Microsoft X-Box One pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000005e040000d102000003020000,Microsoft X-Box One pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,",
|
||||
"030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,",
|
||||
"05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,",
|
||||
"030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Linux,",
|
||||
"050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
|
||||
"050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,",
|
||||
"05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
|
||||
"030000000d0500000308000010010000,Nostromo n45 Dual Analog Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,",
|
||||
"03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000005e0400000202000000010000,Old Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,",
|
||||
"05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,",
|
||||
"05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,",
|
||||
"03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",
|
||||
"030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,",
|
||||
"030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
|
||||
"050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
|
||||
"03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000004c0500006802000011810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
|
||||
"050000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:a12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:a13,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
|
||||
"030000004c0500006802000010810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
|
||||
"030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
|
||||
"060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
|
||||
"05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
|
||||
"050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
|
||||
"050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
|
||||
"030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
|
||||
"050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
|
||||
"030000004c050000cc09000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
|
||||
"030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000300f00001211000011010000,QanBa Arcade JoyStick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux,",
|
||||
"030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,",
|
||||
"030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000321500000010000011010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000790000001100000010010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,",
|
||||
"0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,",
|
||||
"0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,",
|
||||
"030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,",
|
||||
"03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux,",
|
||||
"03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,",
|
||||
"03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux,",
|
||||
"03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux,",
|
||||
"03000000f025000021c1000010010000,ShanWan Gioteck PS3 Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",
|
||||
"03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,",
|
||||
"030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,",
|
||||
"030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,",
|
||||
"030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,",
|
||||
"030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux,",
|
||||
"030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,",
|
||||
"03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,",
|
||||
"03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
|
||||
"03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
|
||||
"03000000790000001100000000010000,USB Gamepad1,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux,",
|
||||
"05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,",
|
||||
"030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000005e040000a102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux,",
|
||||
"0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||
"050000005e040000fd02000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",
|
||||
"03000000450c00002043000010010000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
|
||||
"05000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux,",
|
||||
"03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,",
|
||||
"03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||
"64633436313965656664373634323364,Microsoft X-Box 360 pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,",
|
||||
"61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",
|
||||
"4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",
|
||||
"37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",
|
||||
"35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,",
|
||||
"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,",
|
||||
"5477696e20555342204a6f7973746963,Twin USB Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android,",
|
||||
"34356136633366613530316338376136,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android,",
|
||||
"4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS,",
|
||||
"4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS,",
|
||||
"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS,",
|
||||
|
||||
"78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||
"78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||
"78696e70757403000000000000000000,XInput Arcade Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||
"78696e70757404000000000000000000,XInput Flight Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||
"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||
"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||
"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
// As mappings.h.in, this file is used by CMake to produce the mappings.h
|
||||
// header file. If you are adding a GLFW specific gamepad mapping, this is
|
||||
// where to put it.
|
||||
//========================================================================
|
||||
// As mappings.h, this provides all pre-defined gamepad mappings, including
|
||||
// all available in SDL_GameControllerDB. Do not edit this file. Any gamepad
|
||||
// mappings not specific to GLFW should be submitted to SDL_GameControllerDB.
|
||||
// This file can be re-generated from mappings.h.in and the upstream
|
||||
// gamecontrollerdb.txt with the GenerateMappings.cmake script.
|
||||
//========================================================================
|
||||
|
||||
// All gamepad mappings not labeled GLFW are copied from the
|
||||
// SDL_GameControllerDB project under the following license:
|
||||
//
|
||||
// Simple DirectMedia Layer
|
||||
// Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the
|
||||
// use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
const char* _glfwDefaultMappings[] =
|
||||
{
|
||||
@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,",
|
||||
"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
|
||||
};
|
||||
|
||||
+4
-12
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 Mir - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||
// 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
|
||||
@@ -51,6 +51,7 @@ static void createKeyTables(void)
|
||||
_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;
|
||||
@@ -189,18 +190,11 @@ int _glfwPlatformInit(void)
|
||||
|
||||
createKeyTables();
|
||||
|
||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!_glfwInitJoysticksLinux())
|
||||
return GLFW_FALSE;
|
||||
|
||||
_glfwInitTimerPOSIX();
|
||||
|
||||
// Need the default conf for when we set a NULL cursor
|
||||
_glfw.mir.defaultConf = mir_cursor_configuration_from_name(mir_default_cursor_name);
|
||||
_glfw.mir.disabledConf = mir_cursor_configuration_from_name(mir_disabled_cursor_name);
|
||||
|
||||
_glfw.mir.eventQueue = calloc(1, sizeof(EventQueue));
|
||||
_glfwInitEventQueueMir(_glfw.mir.eventQueue);
|
||||
|
||||
@@ -213,6 +207,7 @@ int _glfwPlatformInit(void)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfwPollMonitorsMir();
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
@@ -220,7 +215,6 @@ void _glfwPlatformTerminate(void)
|
||||
{
|
||||
_glfwTerminateEGL();
|
||||
_glfwTerminateJoysticksLinux();
|
||||
_glfwTerminateThreadLocalStoragePOSIX();
|
||||
|
||||
_glfwDeleteEventQueueMir(_glfw.mir.eventQueue);
|
||||
|
||||
@@ -237,9 +231,7 @@ const char* _glfwPlatformGetVersionString(void)
|
||||
#else
|
||||
" gettimeofday"
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
" /dev/js"
|
||||
#endif
|
||||
" evdev"
|
||||
#if defined(_GLFW_BUILD_DLL)
|
||||
" shared"
|
||||
#endif
|
||||
|
||||
+79
-47
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 Mir - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||
// 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
|
||||
@@ -30,53 +30,55 @@
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
||||
// Poll for changes in the set of connected monitors
|
||||
//
|
||||
void _glfwPollMonitorsMir(void)
|
||||
{
|
||||
int i, found = 0;
|
||||
_GLFWmonitor** monitors = NULL;
|
||||
MirDisplayConfiguration* displayConfig =
|
||||
mir_connection_create_display_config(_glfw.mir.connection);
|
||||
int i;
|
||||
MirDisplayConfig* displayConfig =
|
||||
mir_connection_create_display_configuration(_glfw.mir.connection);
|
||||
|
||||
*count = 0;
|
||||
int numOutputs = mir_display_config_get_num_outputs(displayConfig);
|
||||
|
||||
for (i = 0; i < displayConfig->num_outputs; i++)
|
||||
for (i = 0; i < numOutputs; i++)
|
||||
{
|
||||
const MirDisplayOutput* out = displayConfig->outputs + 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 (out->used &&
|
||||
out->connected &&
|
||||
out->num_modes &&
|
||||
out->current_mode < out->num_modes)
|
||||
if (enabled && state == mir_output_connection_state_connected)
|
||||
{
|
||||
found++;
|
||||
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
|
||||
monitors[i] = _glfwAllocMonitor("Unknown",
|
||||
out->physical_width_mm,
|
||||
out->physical_height_mm);
|
||||
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));
|
||||
|
||||
monitors[i]->mir.x = out->position_x;
|
||||
monitors[i]->mir.y = out->position_y;
|
||||
monitors[i]->mir.outputId = out->output_id;
|
||||
monitors[i]->mir.curMode = out->current_mode;
|
||||
_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);
|
||||
|
||||
monitors[i]->modes = _glfwPlatformGetVideoModes(monitors[i],
|
||||
&monitors[i]->modeCount);
|
||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
||||
}
|
||||
}
|
||||
|
||||
mir_display_config_destroy(displayConfig);
|
||||
|
||||
*count = found;
|
||||
return monitors;
|
||||
mir_display_config_release(displayConfig);
|
||||
}
|
||||
|
||||
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
|
||||
{
|
||||
return first->mir.outputId == second->mir.outputId;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
{
|
||||
@@ -86,7 +88,16 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
*ypos = monitor->mir.y;
|
||||
}
|
||||
|
||||
void FillInRGBBitsFromPixelFormat(GLFWvidmode* mode, const MirPixelFormat pf)
|
||||
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)
|
||||
{
|
||||
@@ -123,30 +134,52 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||
{
|
||||
int i;
|
||||
GLFWvidmode* modes = NULL;
|
||||
MirDisplayConfiguration* displayConfig =
|
||||
mir_connection_create_display_config(_glfw.mir.connection);
|
||||
MirDisplayConfig* displayConfig =
|
||||
mir_connection_create_display_configuration(_glfw.mir.connection);
|
||||
|
||||
for (i = 0; i < displayConfig->num_outputs; i++)
|
||||
int numOutputs = mir_display_config_get_num_outputs(displayConfig);
|
||||
|
||||
for (i = 0; i < numOutputs; i++)
|
||||
{
|
||||
const MirDisplayOutput* out = displayConfig->outputs + i;
|
||||
if (out->output_id != monitor->mir.outputId)
|
||||
const MirOutput* output = mir_display_config_get_output(displayConfig, i);
|
||||
int id = mir_output_get_id(output);
|
||||
|
||||
if (id != monitor->mir.outputId)
|
||||
continue;
|
||||
|
||||
modes = calloc(out->num_modes, sizeof(GLFWvidmode));
|
||||
MirOutputConnectionState state = mir_output_get_connection_state(output);
|
||||
bool enabled = mir_output_is_enabled(output);
|
||||
|
||||
for (*found = 0; *found < out->num_modes; (*found)++)
|
||||
// We must have been disconnected
|
||||
if (!enabled || state != mir_output_connection_state_connected)
|
||||
{
|
||||
modes[*found].width = out->modes[*found].horizontal_resolution;
|
||||
modes[*found].height = out->modes[*found].vertical_resolution;
|
||||
modes[*found].refreshRate = out->modes[*found].refresh_rate;
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Monitor no longer connected");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FillInRGBBitsFromPixelFormat(&modes[*found], out->output_formats[*found]);
|
||||
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_destroy(displayConfig);
|
||||
mir_display_config_release(displayConfig);
|
||||
|
||||
return modes;
|
||||
}
|
||||
@@ -179,4 +212,3 @@ GLFWAPI int glfwGetMirMonitor(GLFWmonitor* handle)
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||
return monitor->mir.outputId;
|
||||
}
|
||||
|
||||
|
||||
+17
-20
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 Mir - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||
// 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
|
||||
@@ -24,40 +24,38 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_mir_platform_h_
|
||||
#define _glfw3_mir_platform_h_
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <pthread.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <mir_toolkit/mir_client_library.h>
|
||||
|
||||
typedef VkFlags VkMirSurfaceCreateFlagsKHR;
|
||||
typedef VkFlags VkMirWindowCreateFlagsKHR;
|
||||
|
||||
typedef struct VkMirSurfaceCreateInfoKHR
|
||||
typedef struct VkMirWindowCreateInfoKHR
|
||||
{
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkMirSurfaceCreateFlagsKHR flags;
|
||||
VkMirWindowCreateFlagsKHR flags;
|
||||
MirConnection* connection;
|
||||
MirSurface* mirSurface;
|
||||
} VkMirSurfaceCreateInfoKHR;
|
||||
MirWindow* mirWindow;
|
||||
} VkMirWindowCreateInfoKHR;
|
||||
|
||||
typedef VkResult (APIENTRY *PFN_vkCreateMirSurfaceKHR)(VkInstance,const VkMirSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||
typedef VkResult (APIENTRY *PFN_vkCreateMirWindowKHR)(VkInstance,const VkMirWindowCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(VkPhysicalDevice,uint32_t,MirConnection*);
|
||||
|
||||
#include "posix_tls.h"
|
||||
#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.window)
|
||||
#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
|
||||
@@ -80,10 +78,10 @@ typedef struct EventQueue
|
||||
//
|
||||
typedef struct _GLFWwindowMir
|
||||
{
|
||||
MirSurface* surface;
|
||||
MirWindow* window;
|
||||
int width;
|
||||
int height;
|
||||
MirEGLNativeWindowType window;
|
||||
MirEGLNativeWindowType nativeWindow;
|
||||
_GLFWcursor* currentCursor;
|
||||
|
||||
} _GLFWwindowMir;
|
||||
@@ -105,18 +103,16 @@ typedef struct _GLFWlibraryMir
|
||||
{
|
||||
MirConnection* connection;
|
||||
MirEGLNativeDisplayType display;
|
||||
MirCursorConfiguration* defaultConf;
|
||||
MirCursorConfiguration* disabledConf;
|
||||
EventQueue* eventQueue;
|
||||
|
||||
short int keycodes[256];
|
||||
short int scancodes[GLFW_KEY_LAST + 1];
|
||||
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;
|
||||
_GLFWwindow* disabledCursorWindow;
|
||||
|
||||
} _GLFWlibraryMir;
|
||||
|
||||
@@ -127,10 +123,11 @@ 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);
|
||||
|
||||
#endif // _glfw3_mir_platform_h_
|
||||
|
||||
+189
-142
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 Mir - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||
// 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
|
||||
@@ -89,9 +89,6 @@ static EventNode* dequeueEvent(EventQueue* queue)
|
||||
return node;
|
||||
}
|
||||
|
||||
/* FIXME Soon to be changed upstream mir! So we can use an egl config to figure out
|
||||
the best pixel format!
|
||||
*/
|
||||
static MirPixelFormat findValidPixelFormat(void)
|
||||
{
|
||||
unsigned int i, validFormats, mirPixelFormats = 32;
|
||||
@@ -120,12 +117,16 @@ static int mirModToGLFWMod(uint32_t mods)
|
||||
|
||||
if (mods & mir_input_event_modifier_alt)
|
||||
publicMods |= GLFW_MOD_ALT;
|
||||
else if (mods & mir_input_event_modifier_shift)
|
||||
if (mods & mir_input_event_modifier_shift)
|
||||
publicMods |= GLFW_MOD_SHIFT;
|
||||
else if (mods & mir_input_event_modifier_ctrl)
|
||||
if (mods & mir_input_event_modifier_ctrl)
|
||||
publicMods |= GLFW_MOD_CONTROL;
|
||||
else if (mods & mir_input_event_modifier_meta)
|
||||
if (mods & mir_input_event_modifier_meta)
|
||||
publicMods |= GLFW_MOD_SUPER;
|
||||
if (mods & mir_input_event_modifier_caps_lock)
|
||||
publicMods |= GLFW_MOD_CAPS_LOCK;
|
||||
if (mods & mir_input_event_modifier_num_lock)
|
||||
publicMods |= GLFW_MOD_NUM_LOCK;
|
||||
|
||||
return publicMods;
|
||||
}
|
||||
@@ -283,14 +284,14 @@ static void handleEvent(const MirEvent* event, _GLFWwindow* window)
|
||||
}
|
||||
}
|
||||
|
||||
static void addNewEvent(MirSurface* surface, const MirEvent* event, void* context)
|
||||
static void addNewEvent(MirWindow* window, const MirEvent* event, void* context)
|
||||
{
|
||||
enqueueEvent(event, context);
|
||||
}
|
||||
|
||||
static GLFWbool createSurface(_GLFWwindow* window)
|
||||
static GLFWbool createWindow(_GLFWwindow* window)
|
||||
{
|
||||
MirSurfaceSpec* spec;
|
||||
MirWindowSpec* spec;
|
||||
MirBufferUsage buffer_usage = mir_buffer_usage_hardware;
|
||||
MirPixelFormat pixel_format = findValidPixelFormat();
|
||||
|
||||
@@ -301,40 +302,39 @@ static GLFWbool createSurface(_GLFWwindow* window)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
spec = mir_connection_create_spec_for_normal_surface(_glfw.mir.connection,
|
||||
window->mir.width,
|
||||
window->mir.height,
|
||||
pixel_format);
|
||||
spec = mir_create_normal_window_spec(_glfw.mir.connection,
|
||||
window->mir.width,
|
||||
window->mir.height);
|
||||
|
||||
mir_surface_spec_set_buffer_usage(spec, buffer_usage);
|
||||
mir_surface_spec_set_name(spec, "MirSurface");
|
||||
mir_window_spec_set_pixel_format(spec, pixel_format);
|
||||
mir_window_spec_set_buffer_usage(spec, buffer_usage);
|
||||
|
||||
window->mir.surface = mir_surface_create_sync(spec);
|
||||
mir_surface_spec_release(spec);
|
||||
window->mir.window = mir_create_window_sync(spec);
|
||||
mir_window_spec_release(spec);
|
||||
|
||||
if (!mir_surface_is_valid(window->mir.surface))
|
||||
if (!mir_window_is_valid(window->mir.window))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unable to create surface: %s",
|
||||
mir_surface_get_error_message(window->mir.surface));
|
||||
"Mir: Unable to create window: %s",
|
||||
mir_window_get_error_message(window->mir.window));
|
||||
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
mir_surface_set_event_handler(window->mir.surface, addNewEvent, window);
|
||||
mir_window_set_event_handler(window->mir.window, addNewEvent, window);
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
static void setSurfaceConfinement(_GLFWwindow* window, MirPointerConfinementState state)
|
||||
static void setWindowConfinement(_GLFWwindow* window, MirPointerConfinementState state)
|
||||
{
|
||||
MirSurfaceSpec* spec;
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
||||
mir_surface_spec_set_pointer_confinement(spec, state);
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_pointer_confinement(spec, state);
|
||||
|
||||
mir_surface_apply_spec(window->mir.surface, spec);
|
||||
mir_surface_spec_release(spec);
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -381,12 +381,12 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
GLFWvidmode mode;
|
||||
_glfwPlatformGetVideoMode(window->monitor, &mode);
|
||||
|
||||
mir_surface_set_state(window->mir.surface, mir_surface_state_fullscreen);
|
||||
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 surface size too large: %ix%i",
|
||||
"Mir: Requested window size too large: %ix%i",
|
||||
wndconfig->width, wndconfig->height);
|
||||
|
||||
return GLFW_FALSE;
|
||||
@@ -397,18 +397,29 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
window->mir.height = wndconfig->height;
|
||||
window->mir.currentCursor = NULL;
|
||||
|
||||
if (!createSurface(window))
|
||||
if (!createWindow(window))
|
||||
return GLFW_FALSE;
|
||||
|
||||
window->mir.window = mir_buffer_stream_get_egl_native_window(
|
||||
mir_surface_get_buffer_stream(window->mir.surface));
|
||||
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 (!_glfwInitEGL())
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
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;
|
||||
@@ -419,10 +430,10 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
if (_glfw.mir.disabledCursorWindow == window)
|
||||
_glfw.mir.disabledCursorWindow = NULL;
|
||||
|
||||
if (mir_surface_is_valid(window->mir.surface))
|
||||
if (mir_window_is_valid(window->mir.window))
|
||||
{
|
||||
mir_surface_release_sync(window->mir.surface);
|
||||
window->mir.surface = NULL;
|
||||
mir_window_release_sync(window->mir.window);
|
||||
window->mir.window= NULL;
|
||||
}
|
||||
|
||||
if (window->context.destroy)
|
||||
@@ -431,14 +442,12 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
|
||||
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
||||
{
|
||||
MirSurfaceSpec* spec;
|
||||
const char* e_title = title ? title : "";
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
||||
mir_surface_spec_set_name(spec, e_title);
|
||||
|
||||
mir_surface_apply_spec(window->mir.surface, spec);
|
||||
mir_surface_spec_release(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,
|
||||
@@ -450,22 +459,30 @@ void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
||||
|
||||
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
||||
{
|
||||
MirSurfaceSpec* spec;
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
||||
mir_surface_spec_set_width (spec, width);
|
||||
mir_surface_spec_set_height(spec, height);
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_width (spec, width);
|
||||
mir_window_spec_set_height(spec, height);
|
||||
|
||||
mir_surface_apply_spec(window->mir.surface, spec);
|
||||
mir_surface_spec_release(spec);
|
||||
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)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
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)
|
||||
@@ -502,59 +519,74 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* 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)
|
||||
{
|
||||
MirSurfaceSpec* spec;
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
||||
mir_surface_spec_set_state(spec, mir_surface_state_minimized);
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_state(spec, mir_window_state_minimized);
|
||||
|
||||
mir_surface_apply_spec(window->mir.surface, spec);
|
||||
mir_surface_spec_release(spec);
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
||||
{
|
||||
MirSurfaceSpec* spec;
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
||||
mir_surface_spec_set_state(spec, mir_surface_state_restored);
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_state(spec, mir_window_state_restored);
|
||||
|
||||
mir_surface_apply_spec(window->mir.surface, spec);
|
||||
mir_surface_spec_release(spec);
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||
{
|
||||
MirSurfaceSpec* spec;
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
||||
mir_surface_spec_set_state(spec, mir_surface_state_maximized);
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_state(spec, mir_window_state_maximized);
|
||||
|
||||
mir_surface_apply_spec(window->mir.surface, spec);
|
||||
mir_surface_spec_release(spec);
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||
{
|
||||
MirSurfaceSpec* spec;
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
||||
mir_surface_spec_set_state(spec, mir_surface_state_hidden);
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_state(spec, mir_window_state_hidden);
|
||||
|
||||
mir_surface_apply_spec(window->mir.surface, spec);
|
||||
mir_surface_spec_release(spec);
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||
{
|
||||
MirSurfaceSpec* spec;
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
||||
mir_surface_spec_set_state(spec, mir_surface_state_restored);
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_state(spec, mir_window_state_restored);
|
||||
|
||||
mir_surface_apply_spec(window->mir.surface, spec);
|
||||
mir_surface_spec_release(spec);
|
||||
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)
|
||||
@@ -575,7 +607,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
|
||||
int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
||||
{
|
||||
return mir_surface_get_focus(window->mir.surface) == mir_surface_focused;
|
||||
return mir_window_get_focus_state(window->mir.window) == mir_window_focus_state_focused;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||
@@ -587,12 +619,26 @@ int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||
|
||||
int _glfwPlatformWindowVisible(_GLFWwindow* window)
|
||||
{
|
||||
return mir_surface_get_visibility(window->mir.surface) == mir_surface_visibility_exposed;
|
||||
return mir_window_get_visibility(window->mir.window) == mir_window_visibility_exposed;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||
{
|
||||
return mir_surface_get_state(window->mir.surface) == mir_surface_state_maximized;
|
||||
return mir_window_get_state(window->mir.window) == mir_window_state_maximized;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||
@@ -613,6 +659,15 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
|
||||
{
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformPollEvents(void)
|
||||
{
|
||||
EventNode* node = NULL;
|
||||
@@ -628,7 +683,7 @@ void _glfwPlatformWaitEvents(void)
|
||||
{
|
||||
pthread_mutex_lock(&_glfw.mir.eventMutex);
|
||||
|
||||
if (emptyEventQueue(_glfw.mir.eventQueue))
|
||||
while (emptyEventQueue(_glfw.mir.eventQueue))
|
||||
pthread_cond_wait(&_glfw.mir.eventCond, &_glfw.mir.eventMutex);
|
||||
|
||||
pthread_mutex_unlock(&_glfw.mir.eventMutex);
|
||||
@@ -671,54 +726,40 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
int xhot, int yhot)
|
||||
{
|
||||
MirBufferStream* stream;
|
||||
MirPixelFormat pixel_format = findValidPixelFormat();
|
||||
|
||||
int i_w = image->width;
|
||||
int i_h = image->height;
|
||||
|
||||
if (pixel_format == mir_pixel_format_invalid)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unable to find a correct pixel format");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
stream = mir_connection_create_buffer_stream_sync(_glfw.mir.connection,
|
||||
i_w, i_h,
|
||||
pixel_format,
|
||||
mir_pixel_format_argb_8888,
|
||||
mir_buffer_usage_software);
|
||||
|
||||
cursor->mir.conf = mir_cursor_configuration_from_buffer_stream(stream, xhot, yhot);
|
||||
|
||||
char* dest;
|
||||
unsigned char *pixels;
|
||||
int i, r_stride, bytes_per_pixel, bytes_per_row;
|
||||
|
||||
MirGraphicsRegion region;
|
||||
mir_buffer_stream_get_graphics_region(stream, ®ion);
|
||||
|
||||
// FIXME Figure this out based on the current_pf
|
||||
bytes_per_pixel = 4;
|
||||
bytes_per_row = bytes_per_pixel * i_w;
|
||||
unsigned char* pixels = image->pixels;
|
||||
char* dest = region.vaddr;
|
||||
int i;
|
||||
|
||||
dest = region.vaddr;
|
||||
pixels = image->pixels;
|
||||
|
||||
r_stride = region.stride;
|
||||
|
||||
for (i = 0; i < i_h; i++)
|
||||
for (i = 0; i < i_w * i_h; i++, pixels += 4)
|
||||
{
|
||||
memcpy(dest, pixels, bytes_per_row);
|
||||
dest += r_stride;
|
||||
pixels += r_stride;
|
||||
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;
|
||||
}
|
||||
|
||||
const char* getSystemCursorName(int shape)
|
||||
static const char* getSystemCursorName(int shape)
|
||||
{
|
||||
switch (shape)
|
||||
{
|
||||
@@ -741,17 +782,11 @@ const char* getSystemCursorName(int shape)
|
||||
|
||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||
{
|
||||
const char* cursor_name = getSystemCursorName(shape);
|
||||
cursor->mir.conf = NULL;
|
||||
cursor->mir.customCursor = NULL;
|
||||
cursor->mir.cursorName = getSystemCursorName(shape);
|
||||
|
||||
if (cursor_name)
|
||||
{
|
||||
cursor->mir.conf = mir_cursor_configuration_from_name(cursor_name);
|
||||
cursor->mir.customCursor = NULL;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
return GLFW_FALSE;
|
||||
return cursor->mir.cursorName != NULL;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
||||
@@ -762,21 +797,32 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
||||
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 && cursor->mir.conf)
|
||||
if (cursor)
|
||||
{
|
||||
window->mir.currentCursor = cursor;
|
||||
|
||||
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, cursor->mir.conf));
|
||||
if (cursor->mir.customCursor)
|
||||
if (cursor->mir.cursorName)
|
||||
{
|
||||
mir_buffer_stream_swap_buffers_sync(cursor->mir.customCursor);
|
||||
setCursorNameForWindow(window->mir.window, cursor->mir.cursorName);
|
||||
}
|
||||
else if (cursor->mir.conf)
|
||||
{
|
||||
mir_window_configure_cursor(window->mir.window, cursor->mir.conf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, _glfw.mir.defaultConf));
|
||||
setCursorNameForWindow(window->mir.window, mir_default_cursor_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -797,8 +843,8 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
||||
if (mode == GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
_glfw.mir.disabledCursorWindow = window;
|
||||
setSurfaceConfinement(window, mir_pointer_confined_to_surface);
|
||||
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, _glfw.mir.disabledConf));
|
||||
setWindowConfinement(window, mir_pointer_confined_to_window);
|
||||
setCursorNameForWindow(window->mir.window, mir_disabled_cursor_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -806,7 +852,7 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
||||
if (_glfw.mir.disabledCursorWindow == window)
|
||||
{
|
||||
_glfw.mir.disabledCursorWindow = NULL;
|
||||
setSurfaceConfinement(window, mir_pointer_unconfined);
|
||||
setWindowConfinement(window, mir_pointer_unconfined);
|
||||
}
|
||||
|
||||
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
||||
@@ -815,12 +861,12 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
||||
}
|
||||
else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
|
||||
{
|
||||
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, _glfw.mir.disabledConf));
|
||||
setCursorNameForWindow(window->mir.window, mir_disabled_cursor_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetKeyName(int key, int scancode)
|
||||
const char* _glfwPlatformGetScancodeName(int scancode)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
@@ -832,13 +878,13 @@ int _glfwPlatformGetKeyScancode(int key)
|
||||
return _glfw.mir.scancodes[key];
|
||||
}
|
||||
|
||||
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
|
||||
void _glfwPlatformSetClipboardString(const char* string)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
const char* _glfwPlatformGetClipboardString(void)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
@@ -859,7 +905,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceMirPresentationSupportKHR vkGetPhysicalDeviceMirPresentationSupportKHR =
|
||||
PFN_vkGetPhysicalDeviceMirPresentationSupportKHR
|
||||
vkGetPhysicalDeviceMirPresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceMirPresentationSupportKHR)
|
||||
@@ -880,12 +927,12 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
VkSurfaceKHR* surface)
|
||||
{
|
||||
VkResult err;
|
||||
VkMirSurfaceCreateInfoKHR sci;
|
||||
PFN_vkCreateMirSurfaceKHR vkCreateMirSurfaceKHR;
|
||||
VkMirWindowCreateInfoKHR sci;
|
||||
PFN_vkCreateMirWindowKHR vkCreateMirWindowKHR;
|
||||
|
||||
vkCreateMirSurfaceKHR = (PFN_vkCreateMirSurfaceKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkCreateMirSurfaceKHR");
|
||||
if (!vkCreateMirSurfaceKHR)
|
||||
vkCreateMirWindowKHR = (PFN_vkCreateMirWindowKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkCreateMirWindowKHR");
|
||||
if (!vkCreateMirWindowKHR)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Mir: Vulkan instance missing VK_KHR_mir_surface extension");
|
||||
@@ -895,9 +942,9 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
memset(&sci, 0, sizeof(sci));
|
||||
sci.sType = VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR;
|
||||
sci.connection = _glfw.mir.connection;
|
||||
sci.mirSurface = window->mir.surface;
|
||||
sci.mirWindow = window->mir.window;
|
||||
|
||||
err = vkCreateMirSurfaceKHR(instance, &sci, allocator, surface);
|
||||
err = vkCreateMirWindowKHR(instance, &sci, allocator, surface);
|
||||
if (err)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
@@ -919,10 +966,10 @@ GLFWAPI MirConnection* glfwGetMirDisplay(void)
|
||||
return _glfw.mir.connection;
|
||||
}
|
||||
|
||||
GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* handle)
|
||||
GLFWAPI MirWindow* glfwGetMirWindow(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
return window->mir.surface;
|
||||
return window->mir.window;
|
||||
}
|
||||
|
||||
|
||||
+95
-68
@@ -86,83 +86,67 @@ static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
|
||||
////// GLFW event API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwInputMonitorChange(void)
|
||||
// Notifies shared code of a monitor connection or disconnection
|
||||
//
|
||||
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
|
||||
{
|
||||
int i, j, monitorCount = _glfw.monitorCount;
|
||||
_GLFWmonitor** monitors = _glfw.monitors;
|
||||
|
||||
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
|
||||
|
||||
// Re-use still connected monitor objects
|
||||
|
||||
for (i = 0; i < _glfw.monitorCount; i++)
|
||||
if (action == GLFW_CONNECTED)
|
||||
{
|
||||
for (j = 0; j < monitorCount; j++)
|
||||
_glfw.monitorCount++;
|
||||
_glfw.monitors =
|
||||
realloc(_glfw.monitors, sizeof(_GLFWmonitor*) * _glfw.monitorCount);
|
||||
|
||||
if (placement == _GLFW_INSERT_FIRST)
|
||||
{
|
||||
if (_glfwPlatformIsSameMonitor(_glfw.monitors[i], monitors[j]))
|
||||
{
|
||||
_glfwFreeMonitor(_glfw.monitors[i]);
|
||||
_glfw.monitors[i] = monitors[j];
|
||||
break;
|
||||
}
|
||||
memmove(_glfw.monitors + 1,
|
||||
_glfw.monitors,
|
||||
(_glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
|
||||
_glfw.monitors[0] = monitor;
|
||||
}
|
||||
else
|
||||
_glfw.monitors[_glfw.monitorCount - 1] = monitor;
|
||||
}
|
||||
|
||||
// Find and report disconnected monitors (not in the new list)
|
||||
|
||||
for (i = 0; i < monitorCount; i++)
|
||||
else if (action == GLFW_DISCONNECTED)
|
||||
{
|
||||
int i;
|
||||
_GLFWwindow* window;
|
||||
|
||||
for (j = 0; j < _glfw.monitorCount; j++)
|
||||
{
|
||||
if (monitors[i] == _glfw.monitors[j])
|
||||
break;
|
||||
}
|
||||
|
||||
if (j < _glfw.monitorCount)
|
||||
continue;
|
||||
|
||||
for (window = _glfw.windowListHead; window; window = window->next)
|
||||
{
|
||||
if (window->monitor == monitors[i])
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (_glfw.callbacks.monitor)
|
||||
_glfw.callbacks.monitor((GLFWmonitor*) monitors[i], GLFW_DISCONNECTED);
|
||||
}
|
||||
|
||||
// Find and report newly connected monitors (not in the old list)
|
||||
// Re-used monitor objects are then removed from the old list to avoid
|
||||
// having them destroyed at the end of this function
|
||||
|
||||
for (i = 0; i < _glfw.monitorCount; i++)
|
||||
{
|
||||
for (j = 0; j < monitorCount; j++)
|
||||
for (i = 0; i < _glfw.monitorCount; i++)
|
||||
{
|
||||
if (_glfw.monitors[i] == monitors[j])
|
||||
if (_glfw.monitors[i] == monitor)
|
||||
{
|
||||
monitors[j] = NULL;
|
||||
_glfw.monitorCount--;
|
||||
memmove(_glfw.monitors + i,
|
||||
_glfw.monitors + i + 1,
|
||||
(_glfw.monitorCount - i) * sizeof(_GLFWmonitor*));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j < monitorCount)
|
||||
continue;
|
||||
|
||||
if (_glfw.callbacks.monitor)
|
||||
_glfw.callbacks.monitor((GLFWmonitor*) _glfw.monitors[i], GLFW_CONNECTED);
|
||||
}
|
||||
|
||||
_glfwFreeMonitors(monitors, monitorCount);
|
||||
if (_glfw.callbacks.monitor)
|
||||
_glfw.callbacks.monitor((GLFWmonitor*) monitor, action);
|
||||
|
||||
if (action == GLFW_DISCONNECTED)
|
||||
_glfwFreeMonitor(monitor);
|
||||
}
|
||||
|
||||
void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window)
|
||||
// Notifies shared code that a full screen window has acquired or released
|
||||
// a monitor
|
||||
//
|
||||
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
|
||||
{
|
||||
monitor->window = window;
|
||||
}
|
||||
@@ -172,6 +156,8 @@ void _glfwInputMonitorWindowChange(_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));
|
||||
@@ -179,11 +165,13 @@ _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)
|
||||
@@ -197,6 +185,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));
|
||||
@@ -205,6 +195,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);
|
||||
@@ -214,16 +206,8 @@ void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
|
||||
memset(ramp, 0, sizeof(GLFWgammaramp));
|
||||
}
|
||||
|
||||
void _glfwFreeMonitors(_GLFWmonitor** monitors, int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
_glfwFreeMonitor(monitors[i]);
|
||||
|
||||
free(monitors);
|
||||
}
|
||||
|
||||
// Chooses the video mode most closely matching the desired one
|
||||
//
|
||||
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
|
||||
const GLFWvidmode* desired)
|
||||
{
|
||||
@@ -274,11 +258,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;
|
||||
@@ -306,6 +294,7 @@ void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
|
||||
GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
|
||||
{
|
||||
assert(count != NULL);
|
||||
|
||||
*count = 0;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
@@ -357,6 +346,21 @@ GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int*
|
||||
*heightMM = monitor->heightMM;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* handle,
|
||||
float* xscale, float* yscale)
|
||||
{
|
||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||
assert(monitor != NULL);
|
||||
|
||||
if (xscale)
|
||||
*xscale = 0.f;
|
||||
if (yscale)
|
||||
*yscale = 0.f;
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
_glfwPlatformGetMonitorContentScale(monitor, xscale, yscale);
|
||||
}
|
||||
|
||||
GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
|
||||
{
|
||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||
@@ -366,6 +370,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);
|
||||
@@ -406,6 +428,10 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
|
||||
int i;
|
||||
unsigned short values[256];
|
||||
GLFWgammaramp ramp;
|
||||
assert(handle != NULL);
|
||||
assert(gamma == gamma);
|
||||
assert(gamma >= 0.f);
|
||||
assert(gamma <= FLT_MAX);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
@@ -417,16 +443,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;
|
||||
}
|
||||
@@ -457,6 +483,7 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
|
||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||
assert(monitor != NULL);
|
||||
assert(ramp != NULL);
|
||||
assert(ramp->size > 0);
|
||||
assert(ramp->red != NULL);
|
||||
assert(ramp->green != NULL);
|
||||
assert(ramp->blue != NULL);
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_nsgl_context_h_
|
||||
#define _glfw3_nsgl_context_h_
|
||||
|
||||
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl
|
||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl
|
||||
|
||||
@@ -57,4 +54,3 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
const _GLFWfbconfig* fbconfig);
|
||||
void _glfwDestroyContextNSGL(_GLFWwindow* window);
|
||||
|
||||
#endif // _glfw3_nsgl_context_h_
|
||||
|
||||
+55
-29
@@ -34,7 +34,7 @@ static void makeContextCurrentNSGL(_GLFWwindow* window)
|
||||
else
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
|
||||
_glfwPlatformSetCurrentContext(window);
|
||||
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||
}
|
||||
|
||||
static void swapBuffersNSGL(_GLFWwindow* window)
|
||||
@@ -45,7 +45,7 @@ static void swapBuffersNSGL(_GLFWwindow* window)
|
||||
|
||||
static void swapIntervalNSGL(int interval)
|
||||
{
|
||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
||||
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
|
||||
GLint sync = interval;
|
||||
[window->context.nsgl.object setValues:&sync
|
||||
@@ -119,8 +119,6 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
unsigned int attributeCount = 0;
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
@@ -145,37 +143,59 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
}
|
||||
}
|
||||
|
||||
// Context robustness modes (GL_KHR_robustness) are not yet supported on
|
||||
// Context robustness modes (GL_KHR_robustness) are not yet supported by
|
||||
// macOS but are not a hard constraint, so ignore and continue
|
||||
|
||||
// Context release behaviors (GL_KHR_context_flush_control) are not yet
|
||||
// supported on macOS but are not a hard constraint, so ignore and continue
|
||||
// supported by macOS but are not a hard constraint, so ignore and continue
|
||||
|
||||
#define ADD_ATTR(x) { attributes[attributeCount++] = x; }
|
||||
#define ADD_ATTR2(x, y) { ADD_ATTR(x); ADD_ATTR(y); }
|
||||
// Debug contexts (GL_KHR_debug) are not yet supported by macOS but are not
|
||||
// a hard constraint, so ignore and continue
|
||||
|
||||
// Arbitrary array size here
|
||||
NSOpenGLPixelFormatAttribute attributes[40];
|
||||
// No-error contexts (GL_KHR_no_error) are not yet supported by macOS but
|
||||
// are not a hard constraint, so ignore and continue
|
||||
|
||||
ADD_ATTR(NSOpenGLPFAAccelerated);
|
||||
ADD_ATTR(NSOpenGLPFAClosestPolicy);
|
||||
#define addAttrib(a) \
|
||||
{ \
|
||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
attribs[index++] = a; \
|
||||
}
|
||||
#define setAttrib(a, v) { addAttrib(a); addAttrib(v); }
|
||||
|
||||
NSOpenGLPixelFormatAttribute attribs[40];
|
||||
int index = 0;
|
||||
|
||||
addAttrib(NSOpenGLPFAAccelerated);
|
||||
addAttrib(NSOpenGLPFAClosestPolicy);
|
||||
|
||||
if (ctxconfig->nsgl.offline)
|
||||
{
|
||||
addAttrib(NSOpenGLPFAAllowOfflineRenderers);
|
||||
// NOTE: This replaces the NSSupportsAutomaticGraphicsSwitching key in
|
||||
// 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
|
||||
addAttrib(kCGLPFASupportsAutomaticGraphicsSwitching);
|
||||
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
||||
}
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
|
||||
if (ctxconfig->major >= 4)
|
||||
{
|
||||
ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
|
||||
setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
|
||||
}
|
||||
else
|
||||
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
||||
if (ctxconfig->major >= 3)
|
||||
{
|
||||
ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
|
||||
setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
|
||||
}
|
||||
|
||||
if (ctxconfig->major <= 2)
|
||||
{
|
||||
if (fbconfig->auxBuffers != GLFW_DONT_CARE)
|
||||
ADD_ATTR2(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
|
||||
setAttrib(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
|
||||
|
||||
if (fbconfig->accumRedBits != GLFW_DONT_CARE &&
|
||||
fbconfig->accumGreenBits != GLFW_DONT_CARE &&
|
||||
@@ -187,7 +207,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
fbconfig->accumBlueBits +
|
||||
fbconfig->accumAlphaBits;
|
||||
|
||||
ADD_ATTR2(NSOpenGLPFAAccumSize, accumBits);
|
||||
setAttrib(NSOpenGLPFAAccumSize, accumBits);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,17 +225,17 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
else if (colorBits < 15)
|
||||
colorBits = 15;
|
||||
|
||||
ADD_ATTR2(NSOpenGLPFAColorSize, colorBits);
|
||||
setAttrib(NSOpenGLPFAColorSize, colorBits);
|
||||
}
|
||||
|
||||
if (fbconfig->alphaBits != GLFW_DONT_CARE)
|
||||
ADD_ATTR2(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
|
||||
setAttrib(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
|
||||
|
||||
if (fbconfig->depthBits != GLFW_DONT_CARE)
|
||||
ADD_ATTR2(NSOpenGLPFADepthSize, fbconfig->depthBits);
|
||||
setAttrib(NSOpenGLPFADepthSize, fbconfig->depthBits);
|
||||
|
||||
if (fbconfig->stencilBits != GLFW_DONT_CARE)
|
||||
ADD_ATTR2(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
|
||||
setAttrib(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
|
||||
|
||||
if (fbconfig->stereo)
|
||||
{
|
||||
@@ -224,36 +244,36 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
"NSGL: Stereo rendering is deprecated");
|
||||
return GLFW_FALSE;
|
||||
#else
|
||||
ADD_ATTR(NSOpenGLPFAStereo);
|
||||
addAttrib(NSOpenGLPFAStereo);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (fbconfig->doublebuffer)
|
||||
ADD_ATTR(NSOpenGLPFADoubleBuffer);
|
||||
addAttrib(NSOpenGLPFADoubleBuffer);
|
||||
|
||||
if (fbconfig->samples != GLFW_DONT_CARE)
|
||||
{
|
||||
if (fbconfig->samples == 0)
|
||||
{
|
||||
ADD_ATTR2(NSOpenGLPFASampleBuffers, 0);
|
||||
setAttrib(NSOpenGLPFASampleBuffers, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ADD_ATTR2(NSOpenGLPFASampleBuffers, 1);
|
||||
ADD_ATTR2(NSOpenGLPFASamples, fbconfig->samples);
|
||||
setAttrib(NSOpenGLPFASampleBuffers, 1);
|
||||
setAttrib(NSOpenGLPFASamples, fbconfig->samples);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB
|
||||
// framebuffer, so there's no need (and no way) to request it
|
||||
|
||||
ADD_ATTR(0);
|
||||
addAttrib(0);
|
||||
|
||||
#undef ADD_ATTR
|
||||
#undef ADD_ATTR2
|
||||
#undef addAttrib
|
||||
#undef setAttrib
|
||||
|
||||
window->context.nsgl.pixelFormat =
|
||||
[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
|
||||
[[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
|
||||
if (window->context.nsgl.pixelFormat == nil)
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
@@ -276,6 +296,12 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (fbconfig->transparent)
|
||||
{
|
||||
GLint opaque = 0;
|
||||
[window->context.nsgl.object setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
|
||||
}
|
||||
|
||||
[window->context.nsgl.object setView:window->ns.view];
|
||||
|
||||
window->context.makeCurrent = makeContextCurrentNSGL;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OSMesa - www.glfw.org
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
@@ -34,9 +34,6 @@
|
||||
|
||||
int _glfwPlatformInit(void)
|
||||
{
|
||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
||||
return GLFW_FALSE;
|
||||
|
||||
_glfwInitTimerPOSIX();
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
@@ -44,11 +41,10 @@ int _glfwPlatformInit(void)
|
||||
void _glfwPlatformTerminate(void)
|
||||
{
|
||||
_glfwTerminateOSMesa();
|
||||
_glfwTerminateThreadLocalStoragePOSIX();
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetVersionString(void)
|
||||
{
|
||||
return _GLFW_VERSION_NUMBER " none OSMesa";
|
||||
return _GLFW_VERSION_NUMBER " null OSMesa";
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 POSIX - www.glfw.org
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
@@ -28,41 +27,16 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWbool _glfwInitThreadLocalStoragePOSIX(void)
|
||||
{
|
||||
if (pthread_key_create(&_glfw.posix_tls.context, NULL) != 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"POSIX: Failed to create context TLS");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.posix_tls.allocated = GLFW_TRUE;
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwTerminateThreadLocalStoragePOSIX(void)
|
||||
{
|
||||
if (_glfw.posix_tls.allocated)
|
||||
pthread_key_delete(_glfw.posix_tls.context);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwPlatformSetCurrentContext(_GLFWwindow* context)
|
||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
{
|
||||
pthread_setspecific(_glfw.posix_tls.context, context);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_GLFWwindow* _glfwPlatformGetCurrentContext(void)
|
||||
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
||||
{
|
||||
return pthread_getspecific(_glfw.posix_tls.context);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#define _GLFW_PLATFORM_JOYSTICK_STATE int nulljs
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE int nulljs
|
||||
|
||||
#define _GLFW_PLATFORM_MAPPING_NAME ""
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OSMesa - www.glfw.org
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
@@ -32,22 +32,19 @@
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
||||
{
|
||||
// OSMesa is headless, so no monitors
|
||||
*count = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||
float* xscale, float* yscale)
|
||||
{
|
||||
if (xscale)
|
||||
*xscale = 1.f;
|
||||
if (yscale)
|
||||
*yscale = 1.f;
|
||||
}
|
||||
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||
{
|
||||
return NULL;
|
||||
@@ -1,5 +1,5 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OSMesa - www.glfw.org
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
@@ -25,23 +25,22 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_osmesa_platform_h_
|
||||
#define _glfw3_osmesa_platform_h_
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowOSMesa osmesa
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNull null
|
||||
|
||||
#define _GLFW_PLATFORM_CONTEXT_STATE
|
||||
#define _GLFW_PLATFORM_MONITOR_STATE
|
||||
#define _GLFW_PLATFORM_CURSOR_STATE
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE
|
||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
|
||||
#define _GLFW_EGL_CONTEXT_STATE
|
||||
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE
|
||||
|
||||
#include "osmesa_context.h"
|
||||
#include "posix_time.h"
|
||||
#include "posix_tls.h"
|
||||
#include "posix_thread.h"
|
||||
#include "null_joystick.h"
|
||||
|
||||
#if defined(_GLFW_WIN32)
|
||||
#define _glfw_dlopen(name) LoadLibraryA(name)
|
||||
@@ -53,13 +52,11 @@
|
||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||
#endif
|
||||
|
||||
// OSMesa-specific per-window data
|
||||
// Null-specific per-window data
|
||||
//
|
||||
typedef struct _GLFWwindowOSMesa
|
||||
typedef struct _GLFWwindowNull
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
} _GLFWwindowOSMesa;
|
||||
} _GLFWwindowNull;
|
||||
|
||||
|
||||
#endif // _glfw3_osmesa_platform_h_
|
||||
@@ -1,5 +1,5 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OSMesa - www.glfw.org
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
@@ -31,8 +31,8 @@
|
||||
static int createNativeWindow(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig)
|
||||
{
|
||||
window->osmesa.width = wndconfig->width;
|
||||
window->osmesa.height = wndconfig->height;
|
||||
window->null.width = wndconfig->width;
|
||||
window->null.height = wndconfig->height;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
@@ -52,7 +52,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
|
||||
if (ctxconfig->client != GLFW_NO_API)
|
||||
{
|
||||
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
|
||||
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API ||
|
||||
ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
||||
{
|
||||
if (!_glfwInitOSMesa())
|
||||
return GLFW_FALSE;
|
||||
@@ -61,7 +62,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: EGL not available");
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Null: EGL not available");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
@@ -103,15 +104,15 @@ void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
|
||||
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
||||
{
|
||||
if (width)
|
||||
*width = window->osmesa.width;
|
||||
*width = window->null.width;
|
||||
if (height)
|
||||
*height = window->osmesa.height;
|
||||
*height = window->null.height;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
||||
{
|
||||
window->osmesa.width = width;
|
||||
window->osmesa.height = height;
|
||||
window->null.width = width;
|
||||
window->null.height = height;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||
@@ -127,19 +128,24 @@ void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int n, int d)
|
||||
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
|
||||
{
|
||||
if (width)
|
||||
*width = window->osmesa.width;
|
||||
*width = window->null.width;
|
||||
if (height)
|
||||
*height = window->osmesa.height;
|
||||
*height = window->null.height;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||
int* left, int* top,
|
||||
int* right, int* bottom)
|
||||
{
|
||||
if (right)
|
||||
*right = window->osmesa.width;
|
||||
if (bottom)
|
||||
*top = window->osmesa.height;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
||||
float* xscale, float* yscale)
|
||||
{
|
||||
if (xscale)
|
||||
*xscale = 1.f;
|
||||
if (yscale)
|
||||
*yscale = 1.f;
|
||||
}
|
||||
|
||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||
@@ -159,6 +165,16 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
}
|
||||
@@ -171,10 +187,24 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
}
|
||||
|
||||
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
|
||||
{
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
@@ -230,10 +260,6 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformApplyCursorMode(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
@@ -254,16 +280,16 @@ 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;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetKeyName(int key, int scancode)
|
||||
const char* _glfwPlatformGetScancodeName(int scancode)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
@@ -273,26 +299,6 @@ int _glfwPlatformGetKeyScancode(int key)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _glfwPlatformJoystickPresent(int joy)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetJoystickName(int joy)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||
{
|
||||
}
|
||||
+19
-16
@@ -36,25 +36,26 @@ static void makeContextCurrentOSMesa(_GLFWwindow* window)
|
||||
{
|
||||
if (window)
|
||||
{
|
||||
int width, height;
|
||||
_glfwPlatformGetFramebufferSize(window, &width, &height);
|
||||
|
||||
// Check to see if we need to allocate a new buffer
|
||||
if ((window->context.osmesa.buffer == NULL) ||
|
||||
(window->osmesa.width != window->context.osmesa.width) ||
|
||||
(window->osmesa.height != window->context.osmesa.height))
|
||||
(width != window->context.osmesa.width) ||
|
||||
(height != window->context.osmesa.height))
|
||||
{
|
||||
free(window->context.osmesa.buffer);
|
||||
|
||||
// Allocate the new buffer (width * height * 8-bit RGBA)
|
||||
window->context.osmesa.buffer =
|
||||
calloc(4, window->osmesa.width * window->osmesa.height);
|
||||
|
||||
window->context.osmesa.width = window->osmesa.width;
|
||||
window->context.osmesa.height = window->osmesa.height;
|
||||
window->context.osmesa.buffer = calloc(4, width * height);
|
||||
window->context.osmesa.width = width;
|
||||
window->context.osmesa.height = height;
|
||||
}
|
||||
|
||||
if (!OSMesaMakeCurrent(window->context.osmesa.handle,
|
||||
window->context.osmesa.buffer,
|
||||
GL_UNSIGNED_BYTE,
|
||||
window->osmesa.width, window->osmesa.height))
|
||||
window->context.osmesa.buffer,
|
||||
GL_UNSIGNED_BYTE,
|
||||
width, height))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"OSMesa: Failed to make context current");
|
||||
@@ -62,7 +63,7 @@ static void makeContextCurrentOSMesa(_GLFWwindow* window)
|
||||
}
|
||||
}
|
||||
|
||||
_glfwPlatformSetCurrentContext(window);
|
||||
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||
}
|
||||
|
||||
static GLFWglproc getProcAddressOSMesa(const char* procname)
|
||||
@@ -112,7 +113,9 @@ GLFWbool _glfwInitOSMesa(void)
|
||||
int i;
|
||||
const char* sonames[] =
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
#if defined(_GLFW_OSMESA_LIBRARY)
|
||||
_GLFW_OSMESA_LIBRARY,
|
||||
#elif defined(_WIN32)
|
||||
"libOSMesa.dll",
|
||||
"OSMesa.dll",
|
||||
#elif defined(__APPLE__)
|
||||
@@ -183,11 +186,11 @@ void _glfwTerminateOSMesa(void)
|
||||
}
|
||||
}
|
||||
|
||||
#define setAttrib(attribName, attribValue) \
|
||||
#define setAttrib(a, v) \
|
||||
{ \
|
||||
attribs[index++] = attribName; \
|
||||
attribs[index++] = attribValue; \
|
||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
attribs[index++] = a; \
|
||||
attribs[index++] = v; \
|
||||
}
|
||||
|
||||
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||
|
||||
+7
-11
@@ -25,9 +25,6 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_osmesa_context_h_
|
||||
#define _glfw3_osmesa_context_h_
|
||||
|
||||
#define OSMESA_RGBA 0x1908
|
||||
#define OSMESA_FORMAT 0x22
|
||||
#define OSMESA_DEPTH_BITS 0x30
|
||||
@@ -40,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);
|
||||
@@ -57,18 +54,18 @@ typedef GLFWglproc (GLAPIENTRY * PFN_OSMesaGetProcAddress)(const char*);
|
||||
#define OSMesaGetDepthBuffer _glfw.osmesa.GetDepthBuffer
|
||||
#define OSMesaGetProcAddress _glfw.osmesa.GetProcAddress
|
||||
|
||||
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextOSMesa osmesa
|
||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryOSMesa osmesa
|
||||
#define _GLFW_OSMESA_CONTEXT_STATE _GLFWcontextOSMesa osmesa
|
||||
#define _GLFW_OSMESA_LIBRARY_CONTEXT_STATE _GLFWlibraryOSMesa osmesa
|
||||
|
||||
|
||||
// OSMesa-specific per-context data
|
||||
//
|
||||
typedef struct _GLFWcontextOSMesa
|
||||
{
|
||||
OSMesaContext handle;
|
||||
int width;
|
||||
int height;
|
||||
void* buffer;
|
||||
OSMesaContext handle;
|
||||
int width;
|
||||
int height;
|
||||
void* buffer;
|
||||
|
||||
} _GLFWcontextOSMesa;
|
||||
|
||||
@@ -95,4 +92,3 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig);
|
||||
|
||||
#endif // _glfw3_osmesa_context_h_
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 POSIX - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 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 "internal.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
|
||||
{
|
||||
assert(tls->posix.allocated == GLFW_FALSE);
|
||||
|
||||
if (pthread_key_create(&tls->posix.key, NULL) != 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"POSIX: Failed to create context TLS");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
tls->posix.allocated = GLFW_TRUE;
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
||||
{
|
||||
if (tls->posix.allocated)
|
||||
pthread_key_delete(tls->posix.key);
|
||||
memset(tls, 0, sizeof(_GLFWtls));
|
||||
}
|
||||
|
||||
void* _glfwPlatformGetTls(_GLFWtls* tls)
|
||||
{
|
||||
assert(tls->posix.allocated == GLFW_TRUE);
|
||||
return pthread_getspecific(tls->posix.key);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
|
||||
{
|
||||
assert(tls->posix.allocated == GLFW_TRUE);
|
||||
pthread_setspecific(tls->posix.key, value);
|
||||
}
|
||||
|
||||
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
assert(mutex->posix.allocated == GLFW_FALSE);
|
||||
|
||||
if (pthread_mutex_init(&mutex->posix.handle, NULL) != 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "POSIX: Failed to create mutex");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return mutex->posix.allocated = GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
if (mutex->posix.allocated)
|
||||
pthread_mutex_destroy(&mutex->posix.handle);
|
||||
memset(mutex, 0, sizeof(_GLFWmutex));
|
||||
}
|
||||
|
||||
void _glfwPlatformLockMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
assert(mutex->posix.allocated == GLFW_TRUE);
|
||||
pthread_mutex_lock(&mutex->posix.handle);
|
||||
}
|
||||
|
||||
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
assert(mutex->posix.allocated == GLFW_TRUE);
|
||||
pthread_mutex_unlock(&mutex->posix.handle);
|
||||
}
|
||||
|
||||
@@ -25,25 +25,27 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_posix_tls_h_
|
||||
#define _glfw3_posix_tls_h_
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsPOSIX posix_tls
|
||||
#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsPOSIX posix
|
||||
#define _GLFW_PLATFORM_MUTEX_STATE _GLFWmutexPOSIX posix
|
||||
|
||||
|
||||
// POSIX-specific global TLS data
|
||||
// POSIX-specific thread local storage data
|
||||
//
|
||||
typedef struct _GLFWtlsPOSIX
|
||||
{
|
||||
GLFWbool allocated;
|
||||
pthread_key_t context;
|
||||
pthread_key_t key;
|
||||
|
||||
} _GLFWtlsPOSIX;
|
||||
|
||||
// POSIX-specific mutex data
|
||||
//
|
||||
typedef struct _GLFWmutexPOSIX
|
||||
{
|
||||
GLFWbool allocated;
|
||||
pthread_mutex_t handle;
|
||||
|
||||
GLFWbool _glfwInitThreadLocalStoragePOSIX(void);
|
||||
void _glfwTerminateThreadLocalStoragePOSIX(void);
|
||||
} _GLFWmutexPOSIX;
|
||||
|
||||
#endif // _glfw3_posix_tls_h_
|
||||
+6
-6
@@ -44,14 +44,14 @@ void _glfwInitTimerPOSIX(void)
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
||||
{
|
||||
_glfw.posix_time.monotonic = GLFW_TRUE;
|
||||
_glfw.posix_time.frequency = 1000000000;
|
||||
_glfw.timer.posix.monotonic = GLFW_TRUE;
|
||||
_glfw.timer.posix.frequency = 1000000000;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_glfw.posix_time.monotonic = GLFW_FALSE;
|
||||
_glfw.posix_time.frequency = 1000000;
|
||||
_glfw.timer.posix.monotonic = GLFW_FALSE;
|
||||
_glfw.timer.posix.frequency = 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ void _glfwInitTimerPOSIX(void)
|
||||
uint64_t _glfwPlatformGetTimerValue(void)
|
||||
{
|
||||
#if defined(CLOCK_MONOTONIC)
|
||||
if (_glfw.posix_time.monotonic)
|
||||
if (_glfw.timer.posix.monotonic)
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
@@ -80,6 +80,6 @@ uint64_t _glfwPlatformGetTimerValue(void)
|
||||
|
||||
uint64_t _glfwPlatformGetTimerFrequency(void)
|
||||
{
|
||||
return _glfw.posix_time.frequency;
|
||||
return _glfw.timer.posix.frequency;
|
||||
}
|
||||
|
||||
|
||||
+3
-7
@@ -25,24 +25,20 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_posix_time_h_
|
||||
#define _glfw3_posix_time_h_
|
||||
|
||||
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimePOSIX posix_time
|
||||
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerPOSIX posix
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
// POSIX-specific global timer data
|
||||
//
|
||||
typedef struct _GLFWtimePOSIX
|
||||
typedef struct _GLFWtimerPOSIX
|
||||
{
|
||||
GLFWbool monotonic;
|
||||
uint64_t frequency;
|
||||
|
||||
} _GLFWtimePOSIX;
|
||||
} _GLFWtimerPOSIX;
|
||||
|
||||
|
||||
void _glfwInitTimerPOSIX(void);
|
||||
|
||||
#endif // _glfw3_posix_time_h_
|
||||
|
||||
+26
-15
@@ -49,11 +49,12 @@ GLFWbool _glfwInitVulkan(int mode)
|
||||
return GLFW_TRUE;
|
||||
|
||||
#if !defined(_GLFW_VULKAN_STATIC)
|
||||
#if defined(_GLFW_WIN32)
|
||||
#if defined(_GLFW_VULKAN_LIBRARY)
|
||||
_glfw.vk.handle = _glfw_dlopen(_GLFW_VULKAN_LIBRARY);
|
||||
#elif defined(_GLFW_WIN32)
|
||||
_glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
|
||||
#elif defined(_GLFW_COCOA)
|
||||
// NULL maps to RTLD_DEFAULT, which searches all loaded binaries
|
||||
_glfw.vk.handle = _glfw_dlopen(NULL);
|
||||
_glfw.vk.handle = _glfw_dlopen("libMoltenVK.dylib");
|
||||
#else
|
||||
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
|
||||
#endif
|
||||
@@ -69,16 +70,8 @@ GLFWbool _glfwInitVulkan(int mode)
|
||||
_glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
|
||||
if (!_glfw.vk.GetInstanceProcAddr)
|
||||
{
|
||||
#if defined(_GLFW_COCOA)
|
||||
if (mode == _GLFW_REQUIRE_LOADER)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Vulkan: vkGetInstanceProcAddr not found in process");
|
||||
}
|
||||
#else
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Vulkan: Loader does not export vkGetInstanceProcAddr");
|
||||
#endif
|
||||
|
||||
_glfwTerminateVulkan();
|
||||
return GLFW_FALSE;
|
||||
@@ -99,9 +92,13 @@ GLFWbool _glfwInitVulkan(int mode)
|
||||
err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
|
||||
if (err)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Vulkan: Failed to query instance extension count: %s",
|
||||
_glfwGetVulkanResultString(err));
|
||||
// NOTE: This happens on systems with a loader but without any Vulkan ICD
|
||||
if (mode == _GLFW_REQUIRE_LOADER)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Vulkan: Failed to query instance extension count: %s",
|
||||
_glfwGetVulkanResultString(err));
|
||||
}
|
||||
|
||||
_glfwTerminateVulkan();
|
||||
return GLFW_FALSE;
|
||||
@@ -112,7 +109,7 @@ GLFWbool _glfwInitVulkan(int mode)
|
||||
err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep);
|
||||
if (err)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Vulkan: Failed to query instance extensions: %s",
|
||||
_glfwGetVulkanResultString(err));
|
||||
|
||||
@@ -230,6 +227,8 @@ GLFWAPI int glfwVulkanSupported(void)
|
||||
|
||||
GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
|
||||
{
|
||||
assert(count != NULL);
|
||||
|
||||
*count = 0;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
@@ -248,6 +247,7 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
|
||||
const char* procname)
|
||||
{
|
||||
GLFWvkproc proc;
|
||||
assert(procname != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
@@ -273,6 +273,9 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
assert(instance != VK_NULL_HANDLE);
|
||||
assert(device != VK_NULL_HANDLE);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
|
||||
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||
@@ -296,6 +299,7 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
|
||||
VkSurfaceKHR* surface)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(instance != VK_NULL_HANDLE);
|
||||
assert(window != NULL);
|
||||
assert(surface != NULL);
|
||||
|
||||
@@ -313,6 +317,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);
|
||||
}
|
||||
|
||||
|
||||
+129
-119
@@ -44,9 +44,8 @@ static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib
|
||||
pixelFormat,
|
||||
0, 1, &attrib, &value))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to retrieve pixel format attribute %i",
|
||||
attrib);
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to retrieve pixel format attribute");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -55,7 +54,9 @@ static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib
|
||||
|
||||
// Return a list of available and usable framebuffer configs
|
||||
//
|
||||
static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired)
|
||||
static int choosePixelFormat(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
_GLFWfbconfig* usableConfigs;
|
||||
const _GLFWfbconfig* closest;
|
||||
@@ -128,19 +129,33 @@ static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired)
|
||||
if (_glfw.wgl.ARB_multisample)
|
||||
u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
|
||||
|
||||
if (_glfw.wgl.ARB_framebuffer_sRGB ||
|
||||
_glfw.wgl.EXT_framebuffer_sRGB)
|
||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
{
|
||||
if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
|
||||
u->sRGB = GLFW_TRUE;
|
||||
if (_glfw.wgl.ARB_framebuffer_sRGB ||
|
||||
_glfw.wgl.EXT_framebuffer_sRGB)
|
||||
{
|
||||
if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
|
||||
u->sRGB = GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_glfw.wgl.EXT_colorspace)
|
||||
{
|
||||
if (getPixelFormatAttrib(window, n, WGL_COLORSPACE_EXT) ==
|
||||
WGL_COLORSPACE_SRGB_EXT)
|
||||
{
|
||||
u->sRGB = GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
|
||||
// Get pixel format attributes through legacy PFDs
|
||||
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
|
||||
if (!DescribePixelFormat(window->context.wgl.dc,
|
||||
n,
|
||||
sizeof(PIXELFORMATDESCRIPTOR),
|
||||
@@ -198,7 +213,7 @@ static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired)
|
||||
return 0;
|
||||
}
|
||||
|
||||
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
|
||||
closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);
|
||||
if (!closest)
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
@@ -214,54 +229,39 @@ static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired)
|
||||
return pixelFormat;
|
||||
}
|
||||
|
||||
// Returns whether desktop compositing is enabled
|
||||
//
|
||||
static GLFWbool isCompositionEnabled(void)
|
||||
{
|
||||
BOOL enabled;
|
||||
|
||||
if (!_glfw_DwmIsCompositionEnabled)
|
||||
return FALSE;
|
||||
|
||||
if (_glfw_DwmIsCompositionEnabled(&enabled) != S_OK)
|
||||
return FALSE;
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static void makeContextCurrentWGL(_GLFWwindow* window)
|
||||
{
|
||||
if (window)
|
||||
{
|
||||
if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
|
||||
_glfwPlatformSetCurrentContext(window);
|
||||
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to make context current");
|
||||
_glfwPlatformSetCurrentContext(NULL);
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to make context current");
|
||||
_glfwPlatformSetTls(&_glfw.contextSlot, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!wglMakeCurrent(NULL, NULL))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to clear current context");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to clear current context");
|
||||
}
|
||||
|
||||
_glfwPlatformSetCurrentContext(NULL);
|
||||
_glfwPlatformSetTls(&_glfw.contextSlot, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void swapBuffersWGL(_GLFWwindow* window)
|
||||
{
|
||||
// HACK: Use DwmFlush when desktop composition is enabled
|
||||
if (isCompositionEnabled() && !window->monitor)
|
||||
if (_glfwIsCompositionEnabledWin32() && !window->monitor)
|
||||
{
|
||||
int count = abs(window->context.wgl.interval);
|
||||
while (count--)
|
||||
_glfw_DwmFlush();
|
||||
DwmFlush();
|
||||
}
|
||||
|
||||
SwapBuffers(window->context.wgl.dc);
|
||||
@@ -269,13 +269,13 @@ static void swapBuffersWGL(_GLFWwindow* window)
|
||||
|
||||
static void swapIntervalWGL(int interval)
|
||||
{
|
||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
||||
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
|
||||
window->context.wgl.interval = interval;
|
||||
|
||||
// HACK: Disable WGL swap interval when desktop composition is enabled to
|
||||
// avoid interfering with DWM vsync
|
||||
if (isCompositionEnabled() && !window->monitor)
|
||||
if (_glfwIsCompositionEnabledWin32() && !window->monitor)
|
||||
interval = 0;
|
||||
|
||||
if (_glfw.wgl.EXT_swap_control)
|
||||
@@ -329,21 +329,52 @@ static void destroyContextWGL(_GLFWwindow* window)
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize WGL-specific extensions
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Initialize WGL
|
||||
//
|
||||
static void loadWGLExtensions(void)
|
||||
GLFWbool _glfwInitWGL(void)
|
||||
{
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
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;
|
||||
@@ -353,26 +384,29 @@ static void loadWGLExtensions(void)
|
||||
|
||||
if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to set pixel format for dummy context");
|
||||
return;
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to set pixel format for dummy context");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
rc = wglCreateContext(dc);
|
||||
if (!rc)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to create dummy context");
|
||||
return;
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to create dummy context");
|
||||
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);
|
||||
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to make dummy context current");
|
||||
return;
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
// NOTE: Functions must be loaded first as they're needed to retrieve the
|
||||
@@ -404,49 +438,19 @@ static void loadWGLExtensions(void)
|
||||
extensionSupportedWGL("WGL_EXT_create_context_es2_profile");
|
||||
_glfw.wgl.ARB_create_context_robustness =
|
||||
extensionSupportedWGL("WGL_ARB_create_context_robustness");
|
||||
_glfw.wgl.ARB_create_context_no_error =
|
||||
extensionSupportedWGL("WGL_ARB_create_context_no_error");
|
||||
_glfw.wgl.EXT_swap_control =
|
||||
extensionSupportedWGL("WGL_EXT_swap_control");
|
||||
_glfw.wgl.EXT_colorspace =
|
||||
extensionSupportedWGL("WGL_EXT_colorspace");
|
||||
_glfw.wgl.ARB_pixel_format =
|
||||
extensionSupportedWGL("WGL_ARB_pixel_format");
|
||||
_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)
|
||||
{
|
||||
_glfwInputError(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;
|
||||
}
|
||||
|
||||
@@ -458,11 +462,11 @@ void _glfwTerminateWGL(void)
|
||||
FreeLibrary(_glfw.wgl.instance);
|
||||
}
|
||||
|
||||
#define setWGLattrib(attribName, attribValue) \
|
||||
#define setAttrib(a, v) \
|
||||
{ \
|
||||
attribs[index++] = attribName; \
|
||||
attribs[index++] = attribValue; \
|
||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
attribs[index++] = a; \
|
||||
attribs[index++] = v; \
|
||||
}
|
||||
|
||||
// Create the OpenGL or OpenGL ES context
|
||||
@@ -476,9 +480,6 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
HGLRC share = NULL;
|
||||
|
||||
if (!_glfw.wgl.extensionsLoaded)
|
||||
loadWGLExtensions();
|
||||
|
||||
if (ctxconfig->share)
|
||||
share = ctxconfig->share->context.wgl.handle;
|
||||
|
||||
@@ -490,22 +491,22 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
pixelFormat = choosePixelFormat(window, fbconfig);
|
||||
pixelFormat = choosePixelFormat(window, ctxconfig, fbconfig);
|
||||
if (!pixelFormat)
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!DescribePixelFormat(window->context.wgl.dc,
|
||||
pixelFormat, sizeof(pfd), &pfd))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to retrieve PFD for selected pixel format");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to retrieve PFD for selected pixel format");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to set selected pixel format");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to set selected pixel format");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
@@ -562,8 +563,6 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
|
||||
if (ctxconfig->debug)
|
||||
flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
|
||||
if (ctxconfig->noerror)
|
||||
flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;
|
||||
|
||||
if (ctxconfig->robustness)
|
||||
{
|
||||
@@ -571,13 +570,13 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
{
|
||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||
{
|
||||
setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
WGL_NO_RESET_NOTIFICATION_ARB);
|
||||
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
WGL_NO_RESET_NOTIFICATION_ARB);
|
||||
}
|
||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||
{
|
||||
setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
WGL_LOSE_CONTEXT_ON_RESET_ARB);
|
||||
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
WGL_LOSE_CONTEXT_ON_RESET_ARB);
|
||||
}
|
||||
|
||||
flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
|
||||
@@ -590,33 +589,39 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
{
|
||||
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||
{
|
||||
setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||
}
|
||||
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||
{
|
||||
setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
||||
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ctxconfig->noerror)
|
||||
{
|
||||
if (_glfw.wgl.ARB_create_context_no_error)
|
||||
setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
|
||||
}
|
||||
|
||||
// NOTE: Only request an explicitly versioned context when necessary, as
|
||||
// explicitly requesting version 1.0 does not always return the
|
||||
// highest version supported by the driver
|
||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||
{
|
||||
setWGLattrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||
setWGLattrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||
setAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||
setAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||
}
|
||||
|
||||
if (flags)
|
||||
setWGLattrib(WGL_CONTEXT_FLAGS_ARB, flags);
|
||||
setAttrib(WGL_CONTEXT_FLAGS_ARB, flags);
|
||||
|
||||
if (mask)
|
||||
setWGLattrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||
setAttrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||
|
||||
setWGLattrib(0, 0);
|
||||
setAttrib(0, 0);
|
||||
|
||||
window->context.wgl.handle =
|
||||
_glfw.wgl.CreateContextAttribsARB(window->context.wgl.dc,
|
||||
@@ -647,6 +652,11 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"WGL: Driver does not support the requested OpenGL profile");
|
||||
}
|
||||
else if (error == (0xc0070000 | ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB))
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_VALUE,
|
||||
"WGL: The share context is not compatible with the requested context");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
@@ -669,8 +679,8 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
window->context.wgl.handle = wglCreateContext(window->context.wgl.dc);
|
||||
if (!window->context.wgl.handle)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"WGL: Failed to create OpenGL context");
|
||||
_glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
|
||||
"WGL: Failed to create OpenGL context");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
@@ -678,8 +688,8 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
{
|
||||
if (!wglShareLists(share, window->context.wgl.handle))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to enable sharing with specified OpenGL context");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to enable sharing with specified OpenGL context");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
@@ -695,7 +705,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
#undef setWGLattrib
|
||||
#undef setAttrib
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+9
-7
@@ -25,10 +25,6 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_wgl_context_h_
|
||||
#define _glfw3_wgl_context_h_
|
||||
|
||||
|
||||
#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
|
||||
#define WGL_SUPPORT_OPENGL_ARB 0x2010
|
||||
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
|
||||
@@ -72,9 +68,13 @@
|
||||
#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
|
||||
#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
|
||||
#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
|
||||
#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
|
||||
#define WGL_COLORSPACE_EXT 0x309d
|
||||
#define WGL_COLORSPACE_SRGB_EXT 0x3089
|
||||
|
||||
#define ERROR_INVALID_VERSION_ARB 0x2095
|
||||
#define ERROR_INVALID_PROFILE_ARB 0x2096
|
||||
#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
|
||||
|
||||
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
|
||||
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);
|
||||
@@ -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,17 +126,17 @@ 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;
|
||||
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
|
||||
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
|
||||
GLFWbool EXT_swap_control;
|
||||
GLFWbool EXT_colorspace;
|
||||
GLFWbool ARB_multisample;
|
||||
GLFWbool ARB_framebuffer_sRGB;
|
||||
GLFWbool EXT_framebuffer_sRGB;
|
||||
@@ -143,6 +145,7 @@ typedef struct _GLFWlibraryWGL
|
||||
GLFWbool ARB_create_context_profile;
|
||||
GLFWbool EXT_create_context_es2_profile;
|
||||
GLFWbool ARB_create_context_robustness;
|
||||
GLFWbool ARB_create_context_no_error;
|
||||
GLFWbool ARB_context_flush_control;
|
||||
|
||||
} _GLFWlibraryWGL;
|
||||
@@ -154,4 +157,3 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig);
|
||||
|
||||
#endif // _glfw3_wgl_context_h_
|
||||
|
||||
+153
-44
@@ -30,8 +30,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include <initguid.h>
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_HID,0x4d1e55b2,0xf16f,0x11cf,0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30);
|
||||
static const GUID _glfw_GUID_DEVINTERFACE_HID =
|
||||
{0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}};
|
||||
|
||||
#define GUID_DEVINTERFACE_HID _glfw_GUID_DEVINTERFACE_HID
|
||||
|
||||
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
|
||||
|
||||
@@ -60,6 +62,17 @@ 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)
|
||||
@@ -67,29 +80,31 @@ static GLFWbool loadLibraries(void)
|
||||
_glfw.win32.winmm.instance = LoadLibraryA("winmm.dll");
|
||||
if (!_glfw.win32.winmm.instance)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load winmm.dll");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to load winmm.dll");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.win32.winmm.timeGetTime = (PFN_timeGetTime)
|
||||
_glfw.win32.winmm.GetTime = (PFN_timeGetTime)
|
||||
GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");
|
||||
|
||||
_glfw.win32.user32.instance = LoadLibraryA("user32.dll");
|
||||
if (!_glfw.win32.user32.instance)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load user32.dll");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to load user32.dll");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.win32.user32.SetProcessDPIAware = (PFN_SetProcessDPIAware)
|
||||
_glfw.win32.user32.SetProcessDPIAware_ = (PFN_SetProcessDPIAware)
|
||||
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");
|
||||
_glfw.win32.user32.ChangeWindowMessageFilterEx = (PFN_ChangeWindowMessageFilterEx)
|
||||
_glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx)
|
||||
GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
|
||||
|
||||
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
|
||||
if (_glfw.win32.dinput8.instance)
|
||||
{
|
||||
_glfw.win32.dinput8.DirectInput8Create = (PFN_DirectInput8Create)
|
||||
_glfw.win32.dinput8.Create = (PFN_DirectInput8Create)
|
||||
GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create");
|
||||
}
|
||||
|
||||
@@ -110,9 +125,9 @@ static GLFWbool loadLibraries(void)
|
||||
_glfw.win32.xinput.instance = LoadLibraryA(names[i]);
|
||||
if (_glfw.win32.xinput.instance)
|
||||
{
|
||||
_glfw.win32.xinput.XInputGetCapabilities = (PFN_XInputGetCapabilities)
|
||||
_glfw.win32.xinput.GetCapabilities = (PFN_XInputGetCapabilities)
|
||||
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities");
|
||||
_glfw.win32.xinput.XInputGetState = (PFN_XInputGetState)
|
||||
_glfw.win32.xinput.GetState = (PFN_XInputGetState)
|
||||
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState");
|
||||
|
||||
break;
|
||||
@@ -123,17 +138,21 @@ static GLFWbool loadLibraries(void)
|
||||
_glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
|
||||
if (_glfw.win32.dwmapi.instance)
|
||||
{
|
||||
_glfw.win32.dwmapi.DwmIsCompositionEnabled = (PFN_DwmIsCompositionEnabled)
|
||||
_glfw.win32.dwmapi.IsCompositionEnabled = (PFN_DwmIsCompositionEnabled)
|
||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
|
||||
_glfw.win32.dwmapi.DwmFlush = (PFN_DwmFlush)
|
||||
_glfw.win32.dwmapi.Flush = (PFN_DwmFlush)
|
||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
|
||||
_glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow)
|
||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");
|
||||
}
|
||||
|
||||
_glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
|
||||
if (_glfw.win32.shcore.instance)
|
||||
{
|
||||
_glfw.win32.shcore.SetProcessDpiAwareness = (PFN_SetProcessDpiAwareness)
|
||||
_glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness)
|
||||
GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
|
||||
_glfw.win32.shcore.GetDpiForMonitor_ = (PFN_GetDpiForMonitor)
|
||||
GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor");
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
@@ -307,16 +326,16 @@ static HWND createHelperWindow(void)
|
||||
MSG msg;
|
||||
HWND window = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
|
||||
_GLFW_WNDCLASSNAME,
|
||||
L"GLFW helper window",
|
||||
L"GLFW message window",
|
||||
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
|
||||
0, 0, 1, 1,
|
||||
HWND_MESSAGE, NULL,
|
||||
NULL, NULL,
|
||||
GetModuleHandleW(NULL),
|
||||
NULL);
|
||||
if (!window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create helper window");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create helper window");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -332,9 +351,10 @@ static HWND createHelperWindow(void)
|
||||
dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
||||
dbi.dbcc_classguid = GUID_DEVINTERFACE_HID;
|
||||
|
||||
RegisterDeviceNotificationW(window,
|
||||
(DEV_BROADCAST_HDR*) &dbi,
|
||||
DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||
_glfw.win32.deviceNotificationHandle =
|
||||
RegisterDeviceNotificationW(window,
|
||||
(DEV_BROADCAST_HDR*) &dbi,
|
||||
DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||
}
|
||||
|
||||
while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE))
|
||||
@@ -356,16 +376,22 @@ static HWND createHelperWindow(void)
|
||||
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
|
||||
{
|
||||
WCHAR* target;
|
||||
int length;
|
||||
int count;
|
||||
|
||||
length = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
|
||||
if (!length)
|
||||
return NULL;
|
||||
|
||||
target = calloc(length, sizeof(WCHAR));
|
||||
|
||||
if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, length))
|
||||
count = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
|
||||
if (!count)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert string from UTF-8");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
target = calloc(count, sizeof(WCHAR));
|
||||
|
||||
if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, count))
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert string from UTF-8");
|
||||
free(target);
|
||||
return NULL;
|
||||
}
|
||||
@@ -378,16 +404,22 @@ WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
|
||||
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
|
||||
{
|
||||
char* target;
|
||||
int length;
|
||||
int size;
|
||||
|
||||
length = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
|
||||
if (!length)
|
||||
return NULL;
|
||||
|
||||
target = calloc(length, 1);
|
||||
|
||||
if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, length, NULL, NULL))
|
||||
size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
|
||||
if (!size)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert string to UTF-8");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
target = calloc(size, 1);
|
||||
|
||||
if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL))
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert string to UTF-8");
|
||||
free(target);
|
||||
return NULL;
|
||||
}
|
||||
@@ -395,6 +427,81 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
|
||||
return target;
|
||||
}
|
||||
|
||||
// Reports the specified error, appending information about the last Win32 error
|
||||
//
|
||||
void _glfwInputErrorWin32(int error, const char* description)
|
||||
{
|
||||
WCHAR buffer[_GLFW_MESSAGE_SIZE] = L"";
|
||||
char message[_GLFW_MESSAGE_SIZE] = "";
|
||||
|
||||
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||
FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||||
NULL,
|
||||
GetLastError() & 0xffff,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
NULL);
|
||||
WideCharToMultiByte(CP_UTF8, 0, buffer, -1, message, sizeof(message), NULL, NULL);
|
||||
|
||||
_glfwInputError(error, "%s: %s", description, message);
|
||||
}
|
||||
|
||||
// Updates key names according to the current keyboard layout
|
||||
//
|
||||
void _glfwUpdateKeyNamesWin32(void)
|
||||
{
|
||||
int key;
|
||||
BYTE state[256] = {0};
|
||||
|
||||
memset(_glfw.win32.keynames, 0, sizeof(_glfw.win32.keynames));
|
||||
|
||||
for (key = GLFW_KEY_SPACE; key <= GLFW_KEY_LAST; key++)
|
||||
{
|
||||
UINT vk;
|
||||
int scancode, length;
|
||||
WCHAR chars[16];
|
||||
|
||||
scancode = _glfw.win32.scancodes[key];
|
||||
if (scancode == -1)
|
||||
continue;
|
||||
|
||||
if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD)
|
||||
{
|
||||
const UINT vks[] = {
|
||||
VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,
|
||||
VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
|
||||
VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, VK_DIVIDE,
|
||||
VK_MULTIPLY, VK_SUBTRACT, VK_ADD
|
||||
};
|
||||
|
||||
vk = vks[key - GLFW_KEY_KP_0];
|
||||
}
|
||||
else
|
||||
vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK);
|
||||
|
||||
length = ToUnicode(vk, scancode, state,
|
||||
chars, sizeof(chars) / sizeof(WCHAR),
|
||||
0);
|
||||
|
||||
if (length == -1)
|
||||
{
|
||||
length = ToUnicode(vk, scancode, state,
|
||||
chars, sizeof(chars) / sizeof(WCHAR),
|
||||
0);
|
||||
}
|
||||
|
||||
if (length < 1)
|
||||
continue;
|
||||
|
||||
WideCharToMultiByte(CP_UTF8, 0, chars, 1,
|
||||
_glfw.win32.keynames[key],
|
||||
sizeof(_glfw.win32.keynames[key]),
|
||||
NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
@@ -402,9 +509,6 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
|
||||
|
||||
int _glfwPlatformInit(void)
|
||||
{
|
||||
if (!_glfwInitThreadLocalStorageWin32())
|
||||
return GLFW_FALSE;
|
||||
|
||||
// To make SetForegroundWindow work as we want, we need to fiddle
|
||||
// with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
|
||||
// as possible in the hope of still being the foreground process)
|
||||
@@ -417,11 +521,12 @@ int _glfwPlatformInit(void)
|
||||
return GLFW_FALSE;
|
||||
|
||||
createKeyTables();
|
||||
_glfwUpdateKeyNamesWin32();
|
||||
|
||||
if (_glfw_SetProcessDpiAwareness)
|
||||
_glfw_SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||
else if (_glfw_SetProcessDPIAware)
|
||||
_glfw_SetProcessDPIAware();
|
||||
if (IsWindows8Point1OrGreater())
|
||||
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||
else if (IsWindowsVistaOrGreater())
|
||||
SetProcessDPIAware();
|
||||
|
||||
if (!_glfwRegisterWindowClassWin32())
|
||||
return GLFW_FALSE;
|
||||
@@ -433,11 +538,15 @@ int _glfwPlatformInit(void)
|
||||
_glfwInitTimerWin32();
|
||||
_glfwInitJoysticksWin32();
|
||||
|
||||
_glfwPollMonitorsWin32();
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformTerminate(void)
|
||||
{
|
||||
if (_glfw.win32.deviceNotificationHandle)
|
||||
UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
|
||||
|
||||
if (_glfw.win32.helperWindowHandle)
|
||||
DestroyWindow(_glfw.win32.helperWindowHandle);
|
||||
|
||||
@@ -449,12 +558,12 @@ void _glfwPlatformTerminate(void)
|
||||
SPIF_SENDCHANGE);
|
||||
|
||||
free(_glfw.win32.clipboardString);
|
||||
free(_glfw.win32.rawInput);
|
||||
|
||||
_glfwTerminateWGL();
|
||||
_glfwTerminateEGL();
|
||||
|
||||
_glfwTerminateJoysticksWin32();
|
||||
_glfwTerminateThreadLocalStorageWin32();
|
||||
|
||||
freeLibraries();
|
||||
}
|
||||
|
||||
+282
-296
@@ -1,5 +1,5 @@
|
||||
//========================================================================
|
||||
// GLFW 3.1 Win32 - www.glfw.org
|
||||
// GLFW 3.3 Win32 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
@@ -27,13 +27,9 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <initguid.h>
|
||||
|
||||
#define _GLFW_PRESENCE_ONLY 1
|
||||
#define _GLFW_UPDATE_STATE 2
|
||||
|
||||
#define _GLFW_TYPE_AXIS 0
|
||||
#define _GLFW_TYPE_SLIDER 1
|
||||
#define _GLFW_TYPE_BUTTON 2
|
||||
@@ -52,18 +48,36 @@ typedef struct _GLFWobjenumWin32
|
||||
int povCount;
|
||||
} _GLFWobjenumWin32;
|
||||
|
||||
// Define only the necessary GUIDs (it's bad enough that we're exporting these)
|
||||
// Define local copies of the necessary GUIDs
|
||||
//
|
||||
DEFINE_GUID(IID_IDirectInput8W,0xbf798031,0x483a,0x4da2,0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00);
|
||||
DEFINE_GUID(GUID_XAxis,0xa36d02e0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
DEFINE_GUID(GUID_YAxis,0xa36d02e1,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
DEFINE_GUID(GUID_ZAxis,0xa36d02e2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
DEFINE_GUID(GUID_RxAxis,0xa36d02f4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
DEFINE_GUID(GUID_RyAxis,0xa36d02f5,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
DEFINE_GUID(GUID_RzAxis,0xa36d02e3,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
DEFINE_GUID(GUID_Slider,0xa36d02e4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
DEFINE_GUID(GUID_Button,0xa36d02f0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
DEFINE_GUID(GUID_POV,0xa36d02f2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
static const GUID _glfw_IID_IDirectInput8W =
|
||||
{0xbf798031,0x483a,0x4da2,{0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00}};
|
||||
static const GUID _glfw_GUID_XAxis =
|
||||
{0xa36d02e0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_YAxis =
|
||||
{0xa36d02e1,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_ZAxis =
|
||||
{0xa36d02e2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_RxAxis =
|
||||
{0xa36d02f4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_RyAxis =
|
||||
{0xa36d02f5,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_RzAxis =
|
||||
{0xa36d02e3,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_Slider =
|
||||
{0xa36d02e4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_POV =
|
||||
{0xa36d02f2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
|
||||
#define IID_IDirectInput8W _glfw_IID_IDirectInput8W
|
||||
#define GUID_XAxis _glfw_GUID_XAxis
|
||||
#define GUID_YAxis _glfw_GUID_YAxis
|
||||
#define GUID_ZAxis _glfw_GUID_ZAxis
|
||||
#define GUID_RxAxis _glfw_GUID_RxAxis
|
||||
#define GUID_RyAxis _glfw_GUID_RyAxis
|
||||
#define GUID_RzAxis _glfw_GUID_RzAxis
|
||||
#define GUID_Slider _glfw_GUID_Slider
|
||||
#define GUID_POV _glfw_GUID_POV
|
||||
|
||||
// Object data array for our clone of c_dfDIJoystick
|
||||
// Generated with https://github.com/elmindreda/c_dfDIJoystick2
|
||||
@@ -149,9 +163,9 @@ static const char* getDeviceDescription(const XINPUT_CAPABILITIES* xic)
|
||||
case XINPUT_DEVSUBTYPE_GAMEPAD:
|
||||
{
|
||||
if (xic->Flags & XINPUT_CAPS_WIRELESS)
|
||||
return "Wireless Xbox 360 Controller";
|
||||
return "Wireless Xbox Controller";
|
||||
else
|
||||
return "Xbox 360 Controller";
|
||||
return "Xbox Controller";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,25 +252,20 @@ static GLFWbool supportsXInput(const GUID* guid)
|
||||
|
||||
// Frees all resources associated with the specified joystick
|
||||
//
|
||||
static void closeJoystick(_GLFWjoystickWin32* js)
|
||||
static void closeJoystick(_GLFWjoystick* js)
|
||||
{
|
||||
if (js->device)
|
||||
if (js->win32.device)
|
||||
{
|
||||
IDirectInputDevice8_Unacquire(js->device);
|
||||
IDirectInputDevice8_Release(js->device);
|
||||
IDirectInputDevice8_Unacquire(js->win32.device);
|
||||
IDirectInputDevice8_Release(js->win32.device);
|
||||
}
|
||||
|
||||
free(js->name);
|
||||
free(js->axes);
|
||||
free(js->buttons);
|
||||
free(js->objects);
|
||||
memset(js, 0, sizeof(_GLFWjoystickWin32));
|
||||
|
||||
_glfwInputJoystickChange((int) (js - _glfw.win32_js), GLFW_DISCONNECTED);
|
||||
_glfwFreeJoystick(js);
|
||||
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
||||
}
|
||||
|
||||
// DirectInput device object enumeration callback
|
||||
// Insights gleaned from SDL2
|
||||
// Insights gleaned from SDL
|
||||
//
|
||||
static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
|
||||
void* user)
|
||||
@@ -337,23 +346,20 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
DIPROPDWORD dipd;
|
||||
IDirectInputDevice8* device;
|
||||
_GLFWobjenumWin32 data;
|
||||
_GLFWjoystickWin32* js;
|
||||
_GLFWjoystick* js;
|
||||
char guid[33];
|
||||
char name[256];
|
||||
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (memcmp(&_glfw.win32_js[jid].guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||
return DIENUM_CONTINUE;
|
||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||
if (js->present)
|
||||
{
|
||||
if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (!_glfw.win32_js[jid].present)
|
||||
break;
|
||||
}
|
||||
|
||||
if (jid > GLFW_JOYSTICK_LAST)
|
||||
return DIENUM_STOP;
|
||||
|
||||
if (supportsXInput(&di->guidProduct))
|
||||
return DIENUM_CONTINUE;
|
||||
|
||||
@@ -426,226 +432,54 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
sizeof(_GLFWjoyobjectWin32),
|
||||
compareJoystickObjects);
|
||||
|
||||
js = _glfw.win32_js + jid;
|
||||
js->device = device;
|
||||
js->guid = di->guidInstance;
|
||||
js->axisCount = data.axisCount + data.sliderCount;
|
||||
js->axes = calloc(js->axisCount, sizeof(float));
|
||||
js->buttonCount += data.buttonCount + data.povCount * 4;
|
||||
js->buttons = calloc(js->buttonCount, 1);
|
||||
js->objects = data.objects;
|
||||
js->objectCount = data.objectCount;
|
||||
js->name = _glfwCreateUTF8FromWideStringWin32(di->tszInstanceName);
|
||||
js->present = GLFW_TRUE;
|
||||
|
||||
_glfwInputJoystickChange(jid, GLFW_CONNECTED);
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
// Attempt to open the specified joystick device
|
||||
// TODO: Pack state arrays for non-gamepad devices
|
||||
//
|
||||
static GLFWbool openXinputDevice(DWORD index)
|
||||
{
|
||||
int jid;
|
||||
XINPUT_CAPABILITIES xic;
|
||||
_GLFWjoystickWin32* js;
|
||||
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
if (!WideCharToMultiByte(CP_UTF8, 0,
|
||||
di->tszInstanceName, -1,
|
||||
name, sizeof(name),
|
||||
NULL, NULL))
|
||||
{
|
||||
if (_glfw.win32_js[jid].present &&
|
||||
_glfw.win32_js[jid].device == NULL &&
|
||||
_glfw.win32_js[jid].index == index)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert joystick name to UTF-8");
|
||||
|
||||
IDirectInputDevice8_Release(device);
|
||||
free(data.objects);
|
||||
return DIENUM_STOP;
|
||||
}
|
||||
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
||||
if (memcmp(&di->guidProduct.Data4[2], "PIDVID", 6) == 0)
|
||||
{
|
||||
if (!_glfw.win32_js[jid].present)
|
||||
break;
|
||||
}
|
||||
|
||||
if (jid > GLFW_JOYSTICK_LAST)
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (_glfw_XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
||||
return GLFW_FALSE;
|
||||
|
||||
js = _glfw.win32_js + jid;
|
||||
js->axisCount = 6;
|
||||
js->axes = calloc(js->axisCount, sizeof(float));
|
||||
js->buttonCount = 14;
|
||||
js->buttons = calloc(js->buttonCount, 1);
|
||||
js->present = GLFW_TRUE;
|
||||
js->name = strdup(getDeviceDescription(&xic));
|
||||
js->index = index;
|
||||
|
||||
_glfwInputJoystickChange(jid, GLFW_CONNECTED);
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
// Polls for and processes events the specified joystick
|
||||
//
|
||||
static GLFWbool pollJoystickState(_GLFWjoystickWin32* js, int mode)
|
||||
{
|
||||
if (!js->present)
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (js->device)
|
||||
{
|
||||
int i, j, ai = 0, bi = 0;
|
||||
HRESULT result;
|
||||
DIJOYSTATE state;
|
||||
|
||||
IDirectInputDevice8_Poll(js->device);
|
||||
result = IDirectInputDevice8_GetDeviceState(js->device,
|
||||
sizeof(state),
|
||||
&state);
|
||||
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
|
||||
{
|
||||
IDirectInputDevice8_Acquire(js->device);
|
||||
IDirectInputDevice8_Poll(js->device);
|
||||
result = IDirectInputDevice8_GetDeviceState(js->device,
|
||||
sizeof(state),
|
||||
&state);
|
||||
}
|
||||
|
||||
if (FAILED(result))
|
||||
{
|
||||
closeJoystick(js);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (mode == _GLFW_PRESENCE_ONLY)
|
||||
return GLFW_TRUE;
|
||||
|
||||
for (i = 0; i < js->objectCount; i++)
|
||||
{
|
||||
const void* data = (char*) &state + js->objects[i].offset;
|
||||
|
||||
switch (js->objects[i].type)
|
||||
{
|
||||
case _GLFW_TYPE_AXIS:
|
||||
case _GLFW_TYPE_SLIDER:
|
||||
{
|
||||
js->axes[ai++] = (*((LONG*) data) + 0.5f) / 32767.5f;
|
||||
break;
|
||||
}
|
||||
|
||||
case _GLFW_TYPE_BUTTON:
|
||||
{
|
||||
if (*((BYTE*) data) & 0x80)
|
||||
js->buttons[bi++] = GLFW_PRESS;
|
||||
else
|
||||
js->buttons[bi++] = GLFW_RELEASE;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case _GLFW_TYPE_POV:
|
||||
{
|
||||
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
||||
// Screams of horror are appropriate at this point
|
||||
int value = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
||||
if (value < 0 || value > 8)
|
||||
value = 8;
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
if (directions[value] & (1 << j))
|
||||
js->buttons[bi++] = GLFW_PRESS;
|
||||
else
|
||||
js->buttons[bi++] = GLFW_RELEASE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
sprintf(guid, "03000000%02x%02x0000%02x%02x000000000000",
|
||||
(uint8_t) di->guidProduct.Data1,
|
||||
(uint8_t) (di->guidProduct.Data1 >> 8),
|
||||
(uint8_t) (di->guidProduct.Data1 >> 16),
|
||||
(uint8_t) (di->guidProduct.Data1 >> 24));
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
DWORD result;
|
||||
XINPUT_STATE xis;
|
||||
const WORD buttons[14] =
|
||||
{
|
||||
XINPUT_GAMEPAD_A,
|
||||
XINPUT_GAMEPAD_B,
|
||||
XINPUT_GAMEPAD_X,
|
||||
XINPUT_GAMEPAD_Y,
|
||||
XINPUT_GAMEPAD_LEFT_SHOULDER,
|
||||
XINPUT_GAMEPAD_RIGHT_SHOULDER,
|
||||
XINPUT_GAMEPAD_BACK,
|
||||
XINPUT_GAMEPAD_START,
|
||||
XINPUT_GAMEPAD_LEFT_THUMB,
|
||||
XINPUT_GAMEPAD_RIGHT_THUMB,
|
||||
XINPUT_GAMEPAD_DPAD_UP,
|
||||
XINPUT_GAMEPAD_DPAD_RIGHT,
|
||||
XINPUT_GAMEPAD_DPAD_DOWN,
|
||||
XINPUT_GAMEPAD_DPAD_LEFT
|
||||
};
|
||||
|
||||
result = _glfw_XInputGetState(js->index, &xis);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
if (result == ERROR_DEVICE_NOT_CONNECTED)
|
||||
closeJoystick(js);
|
||||
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (mode == _GLFW_PRESENCE_ONLY)
|
||||
return GLFW_TRUE;
|
||||
|
||||
if ((float) xis.Gamepad.sThumbLX * xis.Gamepad.sThumbLX +
|
||||
(float) xis.Gamepad.sThumbLY * xis.Gamepad.sThumbLY >
|
||||
(float) XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE *
|
||||
XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
|
||||
{
|
||||
js->axes[0] = (xis.Gamepad.sThumbLX + 0.5f) / 32767.f;
|
||||
js->axes[1] = (xis.Gamepad.sThumbLY + 0.5f) / 32767.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
js->axes[0] = 0.f;
|
||||
js->axes[1] = 0.f;
|
||||
}
|
||||
|
||||
if ((float) xis.Gamepad.sThumbRX * xis.Gamepad.sThumbRX +
|
||||
(float) xis.Gamepad.sThumbRY * xis.Gamepad.sThumbRY >
|
||||
(float) XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE *
|
||||
XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
|
||||
{
|
||||
js->axes[2] = (xis.Gamepad.sThumbRX + 0.5f) / 32767.f;
|
||||
js->axes[3] = (xis.Gamepad.sThumbRY + 0.5f) / 32767.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
js->axes[2] = 0.f;
|
||||
js->axes[3] = 0.f;
|
||||
}
|
||||
|
||||
if (xis.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||
js->axes[4] = xis.Gamepad.bLeftTrigger / 127.5f - 1.f;
|
||||
else
|
||||
js->axes[4] = -1.f;
|
||||
|
||||
if (xis.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||
js->axes[5] = xis.Gamepad.bRightTrigger / 127.5f - 1.f;
|
||||
else
|
||||
js->axes[5] = -1.f;
|
||||
|
||||
for (i = 0; i < 14; i++)
|
||||
js->buttons[i] = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
|
||||
|
||||
return GLFW_TRUE;
|
||||
sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
|
||||
name[0], name[1], name[2], name[3],
|
||||
name[4], name[5], name[6], name[7],
|
||||
name[8], name[9], name[10]);
|
||||
}
|
||||
|
||||
js = _glfwAllocJoystick(name, guid,
|
||||
data.axisCount + data.sliderCount,
|
||||
data.buttonCount,
|
||||
data.povCount);
|
||||
if (!js)
|
||||
{
|
||||
IDirectInputDevice8_Release(device);
|
||||
free(data.objects);
|
||||
return DIENUM_STOP;
|
||||
}
|
||||
|
||||
js->win32.device = device;
|
||||
js->win32.guid = di->guidInstance;
|
||||
js->win32.objects = data.objects;
|
||||
js->win32.objectCount = data.objectCount;
|
||||
|
||||
_glfwInputJoystick(js, GLFW_CONNECTED);
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -659,11 +493,11 @@ void _glfwInitJoysticksWin32(void)
|
||||
{
|
||||
if (_glfw.win32.dinput8.instance)
|
||||
{
|
||||
if (FAILED(_glfw_DirectInput8Create(GetModuleHandle(NULL),
|
||||
DIRECTINPUT_VERSION,
|
||||
&IID_IDirectInput8W,
|
||||
(void**) &_glfw.win32.dinput8.api,
|
||||
NULL)))
|
||||
if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
|
||||
DIRECTINPUT_VERSION,
|
||||
&IID_IDirectInput8W,
|
||||
(void**) &_glfw.win32.dinput8.api,
|
||||
NULL)))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create interface");
|
||||
@@ -680,7 +514,7 @@ void _glfwTerminateJoysticksWin32(void)
|
||||
int jid;
|
||||
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
closeJoystick(_glfw.win32_js + jid);
|
||||
closeJoystick(_glfw.joysticks + jid);
|
||||
|
||||
if (_glfw.win32.dinput8.api)
|
||||
IDirectInput8_Release(_glfw.win32.dinput8.api);
|
||||
@@ -692,10 +526,43 @@ void _glfwDetectJoystickConnectionWin32(void)
|
||||
{
|
||||
if (_glfw.win32.xinput.instance)
|
||||
{
|
||||
DWORD i;
|
||||
DWORD index;
|
||||
|
||||
for (i = 0; i < XUSER_MAX_COUNT; i++)
|
||||
openXinputDevice(i);
|
||||
for (index = 0; index < XUSER_MAX_COUNT; index++)
|
||||
{
|
||||
int jid;
|
||||
char guid[33];
|
||||
XINPUT_CAPABILITIES xic;
|
||||
_GLFWjoystick* js;
|
||||
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (_glfw.joysticks[jid].present &&
|
||||
_glfw.joysticks[jid].win32.device == NULL &&
|
||||
_glfw.joysticks[jid].win32.index == index)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (jid <= GLFW_JOYSTICK_LAST)
|
||||
continue;
|
||||
|
||||
if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
||||
continue;
|
||||
|
||||
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
||||
sprintf(guid, "78696e707574%02x000000000000000000",
|
||||
xic.SubType & 0xff);
|
||||
|
||||
js = _glfwAllocJoystick(getDeviceDescription(&xic), guid, 6, 10, 1);
|
||||
if (!js)
|
||||
continue;
|
||||
|
||||
js->win32.index = index;
|
||||
|
||||
_glfwInputJoystick(js, GLFW_CONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
if (_glfw.win32.dinput8.api)
|
||||
@@ -719,8 +586,12 @@ void _glfwDetectJoystickDisconnectionWin32(void)
|
||||
{
|
||||
int jid;
|
||||
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
pollJoystickState(_glfw.win32_js + jid, _GLFW_PRESENCE_ONLY);
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||
if (js->present)
|
||||
_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -728,38 +599,153 @@ void _glfwDetectJoystickDisconnectionWin32(void)
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformJoystickPresent(int jid)
|
||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
{
|
||||
_GLFWjoystickWin32* js = _glfw.win32_js + jid;
|
||||
return pollJoystickState(js, _GLFW_PRESENCE_ONLY);
|
||||
if (js->win32.device)
|
||||
{
|
||||
int i, ai = 0, bi = 0, pi = 0;
|
||||
HRESULT result;
|
||||
DIJOYSTATE state;
|
||||
|
||||
IDirectInputDevice8_Poll(js->win32.device);
|
||||
result = IDirectInputDevice8_GetDeviceState(js->win32.device,
|
||||
sizeof(state),
|
||||
&state);
|
||||
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
|
||||
{
|
||||
IDirectInputDevice8_Acquire(js->win32.device);
|
||||
IDirectInputDevice8_Poll(js->win32.device);
|
||||
result = IDirectInputDevice8_GetDeviceState(js->win32.device,
|
||||
sizeof(state),
|
||||
&state);
|
||||
}
|
||||
|
||||
if (FAILED(result))
|
||||
{
|
||||
closeJoystick(js);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (mode == _GLFW_POLL_PRESENCE)
|
||||
return GLFW_TRUE;
|
||||
|
||||
for (i = 0; i < js->win32.objectCount; i++)
|
||||
{
|
||||
const void* data = (char*) &state + js->win32.objects[i].offset;
|
||||
|
||||
switch (js->win32.objects[i].type)
|
||||
{
|
||||
case _GLFW_TYPE_AXIS:
|
||||
case _GLFW_TYPE_SLIDER:
|
||||
{
|
||||
const float value = (*((LONG*) data) + 0.5f) / 32767.5f;
|
||||
_glfwInputJoystickAxis(js, ai, value);
|
||||
ai++;
|
||||
break;
|
||||
}
|
||||
|
||||
case _GLFW_TYPE_BUTTON:
|
||||
{
|
||||
const char value = (*((BYTE*) data) & 0x80) != 0;
|
||||
_glfwInputJoystickButton(js, bi, value);
|
||||
bi++;
|
||||
break;
|
||||
}
|
||||
|
||||
case _GLFW_TYPE_POV:
|
||||
{
|
||||
const int states[9] =
|
||||
{
|
||||
GLFW_HAT_UP,
|
||||
GLFW_HAT_RIGHT_UP,
|
||||
GLFW_HAT_RIGHT,
|
||||
GLFW_HAT_RIGHT_DOWN,
|
||||
GLFW_HAT_DOWN,
|
||||
GLFW_HAT_LEFT_DOWN,
|
||||
GLFW_HAT_LEFT,
|
||||
GLFW_HAT_LEFT_UP,
|
||||
GLFW_HAT_CENTERED
|
||||
};
|
||||
|
||||
// Screams of horror are appropriate at this point
|
||||
int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
||||
if (state < 0 || state > 8)
|
||||
state = 8;
|
||||
|
||||
_glfwInputJoystickHat(js, pi, states[state]);
|
||||
pi++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int i, dpad = 0;
|
||||
DWORD result;
|
||||
XINPUT_STATE xis;
|
||||
const WORD buttons[10] =
|
||||
{
|
||||
XINPUT_GAMEPAD_A,
|
||||
XINPUT_GAMEPAD_B,
|
||||
XINPUT_GAMEPAD_X,
|
||||
XINPUT_GAMEPAD_Y,
|
||||
XINPUT_GAMEPAD_LEFT_SHOULDER,
|
||||
XINPUT_GAMEPAD_RIGHT_SHOULDER,
|
||||
XINPUT_GAMEPAD_BACK,
|
||||
XINPUT_GAMEPAD_START,
|
||||
XINPUT_GAMEPAD_LEFT_THUMB,
|
||||
XINPUT_GAMEPAD_RIGHT_THUMB
|
||||
};
|
||||
|
||||
result = XInputGetState(js->win32.index, &xis);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
if (result == ERROR_DEVICE_NOT_CONNECTED)
|
||||
closeJoystick(js);
|
||||
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (mode == _GLFW_POLL_PRESENCE)
|
||||
return GLFW_TRUE;
|
||||
|
||||
_glfwInputJoystickAxis(js, 0, (xis.Gamepad.sThumbLX + 0.5f) / 32767.5f);
|
||||
_glfwInputJoystickAxis(js, 1, -(xis.Gamepad.sThumbLY + 0.5f) / 32767.5f);
|
||||
_glfwInputJoystickAxis(js, 2, (xis.Gamepad.sThumbRX + 0.5f) / 32767.5f);
|
||||
_glfwInputJoystickAxis(js, 3, -(xis.Gamepad.sThumbRY + 0.5f) / 32767.5f);
|
||||
_glfwInputJoystickAxis(js, 4, xis.Gamepad.bLeftTrigger / 127.5f - 1.f);
|
||||
_glfwInputJoystickAxis(js, 5, xis.Gamepad.bRightTrigger / 127.5f - 1.f);
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
const char value = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
|
||||
_glfwInputJoystickButton(js, i, value);
|
||||
}
|
||||
|
||||
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
|
||||
dpad |= GLFW_HAT_UP;
|
||||
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
|
||||
dpad |= GLFW_HAT_RIGHT;
|
||||
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
|
||||
dpad |= GLFW_HAT_DOWN;
|
||||
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
|
||||
dpad |= GLFW_HAT_LEFT;
|
||||
|
||||
_glfwInputJoystickHat(js, 0, dpad);
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
const float* _glfwPlatformGetJoystickAxes(int jid, int* count)
|
||||
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
||||
{
|
||||
_GLFWjoystickWin32* js = _glfw.win32_js + jid;
|
||||
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
|
||||
return NULL;
|
||||
|
||||
*count = js->axisCount;
|
||||
return js->axes;
|
||||
}
|
||||
|
||||
const unsigned char* _glfwPlatformGetJoystickButtons(int jid, int* count)
|
||||
{
|
||||
_GLFWjoystickWin32* js = _glfw.win32_js + jid;
|
||||
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
|
||||
return NULL;
|
||||
|
||||
*count = js->buttonCount;
|
||||
return js->buttons;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetJoystickName(int jid)
|
||||
{
|
||||
_GLFWjoystickWin32* js = _glfw.win32_js + jid;
|
||||
if (!pollJoystickState(js, _GLFW_PRESENCE_ONLY))
|
||||
return NULL;
|
||||
|
||||
return js->name;
|
||||
if (strcmp(guid + 20, "504944564944") == 0)
|
||||
{
|
||||
char original[33];
|
||||
strcpy(original, guid);
|
||||
sprintf(guid, "03000000%.4s0000%.4s000000000000",
|
||||
original, original + 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-11
@@ -24,11 +24,10 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_win32_joystick_h_
|
||||
#define _glfw3_win32_joystick_h_
|
||||
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickWin32 win32
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE int dummy
|
||||
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
|
||||
_GLFWjoystickWin32 win32_js[GLFW_JOYSTICK_LAST + 1]
|
||||
#define _GLFW_PLATFORM_MAPPING_NAME "Windows"
|
||||
|
||||
// Joystick element (axis, button or slider)
|
||||
//
|
||||
@@ -42,14 +41,8 @@ typedef struct _GLFWjoyobjectWin32
|
||||
//
|
||||
typedef struct _GLFWjoystickWin32
|
||||
{
|
||||
GLFWbool present;
|
||||
float* axes;
|
||||
int axisCount;
|
||||
unsigned char* buttons;
|
||||
int buttonCount;
|
||||
_GLFWjoyobjectWin32* objects;
|
||||
int objectCount;
|
||||
char* name;
|
||||
IDirectInputDevice8W* device;
|
||||
DWORD index;
|
||||
GUID guid;
|
||||
@@ -61,4 +54,3 @@ void _glfwTerminateJoysticksWin32(void);
|
||||
void _glfwDetectJoystickConnectionWin32(void);
|
||||
void _glfwDetectJoystickDisconnectionWin32(void);
|
||||
|
||||
#endif // _glfw3_win32_joystick_h_
|
||||
|
||||
+224
-116
@@ -33,33 +33,66 @@
|
||||
#include <malloc.h>
|
||||
|
||||
|
||||
// Callback for EnumDisplayMonitors in createMonitor
|
||||
//
|
||||
static BOOL CALLBACK monitorCallback(HMONITOR handle,
|
||||
HDC dc,
|
||||
RECT* rect,
|
||||
LPARAM data)
|
||||
{
|
||||
MONITORINFOEXW mi;
|
||||
ZeroMemory(&mi, sizeof(mi));
|
||||
mi.cbSize = sizeof(mi);
|
||||
|
||||
if (GetMonitorInfoW(handle, (MONITORINFO*) &mi))
|
||||
{
|
||||
_GLFWmonitor* monitor = (_GLFWmonitor*) data;
|
||||
if (wcscmp(mi.szDevice, monitor->win32.adapterName) == 0)
|
||||
monitor->win32.handle = handle;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Create monitor from an adapter and (optionally) a display
|
||||
//
|
||||
static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
||||
DISPLAY_DEVICEW* display)
|
||||
{
|
||||
_GLFWmonitor* monitor;
|
||||
int widthMM, heightMM;
|
||||
char* name;
|
||||
HDC dc;
|
||||
DEVMODEW dm;
|
||||
RECT rect;
|
||||
|
||||
if (display)
|
||||
name = _glfwCreateUTF8FromWideStringWin32(display->DeviceString);
|
||||
else
|
||||
name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString);
|
||||
if (!name)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert string to UTF-8");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZeroMemory(&dm, sizeof(dm));
|
||||
dm.dmSize = sizeof(dm);
|
||||
EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm);
|
||||
|
||||
dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
|
||||
|
||||
monitor = _glfwAllocMonitor(name,
|
||||
GetDeviceCaps(dc, HORZSIZE),
|
||||
GetDeviceCaps(dc, VERTSIZE));
|
||||
if (IsWindows8Point1OrGreater())
|
||||
{
|
||||
widthMM = GetDeviceCaps(dc, HORZSIZE);
|
||||
heightMM = GetDeviceCaps(dc, VERTSIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
widthMM = (int) (dm.dmPelsWidth * 25.4f / GetDeviceCaps(dc, LOGPIXELSX));
|
||||
heightMM = (int) (dm.dmPelsHeight * 25.4f / GetDeviceCaps(dc, LOGPIXELSY));
|
||||
}
|
||||
|
||||
DeleteDC(dc);
|
||||
|
||||
monitor = _glfwAllocMonitor(name, widthMM, heightMM);
|
||||
free(name);
|
||||
|
||||
if (adapter->StateFlags & DISPLAY_DEVICE_MODESPRUNED)
|
||||
@@ -82,6 +115,12 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
rect.left = dm.dmPosition.x;
|
||||
rect.top = dm.dmPosition.y;
|
||||
rect.right = dm.dmPosition.x + dm.dmPelsWidth;
|
||||
rect.bottom = dm.dmPosition.y + dm.dmPelsHeight;
|
||||
|
||||
EnumDisplayMonitors(NULL, &rect, monitorCallback, (LPARAM) monitor);
|
||||
return monitor;
|
||||
}
|
||||
|
||||
@@ -90,21 +129,132 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Poll for changes in the set of connected monitors
|
||||
//
|
||||
void _glfwPollMonitorsWin32(void)
|
||||
{
|
||||
int i, disconnectedCount;
|
||||
_GLFWmonitor** disconnected = NULL;
|
||||
DWORD adapterIndex, displayIndex;
|
||||
DISPLAY_DEVICEW adapter, display;
|
||||
_GLFWmonitor* monitor;
|
||||
|
||||
disconnectedCount = _glfw.monitorCount;
|
||||
if (disconnectedCount)
|
||||
{
|
||||
disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
|
||||
memcpy(disconnected,
|
||||
_glfw.monitors,
|
||||
_glfw.monitorCount * sizeof(_GLFWmonitor*));
|
||||
}
|
||||
|
||||
for (adapterIndex = 0; ; adapterIndex++)
|
||||
{
|
||||
int type = _GLFW_INSERT_LAST;
|
||||
|
||||
ZeroMemory(&adapter, sizeof(adapter));
|
||||
adapter.cb = sizeof(adapter);
|
||||
|
||||
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
|
||||
break;
|
||||
|
||||
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
||||
continue;
|
||||
|
||||
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
|
||||
type = _GLFW_INSERT_FIRST;
|
||||
|
||||
for (displayIndex = 0; ; displayIndex++)
|
||||
{
|
||||
ZeroMemory(&display, sizeof(display));
|
||||
display.cb = sizeof(display);
|
||||
|
||||
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
|
||||
break;
|
||||
|
||||
if (!(display.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
||||
continue;
|
||||
|
||||
for (i = 0; i < disconnectedCount; i++)
|
||||
{
|
||||
if (disconnected[i] &&
|
||||
wcscmp(disconnected[i]->win32.displayName,
|
||||
display.DeviceName) == 0)
|
||||
{
|
||||
disconnected[i] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < disconnectedCount)
|
||||
continue;
|
||||
|
||||
monitor = createMonitor(&adapter, &display);
|
||||
if (!monitor)
|
||||
{
|
||||
free(disconnected);
|
||||
return;
|
||||
}
|
||||
|
||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
|
||||
|
||||
type = _GLFW_INSERT_LAST;
|
||||
}
|
||||
|
||||
// HACK: If an active adapter does not have any display devices
|
||||
// (as sometimes happens), add it directly as a monitor
|
||||
if (displayIndex == 0)
|
||||
{
|
||||
for (i = 0; i < disconnectedCount; i++)
|
||||
{
|
||||
if (disconnected[i] &&
|
||||
wcscmp(disconnected[i]->win32.adapterName,
|
||||
adapter.DeviceName) == 0)
|
||||
{
|
||||
disconnected[i] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < disconnectedCount)
|
||||
continue;
|
||||
|
||||
monitor = createMonitor(&adapter, NULL);
|
||||
if (!monitor)
|
||||
{
|
||||
free(disconnected);
|
||||
return;
|
||||
}
|
||||
|
||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < disconnectedCount; i++)
|
||||
{
|
||||
if (disconnected[i])
|
||||
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
|
||||
}
|
||||
|
||||
free(disconnected);
|
||||
}
|
||||
|
||||
// Change the current video mode
|
||||
//
|
||||
GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
||||
void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
||||
{
|
||||
GLFWvidmode current;
|
||||
const GLFWvidmode* best;
|
||||
DEVMODEW dm;
|
||||
LONG result;
|
||||
|
||||
best = _glfwChooseVideoMode(monitor, desired);
|
||||
_glfwPlatformGetVideoMode(monitor, ¤t);
|
||||
if (_glfwCompareVideoModes(¤t, best) == 0)
|
||||
return GLFW_TRUE;
|
||||
return;
|
||||
|
||||
ZeroMemory(&dm, sizeof(dm));
|
||||
dm.dmSize = sizeof(DEVMODEW);
|
||||
dm.dmSize = sizeof(dm);
|
||||
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL |
|
||||
DM_DISPLAYFREQUENCY;
|
||||
dm.dmPelsWidth = best->width;
|
||||
@@ -115,18 +265,36 @@ GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desire
|
||||
if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24)
|
||||
dm.dmBitsPerPel = 32;
|
||||
|
||||
if (ChangeDisplaySettingsExW(monitor->win32.adapterName,
|
||||
&dm,
|
||||
NULL,
|
||||
CDS_FULLSCREEN,
|
||||
NULL) != DISP_CHANGE_SUCCESSFUL)
|
||||
result = ChangeDisplaySettingsExW(monitor->win32.adapterName,
|
||||
&dm,
|
||||
NULL,
|
||||
CDS_FULLSCREEN,
|
||||
NULL);
|
||||
if (result == DISP_CHANGE_SUCCESSFUL)
|
||||
monitor->win32.modeChanged = GLFW_TRUE;
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to set video mode");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
const char* description = "Unknown error";
|
||||
|
||||
monitor->win32.modeChanged = GLFW_TRUE;
|
||||
return GLFW_TRUE;
|
||||
if (result == DISP_CHANGE_BADDUALVIEW)
|
||||
description = "The system uses DualView";
|
||||
else if (result == DISP_CHANGE_BADFLAGS)
|
||||
description = "Invalid flags";
|
||||
else if (result == DISP_CHANGE_BADMODE)
|
||||
description = "Graphics mode not supported";
|
||||
else if (result == DISP_CHANGE_BADPARAM)
|
||||
description = "Invalid parameter";
|
||||
else if (result == DISP_CHANGE_FAILED)
|
||||
description = "Graphics mode failed";
|
||||
else if (result == DISP_CHANGE_NOTUPDATED)
|
||||
description = "Failed to write to registry";
|
||||
else if (result == DISP_CHANGE_RESTART)
|
||||
description = "Computer restart required";
|
||||
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to set video mode: %s",
|
||||
description);
|
||||
}
|
||||
}
|
||||
|
||||
// Restore the previously saved (original) video mode
|
||||
@@ -141,111 +309,52 @@ void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor)
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale)
|
||||
{
|
||||
UINT xdpi, ydpi;
|
||||
|
||||
if (IsWindows8Point1OrGreater())
|
||||
GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);
|
||||
else
|
||||
{
|
||||
const HDC dc = GetDC(NULL);
|
||||
xdpi = GetDeviceCaps(dc, LOGPIXELSX);
|
||||
ydpi = GetDeviceCaps(dc, LOGPIXELSY);
|
||||
ReleaseDC(NULL, dc);
|
||||
}
|
||||
|
||||
if (xscale)
|
||||
*xscale = xdpi / 96.f;
|
||||
if (yscale)
|
||||
*yscale = ydpi / 96.f;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
||||
{
|
||||
int found = 0;
|
||||
DWORD adapterIndex, displayIndex, primaryIndex = 0;
|
||||
DISPLAY_DEVICEW adapter, display;
|
||||
GLFWbool hasDisplays = GLFW_FALSE;
|
||||
_GLFWmonitor** monitors = NULL;
|
||||
|
||||
*count = 0;
|
||||
|
||||
// HACK: Check if any active adapters have connected displays
|
||||
// If not, this is a headless system or a VMware guest
|
||||
|
||||
for (adapterIndex = 0; ; adapterIndex++)
|
||||
{
|
||||
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
|
||||
adapter.cb = sizeof(DISPLAY_DEVICEW);
|
||||
|
||||
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
|
||||
break;
|
||||
|
||||
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
||||
continue;
|
||||
|
||||
ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
|
||||
display.cb = sizeof(DISPLAY_DEVICEW);
|
||||
|
||||
if (EnumDisplayDevicesW(adapter.DeviceName, 0, &display, 0))
|
||||
{
|
||||
hasDisplays = GLFW_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (adapterIndex = 0; ; adapterIndex++)
|
||||
{
|
||||
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
|
||||
adapter.cb = sizeof(DISPLAY_DEVICEW);
|
||||
|
||||
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
|
||||
break;
|
||||
|
||||
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
||||
continue;
|
||||
|
||||
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
|
||||
primaryIndex = found;
|
||||
|
||||
if (hasDisplays)
|
||||
{
|
||||
for (displayIndex = 0; ; displayIndex++)
|
||||
{
|
||||
ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
|
||||
display.cb = sizeof(DISPLAY_DEVICEW);
|
||||
|
||||
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
|
||||
break;
|
||||
|
||||
found++;
|
||||
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
|
||||
monitors[found - 1] = createMonitor(&adapter, &display);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
found++;
|
||||
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
|
||||
monitors[found - 1] = createMonitor(&adapter, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
_GLFW_SWAP_POINTERS(monitors[0], monitors[primaryIndex]);
|
||||
|
||||
*count = found;
|
||||
return monitors;
|
||||
}
|
||||
|
||||
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
|
||||
{
|
||||
if (wcslen(first->win32.displayName))
|
||||
return wcscmp(first->win32.displayName, second->win32.displayName) == 0;
|
||||
else
|
||||
return wcscmp(first->win32.adapterName, second->win32.adapterName) == 0;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
{
|
||||
DEVMODEW settings;
|
||||
ZeroMemory(&settings, sizeof(DEVMODEW));
|
||||
settings.dmSize = sizeof(DEVMODEW);
|
||||
DEVMODEW dm;
|
||||
ZeroMemory(&dm, sizeof(dm));
|
||||
dm.dmSize = sizeof(dm);
|
||||
|
||||
EnumDisplaySettingsExW(monitor->win32.adapterName,
|
||||
ENUM_CURRENT_SETTINGS,
|
||||
&settings,
|
||||
&dm,
|
||||
EDS_ROTATEDMODE);
|
||||
|
||||
if (xpos)
|
||||
*xpos = settings.dmPosition.x;
|
||||
*xpos = dm.dmPosition.x;
|
||||
if (ypos)
|
||||
*ypos = settings.dmPosition.y;
|
||||
*ypos = dm.dmPosition.y;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||
float* xscale, float* yscale)
|
||||
{
|
||||
_glfwGetMonitorContentScaleWin32(monitor->win32.handle, xscale, yscale);
|
||||
}
|
||||
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||
@@ -261,8 +370,8 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||
GLFWvidmode mode;
|
||||
DEVMODEW dm;
|
||||
|
||||
ZeroMemory(&dm, sizeof(DEVMODEW));
|
||||
dm.dmSize = sizeof(DEVMODEW);
|
||||
ZeroMemory(&dm, sizeof(dm));
|
||||
dm.dmSize = sizeof(dm);
|
||||
|
||||
if (!EnumDisplaySettingsW(monitor->win32.adapterName, modeIndex, &dm))
|
||||
break;
|
||||
@@ -328,9 +437,8 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||
{
|
||||
DEVMODEW dm;
|
||||
|
||||
ZeroMemory(&dm, sizeof(DEVMODEW));
|
||||
dm.dmSize = sizeof(DEVMODEW);
|
||||
ZeroMemory(&dm, sizeof(dm));
|
||||
dm.dmSize = sizeof(dm);
|
||||
|
||||
EnumDisplaySettingsW(monitor->win32.adapterName, ENUM_CURRENT_SETTINGS, &dm);
|
||||
|
||||
|
||||
+99
-46
@@ -25,9 +25,6 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_win32_platform_h_
|
||||
#define _glfw3_win32_platform_h_
|
||||
|
||||
// We don't need all the fancy stuff
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
@@ -66,16 +63,10 @@
|
||||
|
||||
#include <wctype.h>
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#include <dinput.h>
|
||||
#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
|
||||
@@ -104,28 +95,64 @@
|
||||
#ifndef DISPLAY_DEVICE_ACTIVE
|
||||
#define DISPLAY_DEVICE_ACTIVE 0x00000001
|
||||
#endif
|
||||
#ifndef _WIN32_WINNT_WINBLUE
|
||||
#define _WIN32_WINNT_WINBLUE 0x0602
|
||||
#endif
|
||||
|
||||
#if WINVER < 0x0601
|
||||
typedef struct tagCHANGEFILTERSTRUCT
|
||||
typedef struct
|
||||
{
|
||||
DWORD cbSize;
|
||||
DWORD ExtStatus;
|
||||
|
||||
} CHANGEFILTERSTRUCT, *PCHANGEFILTERSTRUCT;
|
||||
} CHANGEFILTERSTRUCT;
|
||||
#ifndef MSGFLT_ALLOW
|
||||
#define MSGFLT_ALLOW 1
|
||||
#endif
|
||||
#endif /*Windows 7*/
|
||||
|
||||
#if WINVER < 0x0600
|
||||
#define DWM_BB_ENABLE 0x00000001
|
||||
#define DWM_BB_BLURREGION 0x00000002
|
||||
typedef struct
|
||||
{
|
||||
DWORD dwFlags;
|
||||
BOOL fEnable;
|
||||
HRGN hRgnBlur;
|
||||
BOOL fTransitionOnMaximized;
|
||||
} DWM_BLURBEHIND;
|
||||
#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
|
||||
{
|
||||
MDT_EFFECTIVE_DPI = 0,
|
||||
MDT_ANGULAR_DPI = 1,
|
||||
MDT_RAW_DPI = 2,
|
||||
MDT_DEFAULT = MDT_EFFECTIVE_DPI
|
||||
} MONITOR_DPI_TYPE;
|
||||
#endif /*DPI_ENUMS_DECLARED*/
|
||||
|
||||
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
|
||||
BOOL IsWindowsVersionOrGreater(WORD major, WORD minor, WORD sp);
|
||||
#define IsWindowsVistaOrGreater() \
|
||||
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), \
|
||||
LOBYTE(_WIN32_WINNT_VISTA), 0)
|
||||
#define IsWindows7OrGreater() \
|
||||
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), \
|
||||
LOBYTE(_WIN32_WINNT_WIN7), 0)
|
||||
#define IsWindows8OrGreater() \
|
||||
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), \
|
||||
LOBYTE(_WIN32_WINNT_WIN8), 0)
|
||||
#define IsWindows8Point1OrGreater() \
|
||||
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), \
|
||||
LOBYTE(_WIN32_WINNT_WINBLUE), 0)
|
||||
|
||||
// HACK: Define macros that some xinput.h variants don't
|
||||
#ifndef XINPUT_CAPS_WIRELESS
|
||||
#define XINPUT_CAPS_WIRELESS 0x0002
|
||||
@@ -162,33 +189,37 @@ typedef enum PROCESS_DPI_AWARENESS
|
||||
|
||||
// winmm.dll function pointer typedefs
|
||||
typedef DWORD (WINAPI * PFN_timeGetTime)(void);
|
||||
#define _glfw_timeGetTime _glfw.win32.winmm.timeGetTime
|
||||
#define timeGetTime _glfw.win32.winmm.GetTime
|
||||
|
||||
// xinput.dll function pointer typedefs
|
||||
typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*);
|
||||
typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
|
||||
#define _glfw_XInputGetCapabilities _glfw.win32.xinput.XInputGetCapabilities
|
||||
#define _glfw_XInputGetState _glfw.win32.xinput.XInputGetState
|
||||
#define XInputGetCapabilities _glfw.win32.xinput.GetCapabilities
|
||||
#define XInputGetState _glfw.win32.xinput.GetState
|
||||
|
||||
// dinput8.dll function pointer typedefs
|
||||
typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
|
||||
#define _glfw_DirectInput8Create _glfw.win32.dinput8.DirectInput8Create
|
||||
#define DirectInput8Create _glfw.win32.dinput8.Create
|
||||
|
||||
// user32.dll function pointer typedefs
|
||||
typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void);
|
||||
typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,PCHANGEFILTERSTRUCT);
|
||||
#define _glfw_SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware
|
||||
#define _glfw_ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx
|
||||
typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,CHANGEFILTERSTRUCT*);
|
||||
#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
|
||||
#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
|
||||
|
||||
// dwmapi.dll function pointer typedefs
|
||||
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
||||
typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
|
||||
#define _glfw_DwmIsCompositionEnabled _glfw.win32.dwmapi.DwmIsCompositionEnabled
|
||||
#define _glfw_DwmFlush _glfw.win32.dwmapi.DwmFlush
|
||||
typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*);
|
||||
#define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled
|
||||
#define DwmFlush _glfw.win32.dwmapi.Flush
|
||||
#define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow
|
||||
|
||||
// shcore.dll function pointer typedefs
|
||||
typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
|
||||
#define _glfw_SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness
|
||||
typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);
|
||||
#define SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness_
|
||||
#define GetDpiForMonitor _glfw.win32.shcore.GetDpiForMonitor_
|
||||
|
||||
typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
|
||||
|
||||
@@ -207,6 +238,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
|
||||
#include "win32_joystick.h"
|
||||
#include "wgl_context.h"
|
||||
#include "egl_context.h"
|
||||
#include "osmesa_context.h"
|
||||
|
||||
#define _GLFW_WNDCLASSNAME L"GLFW30"
|
||||
|
||||
@@ -219,10 +251,11 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
|
||||
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time
|
||||
#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsWin32 win32_tls
|
||||
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerWin32 win32
|
||||
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 win32
|
||||
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWin32 win32
|
||||
#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsWin32 win32
|
||||
#define _GLFW_PLATFORM_MUTEX_STATE _GLFWmutexWin32 win32
|
||||
|
||||
|
||||
// Win32-specific per-window data
|
||||
@@ -234,8 +267,11 @@ typedef struct _GLFWwindowWin32
|
||||
HICON smallIcon;
|
||||
|
||||
GLFWbool cursorTracked;
|
||||
GLFWbool frameAction;
|
||||
GLFWbool iconified;
|
||||
GLFWbool maximized;
|
||||
// Whether to enable framebuffer transparency on DWM
|
||||
GLFWbool transparent;
|
||||
|
||||
// The last received cursor position, regardless of source
|
||||
int lastCursorPosX, lastCursorPosY;
|
||||
@@ -247,48 +283,54 @@ typedef struct _GLFWwindowWin32
|
||||
typedef struct _GLFWlibraryWin32
|
||||
{
|
||||
HWND helperWindowHandle;
|
||||
HDEVNOTIFY deviceNotificationHandle;
|
||||
DWORD foregroundLockTimeout;
|
||||
int acquiredMonitorCount;
|
||||
char* clipboardString;
|
||||
char keyName[64];
|
||||
short int keycodes[512];
|
||||
short int scancodes[GLFW_KEY_LAST + 1];
|
||||
char keynames[GLFW_KEY_LAST + 1][5];
|
||||
// Where to place the cursor when re-enabled
|
||||
double restoreCursorPosX, restoreCursorPosY;
|
||||
// The window whose disabled cursor mode is active
|
||||
_GLFWwindow* disabledCursorWindow;
|
||||
RAWINPUT* rawInput;
|
||||
int rawInputSize;
|
||||
|
||||
struct {
|
||||
HINSTANCE instance;
|
||||
PFN_timeGetTime timeGetTime;
|
||||
PFN_timeGetTime GetTime;
|
||||
} winmm;
|
||||
|
||||
struct {
|
||||
HINSTANCE instance;
|
||||
PFN_DirectInput8Create DirectInput8Create;
|
||||
PFN_DirectInput8Create Create;
|
||||
IDirectInput8W* api;
|
||||
} dinput8;
|
||||
|
||||
struct {
|
||||
HINSTANCE instance;
|
||||
PFN_XInputGetCapabilities XInputGetCapabilities;
|
||||
PFN_XInputGetState XInputGetState;
|
||||
PFN_XInputGetCapabilities GetCapabilities;
|
||||
PFN_XInputGetState GetState;
|
||||
} xinput;
|
||||
|
||||
struct {
|
||||
HINSTANCE instance;
|
||||
PFN_SetProcessDPIAware SetProcessDPIAware;
|
||||
PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx;
|
||||
PFN_SetProcessDPIAware SetProcessDPIAware_;
|
||||
PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx_;
|
||||
} user32;
|
||||
|
||||
struct {
|
||||
HINSTANCE instance;
|
||||
PFN_DwmIsCompositionEnabled DwmIsCompositionEnabled;
|
||||
PFN_DwmFlush DwmFlush;
|
||||
PFN_DwmIsCompositionEnabled IsCompositionEnabled;
|
||||
PFN_DwmFlush Flush;
|
||||
PFN_DwmEnableBlurBehindWindow EnableBlurBehindWindow;
|
||||
} dwmapi;
|
||||
|
||||
struct {
|
||||
HINSTANCE instance;
|
||||
PFN_SetProcessDpiAwareness SetProcessDpiAwareness;
|
||||
PFN_SetProcessDpiAwareness SetProcessDpiAwareness_;
|
||||
PFN_GetDpiForMonitor GetDpiForMonitor_;
|
||||
} shcore;
|
||||
|
||||
} _GLFWlibraryWin32;
|
||||
@@ -297,11 +339,12 @@ typedef struct _GLFWlibraryWin32
|
||||
//
|
||||
typedef struct _GLFWmonitorWin32
|
||||
{
|
||||
HMONITOR handle;
|
||||
// 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;
|
||||
|
||||
@@ -317,35 +360,45 @@ typedef struct _GLFWcursorWin32
|
||||
|
||||
// Win32-specific global timer data
|
||||
//
|
||||
typedef struct _GLFWtimeWin32
|
||||
typedef struct _GLFWtimerWin32
|
||||
{
|
||||
GLFWbool hasPC;
|
||||
uint64_t frequency;
|
||||
|
||||
} _GLFWtimeWin32;
|
||||
} _GLFWtimerWin32;
|
||||
|
||||
// Win32-specific global TLS data
|
||||
// Win32-specific thread local storage data
|
||||
//
|
||||
typedef struct _GLFWtlsWin32
|
||||
{
|
||||
GLFWbool allocated;
|
||||
DWORD context;
|
||||
DWORD index;
|
||||
|
||||
} _GLFWtlsWin32;
|
||||
|
||||
// Win32-specific mutex data
|
||||
//
|
||||
typedef struct _GLFWmutexWin32
|
||||
{
|
||||
GLFWbool allocated;
|
||||
CRITICAL_SECTION section;
|
||||
|
||||
} _GLFWmutexWin32;
|
||||
|
||||
|
||||
GLFWbool _glfwRegisterWindowClassWin32(void);
|
||||
void _glfwUnregisterWindowClassWin32(void);
|
||||
|
||||
GLFWbool _glfwInitThreadLocalStorageWin32(void);
|
||||
void _glfwTerminateThreadLocalStorageWin32(void);
|
||||
GLFWbool _glfwIsCompositionEnabledWin32(void);
|
||||
|
||||
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
|
||||
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
|
||||
void _glfwInputErrorWin32(int error, const char* description);
|
||||
void _glfwUpdateKeyNamesWin32(void);
|
||||
|
||||
void _glfwInitTimerWin32(void);
|
||||
|
||||
GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||
void _glfwPollMonitorsWin32(void);
|
||||
void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
|
||||
void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale);
|
||||
|
||||
#endif // _glfw3_win32_platform_h_
|
||||
|
||||
@@ -27,43 +27,71 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWbool _glfwInitThreadLocalStorageWin32(void)
|
||||
{
|
||||
_glfw.win32_tls.context = TlsAlloc();
|
||||
if (_glfw.win32_tls.context == TLS_OUT_OF_INDEXES)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to allocate TLS index");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.win32_tls.allocated = GLFW_TRUE;
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwTerminateThreadLocalStorageWin32(void)
|
||||
{
|
||||
if (_glfw.win32_tls.allocated)
|
||||
TlsFree(_glfw.win32_tls.context);
|
||||
}
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwPlatformSetCurrentContext(_GLFWwindow* context)
|
||||
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
|
||||
{
|
||||
TlsSetValue(_glfw.win32_tls.context, context);
|
||||
assert(tls->win32.allocated == GLFW_FALSE);
|
||||
|
||||
tls->win32.index = TlsAlloc();
|
||||
if (tls->win32.index == TLS_OUT_OF_INDEXES)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to allocate TLS index");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
tls->win32.allocated = GLFW_TRUE;
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
_GLFWwindow* _glfwPlatformGetCurrentContext(void)
|
||||
void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
||||
{
|
||||
return TlsGetValue(_glfw.win32_tls.context);
|
||||
if (tls->win32.allocated)
|
||||
TlsFree(tls->win32.index);
|
||||
memset(tls, 0, sizeof(_GLFWtls));
|
||||
}
|
||||
|
||||
void* _glfwPlatformGetTls(_GLFWtls* tls)
|
||||
{
|
||||
assert(tls->win32.allocated == GLFW_TRUE);
|
||||
return TlsGetValue(tls->win32.index);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
|
||||
{
|
||||
assert(tls->win32.allocated == GLFW_TRUE);
|
||||
TlsSetValue(tls->win32.index, value);
|
||||
}
|
||||
|
||||
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
assert(mutex->win32.allocated == GLFW_FALSE);
|
||||
InitializeCriticalSection(&mutex->win32.section);
|
||||
return mutex->win32.allocated = GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
if (mutex->win32.allocated)
|
||||
DeleteCriticalSection(&mutex->win32.section);
|
||||
memset(mutex, 0, sizeof(_GLFWmutex));
|
||||
}
|
||||
|
||||
void _glfwPlatformLockMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
assert(mutex->win32.allocated == GLFW_TRUE);
|
||||
EnterCriticalSection(&mutex->win32.section);
|
||||
}
|
||||
|
||||
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
assert(mutex->win32.allocated == GLFW_TRUE);
|
||||
LeaveCriticalSection(&mutex->win32.section);
|
||||
}
|
||||
|
||||
+7
-7
@@ -40,13 +40,13 @@ void _glfwInitTimerWin32(void)
|
||||
|
||||
if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
|
||||
{
|
||||
_glfw.win32_time.hasPC = GLFW_TRUE;
|
||||
_glfw.win32_time.frequency = frequency;
|
||||
_glfw.timer.win32.hasPC = GLFW_TRUE;
|
||||
_glfw.timer.win32.frequency = frequency;
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfw.win32_time.hasPC = GLFW_FALSE;
|
||||
_glfw.win32_time.frequency = 1000;
|
||||
_glfw.timer.win32.hasPC = GLFW_FALSE;
|
||||
_glfw.timer.win32.frequency = 1000;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,18 +57,18 @@ void _glfwInitTimerWin32(void)
|
||||
|
||||
uint64_t _glfwPlatformGetTimerValue(void)
|
||||
{
|
||||
if (_glfw.win32_time.hasPC)
|
||||
if (_glfw.timer.win32.hasPC)
|
||||
{
|
||||
uint64_t value;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*) &value);
|
||||
return value;
|
||||
}
|
||||
else
|
||||
return (uint64_t) _glfw_timeGetTime();
|
||||
return (uint64_t) timeGetTime();
|
||||
}
|
||||
|
||||
uint64_t _glfwPlatformGetTimerFrequency(void)
|
||||
{
|
||||
return _glfw.win32_time.frequency;
|
||||
return _glfw.timer.win32.frequency;
|
||||
}
|
||||
|
||||
|
||||
+450
-194
File diff suppressed because it is too large
Load Diff
+242
-122
@@ -38,72 +38,96 @@
|
||||
////// GLFW event API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Notifies shared code that a window has lost or received input focus
|
||||
//
|
||||
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
|
||||
{
|
||||
if (focused)
|
||||
{
|
||||
if (window->callbacks.focus)
|
||||
window->callbacks.focus((GLFWwindow*) window, focused);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
if (window->callbacks.focus)
|
||||
window->callbacks.focus((GLFWwindow*) window, focused);
|
||||
|
||||
if (window->callbacks.focus)
|
||||
window->callbacks.focus((GLFWwindow*) window, focused);
|
||||
if (!focused)
|
||||
{
|
||||
int key, button;
|
||||
|
||||
// Release all pressed keyboard keys
|
||||
for (i = 0; i <= GLFW_KEY_LAST; i++)
|
||||
for (key = 0; key <= GLFW_KEY_LAST; key++)
|
||||
{
|
||||
if (window->keys[i] == GLFW_PRESS)
|
||||
_glfwInputKey(window, i, 0, GLFW_RELEASE, 0);
|
||||
if (window->keys[key] == GLFW_PRESS)
|
||||
{
|
||||
const int scancode = _glfwPlatformGetKeyScancode(key);
|
||||
_glfwInputKey(window, key, scancode, GLFW_RELEASE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Release all pressed mouse buttons
|
||||
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
|
||||
for (button = 0; button <= GLFW_MOUSE_BUTTON_LAST; button++)
|
||||
{
|
||||
if (window->mouseButtons[i] == GLFW_PRESS)
|
||||
_glfwInputMouseClick(window, i, GLFW_RELEASE, 0);
|
||||
if (window->mouseButtons[button] == GLFW_PRESS)
|
||||
_glfwInputMouseClick(window, button, GLFW_RELEASE, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
@@ -112,7 +136,9 @@ void _glfwInputWindowCloseRequest(_GLFWwindow* window)
|
||||
window->callbacks.close((GLFWwindow*) window);
|
||||
}
|
||||
|
||||
void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor)
|
||||
// Notifies shared code that a window has changed its desired monitor
|
||||
//
|
||||
void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor)
|
||||
{
|
||||
window->monitor = monitor;
|
||||
}
|
||||
@@ -131,9 +157,10 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
||||
_GLFWctxconfig ctxconfig;
|
||||
_GLFWwndconfig wndconfig;
|
||||
_GLFWwindow* window;
|
||||
_GLFWwindow* previous;
|
||||
|
||||
assert(title != NULL);
|
||||
assert(width >= 0);
|
||||
assert(height >= 0);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
@@ -155,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;
|
||||
|
||||
@@ -193,36 +210,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 = _glfwPlatformGetCurrentContext();
|
||||
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)
|
||||
{
|
||||
@@ -239,23 +252,25 @@ void glfwDefaultWindowHints(void)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
memset(&_glfw.hints, 0, sizeof(_glfw.hints));
|
||||
|
||||
// The default is OpenGL with minimum version 1.0
|
||||
memset(&_glfw.hints.context, 0, sizeof(_glfw.hints.context));
|
||||
_glfw.hints.context.client = GLFW_OPENGL_API;
|
||||
_glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API;
|
||||
_glfw.hints.context.major = 1;
|
||||
_glfw.hints.context.minor = 0;
|
||||
|
||||
// The default is a focused, visible, resizable window with decorations
|
||||
_glfw.hints.window.resizable = GLFW_TRUE;
|
||||
_glfw.hints.window.visible = GLFW_TRUE;
|
||||
_glfw.hints.window.decorated = GLFW_TRUE;
|
||||
_glfw.hints.window.focused = GLFW_TRUE;
|
||||
_glfw.hints.window.autoIconify = GLFW_TRUE;
|
||||
memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
|
||||
_glfw.hints.window.resizable = GLFW_TRUE;
|
||||
_glfw.hints.window.visible = GLFW_TRUE;
|
||||
_glfw.hints.window.decorated = GLFW_TRUE;
|
||||
_glfw.hints.window.focused = GLFW_TRUE;
|
||||
_glfw.hints.window.autoIconify = GLFW_TRUE;
|
||||
_glfw.hints.window.centerCursor = GLFW_TRUE;
|
||||
|
||||
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
|
||||
// double buffered
|
||||
memset(&_glfw.hints.framebuffer, 0, sizeof(_glfw.hints.framebuffer));
|
||||
_glfw.hints.framebuffer.redBits = 8;
|
||||
_glfw.hints.framebuffer.greenBits = 8;
|
||||
_glfw.hints.framebuffer.blueBits = 8;
|
||||
@@ -279,110 +294,143 @@ GLFWAPI void glfwWindowHint(int hint, int value)
|
||||
{
|
||||
case GLFW_RED_BITS:
|
||||
_glfw.hints.framebuffer.redBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_GREEN_BITS:
|
||||
_glfw.hints.framebuffer.greenBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_BLUE_BITS:
|
||||
_glfw.hints.framebuffer.blueBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_ALPHA_BITS:
|
||||
_glfw.hints.framebuffer.alphaBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_DEPTH_BITS:
|
||||
_glfw.hints.framebuffer.depthBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_STENCIL_BITS:
|
||||
_glfw.hints.framebuffer.stencilBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_ACCUM_RED_BITS:
|
||||
_glfw.hints.framebuffer.accumRedBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_ACCUM_GREEN_BITS:
|
||||
_glfw.hints.framebuffer.accumGreenBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_ACCUM_BLUE_BITS:
|
||||
_glfw.hints.framebuffer.accumBlueBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_ACCUM_ALPHA_BITS:
|
||||
_glfw.hints.framebuffer.accumAlphaBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_AUX_BUFFERS:
|
||||
_glfw.hints.framebuffer.auxBuffers = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_STEREO:
|
||||
_glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_DOUBLEBUFFER:
|
||||
_glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_TRANSPARENT_FRAMEBUFFER:
|
||||
_glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
return;
|
||||
case GLFW_SAMPLES:
|
||||
_glfw.hints.framebuffer.samples = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_SRGB_CAPABLE:
|
||||
_glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_RESIZABLE:
|
||||
_glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_DECORATED:
|
||||
_glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_FOCUSED:
|
||||
_glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_AUTO_ICONIFY:
|
||||
_glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_FLOATING:
|
||||
_glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_MAXIMIZED:
|
||||
_glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_VISIBLE:
|
||||
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_COCOA_RETINA_FRAMEBUFFER:
|
||||
_glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_COCOA_GRAPHICS_SWITCHING:
|
||||
_glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
return;
|
||||
case GLFW_CENTER_CURSOR:
|
||||
_glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
return;
|
||||
case GLFW_CLIENT_API:
|
||||
_glfw.hints.context.client = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_CONTEXT_CREATION_API:
|
||||
_glfw.hints.context.source = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_CONTEXT_VERSION_MAJOR:
|
||||
_glfw.hints.context.major = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_CONTEXT_VERSION_MINOR:
|
||||
_glfw.hints.context.minor = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_CONTEXT_ROBUSTNESS:
|
||||
_glfw.hints.context.robustness = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_OPENGL_FORWARD_COMPAT:
|
||||
_glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_OPENGL_DEBUG_CONTEXT:
|
||||
_glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_CONTEXT_NO_ERROR:
|
||||
_glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_OPENGL_PROFILE:
|
||||
_glfw.hints.context.profile = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_CONTEXT_RELEASE_BEHAVIOR:
|
||||
_glfw.hints.context.release = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_REFRESH_RATE:
|
||||
_glfw.hints.refreshRate = value;
|
||||
break;
|
||||
default:
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint %i", hint);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
_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)
|
||||
@@ -400,7 +448,7 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
|
||||
|
||||
// The window's context must not be current on another thread when the
|
||||
// window is destroyed
|
||||
if (window == _glfwPlatformGetCurrentContext())
|
||||
if (window == _glfwPlatformGetTls(&_glfw.contextSlot))
|
||||
glfwMakeContextCurrent(NULL);
|
||||
|
||||
_glfwPlatformDestroyWindow(window);
|
||||
@@ -440,7 +488,6 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
assert(title != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
@@ -504,6 +551,8 @@ GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
assert(width >= 0);
|
||||
assert(height >= 0);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
@@ -562,6 +611,8 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
assert(numer != 0);
|
||||
assert(denom != 0);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
@@ -619,6 +670,49 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle,
|
||||
_glfwPlatformGetWindowFrameSize(window, left, top, right, bottom);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle,
|
||||
float* xscale, float* yscale)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
if (xscale)
|
||||
*xscale = 0.f;
|
||||
if (yscale)
|
||||
*yscale = 0.f;
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
_glfwPlatformGetWindowContentScale(window, xscale, yscale);
|
||||
}
|
||||
|
||||
GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(1.f);
|
||||
return _glfwPlatformGetWindowOpacity(window);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
assert(opacity == opacity);
|
||||
assert(opacity >= 0.f);
|
||||
assert(opacity <= 1.f);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
if (opacity != opacity || opacity < 0.f || opacity > 1.f)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_VALUE, "Invalid window opacity %f", opacity);
|
||||
return;
|
||||
}
|
||||
|
||||
_glfwPlatformSetWindowOpacity(window, opacity);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwIconifyWindow(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
@@ -664,6 +758,16 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle)
|
||||
_glfwPlatformFocusWindow(window);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
_glfwPlatformRequestWindowAttention(window);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwHideWindow(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
@@ -704,6 +808,10 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
|
||||
return _glfwPlatformWindowVisible(window);
|
||||
case GLFW_MAXIMIZED:
|
||||
return _glfwPlatformWindowMaximized(window);
|
||||
case GLFW_HOVERED:
|
||||
return _glfwPlatformWindowHovered(window);
|
||||
case GLFW_TRANSPARENT_FRAMEBUFFER:
|
||||
return _glfwPlatformFramebufferTransparent(window);
|
||||
case GLFW_RESIZABLE:
|
||||
return window->resizable;
|
||||
case GLFW_DECORATED:
|
||||
@@ -736,7 +844,7 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
|
||||
return window->context.noerror;
|
||||
}
|
||||
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute %i", attrib);
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -749,41 +857,37 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
|
||||
|
||||
value = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
|
||||
switch (attrib)
|
||||
if (attrib == GLFW_AUTO_ICONIFY)
|
||||
window->autoIconify = value;
|
||||
else if (attrib == GLFW_RESIZABLE)
|
||||
{
|
||||
case GLFW_RESIZABLE:
|
||||
if (window->resizable != value)
|
||||
{
|
||||
window->resizable = value;
|
||||
if (!window->monitor)
|
||||
_glfwPlatformSetWindowResizable(window, value);
|
||||
}
|
||||
if (window->resizable == value)
|
||||
return;
|
||||
|
||||
case GLFW_DECORATED:
|
||||
if (window->decorated != value)
|
||||
{
|
||||
window->decorated = value;
|
||||
if (!window->monitor)
|
||||
_glfwPlatformSetWindowDecorated(window, value);
|
||||
}
|
||||
return;
|
||||
|
||||
case GLFW_FLOATING:
|
||||
if (window->floating != value)
|
||||
{
|
||||
window->floating = value;
|
||||
if (!window->monitor)
|
||||
_glfwPlatformSetWindowFloating(window, value);
|
||||
}
|
||||
return;
|
||||
|
||||
case GLFW_AUTO_ICONIFY:
|
||||
window->autoIconify = value;
|
||||
return;
|
||||
window->resizable = value;
|
||||
if (!window->monitor)
|
||||
_glfwPlatformSetWindowResizable(window, value);
|
||||
}
|
||||
else if (attrib == GLFW_DECORATED)
|
||||
{
|
||||
if (window->decorated == value)
|
||||
return;
|
||||
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute %i", attrib);
|
||||
window->decorated = value;
|
||||
if (!window->monitor)
|
||||
_glfwPlatformSetWindowDecorated(window, value);
|
||||
}
|
||||
else if (attrib == GLFW_FLOATING)
|
||||
{
|
||||
if (window->floating == value)
|
||||
return;
|
||||
|
||||
window->floating = value;
|
||||
if (!window->monitor)
|
||||
_glfwPlatformSetWindowFloating(window, value);
|
||||
}
|
||||
else
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
|
||||
}
|
||||
|
||||
GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle)
|
||||
@@ -804,6 +908,8 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,
|
||||
_GLFWwindow* window = (_GLFWwindow*) wh;
|
||||
_GLFWmonitor* monitor = (_GLFWmonitor*) mh;
|
||||
assert(window != NULL);
|
||||
assert(width >= 0);
|
||||
assert(height >= 0);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
@@ -938,6 +1044,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();
|
||||
@@ -957,6 +1074,9 @@ GLFWAPI void glfwWaitEvents(void)
|
||||
GLFWAPI void glfwWaitEventsTimeout(double timeout)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT();
|
||||
assert(timeout == timeout);
|
||||
assert(timeout >= 0.0);
|
||||
assert(timeout <= DBL_MAX);
|
||||
|
||||
if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)
|
||||
{
|
||||
|
||||
+183
-37
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <linux/input.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -33,7 +34,6 @@
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <wayland-client.h>
|
||||
#include <wayland-cursor.h>
|
||||
|
||||
|
||||
static inline int min(int n1, int n2)
|
||||
@@ -48,11 +48,17 @@ static void pointerHandleEnter(void* data,
|
||||
wl_fixed_t sx,
|
||||
wl_fixed_t sy)
|
||||
{
|
||||
// Happens in the case we just destroyed the surface.
|
||||
if (!surface)
|
||||
return;
|
||||
|
||||
_GLFWwindow* window = wl_surface_get_user_data(surface);
|
||||
|
||||
_glfw.wl.pointerSerial = serial;
|
||||
_glfw.wl.pointerFocus = window;
|
||||
|
||||
window->wl.hovered = GLFW_TRUE;
|
||||
|
||||
_glfwPlatformSetCursor(window, window->wl.currentCursor);
|
||||
_glfwInputCursorEnter(window, GLFW_TRUE);
|
||||
}
|
||||
@@ -67,6 +73,8 @@ 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);
|
||||
@@ -109,6 +117,8 @@ static void pointerHandleButton(void* data,
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
_glfw.wl.pointerSerial = serial;
|
||||
|
||||
/* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
|
||||
* codes. */
|
||||
glfwButton = button - BTN_LEFT;
|
||||
@@ -128,30 +138,22 @@ static void pointerHandleAxis(void* data,
|
||||
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:
|
||||
x = wl_fixed_to_double(value) * scrollFactor;
|
||||
y = 0.0;
|
||||
break;
|
||||
case WL_POINTER_AXIS_VERTICAL_SCROLL:
|
||||
x = 0.0;
|
||||
y = wl_fixed_to_double(value) * scrollFactor;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
|
||||
x = wl_fixed_to_double(value) * scrollFactor;
|
||||
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
|
||||
y = wl_fixed_to_double(value) * scrollFactor;
|
||||
|
||||
_glfwInputScroll(window, x, y);
|
||||
}
|
||||
@@ -172,8 +174,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;
|
||||
|
||||
@@ -221,6 +227,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);
|
||||
@@ -240,6 +247,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);
|
||||
@@ -254,6 +262,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,
|
||||
@@ -262,6 +274,10 @@ 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);
|
||||
|
||||
_glfw.wl.keyboardFocus = window;
|
||||
@@ -290,9 +306,10 @@ 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)
|
||||
if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
|
||||
return sym;
|
||||
if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym)
|
||||
!= XKB_COMPOSE_FEED_ACCEPTED)
|
||||
@@ -309,6 +326,7 @@ static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
|
||||
return sym;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void inputChar(_GLFWwindow* window, uint32_t key)
|
||||
{
|
||||
@@ -322,7 +340,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)
|
||||
{
|
||||
@@ -393,6 +415,10 @@ 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;
|
||||
}
|
||||
|
||||
@@ -435,6 +461,17 @@ static const struct wl_seat_listener seatListener = {
|
||||
seatHandleCapabilities
|
||||
};
|
||||
|
||||
static void wmBaseHandlePing(void* data,
|
||||
struct xdg_wm_base* wmBase,
|
||||
uint32_t serial)
|
||||
{
|
||||
xdg_wm_base_pong(wmBase, serial);
|
||||
}
|
||||
|
||||
static const struct xdg_wm_base_listener wmBaseListener = {
|
||||
wmBaseHandlePing
|
||||
};
|
||||
|
||||
static void registryHandleGlobal(void* data,
|
||||
struct wl_registry* registry,
|
||||
uint32_t name,
|
||||
@@ -471,6 +508,12 @@ static void registryHandleGlobal(void* data,
|
||||
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, "zwp_relative_pointer_manager_v1") == 0)
|
||||
{
|
||||
_glfw.wl.relativePointerManager =
|
||||
@@ -485,6 +528,13 @@ 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,
|
||||
@@ -519,6 +569,7 @@ static void createKeyTables(void)
|
||||
_glfw.wl.keycodes[KEY_8] = GLFW_KEY_8;
|
||||
_glfw.wl.keycodes[KEY_9] = GLFW_KEY_9;
|
||||
_glfw.wl.keycodes[KEY_0] = GLFW_KEY_0;
|
||||
_glfw.wl.keycodes[KEY_SPACE] = GLFW_KEY_SPACE;
|
||||
_glfw.wl.keycodes[KEY_MINUS] = GLFW_KEY_MINUS;
|
||||
_glfw.wl.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL;
|
||||
_glfw.wl.keycodes[KEY_Q] = GLFW_KEY_Q;
|
||||
@@ -639,6 +690,84 @@ static void createKeyTables(void)
|
||||
|
||||
int _glfwPlatformInit(void)
|
||||
{
|
||||
_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.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)
|
||||
{
|
||||
@@ -650,9 +779,6 @@ int _glfwPlatformInit(void)
|
||||
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
||||
wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
|
||||
|
||||
_glfw.wl.monitors = calloc(4, sizeof(_GLFWmonitor*));
|
||||
_glfw.wl.monitorsSize = 4;
|
||||
|
||||
createKeyTables();
|
||||
|
||||
_glfw.wl.xkb.context = xkb_context_new(0);
|
||||
@@ -669,9 +795,6 @@ int _glfwPlatformInit(void)
|
||||
// Sync so we got all initial output events
|
||||
wl_display_roundtrip(_glfw.wl.display);
|
||||
|
||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!_glfwInitJoysticksLinux())
|
||||
return GLFW_FALSE;
|
||||
|
||||
@@ -683,7 +806,7 @@ int _glfwPlatformInit(void)
|
||||
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;
|
||||
}
|
||||
_glfw.wl.cursorSurface =
|
||||
@@ -695,17 +818,38 @@ int _glfwPlatformInit(void)
|
||||
|
||||
void _glfwPlatformTerminate(void)
|
||||
{
|
||||
_glfwTerminateEGL();
|
||||
_glfwTerminateJoysticksLinux();
|
||||
_glfwTerminateThreadLocalStoragePOSIX();
|
||||
_glfwTerminateEGL();
|
||||
if (_glfw.wl.egl.handle)
|
||||
{
|
||||
_glfw_dlclose(_glfw.wl.egl.handle);
|
||||
_glfw.wl.egl.handle = NULL;
|
||||
}
|
||||
|
||||
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
|
||||
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
||||
xkb_state_unref(_glfw.wl.xkb.state);
|
||||
xkb_context_unref(_glfw.wl.xkb.context);
|
||||
#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.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.compositor)
|
||||
@@ -714,6 +858,8 @@ void _glfwPlatformTerminate(void)
|
||||
wl_shm_destroy(_glfw.wl.shm);
|
||||
if (_glfw.wl.shell)
|
||||
wl_shell_destroy(_glfw.wl.shell);
|
||||
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)
|
||||
@@ -724,6 +870,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)
|
||||
@@ -741,9 +889,7 @@ const char* _glfwPlatformGetVersionString(void)
|
||||
#else
|
||||
" gettimeofday"
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
" /dev/js"
|
||||
#endif
|
||||
" evdev"
|
||||
#if defined(_GLFW_BUILD_DLL)
|
||||
" shared"
|
||||
#endif
|
||||
|
||||
+31
-106
@@ -32,12 +32,6 @@
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
struct _GLFWvidmodeWayland
|
||||
{
|
||||
GLFWvidmode base;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
static void geometry(void* data,
|
||||
struct wl_output* output,
|
||||
int32_t x,
|
||||
@@ -50,21 +44,15 @@ static void geometry(void* data,
|
||||
int32_t transform)
|
||||
{
|
||||
struct _GLFWmonitor *monitor = data;
|
||||
char* name;
|
||||
size_t nameLength;
|
||||
char name[1024];
|
||||
|
||||
monitor->wl.x = x;
|
||||
monitor->wl.y = y;
|
||||
monitor->widthMM = physicalWidth;
|
||||
monitor->heightMM = physicalHeight;
|
||||
|
||||
nameLength = strlen(make) + 1 + strlen(model) + 1;
|
||||
name = realloc(monitor->name, nameLength);
|
||||
if (name)
|
||||
{
|
||||
sprintf(name, "%s %s", make, model);
|
||||
monitor->name = name;
|
||||
}
|
||||
snprintf(name, sizeof(name), "%s %s", make, model);
|
||||
monitor->name = _glfw_strdup(name);
|
||||
}
|
||||
|
||||
static void mode(void* data,
|
||||
@@ -75,32 +63,29 @@ static void mode(void* data,
|
||||
int32_t refresh)
|
||||
{
|
||||
struct _GLFWmonitor *monitor = data;
|
||||
_GLFWvidmodeWayland mode = { { 0 }, };
|
||||
GLFWvidmode mode;
|
||||
|
||||
mode.base.width = width;
|
||||
mode.base.height = height;
|
||||
mode.base.refreshRate = refresh / 1000;
|
||||
mode.flags = flags;
|
||||
mode.width = width;
|
||||
mode.height = height;
|
||||
mode.redBits = 8;
|
||||
mode.greenBits = 8;
|
||||
mode.blueBits = 8;
|
||||
mode.refreshRate = refresh / 1000;
|
||||
|
||||
if (monitor->wl.modesCount + 1 >= monitor->wl.modesSize)
|
||||
{
|
||||
int size = monitor->wl.modesSize * 2;
|
||||
_GLFWvidmodeWayland* modes =
|
||||
realloc(monitor->wl.modes,
|
||||
size * sizeof(_GLFWvidmodeWayland));
|
||||
monitor->wl.modes = modes;
|
||||
monitor->wl.modesSize = size;
|
||||
}
|
||||
monitor->modeCount++;
|
||||
monitor->modes =
|
||||
realloc(monitor->modes, monitor->modeCount * sizeof(GLFWvidmode));
|
||||
monitor->modes[monitor->modeCount - 1] = mode;
|
||||
|
||||
monitor->wl.modes[monitor->wl.modesCount++] = mode;
|
||||
if (flags & WL_OUTPUT_MODE_CURRENT)
|
||||
monitor->wl.currentMode = monitor->modeCount - 1;
|
||||
}
|
||||
|
||||
static void done(void* data,
|
||||
struct wl_output* output)
|
||||
static void done(void* data, struct wl_output* output)
|
||||
{
|
||||
struct _GLFWmonitor *monitor = data;
|
||||
|
||||
monitor->wl.done = GLFW_TRUE;
|
||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
||||
}
|
||||
|
||||
static void scale(void* data,
|
||||
@@ -149,26 +134,10 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
|
||||
return;
|
||||
}
|
||||
|
||||
monitor->wl.modes = calloc(4, sizeof(_GLFWvidmodeWayland));
|
||||
monitor->wl.modesSize = 4;
|
||||
|
||||
monitor->wl.scale = 1;
|
||||
|
||||
monitor->wl.output = output;
|
||||
|
||||
wl_output_add_listener(output, &outputListener, monitor);
|
||||
|
||||
if (_glfw.wl.monitorsCount + 1 >= _glfw.wl.monitorsSize)
|
||||
{
|
||||
_GLFWmonitor** monitors = _glfw.wl.monitors;
|
||||
int size = _glfw.wl.monitorsSize * 2;
|
||||
|
||||
monitors = realloc(monitors, size * sizeof(_GLFWmonitor*));
|
||||
|
||||
_glfw.wl.monitors = monitors;
|
||||
_glfw.wl.monitorsSize = size;
|
||||
}
|
||||
|
||||
_glfw.wl.monitors[_glfw.wl.monitorsCount++] = monitor;
|
||||
}
|
||||
|
||||
|
||||
@@ -176,42 +145,6 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
||||
{
|
||||
_GLFWmonitor** monitors;
|
||||
_GLFWmonitor* monitor;
|
||||
int i, monitorsCount = _glfw.wl.monitorsCount;
|
||||
|
||||
if (_glfw.wl.monitorsCount == 0)
|
||||
goto err;
|
||||
|
||||
monitors = calloc(monitorsCount, sizeof(_GLFWmonitor*));
|
||||
|
||||
for (i = 0; i < monitorsCount; i++)
|
||||
{
|
||||
_GLFWmonitor* origMonitor = _glfw.wl.monitors[i];
|
||||
monitor = calloc(1, sizeof(_GLFWmonitor));
|
||||
|
||||
monitor->modes =
|
||||
_glfwPlatformGetVideoModes(origMonitor,
|
||||
&origMonitor->wl.modesCount);
|
||||
*monitor = *_glfw.wl.monitors[i];
|
||||
monitors[i] = monitor;
|
||||
}
|
||||
|
||||
*count = monitorsCount;
|
||||
return monitors;
|
||||
|
||||
err:
|
||||
*count = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
|
||||
{
|
||||
return first->wl.output == second->wl.output;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
{
|
||||
if (xpos)
|
||||
@@ -220,32 +153,24 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
*ypos = monitor->wl.y;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||
float* xscale, float* yscale)
|
||||
{
|
||||
if (xscale)
|
||||
*xscale = (float) monitor->wl.scale;
|
||||
if (yscale)
|
||||
*yscale = (float) monitor->wl.scale;
|
||||
}
|
||||
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||
{
|
||||
GLFWvidmode *modes;
|
||||
int i, modesCount = monitor->wl.modesCount;
|
||||
|
||||
modes = calloc(modesCount, sizeof(GLFWvidmode));
|
||||
|
||||
for (i = 0; i < modesCount; i++)
|
||||
modes[i] = monitor->wl.modes[i].base;
|
||||
|
||||
*found = modesCount;
|
||||
return modes;
|
||||
*found = monitor->modeCount;
|
||||
return monitor->modes;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < monitor->wl.modesCount; i++)
|
||||
{
|
||||
if (monitor->wl.modes[i].flags & WL_OUTPUT_MODE_CURRENT)
|
||||
{
|
||||
*mode = monitor->wl.modes[i].base;
|
||||
return;
|
||||
}
|
||||
}
|
||||
*mode = monitor->modes[monitor->wl.currentMode];
|
||||
}
|
||||
|
||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
|
||||
+133
-17
@@ -24,12 +24,11 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_wayland_platform_h_
|
||||
#define _glfw3_wayland_platform_h_
|
||||
|
||||
#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;
|
||||
@@ -46,14 +45,17 @@ typedef struct VkWaylandSurfaceCreateInfoKHR
|
||||
typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWaylandSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);
|
||||
|
||||
#include "posix_tls.h"
|
||||
#include "posix_thread.h"
|
||||
#include "posix_time.h"
|
||||
#include "linux_joystick.h"
|
||||
#include "xkb_unicode.h"
|
||||
#include "egl_context.h"
|
||||
#include "osmesa_context.h"
|
||||
|
||||
#include "wayland-xdg-shell-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)
|
||||
@@ -70,10 +72,72 @@ 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 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_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
|
||||
|
||||
// Wayland-specific video mode data
|
||||
//
|
||||
typedef struct _GLFWvidmodeWayland _GLFWvidmodeWayland;
|
||||
|
||||
// Wayland-specific per-window data
|
||||
//
|
||||
@@ -82,11 +146,18 @@ 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;
|
||||
} xdg;
|
||||
|
||||
_GLFWcursor* currentCursor;
|
||||
double cursorPosX, cursorPosY;
|
||||
|
||||
@@ -103,6 +174,12 @@ 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;
|
||||
|
||||
} _GLFWwindowWayland;
|
||||
|
||||
// Wayland-specific global data
|
||||
@@ -117,8 +194,10 @@ typedef struct _GLFWlibraryWayland
|
||||
struct wl_seat* seat;
|
||||
struct wl_pointer* pointer;
|
||||
struct wl_keyboard* keyboard;
|
||||
struct xdg_wm_base* wmBase;
|
||||
struct zwp_relative_pointer_manager_v1* relativePointerManager;
|
||||
struct zwp_pointer_constraints_v1* pointerConstraints;
|
||||
struct zwp_idle_inhibit_manager_v1* idleInhibitManager;
|
||||
|
||||
int compositorVersion;
|
||||
|
||||
@@ -126,28 +205,69 @@ typedef struct _GLFWlibraryWayland
|
||||
struct wl_surface* cursorSurface;
|
||||
uint32_t pointerSerial;
|
||||
|
||||
_GLFWmonitor** monitors;
|
||||
int monitorsCount;
|
||||
int monitorsSize;
|
||||
|
||||
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_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
|
||||
@@ -155,15 +275,12 @@ typedef struct _GLFWlibraryWayland
|
||||
typedef struct _GLFWmonitorWayland
|
||||
{
|
||||
struct wl_output* output;
|
||||
|
||||
_GLFWvidmodeWayland* modes;
|
||||
int modesCount;
|
||||
int modesSize;
|
||||
GLFWbool done;
|
||||
int currentMode;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int scale;
|
||||
|
||||
} _GLFWmonitorWayland;
|
||||
|
||||
// Wayland-specific per-cursor data
|
||||
@@ -179,4 +296,3 @@ typedef struct _GLFWcursorWayland
|
||||
|
||||
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
|
||||
|
||||
#endif // _glfw3_wayland_platform_h_
|
||||
|
||||
+356
-53
@@ -37,9 +37,6 @@
|
||||
#include <sys/mman.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <wayland-egl.h>
|
||||
#include <wayland-cursor.h>
|
||||
|
||||
|
||||
static void handlePing(void* data,
|
||||
struct wl_shell_surface* shellSurface,
|
||||
@@ -125,6 +122,7 @@ static void checkScaleChange(_GLFWwindow* window)
|
||||
wl_surface_set_buffer_scale(window->wl.surface, scale);
|
||||
wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
|
||||
_glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
|
||||
_glfwInputWindowContentScale(window, scale, scale);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,6 +187,24 @@ static void setOpaqueRegion(_GLFWwindow* window)
|
||||
wl_region_destroy(region);
|
||||
}
|
||||
|
||||
static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)
|
||||
{
|
||||
if (enable && !window->wl.idleInhibitor && _glfw.wl.idleInhibitManager)
|
||||
{
|
||||
window->wl.idleInhibitor =
|
||||
zwp_idle_inhibit_manager_v1_create_inhibitor(
|
||||
_glfw.wl.idleInhibitManager, window->wl.surface);
|
||||
if (!window->wl.idleInhibitor)
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Idle inhibitor creation failed");
|
||||
}
|
||||
else if (!enable && window->wl.idleInhibitor)
|
||||
{
|
||||
zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);
|
||||
window->wl.idleInhibitor = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static GLFWbool createSurface(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig)
|
||||
{
|
||||
@@ -212,18 +228,29 @@ static GLFWbool createSurface(_GLFWwindow* window,
|
||||
window->wl.height = wndconfig->height;
|
||||
window->wl.scale = 1;
|
||||
|
||||
// TODO: make this optional once issue #197 is fixed.
|
||||
setOpaqueRegion(window);
|
||||
if (!window->wl.transparent)
|
||||
setOpaqueRegion(window);
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
static GLFWbool createShellSurface(_GLFWwindow* window)
|
||||
{
|
||||
if (!_glfw.wl.shell)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: wl_shell protocol not available");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
window->wl.shellSurface = wl_shell_get_shell_surface(_glfw.wl.shell,
|
||||
window->wl.surface);
|
||||
if (!window->wl.shellSurface)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Shell surface creation failed");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
wl_shell_surface_add_listener(window->wl.shellSurface,
|
||||
&shellSurfaceListener,
|
||||
@@ -239,16 +266,161 @@ static GLFWbool createShellSurface(_GLFWwindow* window)
|
||||
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
|
||||
0,
|
||||
window->monitor->wl.output);
|
||||
setIdleInhibitor(window, GLFW_TRUE);
|
||||
}
|
||||
else if (window->wl.maximized)
|
||||
{
|
||||
wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
|
||||
setIdleInhibitor(window, GLFW_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_shell_surface_set_toplevel(window->wl.shellSurface);
|
||||
setIdleInhibitor(window, GLFW_FALSE);
|
||||
}
|
||||
|
||||
wl_surface_commit(window->wl.surface);
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
static void xdgToplevelHandleConfigure(void* data,
|
||||
struct xdg_toplevel* toplevel,
|
||||
int32_t width,
|
||||
int32_t height,
|
||||
struct wl_array* states)
|
||||
{
|
||||
_GLFWwindow* window = data;
|
||||
float aspectRatio;
|
||||
float targetRatio;
|
||||
uint32_t* state;
|
||||
GLFWbool maximized = GLFW_FALSE;
|
||||
GLFWbool fullscreen = GLFW_FALSE;
|
||||
GLFWbool activated = GLFW_FALSE;
|
||||
|
||||
wl_array_for_each(state, states)
|
||||
{
|
||||
switch (*state)
|
||||
{
|
||||
case XDG_TOPLEVEL_STATE_MAXIMIZED:
|
||||
maximized = GLFW_TRUE;
|
||||
break;
|
||||
case XDG_TOPLEVEL_STATE_FULLSCREEN:
|
||||
fullscreen = GLFW_TRUE;
|
||||
break;
|
||||
case XDG_TOPLEVEL_STATE_RESIZING:
|
||||
break;
|
||||
case XDG_TOPLEVEL_STATE_ACTIVATED:
|
||||
activated = GLFW_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (width != 0 && height != 0)
|
||||
{
|
||||
if (!maximized && !fullscreen)
|
||||
{
|
||||
if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)
|
||||
{
|
||||
aspectRatio = (float)width / (float)height;
|
||||
targetRatio = (float)window->numer / (float)window->denom;
|
||||
if (aspectRatio < targetRatio)
|
||||
height = width / targetRatio;
|
||||
else if (aspectRatio > targetRatio)
|
||||
width = height * targetRatio;
|
||||
}
|
||||
}
|
||||
|
||||
_glfwInputWindowSize(window, width, height);
|
||||
_glfwPlatformSetWindowSize(window, width, height);
|
||||
_glfwInputWindowDamage(window);
|
||||
}
|
||||
|
||||
if (!window->wl.justCreated && !activated && window->autoIconify)
|
||||
_glfwPlatformIconifyWindow(window);
|
||||
_glfwInputWindowFocus(window, activated);
|
||||
window->wl.justCreated = GLFW_FALSE;
|
||||
}
|
||||
|
||||
static void xdgToplevelHandleClose(void* data,
|
||||
struct xdg_toplevel* toplevel)
|
||||
{
|
||||
_GLFWwindow* window = data;
|
||||
_glfwInputWindowCloseRequest(window);
|
||||
}
|
||||
|
||||
static const struct xdg_toplevel_listener xdgToplevelListener = {
|
||||
xdgToplevelHandleConfigure,
|
||||
xdgToplevelHandleClose
|
||||
};
|
||||
|
||||
static void xdgSurfaceHandleConfigure(void* data,
|
||||
struct xdg_surface* surface,
|
||||
uint32_t serial)
|
||||
{
|
||||
xdg_surface_ack_configure(surface, serial);
|
||||
}
|
||||
|
||||
static const struct xdg_surface_listener xdgSurfaceListener = {
|
||||
xdgSurfaceHandleConfigure
|
||||
};
|
||||
|
||||
static GLFWbool createXdgSurface(_GLFWwindow* window)
|
||||
{
|
||||
window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,
|
||||
window->wl.surface);
|
||||
if (!window->wl.xdg.surface)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: xdg-surface creation failed");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
xdg_surface_add_listener(window->wl.xdg.surface,
|
||||
&xdgSurfaceListener,
|
||||
window);
|
||||
|
||||
window->wl.xdg.toplevel = xdg_surface_get_toplevel(window->wl.xdg.surface);
|
||||
if (!window->wl.xdg.toplevel)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: xdg-toplevel creation failed");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
xdg_toplevel_add_listener(window->wl.xdg.toplevel,
|
||||
&xdgToplevelListener,
|
||||
window);
|
||||
|
||||
if (window->wl.title)
|
||||
xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title);
|
||||
|
||||
if (window->minwidth != GLFW_DONT_CARE && window->minheight != GLFW_DONT_CARE)
|
||||
xdg_toplevel_set_min_size(window->wl.xdg.toplevel,
|
||||
window->minwidth, window->minheight);
|
||||
if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE)
|
||||
xdg_toplevel_set_max_size(window->wl.xdg.toplevel,
|
||||
window->maxwidth, window->maxheight);
|
||||
|
||||
if (window->monitor)
|
||||
{
|
||||
xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel,
|
||||
window->monitor->wl.output);
|
||||
setIdleInhibitor(window, GLFW_TRUE);
|
||||
}
|
||||
else if (window->wl.maximized)
|
||||
{
|
||||
xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
|
||||
setIdleInhibitor(window, GLFW_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
setIdleInhibitor(window, GLFW_FALSE);
|
||||
}
|
||||
|
||||
wl_surface_commit(window->wl.surface);
|
||||
wl_display_roundtrip(_glfw.wl.display);
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
@@ -388,29 +560,53 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
window->wl.justCreated = GLFW_TRUE;
|
||||
window->wl.transparent = fbconfig->transparent;
|
||||
|
||||
if (!createSurface(window, wndconfig))
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (ctxconfig->client != GLFW_NO_API)
|
||||
{
|
||||
if (!_glfwInitEGL())
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
if (ctxconfig->source == GLFW_EGL_CONTEXT_API ||
|
||||
ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
|
||||
{
|
||||
if (!_glfwInitEGL())
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
||||
{
|
||||
if (!_glfwInitOSMesa())
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (wndconfig->title)
|
||||
window->wl.title = strdup(wndconfig->title);
|
||||
window->wl.title = _glfw_strdup(wndconfig->title);
|
||||
|
||||
if (wndconfig->visible)
|
||||
{
|
||||
if (!createShellSurface(window))
|
||||
return GLFW_FALSE;
|
||||
if (_glfw.wl.wmBase)
|
||||
{
|
||||
if (!createXdgSurface(window))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!createShellSurface(window))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
window->wl.visible = GLFW_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
window->wl.xdg.surface = NULL;
|
||||
window->wl.xdg.toplevel = NULL;
|
||||
window->wl.shellSurface = NULL;
|
||||
window->wl.visible = GLFW_FALSE;
|
||||
}
|
||||
@@ -437,6 +633,9 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
_glfwInputWindowFocus(window, GLFW_FALSE);
|
||||
}
|
||||
|
||||
if (window->wl.idleInhibitor)
|
||||
zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);
|
||||
|
||||
if (window->context.destroy)
|
||||
window->context.destroy(window);
|
||||
|
||||
@@ -446,6 +645,12 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
if (window->wl.shellSurface)
|
||||
wl_shell_surface_destroy(window->wl.shellSurface);
|
||||
|
||||
if (window->wl.xdg.toplevel)
|
||||
xdg_toplevel_destroy(window->wl.xdg.toplevel);
|
||||
|
||||
if (window->wl.xdg.surface)
|
||||
xdg_surface_destroy(window->wl.xdg.surface);
|
||||
|
||||
if (window->wl.surface)
|
||||
wl_surface_destroy(window->wl.surface);
|
||||
|
||||
@@ -457,8 +662,10 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
||||
{
|
||||
if (window->wl.title)
|
||||
free(window->wl.title);
|
||||
window->wl.title = strdup(title);
|
||||
if (window->wl.shellSurface)
|
||||
window->wl.title = _glfw_strdup(title);
|
||||
if (window->wl.xdg.toplevel)
|
||||
xdg_toplevel_set_title(window->wl.xdg.toplevel, title);
|
||||
else if (window->wl.shellSurface)
|
||||
wl_shell_surface_set_title(window->wl.shellSurface, title);
|
||||
}
|
||||
|
||||
@@ -501,7 +708,8 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
||||
window->wl.width = width;
|
||||
window->wl.height = height;
|
||||
wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
|
||||
setOpaqueRegion(window);
|
||||
if (!window->wl.transparent)
|
||||
setOpaqueRegion(window);
|
||||
_glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
|
||||
}
|
||||
|
||||
@@ -509,8 +717,24 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||
int minwidth, int minheight,
|
||||
int maxwidth, int maxheight)
|
||||
{
|
||||
// TODO: find out how to trigger a resize.
|
||||
// The actual limits are checked in the wl_shell_surface::configure handler.
|
||||
if (_glfw.wl.wmBase)
|
||||
{
|
||||
if (window->wl.xdg.toplevel)
|
||||
{
|
||||
if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
|
||||
minwidth = minheight = 0;
|
||||
if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)
|
||||
maxwidth = maxheight = 0;
|
||||
xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight);
|
||||
xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight);
|
||||
wl_surface_commit(window->wl.surface);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: find out how to trigger a resize.
|
||||
// The actual limits are checked in the wl_shell_surface::configure handler.
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
|
||||
@@ -534,43 +758,70 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||
// implemented, but for now just leave everything as 0.
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
||||
float* xscale, float* yscale)
|
||||
{
|
||||
if (xscale)
|
||||
*xscale = (float) window->wl.scale;
|
||||
if (yscale)
|
||||
*yscale = (float) window->wl.scale;
|
||||
}
|
||||
|
||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||
{
|
||||
// TODO: move to xdg_shell instead of wl_shell.
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Iconify window not supported");
|
||||
if (_glfw.wl.wmBase)
|
||||
{
|
||||
if (window->wl.xdg.toplevel)
|
||||
xdg_toplevel_set_minimized(window->wl.xdg.toplevel);
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Iconify window not supported on wl_shell");
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
||||
{
|
||||
// TODO: also do the same for iconified.
|
||||
if (window->monitor || window->wl.maximized)
|
||||
if (window->wl.xdg.toplevel)
|
||||
{
|
||||
if (window->wl.shellSurface)
|
||||
wl_shell_surface_set_toplevel(window->wl.shellSurface);
|
||||
|
||||
window->wl.maximized = GLFW_FALSE;
|
||||
if (window->monitor)
|
||||
xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
|
||||
if (window->wl.maximized)
|
||||
xdg_toplevel_unset_maximized(window->wl.xdg.toplevel);
|
||||
// There is no way to unset minimized, or even to know if we are
|
||||
// minimized, so there is nothing to do here.
|
||||
}
|
||||
else if (window->wl.shellSurface)
|
||||
{
|
||||
if (window->monitor || window->wl.maximized)
|
||||
wl_shell_surface_set_toplevel(window->wl.shellSurface);
|
||||
}
|
||||
_glfwInputWindowMonitor(window, NULL);
|
||||
window->wl.maximized = GLFW_FALSE;
|
||||
}
|
||||
|
||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (!window->monitor && !window->wl.maximized)
|
||||
if (window->wl.xdg.toplevel)
|
||||
{
|
||||
if (window->wl.shellSurface)
|
||||
{
|
||||
// Let the compositor select the best output.
|
||||
wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
|
||||
}
|
||||
window->wl.maximized = GLFW_TRUE;
|
||||
xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
|
||||
}
|
||||
else if (window->wl.shellSurface)
|
||||
{
|
||||
// Let the compositor select the best output.
|
||||
wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
|
||||
}
|
||||
window->wl.maximized = GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (!window->monitor)
|
||||
if (!window->wl.visible)
|
||||
{
|
||||
if (!window->wl.shellSurface)
|
||||
if (_glfw.wl.wmBase)
|
||||
createXdgSurface(window);
|
||||
else if (!window->wl.shellSurface)
|
||||
createShellSurface(window);
|
||||
window->wl.visible = GLFW_TRUE;
|
||||
}
|
||||
@@ -578,12 +829,26 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||
|
||||
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (!window->monitor)
|
||||
if (window->wl.xdg.toplevel)
|
||||
{
|
||||
if (window->wl.shellSurface)
|
||||
wl_shell_surface_destroy(window->wl.shellSurface);
|
||||
window->wl.visible = GLFW_FALSE;
|
||||
xdg_toplevel_destroy(window->wl.xdg.toplevel);
|
||||
xdg_surface_destroy(window->wl.xdg.surface);
|
||||
window->wl.xdg.toplevel = NULL;
|
||||
window->wl.xdg.surface = NULL;
|
||||
}
|
||||
else if (window->wl.shellSurface)
|
||||
{
|
||||
wl_shell_surface_destroy(window->wl.shellSurface);
|
||||
window->wl.shellSurface = NULL;
|
||||
}
|
||||
window->wl.visible = GLFW_FALSE;
|
||||
}
|
||||
|
||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||
{
|
||||
// TODO
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Window attention request not implemented yet");
|
||||
}
|
||||
|
||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||
@@ -598,19 +863,36 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
int width, int height,
|
||||
int refreshRate)
|
||||
{
|
||||
if (monitor)
|
||||
if (window->wl.xdg.toplevel)
|
||||
{
|
||||
wl_shell_surface_set_fullscreen(
|
||||
window->wl.shellSurface,
|
||||
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
|
||||
refreshRate * 1000, // Convert Hz to mHz.
|
||||
monitor->wl.output);
|
||||
if (monitor)
|
||||
{
|
||||
xdg_toplevel_set_fullscreen(
|
||||
window->wl.xdg.toplevel,
|
||||
monitor->wl.output);
|
||||
}
|
||||
else
|
||||
{
|
||||
xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (window->wl.shellSurface)
|
||||
{
|
||||
wl_shell_surface_set_toplevel(window->wl.shellSurface);
|
||||
if (monitor)
|
||||
{
|
||||
wl_shell_surface_set_fullscreen(
|
||||
window->wl.shellSurface,
|
||||
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
|
||||
refreshRate * 1000, // Convert Hz to mHz.
|
||||
monitor->wl.output);
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_shell_surface_set_toplevel(window->wl.shellSurface);
|
||||
}
|
||||
}
|
||||
_glfwInputWindowMonitorChange(window, monitor);
|
||||
setIdleInhibitor(window, monitor ? GLFW_TRUE : GLFW_FALSE);
|
||||
_glfwInputWindowMonitor(window, monitor);
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
||||
@@ -620,7 +902,8 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
||||
|
||||
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||
{
|
||||
// TODO: move to xdg_shell, wl_shell doesn't have any iconified concept.
|
||||
// wl_shell doesn't have any iconified concept, and xdg-shell doesn’t give
|
||||
// any way to request whether a surface is iconified.
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
@@ -634,6 +917,16 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||
return window->wl.maximized;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
||||
{
|
||||
return window->wl.hovered;
|
||||
}
|
||||
|
||||
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||
{
|
||||
return window->wl.transparent;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
// TODO
|
||||
@@ -655,6 +948,15 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
||||
"Wayland: Window attribute setting not implemented yet");
|
||||
}
|
||||
|
||||
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
|
||||
{
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformPollEvents(void)
|
||||
{
|
||||
handleEvents(0);
|
||||
@@ -701,7 +1003,7 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
||||
_glfwPlatformSetCursor(window, window->wl.currentCursor);
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetKeyName(int key, int scancode)
|
||||
const char* _glfwPlatformGetScancodeName(int scancode)
|
||||
{
|
||||
// TODO
|
||||
return NULL;
|
||||
@@ -971,14 +1273,14 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
|
||||
void _glfwPlatformSetClipboardString(const char* string)
|
||||
{
|
||||
// TODO
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Clipboard setting not implemented yet");
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
const char* _glfwPlatformGetClipboardString(void)
|
||||
{
|
||||
// TODO
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
@@ -999,7 +1301,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR =
|
||||
PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
|
||||
vkGetPhysicalDeviceWaylandPresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceWaylandPresentationSupportKHR)
|
||||
|
||||
+336
-78
@@ -237,8 +237,8 @@ static void createKeyTables(void)
|
||||
|
||||
if (_glfw.x11.xkb.available)
|
||||
{
|
||||
// Use XKB to determine physical key locations independently of the current
|
||||
// keyboard layout
|
||||
// Use XKB to determine physical key locations independently of the
|
||||
// current keyboard layout
|
||||
|
||||
char name[XkbKeyNameLength + 1];
|
||||
XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd);
|
||||
@@ -381,13 +381,11 @@ static void detectEWMH(void)
|
||||
XInternAtom(_glfw.x11.display, "_NET_SUPPORTED", False);
|
||||
|
||||
// Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window
|
||||
if (_glfwGetWindowPropertyX11(_glfw.x11.root,
|
||||
supportingWmCheck,
|
||||
XA_WINDOW,
|
||||
(unsigned char**) &windowFromRoot) != 1)
|
||||
if (!_glfwGetWindowPropertyX11(_glfw.x11.root,
|
||||
supportingWmCheck,
|
||||
XA_WINDOW,
|
||||
(unsigned char**) &windowFromRoot))
|
||||
{
|
||||
if (windowFromRoot)
|
||||
XFree(windowFromRoot);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -395,14 +393,12 @@ static void detectEWMH(void)
|
||||
|
||||
// It should be the ID of a child window (of the root)
|
||||
// Then we look for the same property on the child window
|
||||
if (_glfwGetWindowPropertyX11(*windowFromRoot,
|
||||
supportingWmCheck,
|
||||
XA_WINDOW,
|
||||
(unsigned char**) &windowFromChild) != 1)
|
||||
if (!_glfwGetWindowPropertyX11(*windowFromRoot,
|
||||
supportingWmCheck,
|
||||
XA_WINDOW,
|
||||
(unsigned char**) &windowFromChild))
|
||||
{
|
||||
XFree(windowFromRoot);
|
||||
if (windowFromChild)
|
||||
XFree(windowFromChild);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -442,6 +438,8 @@ static void detectEWMH(void)
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_VERT");
|
||||
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_HORZ");
|
||||
_glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_DEMANDS_ATTENTION");
|
||||
_glfw.x11.NET_WM_FULLSCREEN_MONITORS =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS");
|
||||
_glfw.x11.NET_WM_WINDOW_TYPE =
|
||||
@@ -455,24 +453,25 @@ static void detectEWMH(void)
|
||||
_glfw.x11.NET_REQUEST_FRAME_EXTENTS =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");
|
||||
|
||||
XFree(supportedAtoms);
|
||||
if (supportedAtoms)
|
||||
XFree(supportedAtoms);
|
||||
}
|
||||
|
||||
// Initialize X11 display and look for supported X11 extensions
|
||||
// Look for and initialize supported X11 extensions
|
||||
//
|
||||
static GLFWbool initExtensions(void)
|
||||
{
|
||||
_glfw.x11.vidmode.handle = dlopen("libXxf86vm.so", 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,
|
||||
@@ -480,23 +479,89 @@ static GLFWbool initExtensions(void)
|
||||
&_glfw.x11.vidmode.errorBase);
|
||||
}
|
||||
|
||||
// Check for RandR extension
|
||||
if (XRRQueryExtension(_glfw.x11.display,
|
||||
&_glfw.x11.randr.eventBase,
|
||||
&_glfw.x11.randr.errorBase))
|
||||
_glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6");
|
||||
if (_glfw.x11.xi.handle)
|
||||
{
|
||||
if (XRRQueryVersion(_glfw.x11.display,
|
||||
&_glfw.x11.randr.major,
|
||||
&_glfw.x11.randr.minor))
|
||||
_glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion)
|
||||
_glfw_dlsym(_glfw.x11.xi.handle, "XIQueryVersion");
|
||||
_glfw.x11.xi.SelectEvents = (PFN_XISelectEvents)
|
||||
_glfw_dlsym(_glfw.x11.xi.handle, "XISelectEvents");
|
||||
|
||||
if (XQueryExtension(_glfw.x11.display,
|
||||
"XInputExtension",
|
||||
&_glfw.x11.xi.majorOpcode,
|
||||
&_glfw.x11.xi.eventBase,
|
||||
&_glfw.x11.xi.errorBase))
|
||||
{
|
||||
// The GLFW RandR path requires at least version 1.3
|
||||
if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3)
|
||||
_glfw.x11.randr.available = GLFW_TRUE;
|
||||
_glfw.x11.xi.major = 2;
|
||||
_glfw.x11.xi.minor = 0;
|
||||
|
||||
if (XIQueryVersion(_glfw.x11.display,
|
||||
&_glfw.x11.xi.major,
|
||||
&_glfw.x11.xi.minor) == Success)
|
||||
{
|
||||
_glfw.x11.xi.available = GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2");
|
||||
if (_glfw.x11.randr.handle)
|
||||
{
|
||||
_glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRAllocGamma");
|
||||
_glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
|
||||
_glfw.x11.randr.FreeCrtcInfo = (PFN_XRRFreeCrtcInfo)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeCrtcInfo");
|
||||
_glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
|
||||
_glfw.x11.randr.FreeOutputInfo = (PFN_XRRFreeOutputInfo)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeOutputInfo");
|
||||
_glfw.x11.randr.FreeScreenResources = (PFN_XRRFreeScreenResources)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeScreenResources");
|
||||
_glfw.x11.randr.GetCrtcGamma = (PFN_XRRGetCrtcGamma)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGamma");
|
||||
_glfw.x11.randr.GetCrtcGammaSize = (PFN_XRRGetCrtcGammaSize)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize");
|
||||
_glfw.x11.randr.GetCrtcInfo = (PFN_XRRGetCrtcInfo)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcInfo");
|
||||
_glfw.x11.randr.GetOutputInfo = (PFN_XRRGetOutputInfo)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputInfo");
|
||||
_glfw.x11.randr.GetOutputPrimary = (PFN_XRRGetOutputPrimary)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputPrimary");
|
||||
_glfw.x11.randr.GetScreenResourcesCurrent = (PFN_XRRGetScreenResourcesCurrent)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent");
|
||||
_glfw.x11.randr.QueryExtension = (PFN_XRRQueryExtension)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryExtension");
|
||||
_glfw.x11.randr.QueryVersion = (PFN_XRRQueryVersion)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryVersion");
|
||||
_glfw.x11.randr.SelectInput = (PFN_XRRSelectInput)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRSelectInput");
|
||||
_glfw.x11.randr.SetCrtcConfig = (PFN_XRRSetCrtcConfig)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcConfig");
|
||||
_glfw.x11.randr.SetCrtcGamma = (PFN_XRRSetCrtcGamma)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcGamma");
|
||||
_glfw.x11.randr.UpdateConfiguration = (PFN_XRRUpdateConfiguration)
|
||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRUpdateConfiguration");
|
||||
|
||||
if (XRRQueryExtension(_glfw.x11.display,
|
||||
&_glfw.x11.randr.eventBase,
|
||||
&_glfw.x11.randr.errorBase))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to query RandR version");
|
||||
if (XRRQueryVersion(_glfw.x11.display,
|
||||
&_glfw.x11.randr.major,
|
||||
&_glfw.x11.randr.minor))
|
||||
{
|
||||
// The GLFW RandR path requires at least version 1.3
|
||||
if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3)
|
||||
_glfw.x11.randr.available = GLFW_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to query RandR version");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,27 +572,71 @@ static GLFWbool initExtensions(void)
|
||||
|
||||
if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0]))
|
||||
{
|
||||
// This is either a headless system or an older Nvidia binary driver
|
||||
// with broken gamma support
|
||||
// Flag it as useless and fall back to Xf86VidMode gamma, if
|
||||
// available
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: RandR gamma ramp support seems broken");
|
||||
// This is likely an older Nvidia driver with broken gamma support
|
||||
// Flag it as useless and fall back to xf86vm gamma, if available
|
||||
_glfw.x11.randr.gammaBroken = GLFW_TRUE;
|
||||
}
|
||||
|
||||
XRRFreeScreenResources(sr);
|
||||
if (!sr->ncrtc)
|
||||
{
|
||||
// A system without CRTCs is likely a system with broken RandR
|
||||
// Disable the RandR monitor path and fall back to core functions
|
||||
_glfw.x11.randr.monitorBroken = GLFW_TRUE;
|
||||
}
|
||||
|
||||
XRRFreeScreenResources(sr);
|
||||
}
|
||||
|
||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||
{
|
||||
XRRSelectInput(_glfw.x11.display, _glfw.x11.root,
|
||||
RROutputChangeNotifyMask);
|
||||
}
|
||||
|
||||
if (XineramaQueryExtension(_glfw.x11.display,
|
||||
&_glfw.x11.xinerama.major,
|
||||
&_glfw.x11.xinerama.minor))
|
||||
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1");
|
||||
if (_glfw.x11.xcursor.handle)
|
||||
{
|
||||
if (XineramaIsActive(_glfw.x11.display))
|
||||
_glfw.x11.xinerama.available = GLFW_TRUE;
|
||||
_glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate)
|
||||
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageCreate");
|
||||
_glfw.x11.xcursor.ImageDestroy = (PFN_XcursorImageDestroy)
|
||||
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy");
|
||||
_glfw.x11.xcursor.ImageLoadCursor = (PFN_XcursorImageLoadCursor)
|
||||
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor");
|
||||
}
|
||||
|
||||
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1");
|
||||
if (_glfw.x11.xinerama.handle)
|
||||
{
|
||||
_glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive)
|
||||
_glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaIsActive");
|
||||
_glfw.x11.xinerama.QueryExtension = (PFN_XineramaQueryExtension)
|
||||
_glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryExtension");
|
||||
_glfw.x11.xinerama.QueryScreens = (PFN_XineramaQueryScreens)
|
||||
_glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryScreens");
|
||||
|
||||
if (XineramaQueryExtension(_glfw.x11.display,
|
||||
&_glfw.x11.xinerama.major,
|
||||
&_glfw.x11.xinerama.minor))
|
||||
{
|
||||
if (XineramaIsActive(_glfw.x11.display))
|
||||
_glfw.x11.xinerama.available = GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
_glfw.x11.xss.handle = _glfw_dlopen("libXss.so.1");
|
||||
if (_glfw.x11.xss.handle)
|
||||
{
|
||||
_glfw.x11.xss.QueryExtension = (PFN_XScreenSaverQueryExtension)
|
||||
_glfw_dlsym(_glfw.x11.xss.handle, "XScreenSaverQueryExtension");
|
||||
_glfw.x11.xss.Suspend = (PFN_XScreenSaverSuspend)
|
||||
_glfw_dlsym(_glfw.x11.xss.handle, "XScreenSaverSuspend");
|
||||
|
||||
if (XScreenSaverQueryExtension(_glfw.x11.display,
|
||||
&_glfw.x11.xss.eventBase,
|
||||
&_glfw.x11.xss.errorBase))
|
||||
{
|
||||
_glfw.x11.xss.available = GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if Xkb is supported on this display
|
||||
@@ -552,11 +661,73 @@ static GLFWbool initExtensions(void)
|
||||
}
|
||||
}
|
||||
|
||||
_glfw.x11.x11xcb.handle = dlopen("libX11-xcb.so", RTLD_LAZY | RTLD_GLOBAL);
|
||||
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1");
|
||||
if (_glfw.x11.x11xcb.handle)
|
||||
{
|
||||
_glfw.x11.x11xcb.XGetXCBConnection = (PFN_XGetXCBConnection)
|
||||
dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection");
|
||||
_glfw.x11.x11xcb.GetXCBConnection = (PFN_XGetXCBConnection)
|
||||
_glfw_dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection");
|
||||
}
|
||||
|
||||
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1");
|
||||
if (_glfw.x11.xrender.handle)
|
||||
{
|
||||
_glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension)
|
||||
_glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryExtension");
|
||||
_glfw.x11.xrender.QueryVersion = (PFN_XRenderQueryVersion)
|
||||
_glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryVersion");
|
||||
_glfw.x11.xrender.FindVisualFormat = (PFN_XRenderFindVisualFormat)
|
||||
_glfw_dlsym(_glfw.x11.xrender.handle, "XRenderFindVisualFormat");
|
||||
|
||||
if (XRenderQueryExtension(_glfw.x11.display,
|
||||
&_glfw.x11.xrender.errorBase,
|
||||
&_glfw.x11.xrender.eventBase))
|
||||
{
|
||||
if (XRenderQueryVersion(_glfw.x11.display,
|
||||
&_glfw.x11.xrender.major,
|
||||
&_glfw.x11.xrender.minor))
|
||||
{
|
||||
_glfw.x11.xrender.available = GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
_glfw.x11.dbus.handle = _glfw_dlopen("libdbus-1-3.so");
|
||||
#else
|
||||
_glfw.x11.dbus.handle = _glfw_dlopen("libdbus-1.so.3");
|
||||
#endif
|
||||
if (_glfw.x11.dbus.handle)
|
||||
{
|
||||
DBusError error;
|
||||
|
||||
_glfw.x11.dbus.error_init =
|
||||
_glfw_dlsym(_glfw.x11.dbus.handle, "dbus_error_init");
|
||||
_glfw.x11.dbus.error_is_set =
|
||||
_glfw_dlsym(_glfw.x11.dbus.handle, "dbus_error_is_set");
|
||||
_glfw.x11.dbus.bus_get_private =
|
||||
_glfw_dlsym(_glfw.x11.dbus.handle, "dbus_bus_get_private");
|
||||
_glfw.x11.dbus.connection_set_exit_on_disconnect =
|
||||
_glfw_dlsym(_glfw.x11.dbus.handle, "dbus_connection_set_exit_on_disconnect");
|
||||
_glfw.x11.dbus.connection_send_with_reply_and_block =
|
||||
_glfw_dlsym(_glfw.x11.dbus.handle, "dbus_connection_send_with_reply_and_block");
|
||||
_glfw.x11.dbus.connection_close =
|
||||
_glfw_dlsym(_glfw.x11.dbus.handle, "dbus_connection_close");
|
||||
_glfw.x11.dbus.connection_unref =
|
||||
_glfw_dlsym(_glfw.x11.dbus.handle, "dbus_connection_unref");
|
||||
_glfw.x11.dbus.message_new_method_call =
|
||||
_glfw_dlsym(_glfw.x11.dbus.handle, "dbus_message_new_method_call");
|
||||
_glfw.x11.dbus.message_append_args =
|
||||
_glfw_dlsym(_glfw.x11.dbus.handle, "dbus_message_append_args");
|
||||
_glfw.x11.dbus.message_get_args =
|
||||
_glfw_dlsym(_glfw.x11.dbus.handle, "dbus_message_get_args");
|
||||
_glfw.x11.dbus.message_unref =
|
||||
_glfw_dlsym(_glfw.x11.dbus.handle, "dbus_message_unref");
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
_glfw.x11.dbus.session = dbus_bus_get_private(DBUS_BUS_SESSION, &error);
|
||||
if (!dbus_error_is_set(&error))
|
||||
dbus_connection_set_exit_on_disconnect(_glfw.x11.dbus.session, FALSE);
|
||||
}
|
||||
|
||||
// Update the key code LUT
|
||||
@@ -569,10 +740,7 @@ static GLFWbool initExtensions(void)
|
||||
|
||||
// String format atoms
|
||||
_glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False);
|
||||
_glfw.x11.UTF8_STRING =
|
||||
XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
|
||||
_glfw.x11.COMPOUND_STRING =
|
||||
XInternAtom(_glfw.x11.display, "COMPOUND_STRING", False);
|
||||
_glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
|
||||
_glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False);
|
||||
|
||||
// Custom selection property atom
|
||||
@@ -582,6 +750,8 @@ static GLFWbool initExtensions(void)
|
||||
// ICCCM standard clipboard atoms
|
||||
_glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False);
|
||||
_glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False);
|
||||
_glfw.x11.PRIMARY = XInternAtom(_glfw.x11.display, "PRIMARY", False);
|
||||
_glfw.x11.INCR = XInternAtom(_glfw.x11.display, "INCR", False);
|
||||
_glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False);
|
||||
|
||||
// Clipboard manager atoms
|
||||
@@ -597,9 +767,10 @@ static GLFWbool initExtensions(void)
|
||||
_glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", False);
|
||||
_glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False);
|
||||
_glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", False);
|
||||
_glfw.x11.XdndLeave = XInternAtom(_glfw.x11.display, "XdndLeave", False);
|
||||
_glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False);
|
||||
_glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False);
|
||||
_glfw.x11.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False);
|
||||
_glfw.x11.text_uri_list = XInternAtom(_glfw.x11.display, "text/uri-list", False);
|
||||
|
||||
// ICCCM, EWMH and Motif window property atoms
|
||||
// These can be set safely even without WM support
|
||||
@@ -622,21 +793,64 @@ 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;
|
||||
}
|
||||
|
||||
// Retrieve system content scale via folklore heuristics
|
||||
//
|
||||
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
|
||||
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) *
|
||||
25.4f / DisplayHeightMM(_glfw.x11.display, _glfw.x11.screen);
|
||||
|
||||
// NOTE: Basing the scale on Xft.dpi where available should provide the most
|
||||
// consistent user experience (matches Qt, Gtk, etc), although not
|
||||
// always the most accurate one
|
||||
char* rms = XResourceManagerString(_glfw.x11.display);
|
||||
if (rms)
|
||||
{
|
||||
XrmDatabase db = XrmGetStringDatabase(rms);
|
||||
if (db)
|
||||
{
|
||||
XrmValue value;
|
||||
char* type = NULL;
|
||||
|
||||
if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value))
|
||||
{
|
||||
if (type && strcmp(type, "String") == 0)
|
||||
xdpi = ydpi = atof(value.addr);
|
||||
}
|
||||
|
||||
XrmDestroyDatabase(db);
|
||||
}
|
||||
}
|
||||
|
||||
*xscale = xdpi / 96.f;
|
||||
*yscale = ydpi / 96.f;
|
||||
}
|
||||
|
||||
// Create a blank cursor for hidden and disabled cursor modes
|
||||
//
|
||||
static Cursor createHiddenCursor(void)
|
||||
{
|
||||
unsigned char pixels[16 * 16 * 4];
|
||||
unsigned char pixels[16 * 16 * 4] = { 0 };
|
||||
GLFWimage image = { 16, 16, pixels };
|
||||
|
||||
memset(pixels, 0, sizeof(pixels));
|
||||
|
||||
return _glfwCreateCursorX11(&image, 0, 0);
|
||||
}
|
||||
|
||||
@@ -688,7 +902,7 @@ void _glfwReleaseErrorHandlerX11(void)
|
||||
//
|
||||
void _glfwInputErrorX11(int error, const char* message)
|
||||
{
|
||||
char buffer[8192];
|
||||
char buffer[_GLFW_MESSAGE_SIZE];
|
||||
XGetErrorText(_glfw.x11.display, _glfw.x11.errorCode,
|
||||
buffer, sizeof(buffer));
|
||||
|
||||
@@ -702,6 +916,9 @@ Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot)
|
||||
int i;
|
||||
Cursor cursor;
|
||||
|
||||
if (!_glfw.x11.xcursor.handle)
|
||||
return None;
|
||||
|
||||
XcursorImage* native = XcursorImageCreate(image->width, image->height);
|
||||
if (native == NULL)
|
||||
return None;
|
||||
@@ -736,13 +953,17 @@ Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot)
|
||||
int _glfwPlatformInit(void)
|
||||
{
|
||||
#if !defined(X_HAVE_UTF8_STRING)
|
||||
// HACK: If the current locale is C, apply the environment's locale
|
||||
// This is done because the C locale breaks wide character input
|
||||
// HACK: If the current locale is "C" and the Xlib UTF-8 functions are
|
||||
// unavailable, apply the environment's locale in the hope that it's
|
||||
// both available and not "C"
|
||||
// This is done because the "C" locale breaks wide character input,
|
||||
// which is what we fall back on when UTF-8 support is missing
|
||||
if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0)
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
XInitThreads();
|
||||
XrmInitialize();
|
||||
|
||||
_glfw.x11.display = XOpenDisplay(NULL);
|
||||
if (!_glfw.x11.display)
|
||||
@@ -765,12 +986,15 @@ int _glfwPlatformInit(void)
|
||||
_glfw.x11.screen = DefaultScreen(_glfw.x11.display);
|
||||
_glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen);
|
||||
_glfw.x11.context = XUniqueContext();
|
||||
_glfw.x11.helperWindowHandle = createHelperWindow();
|
||||
_glfw.x11.hiddenCursorHandle = createHiddenCursor();
|
||||
|
||||
getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY);
|
||||
|
||||
if (!initExtensions())
|
||||
return GLFW_FALSE;
|
||||
|
||||
_glfw.x11.helperWindowHandle = createHelperWindow();
|
||||
_glfw.x11.hiddenCursorHandle = createHiddenCursor();
|
||||
|
||||
if (XSupportsLocale())
|
||||
{
|
||||
XSetLocaleModifiers("");
|
||||
@@ -786,25 +1010,19 @@ int _glfwPlatformInit(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
||||
return GLFW_FALSE;
|
||||
|
||||
#if defined(__linux__)
|
||||
if (!_glfwInitJoysticksLinux())
|
||||
return GLFW_FALSE;
|
||||
#endif
|
||||
|
||||
_glfwInitTimerPOSIX();
|
||||
|
||||
_glfwPollMonitorsX11();
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformTerminate(void)
|
||||
{
|
||||
if (_glfw.x11.x11xcb.handle)
|
||||
{
|
||||
dlclose(_glfw.x11.x11xcb.handle);
|
||||
_glfw.x11.x11xcb.handle = NULL;
|
||||
}
|
||||
|
||||
if (_glfw.x11.helperWindowHandle)
|
||||
{
|
||||
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) ==
|
||||
@@ -823,6 +1041,7 @@ void _glfwPlatformTerminate(void)
|
||||
_glfw.x11.hiddenCursorHandle = (Cursor) 0;
|
||||
}
|
||||
|
||||
free(_glfw.x11.primarySelectionString);
|
||||
free(_glfw.x11.clipboardString);
|
||||
|
||||
if (_glfw.x11.im)
|
||||
@@ -831,20 +1050,59 @@ void _glfwPlatformTerminate(void)
|
||||
_glfw.x11.im = NULL;
|
||||
}
|
||||
|
||||
_glfwTerminateEGL();
|
||||
|
||||
if (_glfw.x11.display)
|
||||
{
|
||||
XCloseDisplay(_glfw.x11.display);
|
||||
_glfw.x11.display = NULL;
|
||||
}
|
||||
|
||||
// NOTE: This needs to be done after XCloseDisplay, as libGL registers
|
||||
// cleanup callbacks that get called by it
|
||||
if (_glfw.x11.x11xcb.handle)
|
||||
{
|
||||
_glfw_dlclose(_glfw.x11.x11xcb.handle);
|
||||
_glfw.x11.x11xcb.handle = NULL;
|
||||
}
|
||||
|
||||
if (_glfw.x11.xcursor.handle)
|
||||
{
|
||||
_glfw_dlclose(_glfw.x11.xcursor.handle);
|
||||
_glfw.x11.xcursor.handle = NULL;
|
||||
}
|
||||
|
||||
if (_glfw.x11.randr.handle)
|
||||
{
|
||||
_glfw_dlclose(_glfw.x11.randr.handle);
|
||||
_glfw.x11.randr.handle = NULL;
|
||||
}
|
||||
|
||||
if (_glfw.x11.xinerama.handle)
|
||||
{
|
||||
_glfw_dlclose(_glfw.x11.xinerama.handle);
|
||||
_glfw.x11.xinerama.handle = NULL;
|
||||
}
|
||||
|
||||
if (_glfw.x11.xss.handle)
|
||||
{
|
||||
_glfw_dlclose(_glfw.x11.xss.handle);
|
||||
_glfw.x11.xss.handle = NULL;
|
||||
}
|
||||
|
||||
if (_glfw.x11.dbus.session)
|
||||
{
|
||||
dbus_connection_close(_glfw.x11.dbus.session);
|
||||
dbus_connection_unref(_glfw.x11.dbus.session);
|
||||
}
|
||||
|
||||
if (_glfw.x11.dbus.handle)
|
||||
_glfw_dlclose(_glfw.x11.dbus.handle);
|
||||
|
||||
// NOTE: These need to be unloaded after XCloseDisplay, as they register
|
||||
// cleanup callbacks that get called by that function
|
||||
_glfwTerminateEGL();
|
||||
_glfwTerminateGLX();
|
||||
|
||||
#if defined(__linux__)
|
||||
_glfwTerminateJoysticksLinux();
|
||||
_glfwTerminateThreadLocalStoragePOSIX();
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetVersionString(void)
|
||||
@@ -856,7 +1114,7 @@ const char* _glfwPlatformGetVersionString(void)
|
||||
" gettimeofday"
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
" /dev/js"
|
||||
" evdev"
|
||||
#endif
|
||||
#if defined(_GLFW_BUILD_DLL)
|
||||
" shared"
|
||||
|
||||
+141
-128
@@ -95,9 +95,128 @@ static GLFWvidmode vidmodeFromModeInfo(const XRRModeInfo* mi,
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Poll for changes in the set of connected monitors
|
||||
//
|
||||
void _glfwPollMonitorsX11(void)
|
||||
{
|
||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||
{
|
||||
int i, j, disconnectedCount, screenCount = 0;
|
||||
_GLFWmonitor** disconnected = NULL;
|
||||
XineramaScreenInfo* screens = NULL;
|
||||
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display,
|
||||
_glfw.x11.root);
|
||||
RROutput primary = XRRGetOutputPrimary(_glfw.x11.display,
|
||||
_glfw.x11.root);
|
||||
|
||||
if (_glfw.x11.xinerama.available)
|
||||
screens = XineramaQueryScreens(_glfw.x11.display, &screenCount);
|
||||
|
||||
disconnectedCount = _glfw.monitorCount;
|
||||
if (disconnectedCount)
|
||||
{
|
||||
disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
|
||||
memcpy(disconnected,
|
||||
_glfw.monitors,
|
||||
_glfw.monitorCount * sizeof(_GLFWmonitor*));
|
||||
}
|
||||
|
||||
for (i = 0; i < sr->noutput; i++)
|
||||
{
|
||||
int type, widthMM, heightMM;
|
||||
XRROutputInfo* oi;
|
||||
XRRCrtcInfo* ci;
|
||||
_GLFWmonitor* monitor;
|
||||
|
||||
oi = XRRGetOutputInfo(_glfw.x11.display, sr, sr->outputs[i]);
|
||||
if (oi->connection != RR_Connected || oi->crtc == None)
|
||||
{
|
||||
XRRFreeOutputInfo(oi);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < disconnectedCount; j++)
|
||||
{
|
||||
if (disconnected[j] &&
|
||||
disconnected[j]->x11.output == sr->outputs[i])
|
||||
{
|
||||
disconnected[j] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j < disconnectedCount)
|
||||
{
|
||||
XRRFreeOutputInfo(oi);
|
||||
continue;
|
||||
}
|
||||
|
||||
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc);
|
||||
if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
|
||||
{
|
||||
widthMM = oi->mm_height;
|
||||
heightMM = oi->mm_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
widthMM = oi->mm_width;
|
||||
heightMM = oi->mm_height;
|
||||
}
|
||||
|
||||
monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM);
|
||||
monitor->x11.output = sr->outputs[i];
|
||||
monitor->x11.crtc = oi->crtc;
|
||||
|
||||
for (j = 0; j < screenCount; j++)
|
||||
{
|
||||
if (screens[j].x_org == ci->x &&
|
||||
screens[j].y_org == ci->y &&
|
||||
screens[j].width == ci->width &&
|
||||
screens[j].height == ci->height)
|
||||
{
|
||||
monitor->x11.index = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (monitor->x11.output == primary)
|
||||
type = _GLFW_INSERT_FIRST;
|
||||
else
|
||||
type = _GLFW_INSERT_LAST;
|
||||
|
||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
|
||||
|
||||
XRRFreeOutputInfo(oi);
|
||||
XRRFreeCrtcInfo(ci);
|
||||
}
|
||||
|
||||
XRRFreeScreenResources(sr);
|
||||
|
||||
if (screens)
|
||||
XFree(screens);
|
||||
|
||||
for (i = 0; i < disconnectedCount; i++)
|
||||
{
|
||||
if (disconnected[i])
|
||||
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
|
||||
}
|
||||
|
||||
free(disconnected);
|
||||
}
|
||||
else
|
||||
{
|
||||
const int widthMM = DisplayWidthMM(_glfw.x11.display, _glfw.x11.screen);
|
||||
const int heightMM = DisplayHeightMM(_glfw.x11.display, _glfw.x11.screen);
|
||||
|
||||
_glfwInputMonitor(_glfwAllocMonitor("Display", widthMM, heightMM),
|
||||
GLFW_CONNECTED,
|
||||
_GLFW_INSERT_FIRST);
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
@@ -112,7 +231,7 @@ GLFWbool _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
||||
best = _glfwChooseVideoMode(monitor, desired);
|
||||
_glfwPlatformGetVideoMode(monitor, ¤t);
|
||||
if (_glfwCompareVideoModes(¤t, best) == 0)
|
||||
return GLFW_TRUE;
|
||||
return;
|
||||
|
||||
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||
@@ -150,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
|
||||
@@ -198,119 +308,6 @@ void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor)
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
||||
{
|
||||
int i, j, k, found = 0;
|
||||
_GLFWmonitor** monitors = NULL;
|
||||
|
||||
*count = 0;
|
||||
|
||||
if (_glfw.x11.randr.available)
|
||||
{
|
||||
int screenCount = 0;
|
||||
XineramaScreenInfo* screens = NULL;
|
||||
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display,
|
||||
_glfw.x11.root);
|
||||
RROutput primary = XRRGetOutputPrimary(_glfw.x11.display,
|
||||
_glfw.x11.root);
|
||||
|
||||
monitors = calloc(sr->noutput, sizeof(_GLFWmonitor*));
|
||||
|
||||
if (_glfw.x11.xinerama.available)
|
||||
screens = XineramaQueryScreens(_glfw.x11.display, &screenCount);
|
||||
|
||||
for (i = 0; i < sr->ncrtc; i++)
|
||||
{
|
||||
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display,
|
||||
sr, sr->crtcs[i]);
|
||||
|
||||
for (j = 0; j < ci->noutput; j++)
|
||||
{
|
||||
int widthMM, heightMM;
|
||||
_GLFWmonitor* monitor;
|
||||
XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display,
|
||||
sr, ci->outputs[j]);
|
||||
if (oi->connection != RR_Connected)
|
||||
{
|
||||
XRRFreeOutputInfo(oi);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
|
||||
{
|
||||
widthMM = oi->mm_height;
|
||||
heightMM = oi->mm_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
widthMM = oi->mm_width;
|
||||
heightMM = oi->mm_height;
|
||||
}
|
||||
|
||||
monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM);
|
||||
monitor->x11.output = ci->outputs[j];
|
||||
monitor->x11.crtc = oi->crtc;
|
||||
|
||||
for (k = 0; k < screenCount; k++)
|
||||
{
|
||||
if (screens[k].x_org == ci->x &&
|
||||
screens[k].y_org == ci->y &&
|
||||
screens[k].width == ci->width &&
|
||||
screens[k].height == ci->height)
|
||||
{
|
||||
monitor->x11.index = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
XRRFreeOutputInfo(oi);
|
||||
|
||||
found++;
|
||||
monitors[found - 1] = monitor;
|
||||
|
||||
if (ci->outputs[j] == primary)
|
||||
_GLFW_SWAP_POINTERS(monitors[0], monitors[found - 1]);
|
||||
}
|
||||
|
||||
XRRFreeCrtcInfo(ci);
|
||||
}
|
||||
|
||||
XRRFreeScreenResources(sr);
|
||||
|
||||
if (screens)
|
||||
XFree(screens);
|
||||
|
||||
if (found == 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: RandR monitor support seems broken");
|
||||
|
||||
_glfw.x11.randr.monitorBroken = GLFW_TRUE;
|
||||
free(monitors);
|
||||
monitors = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!monitors)
|
||||
{
|
||||
monitors = calloc(1, sizeof(_GLFWmonitor*));
|
||||
monitors[0] = _glfwAllocMonitor("Display",
|
||||
DisplayWidthMM(_glfw.x11.display,
|
||||
_glfw.x11.screen),
|
||||
DisplayHeightMM(_glfw.x11.display,
|
||||
_glfw.x11.screen));
|
||||
found = 1;
|
||||
}
|
||||
|
||||
*count = found;
|
||||
return monitors;
|
||||
}
|
||||
|
||||
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
|
||||
{
|
||||
return first->x11.crtc == second->x11.crtc;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
{
|
||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||
@@ -331,6 +328,15 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||
float* xscale, float* yscale)
|
||||
{
|
||||
if (xscale)
|
||||
*xscale = _glfw.x11.contentScaleX;
|
||||
if (yscale)
|
||||
*yscale = _glfw.x11.contentScaleY;
|
||||
}
|
||||
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||
{
|
||||
GLFWvidmode* result;
|
||||
@@ -423,9 +429,9 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
|
||||
_glfwAllocGammaArrays(ramp, size);
|
||||
|
||||
memcpy(ramp->red, gamma->red, size * sizeof(unsigned short));
|
||||
memcpy(ramp->red, gamma->red, size * sizeof(unsigned short));
|
||||
memcpy(ramp->green, gamma->green, size * sizeof(unsigned short));
|
||||
memcpy(ramp->blue, gamma->blue, size * sizeof(unsigned short));
|
||||
memcpy(ramp->blue, gamma->blue, size * sizeof(unsigned short));
|
||||
|
||||
XRRFreeGamma(gamma);
|
||||
}
|
||||
@@ -446,11 +452,18 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||
{
|
||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
|
||||
{
|
||||
if (XRRGetCrtcGammaSize(_glfw.x11.display, monitor->x11.crtc) != ramp->size)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Gamma ramp size must match current ramp size");
|
||||
return;
|
||||
}
|
||||
|
||||
XRRCrtcGamma* gamma = XRRAllocGamma(ramp->size);
|
||||
|
||||
memcpy(gamma->red, ramp->red, ramp->size * sizeof(unsigned short));
|
||||
memcpy(gamma->red, ramp->red, ramp->size * sizeof(unsigned short));
|
||||
memcpy(gamma->green, ramp->green, ramp->size * sizeof(unsigned short));
|
||||
memcpy(gamma->blue, ramp->blue, ramp->size * sizeof(unsigned short));
|
||||
memcpy(gamma->blue, ramp->blue, ramp->size * sizeof(unsigned short));
|
||||
|
||||
XRRSetCrtcGamma(_glfw.x11.display, monitor->x11.crtc, gamma);
|
||||
XRRFreeGamma(gamma);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user