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
|
- master
|
||||||
skip_tags: true
|
skip_tags: true
|
||||||
environment:
|
environment:
|
||||||
|
CFLAGS: /WX
|
||||||
matrix:
|
matrix:
|
||||||
- BUILD_SHARED_LIBS: ON
|
- BUILD_SHARED_LIBS: ON
|
||||||
- BUILD_SHARED_LIBS: OFF
|
- BUILD_SHARED_LIBS: OFF
|
||||||
@@ -12,11 +13,11 @@ matrix:
|
|||||||
build_script:
|
build_script:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- cmake -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS% ..
|
- cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS% ..
|
||||||
- cmake --build .
|
- cmake --build .
|
||||||
notifications:
|
notifications:
|
||||||
- provider: Email
|
- provider: Email
|
||||||
to:
|
to:
|
||||||
- ci@glfw.org
|
- ci@glfw.org
|
||||||
- on_build_failure: true
|
on_build_failure: true
|
||||||
- on_build_success: false
|
on_build_success: false
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
*.m linguist-language=Objective-C
|
||||||
+1
-1
@@ -58,6 +58,7 @@ examples/heightmap
|
|||||||
examples/offscreen
|
examples/offscreen
|
||||||
examples/particles
|
examples/particles
|
||||||
examples/splitview
|
examples/splitview
|
||||||
|
examples/sharing
|
||||||
examples/simple
|
examples/simple
|
||||||
examples/wave
|
examples/wave
|
||||||
tests/*.app
|
tests/*.app
|
||||||
@@ -74,7 +75,6 @@ tests/joysticks
|
|||||||
tests/monitors
|
tests/monitors
|
||||||
tests/msaa
|
tests/msaa
|
||||||
tests/reopen
|
tests/reopen
|
||||||
tests/sharing
|
|
||||||
tests/tearing
|
tests/tearing
|
||||||
tests/threads
|
tests/threads
|
||||||
tests/timeout
|
tests/timeout
|
||||||
|
|||||||
+55
-7
@@ -4,23 +4,71 @@ branches:
|
|||||||
only:
|
only:
|
||||||
- ci
|
- ci
|
||||||
- master
|
- master
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
- osx
|
|
||||||
sudo: false
|
sudo: false
|
||||||
|
dist: trusty
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
|
||||||
- kubuntu-backports
|
|
||||||
packages:
|
packages:
|
||||||
- cmake
|
- cmake
|
||||||
env:
|
- libxrandr-dev
|
||||||
|
- libxinerama-dev
|
||||||
|
- libxcursor-dev
|
||||||
|
- libxi-dev
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: linux
|
||||||
|
env:
|
||||||
- BUILD_SHARED_LIBS=ON
|
- BUILD_SHARED_LIBS=ON
|
||||||
|
- CFLAGS=-Werror
|
||||||
|
- os: linux
|
||||||
|
env:
|
||||||
- BUILD_SHARED_LIBS=OFF
|
- 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:
|
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
|
- mkdir build
|
||||||
- cd 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 .
|
- cmake --build .
|
||||||
notifications:
|
notifications:
|
||||||
email:
|
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_FOUND - the system has Mir
|
||||||
# MIR_LIBRARIES - Link these to use Mir
|
# MIR_INCLUDE_DIRS - the Mir include directory
|
||||||
# MIR_INCLUDE_DIR - Include directory for Mir
|
# MIR_LIBRARIES - the Mir libraries
|
||||||
# MIR_DEFINITIONS - Compiler switches required for using Mir
|
# MIR_DEFINITIONS - the Mir definitions
|
||||||
|
|
||||||
if (NOT WIN32)
|
|
||||||
|
|
||||||
find_package (PkgConfig)
|
find_package (PkgConfig)
|
||||||
pkg_check_modules (PKG_MIR QUIET mirclient)
|
if(PKG_CONFIG_FOUND)
|
||||||
set(MIR_DEFINITIONS ${PKG_MIR_CFLAGS_OTHER})
|
pkg_check_modules (PC_MIR mirclient>=0.26.2 QUIET)
|
||||||
|
|
||||||
find_path(MIR_INCLUDE_DIR
|
find_path(MIR_INCLUDE_DIR NAMES mir_toolkit/mir_client_library.h
|
||||||
NAMES xkbcommon/xkbcommon.h
|
PATHS ${PC_MIR_INCLUDE_DIRS})
|
||||||
HINTS ${PC_XKBCOMMON_INCLUDE_DIR} ${PC_XKBCOMMON_INCLUDE_DIRS}
|
|
||||||
)
|
|
||||||
|
|
||||||
find_library(MIR_LIBRARY
|
find_library(MIR_LIBRARY NAMES mirclient
|
||||||
NAMES mirclient
|
PATHS ${PC_MIR_LIBRARIES} ${PC_MIR_LIBRARY_DIRS})
|
||||||
HINTS ${PKG_MIR_LIBRARIES} ${MIR_LIBRARY_DIRS}
|
|
||||||
)
|
|
||||||
|
|
||||||
set (MIR_INCLUDE_DIR ${PKG_MIR_INCLUDE_DIRS})
|
|
||||||
set (MIR_LIBRARIES ${MIR_LIBRARY})
|
|
||||||
|
|
||||||
include (FindPackageHandleStandardArgs)
|
include (FindPackageHandleStandardArgs)
|
||||||
find_package_handle_standard_args (MIR DEFAULT_MSG
|
find_package_handle_standard_args (MIR
|
||||||
MIR_LIBRARIES
|
REQUIRED_VARS MIR_LIBRARY MIR_INCLUDE_DIR)
|
||||||
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
|
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||||
"$ENV{VULKAN_SDK}/Include"
|
"$ENV{VULKAN_SDK}/Include"
|
||||||
"$ENV{VK_SDK_PATH}/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
|
find_library(VULKAN_LIBRARY NAMES vulkan-1 HINTS
|
||||||
|
"$ENV{VULKAN_SDK}/Lib"
|
||||||
"$ENV{VULKAN_SDK}/Bin"
|
"$ENV{VULKAN_SDK}/Bin"
|
||||||
"$ENV{VK_SDK_PATH}/Bin")
|
"$ENV{VK_SDK_PATH}/Bin")
|
||||||
find_library(VULKAN_STATIC_LIBRARY NAMES vkstatic.1 HINTS
|
find_library(VULKAN_STATIC_LIBRARY NAMES vkstatic.1 HINTS
|
||||||
|
"$ENV{VULKAN_SDK}/Lib"
|
||||||
"$ENV{VULKAN_SDK}/Bin"
|
"$ENV{VULKAN_SDK}/Bin"
|
||||||
"$ENV{VK_SDK_PATH}/Bin")
|
"$ENV{VK_SDK_PATH}/Bin")
|
||||||
else()
|
else()
|
||||||
find_library(VULKAN_LIBRARY NAMES vulkan-1 HINTS
|
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{VULKAN_SDK}/Bin32"
|
||||||
"$ENV{VK_SDK_PATH}/Bin32")
|
"$ENV{VK_SDK_PATH}/Bin32")
|
||||||
endif()
|
endif()
|
||||||
elseif (APPLE)
|
elseif (APPLE)
|
||||||
|
set(CMAKE_FIND_FRAMEWORK NEVER)
|
||||||
find_library(VULKAN_LIBRARY MoltenVK)
|
find_library(VULKAN_LIBRARY MoltenVK)
|
||||||
if (VULKAN_LIBRARY)
|
set(CMAKE_FIND_FRAMEWORK ONLY)
|
||||||
set(VULKAN_STATIC_LIBRARY ${VULKAN_LIBRARY})
|
find_library(VULKAN_STATIC_LIBRARY MoltenVK)
|
||||||
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||||
"${VULKAN_LIBRARY}/Headers")
|
"${VULKAN_LIBRARY}/Headers")
|
||||||
endif()
|
|
||||||
else()
|
else()
|
||||||
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||||
"$ENV{VULKAN_SDK}/include")
|
"$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)
|
project(GLFW C)
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 2.8.12)
|
set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
|
||||||
|
|
||||||
if (NOT CMAKE_VERSION VERSION_LESS "3.0")
|
if (NOT CMAKE_VERSION VERSION_LESS "3.0")
|
||||||
# Until all major package systems have moved to CMake 3,
|
# 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)
|
cmake_policy(SET CMP0042 OLD)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (NOT CMAKE_VERSION VERSION_LESS "3.1")
|
||||||
|
cmake_policy(SET CMP0054 NEW)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(GLFW_VERSION_MAJOR "3")
|
set(GLFW_VERSION_MAJOR "3")
|
||||||
set(GLFW_VERSION_MINOR "3")
|
set(GLFW_VERSION_MINOR "3")
|
||||||
set(GLFW_VERSION_PATCH "0")
|
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_BUILD_DOCS "Build the GLFW documentation" ON)
|
||||||
option(GLFW_INSTALL "Generate installation target" ON)
|
option(GLFW_INSTALL "Generate installation target" ON)
|
||||||
option(GLFW_VULKAN_STATIC "Use the Vulkan loader statically linked into application" OFF)
|
option(GLFW_VULKAN_STATIC "Use the Vulkan loader statically linked into application" OFF)
|
||||||
option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF)
|
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
option(GLFW_USE_OSMESA "Use OSMesa for offscreen context creation" OFF)
|
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)
|
option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on hybrid systems" OFF)
|
||||||
endif()
|
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)
|
if (UNIX AND NOT APPLE)
|
||||||
option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF)
|
option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF)
|
||||||
option(GLFW_USE_MIR "Use Mir for window creation" OFF)
|
option(GLFW_USE_MIR "Use Mir for window creation" OFF)
|
||||||
@@ -182,7 +180,7 @@ endif()
|
|||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
if (GLFW_VULKAN_STATIC)
|
if (GLFW_VULKAN_STATIC)
|
||||||
if (VULKAN_FOUND AND VULKAN_STATIC_LIBRARY)
|
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)
|
if (BUILD_SHARED_LIBS)
|
||||||
message(WARNING "Linking Vulkan loader static library into GLFW")
|
message(WARNING "Linking Vulkan loader static library into GLFW")
|
||||||
endif()
|
endif()
|
||||||
@@ -217,6 +215,11 @@ if (UNIX AND NOT APPLE)
|
|||||||
list(APPEND glfw_LIBRARIES "${CMAKE_DL_LIBS}")
|
list(APPEND glfw_LIBRARIES "${CMAKE_DL_LIBS}")
|
||||||
list(APPEND glfw_PKG_LIBS "-l${CMAKE_DL_LIBS}")
|
list(APPEND glfw_PKG_LIBS "-l${CMAKE_DL_LIBS}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_package(DBus)
|
||||||
|
if (DBUS_FOUND)
|
||||||
|
list(APPEND glfw_INCLUDE_DIRS ${DBUS_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
@@ -246,38 +249,28 @@ if (_GLFW_X11)
|
|||||||
|
|
||||||
# Check for XRandR (modern resolution switching and gamma control)
|
# Check for XRandR (modern resolution switching and gamma control)
|
||||||
if (NOT X11_Xrandr_FOUND)
|
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()
|
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)
|
# Check for Xinerama (legacy multi-monitor support)
|
||||||
if (NOT X11_Xinerama_FOUND)
|
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()
|
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)
|
# Check for Xkb (X keyboard extension)
|
||||||
if (NOT X11_Xkb_FOUND)
|
if (NOT X11_Xkb_FOUND)
|
||||||
message(FATAL_ERROR "The X keyboard extension headers were not found")
|
message(FATAL_ERROR "The X keyboard extension headers were not found")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
list(APPEND glfw_INCLUDE_DIR "${X11_Xkb_INCLUDE_PATH}")
|
# Check for Xcursor (cursor creation from RGBA images)
|
||||||
|
|
||||||
# Check for Xcursor
|
|
||||||
if (NOT X11_Xcursor_FOUND)
|
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()
|
endif()
|
||||||
|
|
||||||
list(APPEND glfw_INCLUDE_DIR "${X11_Xcursor_INCLUDE_PATH}")
|
list(APPEND glfw_INCLUDE_DIRS "${X11_Xrandr_INCLUDE_PATH}"
|
||||||
list(APPEND glfw_LIBRARIES "${X11_Xcursor_LIB}")
|
"${X11_Xinerama_INCLUDE_PATH}"
|
||||||
list(APPEND glfw_PKG_DEPS "xcursor")
|
"${X11_Xkb_INCLUDE_PATH}"
|
||||||
|
"${X11_Xcursor_INCLUDE_PATH}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
@@ -285,21 +278,22 @@ endif()
|
|||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
if (_GLFW_WAYLAND)
|
if (_GLFW_WAYLAND)
|
||||||
find_package(ECM REQUIRED NO_MODULE)
|
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(WaylandScanner REQUIRED)
|
||||||
find_package(WaylandProtocols 1.1 REQUIRED)
|
find_package(WaylandProtocols 1.12 REQUIRED)
|
||||||
|
|
||||||
list(APPEND glfw_PKG_DEPS "wayland-egl")
|
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}")
|
list(APPEND glfw_LIBRARIES "${Wayland_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}")
|
||||||
|
|
||||||
find_package(XKBCommon REQUIRED)
|
find_package(XKBCommon REQUIRED)
|
||||||
list(APPEND glfw_PKG_DEPS "xkbcommon")
|
|
||||||
list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}")
|
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()
|
endif()
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
@@ -309,7 +303,7 @@ if (_GLFW_MIR)
|
|||||||
find_package(Mir REQUIRED)
|
find_package(Mir REQUIRED)
|
||||||
list(APPEND glfw_PKG_DEPS "mirclient")
|
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}")
|
list(APPEND glfw_LIBRARIES "${MIR_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}")
|
||||||
|
|
||||||
find_package(XKBCommon REQUIRED)
|
find_package(XKBCommon REQUIRED)
|
||||||
@@ -331,14 +325,6 @@ endif()
|
|||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
if (_GLFW_COCOA)
|
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
|
list(APPEND glfw_LIBRARIES
|
||||||
"-framework Cocoa"
|
"-framework Cocoa"
|
||||||
"-framework IOKit"
|
"-framework IOKit"
|
||||||
@@ -422,6 +408,7 @@ if (GLFW_INSTALL)
|
|||||||
add_custom_target(uninstall
|
add_custom_target(uninstall
|
||||||
"${CMAKE_COMMAND}" -P
|
"${CMAKE_COMMAND}" -P
|
||||||
"${GLFW_BINARY_DIR}/cmake_uninstall.cmake")
|
"${GLFW_BINARY_DIR}/cmake_uninstall.cmake")
|
||||||
|
set_target_properties(uninstall PROPERTIES FOLDER "GLFW3")
|
||||||
endif()
|
endif()
|
||||||
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
|
application development. It provides a simple, platform-independent API for
|
||||||
creating windows, contexts and surfaces, reading input, handling events, etc.
|
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
|
GLFW is licensed under the [zlib/libpng
|
||||||
license](http://www.glfw.org/license.html).
|
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.
|
changes for every release.
|
||||||
|
|
||||||
This is a development branch for version 3.3, which is _not yet described_.
|
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
|
If you are new to GLFW, you may find the
|
||||||
[tutorial](http://www.glfw.org/docs/latest/quick.html) for GLFW
|
[tutorial](http://www.glfw.org/docs/latest/quick.html) for GLFW 3 useful. If
|
||||||
3 useful. If you have used GLFW 2 in the past, there is a
|
you have used GLFW 2 in the past, there is a [transition
|
||||||
[transition guide](http://www.glfw.org/docs/latest/moving.html) for moving to
|
guide](http://www.glfw.org/docs/latest/moving.html) for moving to the GLFW
|
||||||
the GLFW 3 API.
|
3 API.
|
||||||
|
|
||||||
|
|
||||||
## Compiling GLFW
|
## Compiling GLFW
|
||||||
|
|
||||||
GLFW itself requires only the headers and libraries for your window system. It
|
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
|
does not need the headers for any context creation API (WGL, GLX, EGL, NSGL,
|
||||||
rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them.
|
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
|
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
|
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
|
and Clang. It will likely compile in other environments as well, but this is
|
||||||
not regularly tested.
|
not regularly tested.
|
||||||
|
|
||||||
There are also [pre-compiled Windows
|
There are [pre-compiled Windows binaries](http://www.glfw.org/download.html)
|
||||||
binaries](http://www.glfw.org/download.html) available for all compilers
|
available for all supported compilers.
|
||||||
supported on that platform.
|
|
||||||
|
|
||||||
See the [compilation guide](http://www.glfw.org/docs/latest/compile.html) in the
|
See the [compilation guide](http://www.glfw.org/docs/latest/compile.html) for
|
||||||
documentation for more information.
|
more information about how to compile GLFW yourself.
|
||||||
|
|
||||||
|
|
||||||
## Using GLFW
|
## Using GLFW
|
||||||
|
|
||||||
See the [building application guide](http://www.glfw.org/docs/latest/build.html)
|
See the [documentation](http://www.glfw.org/docs/latest/) for tutorials, guides
|
||||||
guide in the documentation for more information.
|
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
|
## System requirements
|
||||||
|
|
||||||
GLFW supports Windows XP and later, OS X 10.7 Lion and later, and Linux and
|
GLFW supports Windows XP and later and macOS 10.7 and later. Linux and other
|
||||||
other Unix-like systems with the X Window System. Experimental implementations
|
Unix-like systems running the X Window System are supported even without
|
||||||
for the Wayland protocol and the Mir display server are available but not yet
|
a desktop environment or modern extensions, although some features require
|
||||||
officially supported.
|
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)
|
See the [compatibility guide](http://www.glfw.org/docs/latest/compat.html)
|
||||||
in the documentation for more information.
|
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.
|
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
|
The examples and test programs depend on a number of tiny libraries. These are
|
||||||
located in the `deps/` directory.
|
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
|
- [Vulkan headers](https://www.khronos.org/registry/vulkan/) for Vulkan tests
|
||||||
|
|
||||||
The Vulkan example additionally requires the Vulkan SDK to be installed, or it
|
The Vulkan example additionally requires the 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
|
The documentation is generated with [Doxygen](http://doxygen.org/) if CMake can
|
||||||
does not find Doxygen, the documentation will not be generated when you build.
|
find that tool.
|
||||||
|
|
||||||
|
|
||||||
## Reporting bugs
|
## Reporting bugs
|
||||||
|
|
||||||
Bugs are reported to our [issue tracker](https://github.com/glfw/glfw/issues).
|
Bugs are reported to our [issue tracker](https://github.com/glfw/glfw/issues).
|
||||||
Please check the [contribution
|
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.
|
information on what to include when reporting a bug.
|
||||||
|
|
||||||
|
|
||||||
## Changelog
|
## 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
|
- Added `glfwGetKeyScancode` function that allows retrieving platform dependent
|
||||||
scancodes for keys (#830)
|
scancodes for keys (#830)
|
||||||
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
|
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
|
||||||
receiving window maximization events (#778)
|
receiving window maximization events (#778)
|
||||||
- Added `glfwSetWindowAttrib` function for changing window attributes (#537)
|
- 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 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_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_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: Calling `glfwMaximizeWindow` on a full screen window was not ignored
|
||||||
- Bugfix: `GLFW_INCLUDE_VULKAN` could not be combined with the corresponding
|
- Bugfix: `GLFW_INCLUDE_VULKAN` could not be combined with the corresponding
|
||||||
OpenGL and OpenGL ES header macros
|
OpenGL and OpenGL ES header macros
|
||||||
- Bugfix: `glfwGetInstanceProcAddress` returned `NULL` for
|
- Bugfix: `glfwGetInstanceProcAddress` returned `NULL` for
|
||||||
`vkGetInstanceProcAddr` when `_GLFW_VULKAN_STATIC` was enabled
|
`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: Undecorated windows could not be iconified by the user (#861)
|
||||||
- [Win32] Bugfix: Deadzone logic could underflow with some controllers (#910)
|
- [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
|
- [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: Disabling window aspect ratio would assert (#852)
|
||||||
- [Cocoa] Bugfix: Window creation failed to set first responder (#876,#883)
|
- [Cocoa] Bugfix: Window creation failed to set first responder (#876,#883)
|
||||||
- [Cocoa] Bugfix: Removed use of deprecated `CGDisplayIOServicePort` function
|
- [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`
|
- [Cocoa] Bugfix: Disabled use of deprecated `CGDisplayModeCopyPixelEncoding`
|
||||||
function on macOS 10.12+
|
function on macOS 10.12+
|
||||||
- [Cocoa] Bugfix: Running in AppSandbox would emit warnings (#816,#882)
|
- [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_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
|
## Contact
|
||||||
@@ -154,20 +299,28 @@ GLFW exists because people around the world donated their time and lent their
|
|||||||
skills.
|
skills.
|
||||||
|
|
||||||
- Bobyshev Alexander
|
- Bobyshev Alexander
|
||||||
- artblanc
|
|
||||||
- arturo
|
|
||||||
- Matt Arsenault
|
- Matt Arsenault
|
||||||
|
- David Avedissian
|
||||||
- Keith Bauer
|
- Keith Bauer
|
||||||
- John Bartholomew
|
- John Bartholomew
|
||||||
- Niklas Behrens
|
- Niklas Behrens
|
||||||
- Niklas Bergström
|
- Niklas Bergström
|
||||||
|
- Denis Bernard
|
||||||
- Doug Binks
|
- Doug Binks
|
||||||
- blanco
|
- blanco
|
||||||
- Kyle Brenneman
|
- Kyle Brenneman
|
||||||
|
- Rok Breulj
|
||||||
- Martin Capitanio
|
- Martin Capitanio
|
||||||
|
- David Carlier
|
||||||
|
- Arturo Castro
|
||||||
- Chi-kwan Chan
|
- Chi-kwan Chan
|
||||||
|
- Ian Clarkson
|
||||||
|
- Michał Cichoń
|
||||||
- Lambert Clara
|
- Lambert Clara
|
||||||
|
- Yaron Cohen-Tal
|
||||||
|
- Omar Cornut
|
||||||
- Andrew Corrigan
|
- Andrew Corrigan
|
||||||
|
- Bailey Cosier
|
||||||
- Noel Cower
|
- Noel Cower
|
||||||
- Jason Daly
|
- Jason Daly
|
||||||
- Jarrod Davis
|
- Jarrod Davis
|
||||||
@@ -176,16 +329,23 @@ skills.
|
|||||||
- Michael Dickens
|
- Michael Dickens
|
||||||
- Роман Донченко
|
- Роман Донченко
|
||||||
- Mario Dorn
|
- Mario Dorn
|
||||||
|
- Wolfgang Draxinger
|
||||||
- Jonathan Dummer
|
- Jonathan Dummer
|
||||||
- Ralph Eastwood
|
- Ralph Eastwood
|
||||||
|
- Fredrik Ehnbom
|
||||||
|
- Robin Eklind
|
||||||
- Siavash Eliasi
|
- Siavash Eliasi
|
||||||
|
- Felipe Ferreira
|
||||||
- Michael Fogleman
|
- Michael Fogleman
|
||||||
- Gerald Franz
|
- Gerald Franz
|
||||||
- Mário Freitas
|
- Mário Freitas
|
||||||
- GeO4d
|
- GeO4d
|
||||||
- Marcus Geelnard
|
- Marcus Geelnard
|
||||||
|
- Stephen Gowen
|
||||||
|
- Kovid Goyal
|
||||||
- Eloi Marín Gratacós
|
- Eloi Marín Gratacós
|
||||||
- Stefan Gustavson
|
- Stefan Gustavson
|
||||||
|
- Jonathan Hale
|
||||||
- Sylvain Hellegouarch
|
- Sylvain Hellegouarch
|
||||||
- Matthew Henry
|
- Matthew Henry
|
||||||
- heromyth
|
- heromyth
|
||||||
@@ -197,64 +357,83 @@ skills.
|
|||||||
- Erik S. V. Jansson
|
- Erik S. V. Jansson
|
||||||
- Toni Jovanoski
|
- Toni Jovanoski
|
||||||
- Arseny Kapoulkine
|
- Arseny Kapoulkine
|
||||||
|
- Cem Karan
|
||||||
- Osman Keskin
|
- Osman Keskin
|
||||||
|
- Josh Kilmer
|
||||||
- Cameron King
|
- Cameron King
|
||||||
- Peter Knut
|
- Peter Knut
|
||||||
- Christoph Kubisch
|
- Christoph Kubisch
|
||||||
|
- Yuri Kunde Schlesner
|
||||||
|
- Konstantin Käfer
|
||||||
- Eric Larson
|
- Eric Larson
|
||||||
- Robin Leffmann
|
- Robin Leffmann
|
||||||
- Glenn Lewis
|
- Glenn Lewis
|
||||||
- Shane Liesegang
|
- Shane Liesegang
|
||||||
- Eyal Lotem
|
- Eyal Lotem
|
||||||
- Дмитри Малышев
|
|
||||||
- Martins Mozeiko
|
|
||||||
- Tristam MacDonald
|
- Tristam MacDonald
|
||||||
- Hans Mackowiak
|
- Hans Mackowiak
|
||||||
|
- Дмитри Малышев
|
||||||
- Zbigniew Mandziejewicz
|
- Zbigniew Mandziejewicz
|
||||||
|
- Célestin Marot
|
||||||
- Kyle McDonald
|
- Kyle McDonald
|
||||||
- David Medlock
|
- David Medlock
|
||||||
- Bryce Mehring
|
- Bryce Mehring
|
||||||
- Jonathan Mercier
|
- Jonathan Mercier
|
||||||
- Marcel Metz
|
- Marcel Metz
|
||||||
|
- Liam Middlebrook
|
||||||
- Jonathan Miller
|
- Jonathan Miller
|
||||||
- Kenneth Miller
|
- Kenneth Miller
|
||||||
- Bruce Mitchener
|
- Bruce Mitchener
|
||||||
- Jack Moffitt
|
- Jack Moffitt
|
||||||
- Jeff Molofee
|
- Jeff Molofee
|
||||||
|
- Pierre Morel
|
||||||
- Jon Morton
|
- Jon Morton
|
||||||
- Pierre Moulon
|
- Pierre Moulon
|
||||||
|
- Martins Mozeiko
|
||||||
- Julian Møller
|
- Julian Møller
|
||||||
|
- ndogxj
|
||||||
|
- Kristian Nielsen
|
||||||
- Kamil Nowakowski
|
- Kamil Nowakowski
|
||||||
|
- Denis Ovod
|
||||||
- Ozzy
|
- Ozzy
|
||||||
- Andri Pálsson
|
- Andri Pálsson
|
||||||
- Peoro
|
- Peoro
|
||||||
- Braden Pellett
|
- Braden Pellett
|
||||||
|
- Christopher Pelloux
|
||||||
- Arturo J. Pérez
|
- Arturo J. Pérez
|
||||||
|
- Anthony Pesch
|
||||||
- Orson Peters
|
- Orson Peters
|
||||||
- Emmanuel Gil Peyrot
|
- Emmanuel Gil Peyrot
|
||||||
- Cyril Pichard
|
- Cyril Pichard
|
||||||
- Pieroman
|
- Keith Pitt
|
||||||
|
- Stanislav Podgorskiy
|
||||||
|
- Alexandre Pretyman
|
||||||
|
- przemekmirek
|
||||||
- Philip Rideout
|
- Philip Rideout
|
||||||
|
- Eddie Ringle
|
||||||
- Jorge Rodriguez
|
- Jorge Rodriguez
|
||||||
- Ed Ropple
|
- Ed Ropple
|
||||||
- Aleksey Rybalkin
|
- Aleksey Rybalkin
|
||||||
- Riku Salminen
|
- Riku Salminen
|
||||||
- Brandon Schaefer
|
- Brandon Schaefer
|
||||||
- Sebastian Schuberth
|
- Sebastian Schuberth
|
||||||
|
- Christian Sdunek
|
||||||
- Matt Sealey
|
- Matt Sealey
|
||||||
- SephiRok
|
|
||||||
- Steve Sexton
|
- Steve Sexton
|
||||||
- Systemcluster
|
- Arkady Shapkin
|
||||||
- Yoshiki Shibukawa
|
- Yoshiki Shibukawa
|
||||||
- Dmitri Shuralyov
|
- Dmitri Shuralyov
|
||||||
- Daniel Skorupski
|
- Daniel Skorupski
|
||||||
- Bradley Smith
|
- Bradley Smith
|
||||||
- Patrick Snape
|
- Patrick Snape
|
||||||
|
- Erlend Sogge Heggen
|
||||||
- Julian Squires
|
- Julian Squires
|
||||||
- Johannes Stein
|
- Johannes Stein
|
||||||
|
- Pontus Stenetorp
|
||||||
- Michael Stocker
|
- Michael Stocker
|
||||||
- Justin Stoecker
|
- Justin Stoecker
|
||||||
- Elviss Strazdins
|
- Elviss Strazdins
|
||||||
|
- Paul Sultana
|
||||||
- Nathan Sweet
|
- Nathan Sweet
|
||||||
- TTK-Bandit
|
- TTK-Bandit
|
||||||
- Sergey Tikhomirov
|
- Sergey Tikhomirov
|
||||||
@@ -264,16 +443,19 @@ skills.
|
|||||||
- Matthew Turner
|
- Matthew Turner
|
||||||
- urraka
|
- urraka
|
||||||
- Elias Vanderstuyft
|
- Elias Vanderstuyft
|
||||||
|
- Stef Velzel
|
||||||
- Jari Vetoniemi
|
- Jari Vetoniemi
|
||||||
- Ricardo Vieira
|
- Ricardo Vieira
|
||||||
- Nicholas Vitovitch
|
- Nicholas Vitovitch
|
||||||
- Simon Voordouw
|
- Simon Voordouw
|
||||||
|
- Corentin Wallez
|
||||||
- Torsten Walluhn
|
- Torsten Walluhn
|
||||||
- Patrick Walton
|
- Patrick Walton
|
||||||
- Xo Wang
|
- Xo Wang
|
||||||
- Jay Weisskopf
|
- Jay Weisskopf
|
||||||
- Frank Wille
|
- Frank Wille
|
||||||
- yuriks
|
- Ryogo Yoshimura
|
||||||
|
- Andrey Zholos
|
||||||
- Santi Zupancic
|
- Santi Zupancic
|
||||||
- Jonas Ådahl
|
- Jonas Ådahl
|
||||||
- Lasse Öörni
|
- 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};
|
vec3 u = {x, y, z};
|
||||||
|
|
||||||
if(vec3_len(u) > 1e-4) {
|
if(vec3_len(u) > 1e-4) {
|
||||||
mat4x4 T, C, S;
|
mat4x4 T, C, S = {{0}};
|
||||||
|
|
||||||
vec3_norm(u, u);
|
vec3_norm(u, u);
|
||||||
mat4x4_from_vec3_mul_outer(T, u, u);
|
mat4x4_from_vec3_mul_outer(T, u, u);
|
||||||
|
|||||||
Vendored
+2744
-987
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.
|
* 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_font_stash_end(void);
|
||||||
|
|
||||||
NK_API void nk_glfw3_new_frame(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_shutdown(void);
|
||||||
|
|
||||||
NK_API void nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint);
|
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
|
#ifndef NK_GLFW_TEXT_MAX
|
||||||
#define NK_GLFW_TEXT_MAX 256
|
#define NK_GLFW_TEXT_MAX 256
|
||||||
#endif
|
#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_glfw_device {
|
||||||
struct nk_buffer cmds;
|
struct nk_buffer cmds;
|
||||||
@@ -67,7 +73,10 @@ static struct nk_glfw {
|
|||||||
struct nk_vec2 fb_scale;
|
struct nk_vec2 fb_scale;
|
||||||
unsigned int text[NK_GLFW_TEXT_MAX];
|
unsigned int text[NK_GLFW_TEXT_MAX];
|
||||||
int text_len;
|
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;
|
} glfw;
|
||||||
|
|
||||||
NK_INTERN void
|
NK_INTERN void
|
||||||
@@ -83,7 +92,7 @@ nk_glfw3_device_upload_atlas(const void *image, int width, int height)
|
|||||||
}
|
}
|
||||||
|
|
||||||
NK_API void
|
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 */
|
/* setup global state */
|
||||||
struct nk_glfw_device *dev = &glfw.ogl;
|
struct nk_glfw_device *dev = &glfw.ogl;
|
||||||
@@ -200,7 +209,24 @@ NK_API void
|
|||||||
nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff)
|
nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff)
|
||||||
{
|
{
|
||||||
(void)win; (void)xoff;
|
(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
|
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) {
|
if (init_state == NK_GLFW3_INSTALL_CALLBACKS) {
|
||||||
glfwSetScrollCallback(win, nk_gflw3_scroll_callback);
|
glfwSetScrollCallback(win, nk_gflw3_scroll_callback);
|
||||||
glfwSetCharCallback(win, nk_glfw3_char_callback);
|
glfwSetCharCallback(win, nk_glfw3_char_callback);
|
||||||
|
glfwSetMouseButtonCallback(win, nk_glfw3_mouse_button_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
nk_init_default(&glfw.ctx, 0);
|
nk_init_default(&glfw.ctx, 0);
|
||||||
glfw.ctx.clip.copy = nk_glfw3_clipbard_copy;
|
glfw.ctx.clip.copy = nk_glfw3_clipbard_copy;
|
||||||
glfw.ctx.clip.paste = nk_glfw3_clipbard_paste;
|
glfw.ctx.clip.paste = nk_glfw3_clipbard_paste;
|
||||||
glfw.ctx.clip.userdata = nk_handle_ptr(0);
|
glfw.ctx.clip.userdata = nk_handle_ptr(0);
|
||||||
nk_buffer_init_default(&glfw.ogl.cmds);
|
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;
|
return &glfw.ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,7 +332,7 @@ nk_glfw3_new_frame(void)
|
|||||||
if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
|
if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
|
||||||
glfwGetKey(win, GLFW_KEY_RIGHT_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_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_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_UNDO, glfwGetKey(win, GLFW_KEY_Z) == GLFW_PRESS);
|
||||||
nk_input_key(ctx, NK_KEY_TEXT_REDO, glfwGetKey(win, GLFW_KEY_R) == 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);
|
glfwGetCursorPos(win, &x, &y);
|
||||||
nk_input_motion(ctx, (int)x, (int)y);
|
nk_input_motion(ctx, (int)x, (int)y);
|
||||||
if (ctx->input.mouse.grabbed) {
|
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.x = ctx->input.mouse.prev.x;
|
||||||
ctx->input.mouse.pos.y = ctx->input.mouse.prev.y;
|
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_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_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_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_scroll(ctx, glfw.scroll);
|
||||||
nk_input_end(&glfw.ctx);
|
nk_input_end(&glfw.ctx);
|
||||||
glfw.text_len = 0;
|
glfw.text_len = 0;
|
||||||
glfw.scroll = 0;
|
glfw.scroll = nk_vec2(0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
NK_API
|
NK_API
|
||||||
|
|||||||
Vendored
+1
-1
@@ -53,7 +53,7 @@ extern "C"
|
|||||||
#define VKAPI_PTR VKAPI_CALL
|
#define VKAPI_PTR VKAPI_CALL
|
||||||
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
|
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
|
||||||
#error "Vulkan isn't supported for the 'armeabi' NDK ABI"
|
#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"
|
// On Android 32-bit ARM targets, Vulkan functions use the "hardfloat"
|
||||||
// calling convention, i.e. float parameters are passed in registers. This
|
// 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,
|
// is true even if the rest of the application passes floats on the stack,
|
||||||
|
|||||||
Vendored
+647
-7
@@ -6,7 +6,7 @@ extern "C" {
|
|||||||
#endif
|
#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");
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
** you may not use this file except in compliance with 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_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
|
||||||
#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
|
#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
|
||||||
// Version of this file
|
// Version of this file
|
||||||
#define VK_HEADER_VERSION 26
|
#define VK_HEADER_VERSION 39
|
||||||
|
|
||||||
|
|
||||||
#define VK_NULL_HANDLE 0
|
#define VK_NULL_HANDLE 0
|
||||||
@@ -145,6 +145,7 @@ typedef enum VkResult {
|
|||||||
VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
|
VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
|
||||||
VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
|
VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
|
||||||
VK_ERROR_INVALID_SHADER_NV = -1000012000,
|
VK_ERROR_INVALID_SHADER_NV = -1000012000,
|
||||||
|
VK_ERROR_OUT_OF_POOL_MEMORY_KHR = -1000069000,
|
||||||
VK_RESULT_BEGIN_RANGE = VK_ERROR_FRAGMENTED_POOL,
|
VK_RESULT_BEGIN_RANGE = VK_ERROR_FRAGMENTED_POOL,
|
||||||
VK_RESULT_END_RANGE = VK_INCOMPLETE,
|
VK_RESULT_END_RANGE = VK_INCOMPLETE,
|
||||||
VK_RESULT_RANGE_SIZE = (VK_INCOMPLETE - VK_ERROR_FRAGMENTED_POOL + 1),
|
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_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000,
|
||||||
VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057001,
|
VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057001,
|
||||||
VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000,
|
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_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||||
VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_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),
|
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_BLIT_DST_BIT = 0x00000800,
|
||||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000,
|
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000,
|
||||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000,
|
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
|
VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
|
||||||
} VkFormatFeatureFlagBits;
|
} VkFormatFeatureFlagBits;
|
||||||
typedef VkFlags VkFormatFeatureFlags;
|
typedef VkFlags VkFormatFeatureFlags;
|
||||||
@@ -856,6 +881,7 @@ typedef enum VkImageCreateFlagBits {
|
|||||||
VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
|
VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
|
||||||
VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008,
|
VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008,
|
||||||
VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010,
|
VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010,
|
||||||
|
VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = 0x00000020,
|
||||||
VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
|
VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
|
||||||
} VkImageCreateFlagBits;
|
} VkImageCreateFlagBits;
|
||||||
typedef VkFlags VkImageCreateFlags;
|
typedef VkFlags VkImageCreateFlags;
|
||||||
@@ -917,6 +943,7 @@ typedef enum VkPipelineStageFlagBits {
|
|||||||
VK_PIPELINE_STAGE_HOST_BIT = 0x00004000,
|
VK_PIPELINE_STAGE_HOST_BIT = 0x00004000,
|
||||||
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000,
|
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000,
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000,
|
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000,
|
||||||
|
VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX = 0x00020000,
|
||||||
VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
|
VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
|
||||||
} VkPipelineStageFlagBits;
|
} VkPipelineStageFlagBits;
|
||||||
typedef VkFlags VkPipelineStageFlags;
|
typedef VkFlags VkPipelineStageFlags;
|
||||||
@@ -1091,6 +1118,8 @@ typedef enum VkAccessFlagBits {
|
|||||||
VK_ACCESS_HOST_WRITE_BIT = 0x00004000,
|
VK_ACCESS_HOST_WRITE_BIT = 0x00004000,
|
||||||
VK_ACCESS_MEMORY_READ_BIT = 0x00008000,
|
VK_ACCESS_MEMORY_READ_BIT = 0x00008000,
|
||||||
VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000,
|
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
|
VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
|
||||||
} VkAccessFlagBits;
|
} VkAccessFlagBits;
|
||||||
typedef VkFlags VkAccessFlags;
|
typedef VkFlags VkAccessFlags;
|
||||||
@@ -3196,6 +3225,18 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR)
|
|||||||
|
|
||||||
typedef enum VkColorSpaceKHR {
|
typedef enum VkColorSpaceKHR {
|
||||||
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0,
|
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_BEGIN_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
|
||||||
VK_COLOR_SPACE_END_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),
|
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_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
|
#define VK_EXT_debug_report 1
|
||||||
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
|
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_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
|
#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_SURFACE_KHR_EXT = 26,
|
||||||
VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT = 27,
|
VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT = 27,
|
||||||
VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = 28,
|
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_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_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_DEBUG_REPORT_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1),
|
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
|
VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF
|
||||||
} VkDebugReportObjectTypeEXT;
|
} VkDebugReportObjectTypeEXT;
|
||||||
|
|
||||||
@@ -3972,8 +4147,8 @@ typedef struct VkDedicatedAllocationMemoryAllocateInfoNV {
|
|||||||
|
|
||||||
|
|
||||||
#define VK_AMD_draw_indirect_count 1
|
#define VK_AMD_draw_indirect_count 1
|
||||||
#define VK_AMD_EXTENSION_DRAW_INDIRECT_COUNT_SPEC_VERSION 1
|
#define VK_AMD_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_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_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);
|
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);
|
uint32_t stride);
|
||||||
#endif
|
#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 1
|
||||||
#define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1
|
#define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1
|
||||||
#define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc"
|
#define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc"
|
||||||
@@ -4116,6 +4306,456 @@ typedef struct VkWin32KeyedMutexAcquireReleaseInfoNV {
|
|||||||
|
|
||||||
#endif /* VK_USE_PLATFORM_WIN32_KHR */
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+3
-6
@@ -14,14 +14,11 @@ set(glfw_DOCS_SOURCES
|
|||||||
"${GLFW_SOURCE_DIR}/docs/window.dox"
|
"${GLFW_SOURCE_DIR}/docs/window.dox"
|
||||||
"${GLFW_SOURCE_DIR}/docs/input.dox"
|
"${GLFW_SOURCE_DIR}/docs/input.dox"
|
||||||
"${GLFW_SOURCE_DIR}/docs/vulkan.dox"
|
"${GLFW_SOURCE_DIR}/docs/vulkan.dox"
|
||||||
"${GLFW_SOURCE_DIR}/docs/compat.dox")
|
"${GLFW_SOURCE_DIR}/docs/compat.dox"
|
||||||
|
"${GLFW_SOURCE_DIR}/docs/internal.dox")
|
||||||
if (GLFW_DOCUMENT_INTERNALS)
|
|
||||||
list(APPEND glfw_DOCS_SOURCES "${GLFW_SOURCE_DIR}/src/internal.h")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
foreach(arg ${glfw_DOCS_SOURCES})
|
foreach(arg ${glfw_DOCS_SOURCES})
|
||||||
set(GLFW_DOCS_SOURCES "${GLFW_DOCS_SOURCES} ${arg}")
|
set(GLFW_DOCS_SOURCES "${GLFW_DOCS_SOURCES} \\\n\"${arg}\"")
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
configure_file(Doxyfile.in Doxyfile @ONLY)
|
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 segfault or other crash bug](#reporting-a-segfault-or-other-crash-bug)
|
||||||
- [Reporting a context creation bug](#reporting-a-context-creation-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 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 some other library bug](#reporting-some-other-library-bug)
|
||||||
- [Reporting a documentation bug](#reporting-a-documentation-bug)
|
- [Reporting a documentation bug](#reporting-a-documentation-bug)
|
||||||
- [Reporting a website bug](#reporting-a-website-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
|
If GLFW is crashing or triggering asserts, make sure that all your object
|
||||||
handles and other pointers are valid.
|
handles and other pointers are valid.
|
||||||
|
|
||||||
For bugs where it makes sense, a [Short, Self Contained, Correct (Compilable),
|
For bugs where it makes sense, a short, self contained example is absolutely
|
||||||
Example](http://www.sscce.org/) is absolutely invaluable. Just put it inline in
|
invaluable. Just put it inline in the body text. Note that if the bug is
|
||||||
the body text. Note that if the bug is reproducible with one of the test
|
reproducible with one of the test programs that come with GLFW, just mention
|
||||||
programs that come with GLFW, just mention that instead.
|
that instead.
|
||||||
|
|
||||||
__Don't worry about adding too much information__. Unimportant information can
|
__Don't worry about adding too much information__. Unimportant information can
|
||||||
be abbreviated or removed later, but missing information can stall bug fixing,
|
be abbreviated or removed later, but missing information can stall bug fixing,
|
||||||
especially when your schedule doesn't align with that of the maintainer.
|
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
|
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
|
need to mention these in the subject line. If you do, it will be removed when
|
||||||
the issue is labeled.
|
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
|
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
||||||
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
|
__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
|
Please also include the __GLFW version string__ (`3.2.0 X11 EGL clock_gettime
|
||||||
/dev/js`), as described
|
/dev/js`), as described
|
||||||
[here](http://www.glfw.org/docs/latest/intro.html#intro_version_string), the
|
[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
|
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
||||||
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
|
__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
|
Please also include any __error messages__ provided to your application via the
|
||||||
[error
|
[error
|
||||||
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
|
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:__ 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
|
__Note:__ Window moving and resizing (by the user) will block the main thread on
|
||||||
platforms. This is not a bug. Set a [refresh
|
some platforms. This is not a bug. Set a [refresh
|
||||||
callback](http://www.glfw.org/docs/latest/window.html#window_refresh) if you
|
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.
|
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
|
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
||||||
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
|
__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
|
Please also include any __error messages__ provided to your application via the
|
||||||
[error
|
[error
|
||||||
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
|
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
|
if relevant, the __output of `events`__ when reporting this kind of bug. If
|
||||||
this tool doesn't run on the machine, mention this instead.
|
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
|
#### 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
|
If the patch fixes a bug introduced after the last release, it should not get
|
||||||
a change log entry.
|
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
|
## 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
|
what license. Even code using the same license as GLFW may not be copied
|
||||||
without attribution.
|
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
|
__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
|
as one adding a thousand line one, if that is the appropriate size for the
|
||||||
feature.
|
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
|
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`.
|
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,
|
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
|
but please keep in mind that maintainer time is finite and that there are many
|
||||||
other features and bugs to work on.
|
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
|
# 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.
|
# 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
|
# 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
|
# 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:__" \
|
"x11=__X11:__" \
|
||||||
"wayland=__Wayland:__" \
|
"wayland=__Wayland:__" \
|
||||||
"win32=__Windows:__" \
|
"win32=__Windows:__" \
|
||||||
"macos=__macOS:__"
|
"macos=__macOS:__" \
|
||||||
|
"linux=__Linux:__"
|
||||||
|
|
||||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
# 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
|
# 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
|
# by member name. If set to NO (the default) the members will appear in
|
||||||
# declaration order.
|
# declaration order.
|
||||||
|
|
||||||
SORT_BRIEF_DOCS = YES
|
SORT_BRIEF_DOCS = NO
|
||||||
|
|
||||||
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
|
# 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
|
# 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
|
# and error messages should be written. If left blank the output is written
|
||||||
# to stderr.
|
# 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
|
# 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
|
# directories that contain example code fragments that are included (see
|
||||||
# the \include command).
|
# 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
|
# 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
|
# 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
|
# have to redo this when upgrading to a newer version of doxygen or when
|
||||||
# changing the value of configuration settings such as GENERATE_TREEVIEW!
|
# 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
|
# 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
|
# each generated HTML page. If it is left blank doxygen will generate a
|
||||||
# standard footer.
|
# 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
|
# 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
|
# 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
|
# robust against future updates. Doxygen will copy the style sheet file to
|
||||||
# the output directory.
|
# 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
|
# 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
|
# 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
|
# 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.
|
# 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.
|
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
|
||||||
# Doxygen will adjust the colors in the style sheet and background images
|
# 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
|
and linking process should be explained in your C programming material and in
|
||||||
the documentation for your development environment.
|
the documentation for your development environment.
|
||||||
|
|
||||||
|
|
||||||
@section build_include Including the GLFW header file
|
@section build_include Including the GLFW header file
|
||||||
|
|
||||||
In the source files of your application where you use OpenGL or GLFW, you should
|
You should include the GLFW header in the source files where you use OpenGL or
|
||||||
include the GLFW header file, i.e.:
|
GLFW.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
The GLFW header declares the GLFW API and by default also includes the OpenGL
|
This header declares the GLFW API and by default also includes the OpenGL header
|
||||||
header of your development environment, which in turn defines all the constants,
|
from your development environment. See below for how to control this.
|
||||||
types and function prototypes of the OpenGL API.
|
|
||||||
|
|
||||||
The GLFW header also defines everything necessary for your OpenGL header to
|
The GLFW header also defines any platform-specific macros needed by your OpenGL
|
||||||
function. For example, under Windows you are normally required to include
|
header, so it can be included without needing any window system headers.
|
||||||
`windows.h` before the OpenGL header, which would pollute your code namespace
|
|
||||||
with the entire Win32 API.
|
|
||||||
|
|
||||||
Instead, the GLFW header takes care of this for you, not by including
|
For example, under Windows you are normally required to include `windows.h`
|
||||||
`windows.h`, but by duplicating only the very few necessary parts of it. It
|
before the OpenGL header, which would bring in the whole Win32 API. The GLFW
|
||||||
does this only when needed, so if `windows.h` _is_ included, the GLFW header
|
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.
|
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.
|
`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
|
If you are using an OpenGL extension loading library such as
|
||||||
[glad](https://github.com/Dav1dde/glad), the extension loader header should
|
[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
|
be included _before_ the GLFW one.
|
||||||
(described below) should be defined.
|
|
||||||
|
@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
|
@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
|
__GLFW_INCLUDE_ES31__ makes the GLFW header include the OpenGL ES 3.1
|
||||||
`GLES3/gl31.h` header instead of the regular OpenGL header.
|
`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
|
@anchor GLFW_INCLUDE_NONE
|
||||||
__GLFW_INCLUDE_NONE__ makes the GLFW header not include any OpenGL or OpenGL ES
|
__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.
|
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
|
application. If you want to use an installed binary instead, see @ref
|
||||||
build_link_cmake_package.
|
build_link_cmake_package.
|
||||||
|
|
||||||
With just a few changes to your `CMakeLists.txt` you can have the GLFW source
|
With a few changes to your `CMakeLists.txt` you can have the GLFW source tree
|
||||||
tree built along with your application.
|
built along with your application.
|
||||||
|
|
||||||
When including GLFW as part of your build, you probably don't want to build the
|
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
|
GLFW tests, examples and documentation. To disable these, set the corresponding
|
||||||
@@ -222,7 +239,8 @@ target_link_libraries(myapp ${OPENGL_glu_LIBRARY})
|
|||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
@note GLU has been deprecated and should not be used in new code, but some
|
@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
|
@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
|
installed. If you want to build it along with your application instead, see
|
||||||
@ref build_link_cmake_source.
|
@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.
|
target files generated when GLFW is installed.
|
||||||
|
|
||||||
@code{.cmake}
|
@code{.cmake}
|
||||||
find_package(glfw3 3.3 REQUIRED)
|
find_package(glfw3 3.3 REQUIRED)
|
||||||
@endcode
|
@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
|
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.
|
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
|
If your application calls OpenGL directly, instead of using a modern
|
||||||
@@ -265,7 +292,8 @@ target_link_libraries(myapp ${OPENGL_glu_LIBRARY})
|
|||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
@note GLU has been deprecated and should not be used in new code, but some
|
@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
|
@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`
|
cc `pkg-config --cflags glfw3` -o myprog myprog.c `pkg-config --static --libs glfw3`
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
If you are using the shared version of the GLFW library, simply omit the
|
If you are using the shared version of the GLFW library, omit the `--static`
|
||||||
`--static` flag.
|
flag.
|
||||||
|
|
||||||
@code{.sh}
|
@code{.sh}
|
||||||
cc `pkg-config --cflags glfw3` -o myprog myprog.c `pkg-config --libs glfw3`
|
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
|
@endcode
|
||||||
|
|
||||||
@note GLU has been deprecated and should not be used in new code, but some
|
@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
|
If you are using the static version of the GLFW library, make sure you don't
|
||||||
link statically against GLU.
|
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
|
@subsection build_link_xcode With Xcode on macOS
|
||||||
|
|
||||||
If you are using the dynamic library version of GLFW, simply add it to the
|
If you are using the dynamic library version of GLFW, add it to the project
|
||||||
project dependencies.
|
dependencies.
|
||||||
|
|
||||||
If you are using the static library version of GLFW, add it and the Cocoa,
|
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
|
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
|
input. If the running X server does not support this extension, a non-Xkb
|
||||||
fallback path is used.
|
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
|
@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.
|
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
|
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
|
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,
|
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
|
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
|
contexts or no-error contexts. Versions of Mac OS X earlier than 10.7 support
|
||||||
version 2.1.
|
at most OpenGL version 2.1.
|
||||||
|
|
||||||
Because of this, on OS X 10.7 and later, the `GLFW_CONTEXT_VERSION_MAJOR` and
|
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
|
`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_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_CORE_PROFILE` when creating OpenGL 3.2 and later contexts. The
|
||||||
`GLFW_OPENGL_DEBUG_CONTEXT` hint is ignored.
|
`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
|
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,
|
`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
|
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
|
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
|
drivers and Vulkan SDKs. If either the loader or at least one minimally
|
||||||
will return `GLFW_FALSE` and all other Vulkan-related functions will fail with
|
functional ICD is missing, @ref glfwVulkanSupported will return `GLFW_FALSE` and
|
||||||
an @ref GLFW_API_UNAVAILABLE error.
|
all other Vulkan-related functions will fail with an @ref GLFW_API_UNAVAILABLE
|
||||||
|
error.
|
||||||
|
|
||||||
|
|
||||||
@section compat_wsi Vulkan WSI extensions
|
@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
|
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
|
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
|
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
|
installers for Windows and macOS from the
|
||||||
[CMake website](http://www.cmake.org/).
|
[CMake website](http://www.cmake.org/).
|
||||||
|
|
||||||
@@ -33,9 +33,9 @@ below.
|
|||||||
|
|
||||||
@subsubsection compile_deps_msvc Dependencies for Visual C++ on Windows
|
@subsubsection compile_deps_msvc Dependencies for Visual C++ on Windows
|
||||||
|
|
||||||
The Microsoft Platform SDK that is installed along with Visual C++ already
|
The Windows SDK bundled with Visual C++ already contains all the necessary
|
||||||
contains all the necessary headers, link libraries and tools except for CMake.
|
headers, link libraries and tools except for CMake. Move on to @ref
|
||||||
Move on to @ref compile_generate.
|
compile_generate.
|
||||||
|
|
||||||
|
|
||||||
@subsubsection compile_deps_mingw Dependencies for MinGW or MinGW-w64 on Windows
|
@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
|
@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
|
To compile GLFW for X11, you need to have the X11 and libdbus development
|
||||||
the basic development tools like GCC and make. For example, on Ubuntu and other
|
packages installed, as well as the basic development tools like GCC and make.
|
||||||
distributions based on Debian GNU/Linux, you need to install the `xorg-dev`
|
For example, on Ubuntu and other distributions based on Debian GNU/Linux, you
|
||||||
package, which pulls in all X.org header packages.
|
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
|
Once you have installed the necessary packages, move on to @ref
|
||||||
compile_generate.
|
compile_generate.
|
||||||
@@ -219,17 +233,6 @@ __GLFW_VULKAN_STATIC__ determines whether to use the Vulkan loader linked
|
|||||||
statically into the application.
|
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
|
@subsubsection compile_options_win32 Windows specific CMake options
|
||||||
|
|
||||||
@anchor USE_MSVC_RUNTIME_LIBRARY_DLL
|
@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
|
must also define @b _GLFW_VULKAN_STATIC. Otherwise, GLFW will attempt to use the
|
||||||
external version.
|
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:
|
For the EGL context creation API, the following options are available:
|
||||||
|
|
||||||
- @b _GLFW_USE_EGLPLATFORM_H to use `EGL/eglplatform.h` for native handle
|
- @b _GLFW_USE_EGLPLATFORM_H to use `EGL/eglplatform.h` for native handle
|
||||||
definitions (fallback)
|
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
|
@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
|
GLFW. If you define any of these in your build files, make sure they are not
|
||||||
applied to the GLFW sources.
|
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
|
versions and APIs, but has at times been named _Shared Objects and Multiple
|
||||||
Contexts_.
|
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
|
@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
|
You should still [process events](@ref events) as long as you have at least one
|
||||||
window, even if none of them are visible.
|
window, even if none of them are visible.
|
||||||
|
|
||||||
@macos The first time a window is created the menu bar is populated with
|
@macos The first time a window is created the menu bar is created. This is not
|
||||||
common commands like Hide, Quit and About. This is not desirable for example
|
desirable for example when writing a command-line only application. Menu bar
|
||||||
when writing a command-line only application. The menu bar setup can be
|
creation can be disabled with the @ref GLFW_COCOA_MENUBAR init hint.
|
||||||
disabled with a [compile-time option](@ref compile_options_osx).
|
|
||||||
|
|
||||||
|
|
||||||
@subsection context_less Windows without contexts
|
@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
|
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.
|
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.
|
The context of a window is made current with @ref glfwMakeContextCurrent.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
@@ -127,8 +129,7 @@ error.
|
|||||||
|
|
||||||
@section context_swap Buffer swapping
|
@section context_swap Buffer swapping
|
||||||
|
|
||||||
Buffer swapping is part of the window and framebuffer, not the context. See
|
See @ref buffer_swap in the window guide.
|
||||||
@ref buffer_swap.
|
|
||||||
|
|
||||||
|
|
||||||
@section context_glext OpenGL and OpenGL ES extensions
|
@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%);
|
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;
|
background:none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +111,7 @@
|
|||||||
border:none;
|
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;
|
text-shadow:none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,28 +209,45 @@ address.footer {
|
|||||||
background:@header-footer-link-color;
|
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;
|
max-width:920px;
|
||||||
min-width:800px;
|
min-width:800px;
|
||||||
margin:0 auto;
|
margin:0 auto;
|
||||||
font-size:13px;
|
font-size:13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tablist {
|
.memtitle {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memproto,.memname {
|
||||||
|
font-weight:bold;
|
||||||
|
text-shadow:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-menu {
|
||||||
height:36px;
|
height:36px;
|
||||||
display:block;
|
display:block;
|
||||||
position:relative;
|
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;
|
color:@navbar-link-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tablist li.current a {
|
#main-menu li ul.sm-nowrap li a {
|
||||||
background:linear-gradient(to bottom,@tab-background-color2 0%,@tab-background-color1 100%);
|
color:@default-text-color;
|
||||||
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:hover {
|
||||||
|
color:@default-link-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contents {
|
.contents {
|
||||||
@@ -222,6 +265,7 @@ table.doxtable th,dl.reflist dt {
|
|||||||
background:linear-gradient(to bottom,@table-background-color2 0%,@table-background-color1 100%);
|
background:linear-gradient(to bottom,@table-background-color2 0%,@table-background-color1 100%);
|
||||||
box-shadow:inset 0 0 32px @table-background-color1;
|
box-shadow:inset 0 0 32px @table-background-color1;
|
||||||
text-shadow:0 -1px 1px darken(@table-background-color1, 15%);
|
text-shadow:0 -1px 1px darken(@table-background-color1, 15%);
|
||||||
|
text-align:left;
|
||||||
color:@table-text-color;
|
color:@table-text-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,7 +329,7 @@ table.doxtable {
|
|||||||
border-radius:4px;
|
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;
|
color:@default-link-color;
|
||||||
text-decoration:none;
|
text-decoration:none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ $extrastylesheet
|
|||||||
<ul class="glfwnavbar">
|
<ul class="glfwnavbar">
|
||||||
<li><a href="http://www.glfw.org/documentation.html">Documentation</a></li>
|
<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/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>
|
<li><a href="http://www.glfw.org/community.html">Community</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+292
-52
@@ -145,7 +145,9 @@ per-window state arrays that can be polled with @ref glfwGetKey.
|
|||||||
@code
|
@code
|
||||||
int state = glfwGetKey(window, GLFW_KEY_E);
|
int state = glfwGetKey(window, GLFW_KEY_E);
|
||||||
if (state == GLFW_PRESS)
|
if (state == GLFW_PRESS)
|
||||||
|
{
|
||||||
activate_airship();
|
activate_airship();
|
||||||
|
}
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
|
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
|
This function only returns cached key event state. It does not poll the
|
||||||
system for the current physical state of the key.
|
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.
|
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
|
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
|
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,
|
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`.
|
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
|
The `GLFW_KEY_LAST` constant holds the highest value of any
|
||||||
[named key](@ref keys).
|
[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
|
operating system text input system. Unlike key input, text input obeys keyboard
|
||||||
layouts and modifier keys and supports composing characters using
|
layouts and modifier keys and supports composing characters using
|
||||||
[dead keys](https://en.wikipedia.org/wiki/Dead_key). Once received, you can
|
[dead keys](https://en.wikipedia.org/wiki/Dead_key). Once received, you can
|
||||||
encode the code points into
|
encode the code points into UTF-8 or any other encoding you prefer.
|
||||||
[UTF-8](https://en.wikipedia.org/wiki/UTF-8) or any other encoding you prefer.
|
|
||||||
|
|
||||||
Because an `unsigned int` is 32 bits long on all platforms supported by GLFW,
|
Because an `unsigned int` is 32 bits long on all platforms supported by GLFW,
|
||||||
you can treat the code point argument as native endian
|
you can treat the code point argument as native endian UTF-32.
|
||||||
[UTF-32](https://en.wikipedia.org/wiki/UTF-32).
|
|
||||||
|
|
||||||
There are two callbacks for receiving Unicode code points. If you wish to
|
If you wish to offer regular text input, set a character callback.
|
||||||
offer regular text input, set a character callback.
|
|
||||||
|
|
||||||
@code
|
@code
|
||||||
glfwSetCharCallback(window, character_callback);
|
glfwSetCharCallback(window, character_callback);
|
||||||
@@ -202,23 +215,6 @@ void character_callback(GLFWwindow* window, unsigned int codepoint)
|
|||||||
}
|
}
|
||||||
@endcode
|
@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
|
@subsection input_key_name Key names
|
||||||
|
|
||||||
@@ -271,8 +267,9 @@ glfwGetCursorPos(window, &xpos, &ypos);
|
|||||||
@endcode
|
@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
|
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`,
|
mouse motion input. By default, the cursor mode is `GLFW_CURSOR_NORMAL`,
|
||||||
meaning the regular arrow cursor (or another cursor set with @ref glfwSetCursor)
|
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
|
other features of GLFW. It is not supported and will not work as robustly as
|
||||||
`GLFW_CURSOR_DISABLED`.
|
`GLFW_CURSOR_DISABLED`.
|
||||||
|
|
||||||
If you just wish the cursor to become hidden when it is over a window, set
|
If you only wish the cursor to become hidden when it is over a window but still
|
||||||
the cursor mode to `GLFW_CURSOR_HIDDEN`.
|
want it to behave normally, set the cursor mode to `GLFW_CURSOR_HIDDEN`.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
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 return value.
|
||||||
|
|
||||||
The image data is 32-bit, little-endian, non-premultiplied RGBA, i.e. eight bits
|
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
|
per channel with the red channel first. The pixels are arranged canonically as
|
||||||
from the top-left corner.
|
sequential rows, starting from the top-left corner.
|
||||||
|
|
||||||
|
|
||||||
@subsubsection cursor_standard Standard cursor creation
|
@subsubsection cursor_standard Standard cursor creation
|
||||||
@@ -367,8 +364,10 @@ When a cursor is no longer needed, destroy it with @ref glfwDestroyCursor.
|
|||||||
glfwDestroyCursor(cursor);
|
glfwDestroyCursor(cursor);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Cursor destruction always succeeds. All cursors remaining when @ref
|
Cursor destruction always succeeds. If the cursor is current for any window,
|
||||||
glfwTerminate is called are destroyed as well.
|
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
|
@subsubsection cursor_set Cursor setting
|
||||||
@@ -385,14 +384,14 @@ to `GLFW_CURSOR_NORMAL`.
|
|||||||
|
|
||||||
A single cursor may be set for any number of windows.
|
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
|
@code
|
||||||
glfwSetCursor(window, NULL);
|
glfwSetCursor(window, NULL);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
When a cursor is destroyed, it is removed from any window where it is set. This
|
When a cursor is destroyed, any window that has it set will revert to the
|
||||||
does not affect the cursor modes of those windows.
|
default cursor. This does not affect the cursor mode.
|
||||||
|
|
||||||
|
|
||||||
@subsection cursor_enter Cursor enter/leave events
|
@subsection cursor_enter Cursor enter/leave events
|
||||||
@@ -420,6 +419,16 @@ void cursor_enter_callback(GLFWwindow* window, int entered)
|
|||||||
}
|
}
|
||||||
@endcode
|
@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
|
@subsection input_mouse_button Mouse button input
|
||||||
|
|
||||||
@@ -449,7 +458,9 @@ per-window state arrays that can be polled with @ref glfwGetMouseButton.
|
|||||||
@code
|
@code
|
||||||
int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
|
int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
|
||||||
if (state == GLFW_PRESS)
|
if (state == GLFW_PRESS)
|
||||||
|
{
|
||||||
upgrade_cow();
|
upgrade_cow();
|
||||||
|
}
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
|
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
|
This function only returns cached mouse button event state. It does not poll
|
||||||
the system for the current state of the mouse button.
|
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.
|
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
|
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
|
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
|
@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
|
@section joystick Joystick input
|
||||||
|
|
||||||
The joystick functions expose connected joysticks and controllers, with both
|
The joystick functions expose connected joysticks and controllers, with both
|
||||||
referred to as joysticks. It supports up to sixteen joysticks, ranging from
|
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
|
`GLFW_JOYSTICK_1`, `GLFW_JOYSTICK_2` up to and including `GLFW_JOYSTICK_16` or
|
||||||
whether a [joystick](@ref joysticks) is present with @ref glfwJoystickPresent.
|
`GLFW_JOYSTICK_LAST`. You can test whether a [joystick](@ref joysticks) is
|
||||||
|
present with @ref glfwJoystickPresent.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
int present = glfwJoystickPresent(GLFW_JOYSTICK_1);
|
int present = glfwJoystickPresent(GLFW_JOYSTICK_1);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
When GLFW is initialized, detected joysticks are added to to the beginning of
|
Each joystick has zero or more axes, zero or more buttons, zero or more hats,
|
||||||
the array, starting with `GLFW_JOYSTICK_1`. Once a joystick is detected, it
|
a human-readable name, a user pointer and an SDL compatible GUID.
|
||||||
keeps its assigned index until it is disconnected, so as joysticks are connected
|
|
||||||
and disconnected, they will become spread out.
|
|
||||||
|
|
||||||
Joystick state is updated as needed when a joystick function is called and does
|
When GLFW is initialized, detected joysticks are added to to the beginning of
|
||||||
not require a window to be created or @ref glfwPollEvents or @ref glfwWaitEvents
|
the array. Once a joystick is detected, it keeps its assigned ID until it is
|
||||||
to be called.
|
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
|
To see all the properties of all connected joysticks in real-time, run the
|
||||||
`joysticks` test program.
|
`joysticks` test program.
|
||||||
@@ -529,7 +547,7 @@ returned array.
|
|||||||
|
|
||||||
@code
|
@code
|
||||||
int count;
|
int count;
|
||||||
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &count);
|
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_5, &count);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Each element in the returned array is a value between -1.0 and 1.0.
|
Each element in the returned array is a value between -1.0 and 1.0.
|
||||||
@@ -543,11 +561,55 @@ returned array.
|
|||||||
|
|
||||||
@code
|
@code
|
||||||
int count;
|
int count;
|
||||||
const unsigned char* axes = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &count);
|
const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_3, &count);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Each element in the returned array is either `GLFW_PRESS` or `GLFW_RELEASE`.
|
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
|
@subsection joystick_name Joystick name
|
||||||
|
|
||||||
@@ -556,7 +618,7 @@ glfwGetJoystickName. See the reference documentation for the lifetime of the
|
|||||||
returned string.
|
returned string.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
const char* name = glfwGetJoystickName(GLFW_JOYSTICK_1);
|
const char* name = glfwGetJoystickName(GLFW_JOYSTICK_4);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Joystick names are not guaranteed to be unique. Two joysticks of the same model
|
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.
|
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
|
@subsection joystick_event Joystick configuration changes
|
||||||
|
|
||||||
If you wish to be notified when a joystick is connected or disconnected, set
|
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
|
@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
|
@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.
|
reference documentation for the lifetime of the returned string.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
const char* text = glfwGetClipboardString(window);
|
const char* text = glfwGetClipboardString(NULL);
|
||||||
if (text)
|
if (text)
|
||||||
|
{
|
||||||
insert_text(text);
|
insert_text(text);
|
||||||
|
}
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
If the clipboard is empty or if its contents could not be converted, `NULL` is
|
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.
|
@ref glfwSetClipboardString.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
glfwSetClipboardString(window, "A string with words in it");
|
glfwSetClipboardString(NULL, "A string with words in it");
|
||||||
@endcode
|
@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
|
@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,
|
glfw instead of GL and gl. For struct members, where OpenGL sets no precedent,
|
||||||
it use headless camel case.
|
it use headless camel case.
|
||||||
|
|
||||||
Examples: @ref glfwCreateWindow, @ref GLFWwindow, @ref GLFWvidmode.redBits,
|
Examples: `glfwCreateWindow`, `GLFWwindow`, `GLFW_RED_BITS`
|
||||||
`GLFW_RED_BITS`
|
|
||||||
|
|
||||||
|
|
||||||
@section internals_native Native interface
|
@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
|
interface, but embeds the name of the interface that the returned handle is
|
||||||
from.
|
from.
|
||||||
|
|
||||||
Examples: @ref glfwGetX11Window, @ref glfwGetWGLContext
|
Examples: `glfwGetX11Window`, `glfwGetWGLContext`
|
||||||
|
|
||||||
|
|
||||||
@section internals_internal Internal interface
|
@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
|
The internal interface uses the same style as the public interface, except all
|
||||||
global names have a leading underscore.
|
global names have a leading underscore.
|
||||||
|
|
||||||
Examples: @ref _glfwIsValidContextConfig, @ref _GLFWwindow, `_glfw.currentRamp`
|
Examples: `_glfwIsValidContextConfig`, `_GLFWwindow`, `_glfw.monitorCount`
|
||||||
|
|
||||||
|
|
||||||
@section internals_platform Platform interface
|
@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
|
named the same except that the glfw function prefix is replaced by
|
||||||
_glfwPlatform.
|
_glfwPlatform.
|
||||||
|
|
||||||
Examples: @ref _glfwPlatformCreateWindow
|
Examples: `_glfwPlatformCreateWindow`
|
||||||
|
|
||||||
The platform interface also defines structs that contain platform-specific
|
The platform interface also defines structs that contain platform-specific
|
||||||
global and per-object state. Their names mirror those of the internal
|
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
|
using special macros that name them after the specific interface used. This
|
||||||
prevents shared code from accidentally using these members.
|
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
|
@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
|
The function names of the event interface use a `_glfwInput` prefix and the
|
||||||
ObjectEvent pattern.
|
ObjectEvent pattern.
|
||||||
|
|
||||||
Examples: @ref _glfwInputWindowFocus, @ref _glfwInputCursorMotion
|
Examples: `_glfwInputWindowFocus`, `_glfwInputCursorPos`
|
||||||
|
|
||||||
|
|
||||||
@section internals_static Static functions
|
@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.
|
Static functions may be used by any interface and have no prefixes or suffixes.
|
||||||
These use headless camel case.
|
These use headless camel case.
|
||||||
|
|
||||||
Examples: `clearScrollOffsets`
|
Examples: `isValidElementForJoystick`
|
||||||
|
|
||||||
|
|
||||||
@section internals_config Configuration macros
|
@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
|
Configuration macros the same style as tokens in the public interface, except
|
||||||
with a leading underscore.
|
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 glfwGetVersion
|
||||||
- @ref glfwGetVersionString
|
- @ref glfwGetVersionString
|
||||||
|
- @ref glfwGetError
|
||||||
- @ref glfwSetErrorCallback
|
- @ref glfwSetErrorCallback
|
||||||
|
- @ref glfwInitHint
|
||||||
- @ref glfwInit
|
- @ref glfwInit
|
||||||
- @ref glfwTerminate
|
- @ref glfwTerminate
|
||||||
|
|
||||||
@@ -52,13 +54,61 @@ if (!glfwInit())
|
|||||||
|
|
||||||
If any part of initialization fails, any parts that succeeded are terminated as
|
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
|
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.
|
`GLFW_TRUE` immediately.
|
||||||
|
|
||||||
Once the library has been successfully initialized, it should be terminated
|
Once the library has been successfully initialized, it should be terminated
|
||||||
before the application exits. Modern systems are very good at freeing resources
|
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
|
allocated by programs that exit, but GLFW sometimes has to change global system
|
||||||
system settings and these might not be restored without termination.
|
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
|
@subsection intro_init_terminate Terminating GLFW
|
||||||
@@ -83,41 +133,76 @@ immediately.
|
|||||||
@section error_handling Error handling
|
@section error_handling Error handling
|
||||||
|
|
||||||
Some GLFW functions have return values that indicate an error, but this is often
|
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
|
not very helpful when trying to figure out what happened or why it occurred.
|
||||||
functions also return otherwise valid values on error. Finally, far from all
|
Other functions have no return value reserved for errors, so error notification
|
||||||
GLFW functions have return values.
|
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
|
The last [error code](@ref errors) for the calling thread can be queried at any
|
||||||
error occurs. It is set with @ref glfwSetErrorCallback, a function that may be
|
time with @ref glfwGetError.
|
||||||
called regardless of whether GLFW is initialized.
|
|
||||||
|
|
||||||
@code
|
@code
|
||||||
glfwSetErrorCallback(error_callback);
|
int code = glfwGetError(NULL);
|
||||||
|
|
||||||
|
if (code != GLFW_NO_ERROR)
|
||||||
|
handle_error(code);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
The error callback receives a human-readable description of the error and (when
|
If no error has occurred since the last call, @ref GLFW_NO_ERROR (zero) is
|
||||||
possible) its cause. The description encoded as UTF-8. The callback is also
|
returned. The error is cleared before the function returns.
|
||||||
provided with an [error code](@ref errors).
|
|
||||||
|
|
||||||
@code
|
|
||||||
void error_callback(int error, const char* description)
|
|
||||||
{
|
|
||||||
puts(description);
|
|
||||||
}
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
The error code indicates the general category of the error. Some error codes,
|
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
|
such as @ref GLFW_NOT_INITIALIZED has only a single meaning, whereas others like
|
||||||
@ref GLFW_PLATFORM_ERROR are used for many different errors.
|
@ref GLFW_PLATFORM_ERROR are used for many different errors.
|
||||||
|
|
||||||
The description string is only valid until the error callback returns, as it may
|
GLFW often has more information about an error than its general category. You
|
||||||
have been generated specifically for that error. This lets GLFW provide much
|
can retrieve a UTF-8 encoded human-readable description along with the error
|
||||||
more specific error descriptions but means you must make a copy if you want to
|
code. If no error has occurred since the last call, the description is set to
|
||||||
keep the description string.
|
`NULL`.
|
||||||
|
|
||||||
@note Relying on erroneous behavior is not forward compatible. In other words,
|
@code
|
||||||
do not rely on a currently invalid call to generate a specific error, as that
|
const char* description;
|
||||||
same call may in future versions generate a different error or become valid.
|
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
|
@section coordinate_systems Coordinate systems
|
||||||
@@ -188,14 +273,10 @@ releases.
|
|||||||
|
|
||||||
@subsection reentrancy Reentrancy
|
@subsection reentrancy Reentrancy
|
||||||
|
|
||||||
GLFW event processing and object creation and destruction are not reentrant.
|
GLFW event processing and object destruction are not reentrant. This means that
|
||||||
This means that the following functions must not be called from any callback
|
the following functions must not be called from any callback function:
|
||||||
function:
|
|
||||||
|
|
||||||
- @ref glfwCreateWindow
|
|
||||||
- @ref glfwDestroyWindow
|
- @ref glfwDestroyWindow
|
||||||
- @ref glfwCreateCursor
|
|
||||||
- @ref glfwCreateStandardCursor
|
|
||||||
- @ref glfwDestroyCursor
|
- @ref glfwDestroyCursor
|
||||||
- @ref glfwPollEvents
|
- @ref glfwPollEvents
|
||||||
- @ref glfwWaitEvents
|
- @ref glfwWaitEvents
|
||||||
@@ -208,35 +289,39 @@ functions not on this list will not be made non-reentrant.
|
|||||||
|
|
||||||
@subsection thread_safety Thread safety
|
@subsection thread_safety Thread safety
|
||||||
|
|
||||||
Most GLFW functions must only be called from the main thread, but some may be
|
Most GLFW functions must only be called from the main thread (the thread that
|
||||||
called from any thread. However, no GLFW function may be called from any thread
|
calls main), but some may be called from any thread once the library has been
|
||||||
but the main thread until GLFW has been successfully initialized, including
|
initialized. Before initialization the whole library is thread-unsafe.
|
||||||
functions that may called before initialization.
|
|
||||||
|
|
||||||
The reference documentation for every GLFW function states whether it is limited
|
The reference documentation for every GLFW function states whether it is limited
|
||||||
to the main thread.
|
to the main thread.
|
||||||
|
|
||||||
Initialization and termination, event processing and the creation and
|
Initialization, termination, event processing and the creation and
|
||||||
destruction of windows, contexts and cursors are all limited to the main thread
|
destruction of windows, cursors and OpenGL and OpenGL ES contexts are all
|
||||||
due to limitations of one or several platforms.
|
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
|
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
|
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.
|
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
|
The error code and description may be queried from any thread.
|
||||||
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
|
- @ref glfwGetError
|
||||||
be called from any thread:
|
|
||||||
|
Empty events may be posted from any thread.
|
||||||
|
|
||||||
- @ref glfwPostEmptyEvent
|
- @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 glfwGetWindowUserPointer
|
||||||
- @ref glfwSetWindowUserPointer
|
- @ref glfwSetWindowUserPointer
|
||||||
- @ref glfwWindowShouldClose
|
- @ref glfwWindowShouldClose
|
||||||
- @ref glfwSetWindowShouldClose
|
- @ref glfwSetWindowShouldClose
|
||||||
|
|
||||||
Rendering may be done on any thread. The following context related functions
|
These functions for working with OpenGL and OpenGL ES contexts may be called
|
||||||
may be called from any thread:
|
from any thread, but the window object is not synchronized by GLFW.
|
||||||
|
|
||||||
- @ref glfwMakeContextCurrent
|
- @ref glfwMakeContextCurrent
|
||||||
- @ref glfwGetCurrentContext
|
- @ref glfwGetCurrentContext
|
||||||
@@ -245,27 +330,23 @@ may be called from any thread:
|
|||||||
- @ref glfwExtensionSupported
|
- @ref glfwExtensionSupported
|
||||||
- @ref glfwGetProcAddress
|
- @ref glfwGetProcAddress
|
||||||
|
|
||||||
The raw timer may be queried from any thread. The following raw timer related
|
The raw timer functions may be called from any thread.
|
||||||
functions may be called from any thread:
|
|
||||||
|
|
||||||
- @ref glfwGetTimerFrequency
|
- @ref glfwGetTimerFrequency
|
||||||
- @ref glfwGetTimerValue
|
- @ref glfwGetTimerValue
|
||||||
|
|
||||||
The regular timer may be used from any thread, but the reading and writing of
|
The regular timer may be used from any thread, but reading and writing the timer
|
||||||
the timer offset is not synchronized by GLFW. The following timer related
|
offset is not synchronized by GLFW.
|
||||||
functions may be called from any thread:
|
|
||||||
|
|
||||||
- @ref glfwGetTime
|
- @ref glfwGetTime
|
||||||
- @ref glfwSetTime
|
- @ref glfwSetTime
|
||||||
|
|
||||||
Library version information may be queried from any thread. The following
|
Library version information may be queried from any thread.
|
||||||
version related functions may be called from any thread:
|
|
||||||
|
|
||||||
- @ref glfwGetVersion
|
- @ref glfwGetVersion
|
||||||
- @ref glfwGetVersionString
|
- @ref glfwGetVersionString
|
||||||
|
|
||||||
Vulkan objects may be created and information queried from any thread. The
|
All Vulkan related functions may be called from any thread.
|
||||||
following Vulkan related functions may be called from any thread:
|
|
||||||
|
|
||||||
- @ref glfwVulkanSupported
|
- @ref glfwVulkanSupported
|
||||||
- @ref glfwGetRequiredInstanceExtensions
|
- @ref glfwGetRequiredInstanceExtensions
|
||||||
@@ -273,9 +354,9 @@ following Vulkan related functions may be called from any thread:
|
|||||||
- @ref glfwGetPhysicalDevicePresentationSupport
|
- @ref glfwGetPhysicalDevicePresentationSupport
|
||||||
- @ref glfwCreateWindowSurface
|
- @ref glfwCreateWindowSurface
|
||||||
|
|
||||||
GLFW uses no synchronization objects internally except for thread-local storage
|
GLFW uses synchronization objects internally only to manage the per-thread
|
||||||
to keep track of the current context for each thread. Synchronization is left
|
context and error states. Additional synchronization is left to the
|
||||||
to the application.
|
application.
|
||||||
|
|
||||||
Functions that may currently be called from any thread will always remain so,
|
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
|
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.
|
may change at any time until it is documented.
|
||||||
|
|
||||||
If the reference documentation and the implementation differ, the reference
|
If the reference documentation and the implementation differ, the reference
|
||||||
documentation is correct and the implementation will be fixed in the next
|
documentation will almost always take precedence and the implementation will be
|
||||||
release.
|
fixed in the next release. The reference documentation will also take
|
||||||
|
precedence over anything stated in a guide.
|
||||||
|
|
||||||
|
|
||||||
@subsection event_order Event order
|
@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
|
Vulkan application development. It provides a simple, platform-independent API
|
||||||
for creating windows, contexts and surfaces, reading input, handling events, etc.
|
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.
|
[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
|
@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
|
@endcode
|
||||||
|
|
||||||
If a monitor is disconnected, any windows that are full screen on it get forced
|
If a monitor is disconnected, all windows that are full screen on it will be
|
||||||
into windowed mode.
|
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
|
@section monitor_properties Monitor properties
|
||||||
|
|
||||||
Each monitor has a current video mode, a list of supported video modes,
|
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 virtual position, a human-readable name, a user pointer, an estimated physical
|
||||||
a gamma ramp.
|
size and a gamma ramp.
|
||||||
|
|
||||||
|
|
||||||
@subsection monitor_modes Video modes
|
@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).
|
[video mode](@ref monitor_modes).
|
||||||
|
|
||||||
@code
|
@code
|
||||||
int widthMM, heightMM;
|
int width_mm, height_mm;
|
||||||
glfwGetMonitorPhysicalSize(monitor, &widthMM, &heightMM);
|
glfwGetMonitorPhysicalSize(monitor, &width_mm, &height_mm);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
This can, for example, be used together with the current video mode to calculate
|
While this can be used to calculate the raw DPI of a monitor, this is often not
|
||||||
the DPI of a monitor.
|
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
|
@code
|
||||||
const double dpi = mode->width / (widthMM / 25.4);
|
float xscale, yscale;
|
||||||
|
glfwGetMonitorContentScale(monitor, &xscale, &yscale);
|
||||||
@endcode
|
@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
|
@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.
|
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
|
@subsection monitor_gamma Gamma ramp
|
||||||
|
|
||||||
The gamma ramp of a monitor can be set with @ref glfwSetGammaRamp, which accepts
|
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
|
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.
|
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
|
It is recommended that your gamma ramp have the same size as the current gamma
|
||||||
supported by all graphics cards on all platforms.
|
ramp for that monitor.
|
||||||
|
|
||||||
The current gamma ramp for a monitor is returned by @ref glfwGetGammaRamp. See
|
The current gamma ramp for a monitor is returned by @ref glfwGetGammaRamp. See
|
||||||
the reference documentation for the lifetime of the returned structure.
|
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
|
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
|
`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
|
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
|
You can query the close flag at any time with @ref glfwWindowShouldClose and set
|
||||||
it at any time with @ref glfwSetWindowShouldClose.
|
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>
|
#include <GLFW/glfw3.h>
|
||||||
@endcode
|
@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
|
@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
|
@subsection news_33_maximize Window maximization callback
|
||||||
|
|
||||||
GLFW now supports window maximization notifications with @ref
|
GLFW now supports notifying the application that the window has been maximized
|
||||||
glfwSetWindowMaximizeCallback.
|
@ref glfwSetWindowMaximizeCallback.
|
||||||
|
|
||||||
|
@see @ref window_maximize
|
||||||
|
|
||||||
|
|
||||||
@subsection news_33_keyscancode Platform-specific key scancode query
|
@subsection news_33_keyscancode Platform-specific key scancode query
|
||||||
|
|
||||||
GLFW now supports querying the platform dependent scancode of any key with
|
GLFW now supports querying the platform dependent scancode of any physical key
|
||||||
@ref glfwGetKeyScancode.
|
with @ref glfwGetKeyScancode.
|
||||||
|
|
||||||
|
@see @ref input_key
|
||||||
|
|
||||||
|
|
||||||
@subsection news_33_setwindowattrib Support for updating window attributes
|
@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
|
[GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) attributes for existing
|
||||||
windows with @ref glfwSetWindowAttrib.
|
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
|
@subsection news_33_moltenvk Support for Vulkan on macOS via MoltenVK
|
||||||
|
|
||||||
GLFW now supports the `VK_MVK_macos_surface` window surface creation extension
|
GLFW now supports the `VK_MVK_macos_surface` window surface creation extension
|
||||||
provided by [MoltenVK](https://moltengl.com/moltenvk/).
|
provided by [MoltenVK](https://moltengl.com/moltenvk/).
|
||||||
|
|
||||||
|
@see @ref vulkan_guide
|
||||||
|
|
||||||
|
|
||||||
@subsection news_33_osmesa OSMesa backend for headless software rendering
|
@subsection news_33_osmesa OSMesa backend for headless software rendering
|
||||||
|
|
||||||
GLFW now supports headless context creation and software rendering via OSMesa,
|
GLFW now supports creating offscreen OpenGL contexts using
|
||||||
intended for automated testing. This backend does not provide input.
|
[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
|
@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.
|
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
|
These are the release highlights. For a full list of changes see the
|
||||||
[version history](http://www.glfw.org/changelog.html).
|
[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.
|
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
|
These are the release highlights. For a full list of changes see the
|
||||||
[version history](http://www.glfw.org/changelog.html).
|
[version history](http://www.glfw.org/changelog.html).
|
||||||
|
|||||||
+5
-7
@@ -69,7 +69,7 @@ if (!glfwInit())
|
|||||||
}
|
}
|
||||||
@endcode
|
@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
|
When you are done using GLFW, typically just before the application exits, you
|
||||||
need to terminate GLFW.
|
need to terminate GLFW.
|
||||||
@@ -86,14 +86,12 @@ functions that require it.
|
|||||||
@subsection quick_capture_error Setting an error callback
|
@subsection quick_capture_error Setting an error callback
|
||||||
|
|
||||||
Most events are reported through callbacks, whether it's a key being pressed,
|
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
|
a GLFW window being moved, or an error occurring. Callbacks are C functions (or
|
||||||
C functions (or C++ static methods) that are called by GLFW with arguments
|
C++ static methods) that are called by GLFW with arguments describing the event.
|
||||||
describing the event.
|
|
||||||
|
|
||||||
In case a GLFW function fails, an error is reported to the GLFW error callback.
|
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
|
You can receive these reports with an error callback. This function must have
|
||||||
the signature below. This simple error callback just prints the error
|
the signature below but may do anything permitted in other callbacks.
|
||||||
description to `stderr`.
|
|
||||||
|
|
||||||
@code
|
@code
|
||||||
void error_callback(int error, const char* description)
|
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.
|
glfwSetFramebufferSizeCallback and be notified when the size changes.
|
||||||
|
|
||||||
Actual rendering with OpenGL is outside the scope of this tutorial, but there
|
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
|
[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
|
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
|
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
|
However, any Vulkan-specific test and example programs are built only if the
|
||||||
CMake files find a Vulkan SDK.
|
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
|
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.
|
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
|
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
|
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
|
Unix-like systems and `libMoltenVK.dylib` on macOS). This means that GLFW does
|
||||||
loader. However, it also means that if you are using the static library form of
|
not need to be linked against the loader. However, it also means that if you
|
||||||
the Vulkan loader GLFW will either fail to find it or (worse) use the wrong one.
|
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
|
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
|
static library form. Not linking against the Vulkan loader will then be
|
||||||
error.
|
a compile-time error.
|
||||||
|
|
||||||
@macos MoltenVK only provides the static library form of the Vulkan loader, but
|
@macos When using the static library form of MoltenVK (i.e. `MetalVK.framework`
|
||||||
GLFW is able to find it without @ref GLFW_VULKAN_STATIC as long as it is linked
|
and not `libMoltenVK.dylib`) you must also link against its dependencies: the
|
||||||
into any of the binaries already loaded into the process. As it is a static
|
`Cocoa`, `Metal` and `QuartzCore` system frameworks and the `libc++` library.
|
||||||
library, you must also link against its dependencies: the `Cocoa`, `Metal` and
|
|
||||||
`QuartzCore` frameworks and the `libc++` library.
|
|
||||||
|
|
||||||
|
|
||||||
@section vulkan_include Including the Vulkan and GLFW header files
|
@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.
|
Khronos extension functions, allowing them to be called directly.
|
||||||
|
|
||||||
If you are loading the Vulkan loader dynamically instead of linking 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.
|
glfwVulkanSupported.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
@@ -91,11 +95,11 @@ if (glfwVulkanSupported())
|
|||||||
}
|
}
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
This function returns `GLFW_TRUE` if the Vulkan loader was found. This check is
|
This function returns `GLFW_TRUE` if the Vulkan loader and any minimally
|
||||||
performed by @ref glfwInit.
|
functional ICD was found.
|
||||||
|
|
||||||
If no loader was found, calling any other Vulkan related GLFW function will
|
If if one or both were not found, calling any other Vulkan related GLFW function
|
||||||
generate a @ref GLFW_API_UNAVAILABLE error.
|
will generate a @ref GLFW_API_UNAVAILABLE error.
|
||||||
|
|
||||||
|
|
||||||
@subsection vulkan_proc Querying Vulkan function pointers
|
@subsection vulkan_proc Querying Vulkan function pointers
|
||||||
@@ -226,6 +230,10 @@ if (err)
|
|||||||
}
|
}
|
||||||
@endcode
|
@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
|
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.
|
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
|
GLFWvidmode.refreshRate | @ref GLFW_REFRESH_RATE hint
|
||||||
|
|
||||||
Once you have a full screen window, you can change its resolution, refresh rate
|
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
|
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
|
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
|
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
|
window iconified if it loses input focus, to allow the user to switch back to
|
||||||
the desktop. This behavior can be disabled with the
|
the desktop. This behavior can be disabled with the
|
||||||
[GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_hint) window hint, for example if you
|
[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
|
@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
|
mode will not be changed, making window creation faster and application
|
||||||
switching much smoother. This is sometimes called _windowed full screen_ or
|
switching much smoother. This is sometimes called _windowed full screen_ or
|
||||||
_borderless full screen_ window and counts as a full screen window. To create
|
_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
|
@code
|
||||||
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
|
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
|
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. Some affect the window itself, others affect the framebuffer or
|
||||||
context. These hints are set to their default values each time the library is
|
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
|
initialized with @ref glfwInit. Integer value hints can be set individually
|
||||||
and reset all at once to their defaults with @ref glfwDefaultWindowHints.
|
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
|
Some hints are platform specific. These are always valid to set on any
|
||||||
platform but they will only affect their specific platform. Other platforms
|
platform but they will only affect their specific platform. Other platforms
|
||||||
will simply ignore them. Setting these hints requires no platform specific
|
will ignore them. Setting these hints requires no platform specific headers or
|
||||||
headers or calls.
|
calls.
|
||||||
|
|
||||||
Note that hints need to be set _before_ the creation of the window and context
|
@note Window hints need to be set before the creation of the window and context
|
||||||
you wish to have the specified attributes.
|
you wish to have the specified attributes. They function as additional
|
||||||
|
arguments to @ref glfwCreateWindow.
|
||||||
|
|
||||||
|
|
||||||
@subsubsection window_hints_hard Hard and soft constraints
|
@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
|
@anchor GLFW_RESIZABLE_hint
|
||||||
__GLFW_RESIZABLE__ specifies whether the windowed mode window will be resizable
|
__GLFW_RESIZABLE__ specifies whether the windowed mode window will be resizable
|
||||||
_by the user_. The window will still be resizable using the @ref
|
_by the user_. The window will still be resizable using the @ref
|
||||||
glfwSetWindowSize function. This hint is ignored for full screen and
|
glfwSetWindowSize function. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
|
||||||
undecorated windows.
|
This hint is ignored for full screen and undecorated windows.
|
||||||
|
|
||||||
@anchor GLFW_VISIBLE_hint
|
@anchor GLFW_VISIBLE_hint
|
||||||
__GLFW_VISIBLE__ specifies whether the windowed mode window will be initially
|
__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
|
@anchor GLFW_DECORATED_hint
|
||||||
__GLFW_DECORATED__ specifies whether the windowed mode window will have window
|
__GLFW_DECORATED__ specifies whether the windowed mode window will have window
|
||||||
decorations such as a border, a close widget, etc. An undecorated window will
|
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
|
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
|
@anchor GLFW_FOCUSED_hint
|
||||||
__GLFW_FOCUSED__ specifies whether the windowed mode window will be given input
|
__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
|
focus when created. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This
|
||||||
windows.
|
hint is ignored for full screen and initially hidden windows.
|
||||||
|
|
||||||
@anchor GLFW_AUTO_ICONIFY_hint
|
@anchor GLFW_AUTO_ICONIFY_hint
|
||||||
__GLFW_AUTO_ICONIFY__ specifies whether the full screen window will
|
__GLFW_AUTO_ICONIFY__ specifies whether the full screen window will
|
||||||
automatically iconify and restore the previous video mode on input focus loss.
|
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
|
@anchor GLFW_FLOATING_hint
|
||||||
__GLFW_FLOATING__ specifies whether the windowed mode window will be floating
|
__GLFW_FLOATING__ specifies whether the windowed mode window will be floating
|
||||||
above other regular windows, also called topmost or always-on-top. This is
|
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
|
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
|
@anchor GLFW_MAXIMIZED_hint
|
||||||
__GLFW_MAXIMIZED__ specifies whether the windowed mode window will be maximized
|
__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
|
@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.
|
code.
|
||||||
|
|
||||||
@anchor GLFW_STEREO
|
@anchor GLFW_STEREO
|
||||||
__GLFW_STEREO__ specifies whether to use OpenGL stereoscopic rendering. This is
|
__GLFW_STEREO__ specifies whether to use OpenGL stereoscopic rendering.
|
||||||
a hard constraint.
|
Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This is a hard constraint.
|
||||||
|
|
||||||
@anchor GLFW_SAMPLES
|
@anchor GLFW_SAMPLES
|
||||||
__GLFW_SAMPLES__ specifies the desired number of samples to use for
|
__GLFW_SAMPLES__ specifies the desired number of samples to use for
|
||||||
@@ -258,14 +280,21 @@ the application has no preference.
|
|||||||
|
|
||||||
@anchor GLFW_SRGB_CAPABLE
|
@anchor GLFW_SRGB_CAPABLE
|
||||||
__GLFW_SRGB_CAPABLE__ specifies whether the framebuffer should be 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`
|
Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
|
||||||
enable, also called `GL_FRAMEBUFFER_SRGB_EXT`) for controlling sRGB rendering
|
|
||||||
and a created OpenGL ES context will always have sRGB rendering enabled.
|
@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
|
@anchor GLFW_DOUBLEBUFFER
|
||||||
__GLFW_DOUBLEBUFFER__ specifies whether the framebuffer should be double
|
__GLFW_DOUBLEBUFFER__ specifies whether the framebuffer should be double
|
||||||
buffered. You nearly always want to use double buffering. This is a hard
|
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
|
@subsubsection window_hints_mtr Monitor related hints
|
||||||
@@ -285,9 +314,9 @@ This is a hard constraint.
|
|||||||
|
|
||||||
@anchor GLFW_CONTEXT_CREATION_API_hint
|
@anchor GLFW_CONTEXT_CREATION_API_hint
|
||||||
__GLFW_CONTEXT_CREATION_API__ specifies which context creation API to use to
|
__GLFW_CONTEXT_CREATION_API__ specifies which context creation API to use to
|
||||||
create the context. Possible values are `GLFW_NATIVE_CONTEXT_API` and
|
create the context. Possible values are `GLFW_NATIVE_CONTEXT_API`,
|
||||||
`GLFW_EGL_CONTEXT_API`. This is a hard constraint. If no client API is
|
`GLFW_EGL_CONTEXT_API` and `GLFW_OSMESA_CONTEXT_API`. This is a hard
|
||||||
requested, this hint is ignored.
|
constraint. If no client API is requested, this hint is ignored.
|
||||||
|
|
||||||
@par
|
@par
|
||||||
@macos The EGL API is not available on this platform and requests to use it
|
@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
|
__Wayland, Mir:__ The EGL API _is_ the native context creation API, so this hint
|
||||||
will have no effect.
|
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
|
@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
|
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
|
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
|
client API version that the created context must be compatible with. The exact
|
||||||
behavior of these hints depend on the requested client API.
|
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
|
@par
|
||||||
__OpenGL:__ These hints are not hard constraints, but creation will fail if the
|
__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
|
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
|
@anchor GLFW_OPENGL_DEBUG_CONTEXT_hint
|
||||||
__GLFW_OPENGL_DEBUG_CONTEXT__ specifies whether to create a debug OpenGL
|
__GLFW_OPENGL_DEBUG_CONTEXT__ specifies whether to create a debug OpenGL
|
||||||
context, which may have additional error and performance issue reporting
|
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
|
@anchor GLFW_OPENGL_PROFILE_hint
|
||||||
__GLFW_OPENGL_PROFILE__ specifies which OpenGL profile to create the context
|
__GLFW_OPENGL_PROFILE__ specifies which OpenGL profile to create the context
|
||||||
@@ -388,28 +427,53 @@ extension.
|
|||||||
|
|
||||||
@anchor GLFW_CONTEXT_NO_ERROR_hint
|
@anchor GLFW_CONTEXT_NO_ERROR_hint
|
||||||
__GLFW_CONTEXT_NO_ERROR__ specifies whether errors should be generated by the
|
__GLFW_CONTEXT_NO_ERROR__ specifies whether errors should be generated by the
|
||||||
context. If enabled, situations that would have generated errors instead cause
|
context. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. If enabled,
|
||||||
undefined behavior.
|
situations that would have generated errors instead cause undefined behavior.
|
||||||
|
|
||||||
@par
|
@par
|
||||||
The no error mode for OpenGL and OpenGL ES is described in detail by the
|
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)
|
[GL_KHR_no_error](https://www.opengl.org/registry/specs/KHR/no_error.txt)
|
||||||
extension.
|
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 window hints
|
||||||
@subsubsection window_hints_osx macOS specific hints
|
|
||||||
|
|
||||||
@anchor GLFW_COCOA_RETINA_FRAMEBUFFER_hint
|
@anchor GLFW_COCOA_RETINA_FRAMEBUFFER_hint
|
||||||
__GLFW_COCOA_RETINA_FRAMEBUFFER__ specifies whether to use full resolution
|
__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
|
@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_AUTO_ICONIFY | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||||
GLFW_FLOATING | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
GLFW_FLOATING | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||||
GLFW_MAXIMIZED | `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_RED_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||||
GLFW_GREEN_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`
|
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_SRGB_CAPABLE | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||||
GLFW_DOUBLEBUFFER | `GLFW_TRUE` | `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_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_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_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`
|
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_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_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_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
|
@section window_events Window event processing
|
||||||
@@ -461,7 +531,7 @@ See @ref events.
|
|||||||
@subsection window_userptr User pointer
|
@subsection window_userptr User pointer
|
||||||
|
|
||||||
Each window has a user pointer that can be set with @ref
|
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
|
can be used for any purpose you need and will not be modified by GLFW throughout
|
||||||
the life-time of the window.
|
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
|
desired video mode is set immediately. The window is resized to fit the
|
||||||
resolution of the set video mode.
|
resolution of the set video mode.
|
||||||
|
|
||||||
If you wish to be notified when a window is resized, whether by the user or
|
If you wish to be notified when a window is resized, whether by the user, the
|
||||||
the system, set a size callback.
|
system or your own code, set a size callback.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
glfwSetWindowSizeCallback(window, window_size_callback);
|
glfwSetWindowSizeCallback(window, window_size_callback);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
The callback function receives the new size, in screen coordinates, of the
|
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
|
@code
|
||||||
void window_size_callback(GLFWwindow* window, int width, int height)
|
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.
|
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
|
@subsection window_sizelimits Window size limits
|
||||||
|
|
||||||
The minimum and maximum size of the client area of a windowed mode window can be
|
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 aspect ratio is specified as a numerator and denominator, corresponding to
|
||||||
the width and height, respectively. If you want a window to maintain its
|
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
|
@code
|
||||||
int width, height;
|
int width, height;
|
||||||
@@ -663,15 +770,15 @@ The window system may put limitations on window placement.
|
|||||||
glfwSetWindowPos(window, 100, 100);
|
glfwSetWindowPos(window, 100, 100);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
If you wish to be notified when a window is moved, whether by the user, system
|
If you wish to be notified when a window is moved, whether by the user, the
|
||||||
or your own code, set a position callback.
|
system or your own code, set a position callback.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
glfwSetWindowPosCallback(window, window_pos_callback);
|
glfwSetWindowPosCallback(window, window_pos_callback);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
The callback function receives the new position of the upper-left corner of the
|
The callback function receives the new position, in screen coordinates, of the
|
||||||
client area when the window is moved.
|
upper-left corner of the client area when the window is moved.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
void window_pos_callback(GLFWwindow* window, int xpos, int ypos)
|
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);
|
glfwSetWindowIcon(window, 2, images);
|
||||||
@endcode
|
@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.
|
To revert to the default window icon, pass in an empty image array.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
@@ -927,6 +1038,10 @@ glfwFocusWindow.
|
|||||||
glfwFocusWindow(window);
|
glfwFocusWindow(window);
|
||||||
@endcode
|
@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
|
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.
|
the user, system or your own code, set a focus callback.
|
||||||
|
|
||||||
@@ -965,6 +1080,20 @@ glfwWindowHint(GLFW_FOCUSED, GLFW_FALSE);
|
|||||||
@endcode
|
@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
|
@subsection window_refresh Window damage and refresh
|
||||||
|
|
||||||
If you wish to be notified when the contents of a window is damaged and needs
|
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.
|
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
|
@subsection window_attribs Window attributes
|
||||||
|
|
||||||
Windows have a number of attributes that can be returned using @ref
|
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
|
__GLFW_MAXIMIZED__ indicates whether the specified window is maximized. See
|
||||||
@ref window_maximize for details.
|
@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
|
@anchor GLFW_VISIBLE_attrib
|
||||||
__GLFW_VISIBLE__ indicates whether the specified window is visible. See @ref
|
__GLFW_VISIBLE__ indicates whether the specified window is visible. See @ref
|
||||||
window_hide for details.
|
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
|
[GLFW_FLOATING](@ref GLFW_FLOATING_hint) window hint or after with @ref
|
||||||
glfwSetWindowAttrib.
|
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
|
@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
|
@anchor GLFW_CONTEXT_CREATION_API_attrib
|
||||||
__GLFW_CONTEXT_CREATION_API__ indicates the context creation API used to create
|
__GLFW_CONTEXT_CREATION_API__ indicates the context creation API used to create
|
||||||
the window's context; either `GLFW_NATIVE_CONTEXT_API` or
|
the window's context; either `GLFW_NATIVE_CONTEXT_API`, `GLFW_EGL_CONTEXT_API`
|
||||||
`GLFW_EGL_CONTEXT_API`.
|
or `GLFW_OSMESA_CONTEXT_API`.
|
||||||
|
|
||||||
@anchor GLFW_CONTEXT_VERSION_MAJOR_attrib
|
@anchor GLFW_CONTEXT_VERSION_MAJOR_attrib
|
||||||
@anchor GLFW_CONTEXT_VERSION_MINOR_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
|
__GLFW_CONTEXT_REVISION__ indicate the client API version of the window's
|
||||||
context.
|
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
|
@anchor GLFW_OPENGL_FORWARD_COMPAT_attrib
|
||||||
__GLFW_OPENGL_FORWARD_COMPAT__ is `GLFW_TRUE` if the window's context is an
|
__GLFW_OPENGL_FORWARD_COMPAT__ is `GLFW_TRUE` if the window's context is an
|
||||||
OpenGL forward-compatible one, or `GLFW_FALSE` otherwise.
|
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
|
user-controlled settings that override any swap interval the application
|
||||||
requests.
|
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")
|
include_directories(${glfw_INCLUDE_DIRS} "${GLFW_SOURCE_DIR}/deps")
|
||||||
|
|
||||||
if (BUILD_SHARED_LIBS)
|
if (MATH_LIBRARY)
|
||||||
link_libraries("${MATH_LIBRARY}")
|
link_libraries("${MATH_LIBRARY}")
|
||||||
endif()
|
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(heightmap WIN32 MACOSX_BUNDLE heightmap.c ${ICON} ${GLAD})
|
||||||
add_executable(offscreen offscreen.c ${ICON} ${GLAD})
|
add_executable(offscreen offscreen.c ${ICON} ${GLAD})
|
||||||
add_executable(particles WIN32 MACOSX_BUNDLE particles.c ${ICON} ${TINYCTHREAD} ${GETOPT} ${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(simple WIN32 MACOSX_BUNDLE simple.c ${ICON} ${GLAD})
|
||||||
add_executable(splitview WIN32 MACOSX_BUNDLE splitview.c ${ICON} ${GLAD})
|
add_executable(splitview WIN32 MACOSX_BUNDLE splitview.c ${ICON} ${GLAD})
|
||||||
add_executable(wave WIN32 MACOSX_BUNDLE wave.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(CONSOLE_BINARIES offscreen)
|
||||||
|
|
||||||
set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
|
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(gears PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gears")
|
||||||
set_target_properties(heightmap PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Heightmap")
|
set_target_properties(heightmap PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Heightmap")
|
||||||
set_target_properties(particles PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Particles")
|
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(simple PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Simple")
|
||||||
set_target_properties(splitview PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "SplitView")
|
set_target_properties(splitview PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "SplitView")
|
||||||
set_target_properties(wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave")
|
set_target_properties(wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave")
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ static GLfloat angle = 0.f;
|
|||||||
/* OpenGL draw function & timing */
|
/* OpenGL draw function & timing */
|
||||||
static void draw(void)
|
static void draw(void)
|
||||||
{
|
{
|
||||||
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
@@ -311,6 +312,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
glfwWindowHint(GLFW_DEPTH_BITS, 16);
|
glfwWindowHint(GLFW_DEPTH_BITS, 16);
|
||||||
|
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
|
||||||
|
|
||||||
window = glfwCreateWindow( 300, 300, "Gears", NULL, NULL );
|
window = glfwCreateWindow( 300, 300, "Gears", NULL, NULL );
|
||||||
if (!window)
|
if (!window)
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ int main(void)
|
|||||||
|
|
||||||
glfwSetErrorCallback(error_callback);
|
glfwSetErrorCallback(error_callback);
|
||||||
|
|
||||||
|
glfwInitHint(GLFW_COCOA_MENUBAR, GLFW_FALSE);
|
||||||
|
|
||||||
if (!glfwInit())
|
if (!glfwInit())
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// Context sharing test program
|
// Context sharing example
|
||||||
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
@@ -22,15 +22,10 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
//
|
|
||||||
// This program is used to test sharing of objects between contexts
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@@ -71,17 +66,6 @@ static void error_callback(int error, const char* description)
|
|||||||
fprintf(stderr, "Error: %s\n", 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)
|
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||||
{
|
{
|
||||||
if (action == GLFW_PRESS && key == GLFW_KEY_ESCAPE)
|
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 main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
int ch;
|
|
||||||
GLFWwindow* windows[2];
|
GLFWwindow* windows[2];
|
||||||
GLuint texture, program, vertex_buffer;
|
GLuint texture, program, vertex_buffer;
|
||||||
GLint mvp_location, vpos_location, color_location, texture_location;
|
GLint mvp_location, vpos_location, color_location, texture_location;
|
||||||
|
|
||||||
srand((unsigned int) time(NULL));
|
|
||||||
|
|
||||||
glfwSetErrorCallback(error_callback);
|
glfwSetErrorCallback(error_callback);
|
||||||
|
|
||||||
if (!glfwInit())
|
if (!glfwInit())
|
||||||
exit(EXIT_FAILURE);
|
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_MAJOR, 2);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||||
|
|
||||||
@@ -134,12 +105,6 @@ int main(int argc, char** argv)
|
|||||||
// pointers should be re-usable between them
|
// pointers should be re-usable between them
|
||||||
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
|
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
|
// Create the OpenGL objects inside the first context, created above
|
||||||
// All objects will be shared with the second context, created below
|
// All objects will be shared with the second context, created below
|
||||||
{
|
{
|
||||||
@@ -150,6 +115,8 @@ int main(int argc, char** argv)
|
|||||||
glGenTextures(1, &texture);
|
glGenTextures(1, &texture);
|
||||||
glBindTexture(GL_TEXTURE_2D, texture);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
|
srand((unsigned int) glfwGetTimerValue());
|
||||||
|
|
||||||
for (y = 0; y < 16; y++)
|
for (y = 0; y < 16; y++)
|
||||||
{
|
{
|
||||||
for (x = 0; x < 16; x++)
|
for (x = 0; x < 16; x++)
|
||||||
@@ -235,8 +202,8 @@ int main(int argc, char** argv)
|
|||||||
int i;
|
int i;
|
||||||
const vec3 colors[2] =
|
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++)
|
for (i = 0; i < 2; i++)
|
||||||
+1014
-141
File diff suppressed because it is too large
Load Diff
@@ -45,6 +45,7 @@ extern "C" {
|
|||||||
* more information.
|
* more information.
|
||||||
*/
|
*/
|
||||||
/*! @defgroup native Native access
|
/*! @defgroup native Native access
|
||||||
|
* @brief Functions related to accessing native handles.
|
||||||
*
|
*
|
||||||
* **By using the native access functions you assert that you know what you're
|
* **By using the native access functions you assert that you know what you're
|
||||||
* doing and how to fix problems caused by using them. If you don't, you
|
* doing and how to fix problems caused by using them. If you don't, you
|
||||||
@@ -85,7 +86,10 @@ extern "C" {
|
|||||||
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
|
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
|
||||||
// example to allow applications to correctly declare a GL_ARB_debug_output
|
// example to allow applications to correctly declare a GL_ARB_debug_output
|
||||||
// callback) but windows.h assumes no one will define APIENTRY before it does
|
// callback) but windows.h assumes no one will define APIENTRY before it does
|
||||||
|
#if defined(GLFW_APIENTRY_DEFINED)
|
||||||
#undef APIENTRY
|
#undef APIENTRY
|
||||||
|
#undef GLFW_APIENTRY_DEFINED
|
||||||
|
#endif
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#elif defined(GLFW_EXPOSE_NATIVE_COCOA)
|
#elif defined(GLFW_EXPOSE_NATIVE_COCOA)
|
||||||
#include <ApplicationServices/ApplicationServices.h>
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
@@ -288,6 +292,56 @@ GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
|
|||||||
* @ingroup native
|
* @ingroup native
|
||||||
*/
|
*/
|
||||||
GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
|
GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
|
||||||
|
|
||||||
|
/*! @brief Sets the current primary selection to the specified string.
|
||||||
|
*
|
||||||
|
* @param[in] string A UTF-8 encoded string.
|
||||||
|
*
|
||||||
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
|
* GLFW_PLATFORM_ERROR.
|
||||||
|
*
|
||||||
|
* @pointer_lifetime The specified string is copied before this function
|
||||||
|
* returns.
|
||||||
|
*
|
||||||
|
* @thread_safety This function must only be called from the main thread.
|
||||||
|
*
|
||||||
|
* @sa @ref clipboard
|
||||||
|
* @sa glfwGetX11SelectionString
|
||||||
|
* @sa glfwSetClipboardString
|
||||||
|
*
|
||||||
|
* @since Added in version 3.3.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI void glfwSetX11SelectionString(const char* string);
|
||||||
|
|
||||||
|
/*! @brief Returns the contents of the current primary selection as a string.
|
||||||
|
*
|
||||||
|
* If the selection is empty or if its contents cannot be converted, `NULL`
|
||||||
|
* is returned and a @ref GLFW_FORMAT_UNAVAILABLE error is generated.
|
||||||
|
*
|
||||||
|
* @return The contents of the selection as a UTF-8 encoded string, or `NULL`
|
||||||
|
* if an [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
|
* GLFW_PLATFORM_ERROR.
|
||||||
|
*
|
||||||
|
* @pointer_lifetime The returned string is allocated and freed by GLFW. You
|
||||||
|
* should not free it yourself. It is valid until the next call to @ref
|
||||||
|
* glfwGetX11SelectionString or @ref glfwSetX11SelectionString, or until the
|
||||||
|
* library is terminated.
|
||||||
|
*
|
||||||
|
* @thread_safety This function must only be called from the main thread.
|
||||||
|
*
|
||||||
|
* @sa @ref clipboard
|
||||||
|
* @sa glfwSetX11SelectionString
|
||||||
|
* @sa glfwGetClipboardString
|
||||||
|
*
|
||||||
|
* @since Added in version 3.3.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI const char* glfwGetX11SelectionString(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(GLFW_EXPOSE_NATIVE_GLX)
|
#if defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||||
@@ -393,9 +447,9 @@ GLFWAPI MirConnection* glfwGetMirDisplay(void);
|
|||||||
*/
|
*/
|
||||||
GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor);
|
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.
|
* [error](@ref error_handling) occurred.
|
||||||
*
|
*
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
@@ -405,7 +459,7 @@ GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor);
|
|||||||
*
|
*
|
||||||
* @ingroup native
|
* @ingroup native
|
||||||
*/
|
*/
|
||||||
GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window);
|
GLFWAPI MirWindow* glfwGetMirWindow(GLFWwindow* window);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(GLFW_EXPOSE_NATIVE_EGL)
|
#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_BINARY_DIR}/src/glfw_config.h"
|
||||||
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h"
|
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h"
|
||||||
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.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)
|
if (_GLFW_COCOA)
|
||||||
set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h cocoa_joystick.h
|
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
|
set(glfw_SOURCES ${common_SOURCES} cocoa_init.m cocoa_joystick.m
|
||||||
cocoa_monitor.m cocoa_window.m cocoa_time.c posix_tls.c
|
cocoa_monitor.m cocoa_window.m cocoa_time.c posix_thread.c
|
||||||
nsgl_context.m)
|
nsgl_context.m egl_context.c osmesa_context.c)
|
||||||
elseif (_GLFW_WIN32)
|
elseif (_GLFW_WIN32)
|
||||||
set(glfw_HEADERS ${common_HEADERS} win32_platform.h win32_joystick.h
|
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
|
set(glfw_SOURCES ${common_SOURCES} win32_init.c win32_joystick.c
|
||||||
win32_monitor.c win32_time.c win32_tls.c win32_window.c
|
win32_monitor.c win32_time.c win32_thread.c win32_window.c
|
||||||
wgl_context.c egl_context.c)
|
wgl_context.c egl_context.c osmesa_context.c)
|
||||||
elseif (_GLFW_X11)
|
elseif (_GLFW_X11)
|
||||||
set(glfw_HEADERS ${common_HEADERS} x11_platform.h xkb_unicode.h
|
set(glfw_HEADERS ${common_HEADERS} x11_platform.h xkb_unicode.h posix_time.h
|
||||||
linux_joystick.h posix_time.h posix_tls.h glx_context.h
|
posix_thread.h glx_context.h egl_context.h osmesa_context.h)
|
||||||
egl_context.h)
|
|
||||||
set(glfw_SOURCES ${common_SOURCES} x11_init.c x11_monitor.c x11_window.c
|
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
|
xkb_unicode.c posix_time.c posix_thread.c glx_context.c
|
||||||
glx_context.c egl_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)
|
elseif (_GLFW_WAYLAND)
|
||||||
set(glfw_HEADERS ${common_HEADERS} wl_platform.h linux_joystick.h
|
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
|
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
|
linux_joystick.c posix_time.c posix_thread.c xkb_unicode.c
|
||||||
egl_context.c)
|
egl_context.c osmesa_context.c)
|
||||||
|
|
||||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
ecm_add_wayland_client_protocol(glfw_SOURCES
|
||||||
PROTOCOL
|
PROTOCOL
|
||||||
${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml
|
"${WAYLAND_PROTOCOLS_PKGDATADIR}/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)
|
BASENAME relative-pointer-unstable-v1)
|
||||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
ecm_add_wayland_client_protocol(glfw_SOURCES
|
||||||
PROTOCOL
|
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)
|
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)
|
elseif (_GLFW_MIR)
|
||||||
set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
|
set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
|
||||||
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
|
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
|
linux_joystick.c posix_time.c posix_thread.c xkb_unicode.c
|
||||||
egl_context.c)
|
egl_context.c osmesa_context.c)
|
||||||
elseif (_GLFW_OSMESA)
|
elseif (_GLFW_OSMESA)
|
||||||
set(glfw_HEADERS ${common_HEADERS} osmesa_platform.h
|
set(glfw_HEADERS ${common_HEADERS} null_platform.h null_joystick.h
|
||||||
posix_time.h posix_tls.h osmesa_context.h)
|
posix_time.h posix_thread.h osmesa_context.h)
|
||||||
set(glfw_SOURCES ${common_SOURCES} osmesa_init.c osmesa_monitor.c
|
set(glfw_SOURCES ${common_SOURCES} null_init.c null_monitor.c null_window.c
|
||||||
osmesa_window.c posix_time.c posix_tls.c
|
null_joystick.c posix_time.c posix_thread.c osmesa_context.c)
|
||||||
osmesa_context.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
@@ -58,6 +74,18 @@ if (APPLE)
|
|||||||
set_source_files_properties(${glfw_SOURCES} PROPERTIES LANGUAGE C)
|
set_source_files_properties(${glfw_SOURCES} PROPERTIES LANGUAGE C)
|
||||||
endif()
|
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})
|
add_library(glfw ${glfw_SOURCES} ${glfw_HEADERS})
|
||||||
set_target_properties(glfw PROPERTIES
|
set_target_properties(glfw PROPERTIES
|
||||||
OUTPUT_NAME ${GLFW_LIB_NAME}
|
OUTPUT_NAME ${GLFW_LIB_NAME}
|
||||||
@@ -66,10 +94,10 @@ set_target_properties(glfw PROPERTIES
|
|||||||
POSITION_INDEPENDENT_CODE ON
|
POSITION_INDEPENDENT_CODE ON
|
||||||
FOLDER "GLFW3")
|
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
|
target_include_directories(glfw PUBLIC
|
||||||
$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>
|
"$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>"
|
||||||
$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>)
|
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>")
|
||||||
target_include_directories(glfw PRIVATE
|
target_include_directories(glfw PRIVATE
|
||||||
"${GLFW_SOURCE_DIR}/src"
|
"${GLFW_SOURCE_DIR}/src"
|
||||||
"${GLFW_BINARY_DIR}/src"
|
"${GLFW_BINARY_DIR}/src"
|
||||||
@@ -110,7 +138,7 @@ if (BUILD_SHARED_LIBS)
|
|||||||
target_compile_options(glfw PRIVATE "-fvisibility=hidden")
|
target_compile_options(glfw PRIVATE "-fvisibility=hidden")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_compile_definitions(glfw INTERFACE -DGLFW_DLL)
|
target_compile_definitions(glfw INTERFACE GLFW_DLL)
|
||||||
target_link_libraries(glfw PRIVATE ${glfw_LIBRARIES})
|
target_link_libraries(glfw PRIVATE ${glfw_LIBRARIES})
|
||||||
else()
|
else()
|
||||||
target_link_libraries(glfw INTERFACE ${glfw_LIBRARIES})
|
target_link_libraries(glfw INTERFACE ${glfw_LIBRARIES})
|
||||||
@@ -121,6 +149,10 @@ if (MSVC)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (GLFW_INSTALL)
|
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()
|
endif()
|
||||||
|
|
||||||
|
|||||||
+8
-23
@@ -28,8 +28,6 @@
|
|||||||
#include <sys/param.h> // For MAXPATHLEN
|
#include <sys/param.h> // For MAXPATHLEN
|
||||||
|
|
||||||
|
|
||||||
#if defined(_GLFW_USE_CHDIR)
|
|
||||||
|
|
||||||
// Change to our application bundle's resources directory, if present
|
// Change to our application bundle's resources directory, if present
|
||||||
//
|
//
|
||||||
static void changeToResourcesDirectory(void)
|
static void changeToResourcesDirectory(void)
|
||||||
@@ -66,8 +64,6 @@ static void changeToResourcesDirectory(void)
|
|||||||
chdir(resourcesPath);
|
chdir(resourcesPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _GLFW_USE_CHDIR */
|
|
||||||
|
|
||||||
// Create key code translation tables
|
// Create key code translation tables
|
||||||
//
|
//
|
||||||
static void createKeyTables(void)
|
static void createKeyTables(void)
|
||||||
@@ -219,7 +215,8 @@ static GLFWbool updateUnicodeDataNS(void)
|
|||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.ns.unicodeData = TISGetInputSourceProperty(_glfw.ns.inputSource,
|
_glfw.ns.unicodeData =
|
||||||
|
TISGetInputSourceProperty(_glfw.ns.inputSource,
|
||||||
kTISPropertyUnicodeKeyLayoutData);
|
kTISPropertyUnicodeKeyLayoutData);
|
||||||
if (!_glfw.ns.unicodeData)
|
if (!_glfw.ns.unicodeData)
|
||||||
{
|
{
|
||||||
@@ -236,7 +233,8 @@ static GLFWbool updateUnicodeDataNS(void)
|
|||||||
static GLFWbool initializeTIS(void)
|
static GLFWbool initializeTIS(void)
|
||||||
{
|
{
|
||||||
// This works only because Cocoa has already loaded it properly
|
// 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)
|
if (!_glfw.ns.tis.bundle)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
@@ -294,6 +292,9 @@ int _glfwPlatformInit(void)
|
|||||||
{
|
{
|
||||||
_glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
|
_glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
|
if (_glfw.hints.init.ns.chdir)
|
||||||
|
changeToResourcesDirectory();
|
||||||
|
|
||||||
_glfw.ns.listener = [[GLFWLayoutListener alloc] init];
|
_glfw.ns.listener = [[GLFWLayoutListener alloc] init];
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
addObserver:_glfw.ns.listener
|
addObserver:_glfw.ns.listener
|
||||||
@@ -301,10 +302,6 @@ int _glfwPlatformInit(void)
|
|||||||
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
||||||
object:nil];
|
object:nil];
|
||||||
|
|
||||||
#if defined(_GLFW_USE_CHDIR)
|
|
||||||
changeToResourcesDirectory();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
createKeyTables();
|
createKeyTables();
|
||||||
|
|
||||||
_glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
_glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||||
@@ -316,12 +313,10 @@ int _glfwPlatformInit(void)
|
|||||||
if (!initializeTIS())
|
if (!initializeTIS())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
_glfwInitTimerNS();
|
_glfwInitTimerNS();
|
||||||
_glfwInitJoysticksNS();
|
_glfwInitJoysticksNS();
|
||||||
|
|
||||||
|
_glfwPollMonitorsNS();
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,14 +354,10 @@ void _glfwPlatformTerminate(void)
|
|||||||
_glfw.ns.listener = nil;
|
_glfw.ns.listener = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
[_glfw.ns.cursor release];
|
|
||||||
_glfw.ns.cursor = nil;
|
|
||||||
|
|
||||||
free(_glfw.ns.clipboardString);
|
free(_glfw.ns.clipboardString);
|
||||||
|
|
||||||
_glfwTerminateNSGL();
|
_glfwTerminateNSGL();
|
||||||
_glfwTerminateJoysticksNS();
|
_glfwTerminateJoysticksNS();
|
||||||
_glfwTerminateThreadLocalStoragePOSIX();
|
|
||||||
|
|
||||||
[_glfw.ns.autoreleasePool release];
|
[_glfw.ns.autoreleasePool release];
|
||||||
_glfw.ns.autoreleasePool = nil;
|
_glfw.ns.autoreleasePool = nil;
|
||||||
@@ -375,12 +366,6 @@ void _glfwPlatformTerminate(void)
|
|||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
{
|
{
|
||||||
return _GLFW_VERSION_NUMBER " Cocoa NSGL"
|
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)
|
#if defined(_GLFW_BUILD_DLL)
|
||||||
" dynamic"
|
" dynamic"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+7
-17
@@ -24,37 +24,27 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _glfw3_cocoa_joystick_h_
|
|
||||||
#define _glfw3_cocoa_joystick_h_
|
|
||||||
|
|
||||||
#include <IOKit/IOKitLib.h>
|
#include <IOKit/IOKitLib.h>
|
||||||
#include <IOKit/IOCFPlugIn.h>
|
#include <IOKit/IOCFPlugIn.h>
|
||||||
#include <IOKit/hid/IOHIDLib.h>
|
#include <IOKit/hid/IOHIDLib.h>
|
||||||
#include <IOKit/hid/IOHIDKeys.h>
|
#include <IOKit/hid/IOHIDKeys.h>
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
|
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickNS ns
|
||||||
_GLFWjoystickNS ns_js[GLFW_JOYSTICK_LAST + 1]
|
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_MAPPING_NAME "Mac OS X"
|
||||||
|
|
||||||
// Cocoa-specific per-joystick data
|
// Cocoa-specific per-joystick data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWjoystickNS
|
typedef struct _GLFWjoystickNS
|
||||||
{
|
{
|
||||||
GLFWbool present;
|
IOHIDDeviceRef device;
|
||||||
char name[256];
|
CFMutableArrayRef axes;
|
||||||
|
CFMutableArrayRef buttons;
|
||||||
IOHIDDeviceRef deviceRef;
|
CFMutableArrayRef hats;
|
||||||
|
|
||||||
CFMutableArrayRef axisElements;
|
|
||||||
CFMutableArrayRef buttonElements;
|
|
||||||
CFMutableArrayRef hatElements;
|
|
||||||
|
|
||||||
float* axes;
|
|
||||||
unsigned char* buttons;
|
|
||||||
} _GLFWjoystickNS;
|
} _GLFWjoystickNS;
|
||||||
|
|
||||||
|
|
||||||
void _glfwInitJoysticksNS(void);
|
void _glfwInitJoysticksNS(void);
|
||||||
void _glfwTerminateJoysticksNS(void);
|
void _glfwTerminateJoysticksNS(void);
|
||||||
|
|
||||||
#endif // _glfw3_cocoa_joystick_h_
|
|
||||||
|
|||||||
+301
-350
@@ -42,42 +42,167 @@
|
|||||||
//
|
//
|
||||||
typedef struct _GLFWjoyelementNS
|
typedef struct _GLFWjoyelementNS
|
||||||
{
|
{
|
||||||
IOHIDElementRef elementRef;
|
IOHIDElementRef native;
|
||||||
|
uint32_t usage;
|
||||||
long min;
|
int index;
|
||||||
long max;
|
long minimum;
|
||||||
|
long maximum;
|
||||||
long minReport;
|
|
||||||
long maxReport;
|
|
||||||
|
|
||||||
} _GLFWjoyelementNS;
|
} _GLFWjoyelementNS;
|
||||||
|
|
||||||
|
|
||||||
static void getElementsCFArrayHandler(const void* value, void* parameter);
|
// Returns the value of the specified element of the specified joystick
|
||||||
|
|
||||||
// Adds an element to the specified joystick
|
|
||||||
//
|
//
|
||||||
static void addJoystickElement(_GLFWjoystickNS* js,
|
static long getElementValue(_GLFWjoystick* js, _GLFWjoyelementNS* element)
|
||||||
IOHIDElementRef elementRef)
|
|
||||||
{
|
{
|
||||||
IOHIDElementType elementType;
|
IOHIDValueRef valueRef;
|
||||||
long usagePage, usage;
|
long value = 0;
|
||||||
CFMutableArrayRef elementsArray = NULL;
|
|
||||||
|
|
||||||
elementType = IOHIDElementGetType(elementRef);
|
if (js->ns.device)
|
||||||
usagePage = IOHIDElementGetUsagePage(elementRef);
|
|
||||||
usage = IOHIDElementGetUsage(elementRef);
|
|
||||||
|
|
||||||
if ((elementType != kIOHIDElementTypeInput_Axis) &&
|
|
||||||
(elementType != kIOHIDElementTypeInput_Button) &&
|
|
||||||
(elementType != kIOHIDElementTypeInput_Misc))
|
|
||||||
{
|
{
|
||||||
|
if (IOHIDDeviceGetValue(js->ns.device,
|
||||||
|
element->native,
|
||||||
|
&valueRef) == kIOReturnSuccess)
|
||||||
|
{
|
||||||
|
value = IOHIDValueGetIntegerValue(valueRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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++)
|
||||||
|
{
|
||||||
|
if (_glfw.joysticks[jid].ns.device == device)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (usagePage)
|
axes = CFArrayCreateMutable(NULL, 0, NULL);
|
||||||
|
buttons = CFArrayCreateMutable(NULL, 0, NULL);
|
||||||
|
hats = CFArrayCreateMutable(NULL, 0, NULL);
|
||||||
|
|
||||||
|
property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
|
||||||
|
if (property)
|
||||||
{
|
{
|
||||||
case kHIDPage_GenericDesktop:
|
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)
|
switch (usage)
|
||||||
{
|
{
|
||||||
@@ -90,241 +215,48 @@ static void addJoystickElement(_GLFWjoystickNS* js,
|
|||||||
case kHIDUsage_GD_Slider:
|
case kHIDUsage_GD_Slider:
|
||||||
case kHIDUsage_GD_Dial:
|
case kHIDUsage_GD_Dial:
|
||||||
case kHIDUsage_GD_Wheel:
|
case kHIDUsage_GD_Wheel:
|
||||||
elementsArray = js->axisElements;
|
target = axes;
|
||||||
break;
|
break;
|
||||||
case kHIDUsage_GD_Hatswitch:
|
case kHIDUsage_GD_Hatswitch:
|
||||||
elementsArray = js->hatElements;
|
target = hats;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else if (page == kHIDPage_Button)
|
||||||
|
target = buttons;
|
||||||
|
|
||||||
case kHIDPage_Button:
|
if (target)
|
||||||
elementsArray = js->buttonElements;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (elementsArray)
|
|
||||||
{
|
{
|
||||||
_GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));
|
_GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));
|
||||||
|
element->native = native;
|
||||||
CFArrayAppendValue(elementsArray, element);
|
element->usage = usage;
|
||||||
|
element->index = (int) CFArrayGetCount(target);
|
||||||
element->elementRef = elementRef;
|
element->minimum = IOHIDElementGetLogicalMin(native);
|
||||||
|
element->maximum = IOHIDElementGetLogicalMax(native);
|
||||||
element->minReport = IOHIDElementGetLogicalMin(elementRef);
|
CFArrayAppendValue(target, element);
|
||||||
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)
|
|
||||||
{
|
|
||||||
value = IOHIDValueGetIntegerValue(valueRef);
|
|
||||||
|
|
||||||
// Record min and max for auto calibration
|
|
||||||
if (value < element->minReport)
|
|
||||||
element->minReport = value;
|
|
||||||
if (value > element->maxReport)
|
|
||||||
element->maxReport = value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auto user scale
|
CFRelease(elements);
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removes the specified joystick
|
CFArraySortValues(axes, CFRangeMake(0, CFArrayGetCount(axes)),
|
||||||
//
|
compareElements, NULL);
|
||||||
static void removeJoystick(_GLFWjoystickNS* js)
|
CFArraySortValues(buttons, CFRangeMake(0, CFArrayGetCount(buttons)),
|
||||||
{
|
compareElements, NULL);
|
||||||
int i;
|
CFArraySortValues(hats, CFRangeMake(0, CFArrayGetCount(hats)),
|
||||||
|
compareElements, NULL);
|
||||||
|
|
||||||
if (!js->present)
|
js = _glfwAllocJoystick(name, guid,
|
||||||
return;
|
(int) CFArrayGetCount(axes),
|
||||||
|
(int) CFArrayGetCount(buttons),
|
||||||
|
(int) CFArrayGetCount(hats));
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(js->axisElements); i++)
|
js->ns.device = device;
|
||||||
free((void*) CFArrayGetValueAtIndex(js->axisElements, i));
|
js->ns.axes = axes;
|
||||||
CFArrayRemoveAllValues(js->axisElements);
|
js->ns.buttons = buttons;
|
||||||
CFRelease(js->axisElements);
|
js->ns.hats = hats;
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(js->buttonElements); i++)
|
_glfwInputJoystick(js, GLFW_CONNECTED);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callback for user-initiated joystick removal
|
// Callback for user-initiated joystick removal
|
||||||
@@ -332,60 +264,20 @@ static void matchCallback(void* context,
|
|||||||
static void removeCallback(void* context,
|
static void removeCallback(void* context,
|
||||||
IOReturn result,
|
IOReturn result,
|
||||||
void* sender,
|
void* sender,
|
||||||
IOHIDDeviceRef deviceRef)
|
IOHIDDeviceRef device)
|
||||||
{
|
{
|
||||||
int jid;
|
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;
|
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 //////
|
////// GLFW internal API //////
|
||||||
@@ -395,56 +287,73 @@ static CFMutableDictionaryRef createMatchingDictionary(long usagePage,
|
|||||||
//
|
//
|
||||||
void _glfwInitJoysticksNS(void)
|
void _glfwInitJoysticksNS(void)
|
||||||
{
|
{
|
||||||
CFMutableArrayRef matchingCFArrayRef;
|
CFMutableArrayRef matching;
|
||||||
|
const long usages[] =
|
||||||
|
{
|
||||||
|
kHIDUsage_GD_Joystick,
|
||||||
|
kHIDUsage_GD_GamePad,
|
||||||
|
kHIDUsage_GD_MultiAxisController
|
||||||
|
};
|
||||||
|
|
||||||
_glfw.ns.hidManager = IOHIDManagerCreate(kCFAllocatorDefault,
|
_glfw.ns.hidManager = IOHIDManagerCreate(kCFAllocatorDefault,
|
||||||
kIOHIDOptionsTypeNone);
|
kIOHIDOptionsTypeNone);
|
||||||
|
|
||||||
matchingCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault,
|
matching = CFArrayCreateMutable(kCFAllocatorDefault,
|
||||||
0,
|
0,
|
||||||
&kCFTypeArrayCallBacks);
|
&kCFTypeArrayCallBacks);
|
||||||
if (matchingCFArrayRef)
|
if (!matching)
|
||||||
{
|
{
|
||||||
CFDictionaryRef matchingCFDictRef =
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create array");
|
||||||
createMatchingDictionary(kHIDPage_GenericDesktop,
|
return;
|
||||||
kHIDUsage_GD_Joystick);
|
|
||||||
if (matchingCFDictRef)
|
|
||||||
{
|
|
||||||
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
|
|
||||||
CFRelease(matchingCFDictRef);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
matchingCFDictRef = createMatchingDictionary(kHIDPage_GenericDesktop,
|
for (int i = 0; i < sizeof(usages) / sizeof(long); i++)
|
||||||
kHIDUsage_GD_GamePad);
|
|
||||||
if (matchingCFDictRef)
|
|
||||||
{
|
{
|
||||||
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
|
const long page = kHIDPage_GenericDesktop;
|
||||||
CFRelease(matchingCFDictRef);
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
matchingCFDictRef =
|
if (pageRef)
|
||||||
createMatchingDictionary(kHIDPage_GenericDesktop,
|
CFRelease(pageRef);
|
||||||
kHIDUsage_GD_MultiAxisController);
|
if (usageRef)
|
||||||
if (matchingCFDictRef)
|
CFRelease(usageRef);
|
||||||
{
|
|
||||||
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
|
CFRelease(dict);
|
||||||
CFRelease(matchingCFDictRef);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IOHIDManagerSetDeviceMatchingMultiple(_glfw.ns.hidManager,
|
IOHIDManagerSetDeviceMatchingMultiple(_glfw.ns.hidManager, matching);
|
||||||
matchingCFArrayRef);
|
CFRelease(matching);
|
||||||
CFRelease(matchingCFArrayRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
IOHIDManagerRegisterDeviceMatchingCallback(_glfw.ns.hidManager,
|
IOHIDManagerRegisterDeviceMatchingCallback(_glfw.ns.hidManager,
|
||||||
&matchCallback, NULL);
|
&matchCallback, NULL);
|
||||||
IOHIDManagerRegisterDeviceRemovalCallback(_glfw.ns.hidManager,
|
IOHIDManagerRegisterDeviceRemovalCallback(_glfw.ns.hidManager,
|
||||||
&removeCallback, NULL);
|
&removeCallback, NULL);
|
||||||
|
|
||||||
IOHIDManagerScheduleWithRunLoop(_glfw.ns.hidManager,
|
IOHIDManagerScheduleWithRunLoop(_glfw.ns.hidManager,
|
||||||
CFRunLoopGetMain(),
|
CFRunLoopGetMain(),
|
||||||
kCFRunLoopDefaultMode);
|
kCFRunLoopDefaultMode);
|
||||||
|
|
||||||
IOHIDManagerOpen(_glfw.ns.hidManager, kIOHIDOptionsTypeNone);
|
IOHIDManagerOpen(_glfw.ns.hidManager, kIOHIDOptionsTypeNone);
|
||||||
|
|
||||||
// Execute the run loop once in order to register any initially-attached
|
// Execute the run loop once in order to register any initially-attached
|
||||||
@@ -458,11 +367,8 @@ void _glfwTerminateJoysticksNS(void)
|
|||||||
{
|
{
|
||||||
int jid;
|
int jid;
|
||||||
|
|
||||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
{
|
closeJoystick(_glfw.joysticks + jid);
|
||||||
_GLFWjoystickNS* js = _glfw.ns_js + jid;
|
|
||||||
removeJoystick(js);
|
|
||||||
}
|
|
||||||
|
|
||||||
CFRelease(_glfw.ns.hidManager);
|
CFRelease(_glfw.ns.hidManager);
|
||||||
_glfw.ns.hidManager = NULL;
|
_glfw.ns.hidManager = NULL;
|
||||||
@@ -473,39 +379,84 @@ void _glfwTerminateJoysticksNS(void)
|
|||||||
////// GLFW platform API //////
|
////// 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;
|
return js->present;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float* _glfwPlatformGetJoystickAxes(int jid, int* count)
|
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
||||||
{
|
{
|
||||||
_GLFWjoystickNS* js = _glfw.ns_js + jid;
|
if ((strncmp(guid + 4, "000000000000", 12) == 0) &&
|
||||||
if (!pollJoystickAxisEvents(js))
|
(strncmp(guid + 20, "000000000000", 12) == 0))
|
||||||
return NULL;
|
{
|
||||||
|
char original[33];
|
||||||
*count = (int) CFArrayGetCount(js->axisElements);
|
strcpy(original, guid);
|
||||||
return js->axes;
|
sprintf(guid, "03000000%.4s0000%.4s000000000000",
|
||||||
}
|
original, original + 16);
|
||||||
|
}
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+131
-71
@@ -48,14 +48,14 @@ static char* getDisplayName(CGDirectDisplayID displayID)
|
|||||||
IOServiceMatching("IODisplayConnect"),
|
IOServiceMatching("IODisplayConnect"),
|
||||||
&it) != 0)
|
&it) != 0)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
// This may happen if a desktop Mac is running headless
|
||||||
"Cocoa: Failed to get display service port iterator");
|
return NULL;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((service = IOIteratorNext(it)) != 0)
|
while ((service = IOIteratorNext(it)) != 0)
|
||||||
{
|
{
|
||||||
info = IODisplayCreateInfoDictionary(service, kIODisplayOnlyPreferredName);
|
info = IODisplayCreateInfoDictionary(service,
|
||||||
|
kIODisplayOnlyPreferredName);
|
||||||
|
|
||||||
CFNumberRef vendorIDRef =
|
CFNumberRef vendorIDRef =
|
||||||
CFDictionaryGetValue(info, CFSTR(kDisplayVendorID));
|
CFDictionaryGetValue(info, CFSTR(kDisplayVendorID));
|
||||||
@@ -99,8 +99,6 @@ static char* getDisplayName(CGDirectDisplayID displayID)
|
|||||||
(const void**) &nameRef))
|
(const void**) &nameRef))
|
||||||
{
|
{
|
||||||
// This may happen if a desktop Mac is running headless
|
// This may happen if a desktop Mac is running headless
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Cocoa: Failed to retrieve display name");
|
|
||||||
CFRelease(info);
|
CFRelease(info);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -128,7 +126,7 @@ static GLFWbool modeIsGood(CGDisplayModeRef mode)
|
|||||||
if (flags & kDisplayModeStretchedFlag)
|
if (flags & kDisplayModeStretchedFlag)
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101200
|
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
||||||
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
|
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
|
||||||
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) &&
|
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) &&
|
||||||
CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
|
CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
|
||||||
@@ -159,7 +157,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
|
|||||||
result.refreshRate = (int) (time.timeScale / (double) time.timeValue);
|
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);
|
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
|
||||||
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0)
|
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0)
|
||||||
{
|
{
|
||||||
@@ -175,7 +173,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
|
|||||||
result.blueBits = 8;
|
result.blueBits = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101200
|
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
||||||
CFRelease(format);
|
CFRelease(format);
|
||||||
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
|
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
|
||||||
return result;
|
return result;
|
||||||
@@ -188,7 +186,13 @@ static CGDisplayFadeReservationToken beginFadeReservation(void)
|
|||||||
CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken;
|
CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken;
|
||||||
|
|
||||||
if (CGAcquireDisplayFadeReservation(5, &token) == kCGErrorSuccess)
|
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;
|
return token;
|
||||||
}
|
}
|
||||||
@@ -199,7 +203,11 @@ static void endFadeReservation(CGDisplayFadeReservationToken token)
|
|||||||
{
|
{
|
||||||
if (token != kCGDisplayFadeReservationInvalidToken)
|
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);
|
CGReleaseDisplayFadeReservation(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -209,9 +217,77 @@ static void endFadeReservation(CGDisplayFadeReservationToken token)
|
|||||||
////// GLFW internal API //////
|
////// 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
|
// Change the current video mode
|
||||||
//
|
//
|
||||||
GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
||||||
{
|
{
|
||||||
CFArrayRef modes;
|
CFArrayRef modes;
|
||||||
CFIndex count, i;
|
CFIndex count, i;
|
||||||
@@ -223,7 +299,7 @@ GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
|||||||
best = _glfwChooseVideoMode(monitor, desired);
|
best = _glfwChooseVideoMode(monitor, desired);
|
||||||
_glfwPlatformGetVideoMode(monitor, ¤t);
|
_glfwPlatformGetVideoMode(monitor, ¤t);
|
||||||
if (_glfwCompareVideoModes(¤t, best) == 0)
|
if (_glfwCompareVideoModes(¤t, best) == 0)
|
||||||
return GLFW_TRUE;
|
return;
|
||||||
|
|
||||||
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
|
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
|
||||||
|
|
||||||
@@ -256,15 +332,6 @@ GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
|||||||
|
|
||||||
CFRelease(modes);
|
CFRelease(modes);
|
||||||
CVDisplayLinkRelease(link);
|
CVDisplayLinkRelease(link);
|
||||||
|
|
||||||
if (!native)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Cocoa: Monitor mode list changed");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore the previously saved (original) video mode
|
// Restore the previously saved (original) video mode
|
||||||
@@ -288,55 +355,6 @@ void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor)
|
|||||||
////// GLFW platform API //////
|
////// 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)
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||||
{
|
{
|
||||||
const CGRect bounds = CGDisplayBounds(monitor->ns.displayID);
|
const CGRect bounds = CGDisplayBounds(monitor->ns.displayID);
|
||||||
@@ -347,6 +365,48 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
|||||||
*ypos = (int) bounds.origin.y;
|
*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)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||||
{
|
{
|
||||||
CFArrayRef modes;
|
CFArrayRef modes;
|
||||||
|
|||||||
+19
-13
@@ -24,9 +24,6 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _glfw3_cocoa_platform_h_
|
|
||||||
#define _glfw3_cocoa_platform_h_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
@@ -51,23 +48,25 @@ typedef struct VkMacOSSurfaceCreateInfoMVK
|
|||||||
|
|
||||||
typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||||
|
|
||||||
#include "posix_tls.h"
|
#include "posix_thread.h"
|
||||||
#include "cocoa_joystick.h"
|
#include "cocoa_joystick.h"
|
||||||
#include "nsgl_context.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_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||||
#define _glfw_dlclose(handle) dlclose(handle)
|
#define _glfw_dlclose(handle) dlclose(handle)
|
||||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
#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_WINDOW_STATE _GLFWwindowNS ns
|
||||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS 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_MONITOR_STATE _GLFWmonitorNS ns
|
||||||
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorNS ns
|
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorNS ns
|
||||||
|
|
||||||
#define _GLFW_EGL_CONTEXT_STATE
|
|
||||||
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE
|
|
||||||
|
|
||||||
// HIToolbox.framework pointer typedefs
|
// HIToolbox.framework pointer typedefs
|
||||||
#define kTISPropertyUnicodeKeyLayoutData _glfw.ns.tis.kPropertyUnicodeKeyLayoutData
|
#define kTISPropertyUnicodeKeyLayoutData _glfw.ns.tis.kPropertyUnicodeKeyLayoutData
|
||||||
typedef TISInputSourceRef (*PFN_TISCopyCurrentKeyboardLayoutInputSource)(void);
|
typedef TISInputSourceRef (*PFN_TISCopyCurrentKeyboardLayoutInputSource)(void);
|
||||||
@@ -89,6 +88,11 @@ typedef struct _GLFWwindowNS
|
|||||||
|
|
||||||
GLFWbool maximized;
|
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
|
// The total sum of the distances the cursor has been warped
|
||||||
// since the last cursor motion event was processed
|
// since the last cursor motion event was processed
|
||||||
// This is kept to counteract Cocoa doing the same internally
|
// This is kept to counteract Cocoa doing the same internally
|
||||||
@@ -103,7 +107,7 @@ typedef struct _GLFWlibraryNS
|
|||||||
CGEventSourceRef eventSource;
|
CGEventSourceRef eventSource;
|
||||||
id delegate;
|
id delegate;
|
||||||
id autoreleasePool;
|
id autoreleasePool;
|
||||||
id cursor;
|
GLFWbool cursorHidden;
|
||||||
TISInputSourceRef inputSource;
|
TISInputSourceRef inputSource;
|
||||||
IOHIDManagerRef hidManager;
|
IOHIDManagerRef hidManager;
|
||||||
id unicodeData;
|
id unicodeData;
|
||||||
@@ -113,6 +117,7 @@ typedef struct _GLFWlibraryNS
|
|||||||
short int keycodes[256];
|
short int keycodes[256];
|
||||||
short int scancodes[GLFW_KEY_LAST + 1];
|
short int scancodes[GLFW_KEY_LAST + 1];
|
||||||
char* clipboardString;
|
char* clipboardString;
|
||||||
|
CGPoint cascadePoint;
|
||||||
// Where to place the cursor when re-enabled
|
// Where to place the cursor when re-enabled
|
||||||
double restoreCursorPosX, restoreCursorPosY;
|
double restoreCursorPosX, restoreCursorPosY;
|
||||||
// The window whose disabled cursor mode is active
|
// The window whose disabled cursor mode is active
|
||||||
@@ -135,6 +140,7 @@ typedef struct _GLFWmonitorNS
|
|||||||
CGDirectDisplayID displayID;
|
CGDirectDisplayID displayID;
|
||||||
CGDisplayModeRef previousMode;
|
CGDisplayModeRef previousMode;
|
||||||
uint32_t unitNumber;
|
uint32_t unitNumber;
|
||||||
|
id screen;
|
||||||
|
|
||||||
} _GLFWmonitorNS;
|
} _GLFWmonitorNS;
|
||||||
|
|
||||||
@@ -148,16 +154,16 @@ typedef struct _GLFWcursorNS
|
|||||||
|
|
||||||
// Cocoa-specific global timer data
|
// Cocoa-specific global timer data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWtimeNS
|
typedef struct _GLFWtimerNS
|
||||||
{
|
{
|
||||||
uint64_t frequency;
|
uint64_t frequency;
|
||||||
|
|
||||||
} _GLFWtimeNS;
|
} _GLFWtimerNS;
|
||||||
|
|
||||||
|
|
||||||
void _glfwInitTimerNS(void);
|
void _glfwInitTimerNS(void);
|
||||||
|
|
||||||
GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
void _glfwPollMonitorsNS(void);
|
||||||
|
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||||
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
|
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_data_t info;
|
||||||
mach_timebase_info(&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)
|
uint64_t _glfwPlatformGetTimerFrequency(void)
|
||||||
{
|
{
|
||||||
return _glfw.ns_time.frequency;
|
return _glfw.timer.ns.frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+264
-129
@@ -43,6 +43,7 @@
|
|||||||
#define NSEventModifierFlagControl NSControlKeyMask
|
#define NSEventModifierFlagControl NSControlKeyMask
|
||||||
#define NSEventModifierFlagOption NSAlternateKeyMask
|
#define NSEventModifierFlagOption NSAlternateKeyMask
|
||||||
#define NSEventModifierFlagShift NSShiftKeyMask
|
#define NSEventModifierFlagShift NSShiftKeyMask
|
||||||
|
#define NSEventModifierFlagCapsLock NSAlphaShiftKeyMask
|
||||||
#define NSEventModifierFlagDeviceIndependentFlagsMask NSDeviceIndependentModifierFlagsMask
|
#define NSEventModifierFlagDeviceIndependentFlagsMask NSDeviceIndependentModifierFlagsMask
|
||||||
#define NSEventMaskAny NSAnyEventMask
|
#define NSEventMaskAny NSAnyEventMask
|
||||||
#define NSEventTypeApplicationDefined NSApplicationDefined
|
#define NSEventTypeApplicationDefined NSApplicationDefined
|
||||||
@@ -50,29 +51,6 @@
|
|||||||
#endif
|
#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
|
// Returns the style mask corresponding to the window settings
|
||||||
//
|
//
|
||||||
static NSUInteger getStyleMask(_GLFWwindow* window)
|
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]];
|
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
|
// Updates the cursor image according to its cursor mode
|
||||||
//
|
//
|
||||||
static void updateCursorImage(_GLFWwindow* window)
|
static void updateCursorImage(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
||||||
{
|
{
|
||||||
|
showCursor(window);
|
||||||
|
|
||||||
if (window->cursor)
|
if (window->cursor)
|
||||||
[(NSCursor*) window->cursor->ns.object set];
|
[(NSCursor*) window->cursor->ns.object set];
|
||||||
else
|
else
|
||||||
[[NSCursor arrowCursor] set];
|
[[NSCursor arrowCursor] set];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
[(NSCursor*) _glfw.ns.cursor set];
|
hideCursor(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transforms the specified y-coordinate between the CG display and NS screen
|
// 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
|
// Make the specified window and its video mode active on its monitor
|
||||||
//
|
//
|
||||||
static GLFWbool acquireMonitor(_GLFWwindow* window)
|
static void acquireMonitor(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
const GLFWbool status = _glfwSetVideoModeNS(window->monitor, &window->videoMode);
|
_glfwSetVideoModeNS(window->monitor, &window->videoMode);
|
||||||
const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID);
|
const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID);
|
||||||
const NSRect frame = NSMakeRect(bounds.origin.x,
|
const NSRect frame = NSMakeRect(bounds.origin.x,
|
||||||
transformY(bounds.origin.y + bounds.size.height),
|
transformY(bounds.origin.y + bounds.size.height),
|
||||||
@@ -147,8 +149,7 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
|
|||||||
|
|
||||||
[window->ns.object setFrame:frame display:YES];
|
[window->ns.object setFrame:frame display:YES];
|
||||||
|
|
||||||
_glfwInputMonitorWindowChange(window->monitor, window);
|
_glfwInputMonitorWindow(window->monitor, window);
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the window and restore the original video mode
|
// Remove the window and restore the original video mode
|
||||||
@@ -158,7 +159,7 @@ static void releaseMonitor(_GLFWwindow* window)
|
|||||||
if (window->monitor->window != window)
|
if (window->monitor->window != window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_glfwInputMonitorWindowChange(window->monitor, NULL);
|
_glfwInputMonitorWindow(window->monitor, NULL);
|
||||||
_glfwRestoreVideoModeNS(window->monitor);
|
_glfwRestoreVideoModeNS(window->monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,6 +177,8 @@ static int translateFlags(NSUInteger flags)
|
|||||||
mods |= GLFW_MOD_ALT;
|
mods |= GLFW_MOD_ALT;
|
||||||
if (flags & NSEventModifierFlagCommand)
|
if (flags & NSEventModifierFlagCommand)
|
||||||
mods |= GLFW_MOD_SUPER;
|
mods |= GLFW_MOD_SUPER;
|
||||||
|
if (flags & NSEventModifierFlagCapsLock)
|
||||||
|
mods |= GLFW_MOD_CAPS_LOCK;
|
||||||
|
|
||||||
return mods;
|
return mods;
|
||||||
}
|
}
|
||||||
@@ -227,13 +230,13 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
_GLFWwindow* window;
|
_GLFWwindow* window;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithGlfwWindow:(_GLFWwindow *)initWindow;
|
- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GLFWWindowDelegate
|
@implementation GLFWWindowDelegate
|
||||||
|
|
||||||
- (id)initWithGlfwWindow:(_GLFWwindow *)initWindow
|
- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self != nil)
|
if (self != nil)
|
||||||
@@ -266,8 +269,21 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
const NSRect contentRect = [window->ns.view frame];
|
const NSRect contentRect = [window->ns.view frame];
|
||||||
const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
|
const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
|
||||||
|
|
||||||
|
if (fbRect.size.width != window->ns.fbWidth ||
|
||||||
|
fbRect.size.height != window->ns.fbHeight)
|
||||||
|
{
|
||||||
|
window->ns.fbWidth = fbRect.size.width;
|
||||||
|
window->ns.fbHeight = fbRect.size.height;
|
||||||
_glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
|
_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);
|
_glfwInputWindowSize(window, contentRect.size.width, contentRect.size.height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)windowDidMove:(NSNotification *)notification
|
- (void)windowDidMove:(NSNotification *)notification
|
||||||
@@ -340,7 +356,15 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
|
|
||||||
- (void)applicationDidChangeScreenParameters:(NSNotification *) notification
|
- (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
|
- (void)applicationDidFinishLaunching:(NSNotification *)notification
|
||||||
@@ -372,27 +396,13 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
NSMutableAttributedString* markedText;
|
NSMutableAttributedString* markedText;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithGlfwWindow:(_GLFWwindow *)initWindow;
|
- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GLFWContentView
|
@implementation GLFWContentView
|
||||||
|
|
||||||
+ (void)initialize
|
- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self != nil)
|
if (self != nil)
|
||||||
@@ -418,7 +428,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
|
|
||||||
- (BOOL)isOpaque
|
- (BOOL)isOpaque
|
||||||
{
|
{
|
||||||
return YES;
|
return [window->ns.object isOpaque];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)canBecomeKeyView
|
- (BOOL)canBecomeKeyView
|
||||||
@@ -438,7 +448,10 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
|
|
||||||
- (id)makeBackingLayer
|
- (id)makeBackingLayer
|
||||||
{
|
{
|
||||||
|
if (window->ns.layer)
|
||||||
return window->ns.layer;
|
return window->ns.layer;
|
||||||
|
|
||||||
|
return [super makeBackingLayer];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)cursorUpdate:(NSEvent *)event
|
- (void)cursorUpdate:(NSEvent *)event
|
||||||
@@ -534,11 +547,17 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
|
|
||||||
- (void)mouseExited:(NSEvent *)event
|
- (void)mouseExited:(NSEvent *)event
|
||||||
{
|
{
|
||||||
|
if (window->cursorMode == GLFW_CURSOR_HIDDEN)
|
||||||
|
showCursor(window);
|
||||||
|
|
||||||
_glfwInputCursorEnter(window, GLFW_FALSE);
|
_glfwInputCursorEnter(window, GLFW_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseEntered:(NSEvent *)event
|
- (void)mouseEntered:(NSEvent *)event
|
||||||
{
|
{
|
||||||
|
if (window->cursorMode == GLFW_CURSOR_HIDDEN)
|
||||||
|
hideCursor(window);
|
||||||
|
|
||||||
_glfwInputCursorEnter(window, GLFW_TRUE);
|
_glfwInputCursorEnter(window, GLFW_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,7 +566,23 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
const NSRect contentRect = [window->ns.view frame];
|
const NSRect contentRect = [window->ns.view frame];
|
||||||
const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
|
const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
|
||||||
|
|
||||||
|
if (fbRect.size.width != window->ns.fbWidth ||
|
||||||
|
fbRect.size.height != window->ns.fbHeight)
|
||||||
|
{
|
||||||
|
window->ns.fbWidth = fbRect.size.width;
|
||||||
|
window->ns.fbHeight = fbRect.size.height;
|
||||||
_glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
|
_glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
const float xscale = fbRect.size.width / contentRect.size.width;
|
||||||
|
const float yscale = fbRect.size.height / contentRect.size.height;
|
||||||
|
|
||||||
|
if (xscale != window->ns.xscale || yscale != window->ns.yscale)
|
||||||
|
{
|
||||||
|
window->ns.xscale = xscale;
|
||||||
|
window->ns.yscale = yscale;
|
||||||
|
_glfwInputWindowContentScale(window, xscale, yscale);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)drawRect:(NSRect)rect
|
- (void)drawRect:(NSRect)rect
|
||||||
@@ -663,17 +698,17 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
[sender draggingLocation].x,
|
[sender draggingLocation].x,
|
||||||
contentRect.size.height - [sender draggingLocation].y);
|
contentRect.size.height - [sender draggingLocation].y);
|
||||||
|
|
||||||
const int count = [files count];
|
const NSUInteger count = [files count];
|
||||||
if (count)
|
if (count)
|
||||||
{
|
{
|
||||||
NSEnumerator* e = [files objectEnumerator];
|
NSEnumerator* e = [files objectEnumerator];
|
||||||
char** paths = calloc(count, sizeof(char*));
|
char** paths = calloc(count, sizeof(char*));
|
||||||
int i;
|
NSUInteger i;
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
paths[i] = strdup([[e nextObject] UTF8String]);
|
paths[i] = _glfw_strdup([[e nextObject] UTF8String]);
|
||||||
|
|
||||||
_glfwInputDrop(window, count, (const char**) paths);
|
_glfwInputDrop(window, (int) count, (const char**) paths);
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
free(paths[i]);
|
free(paths[i]);
|
||||||
@@ -710,10 +745,11 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
selectedRange:(NSRange)selectedRange
|
selectedRange:(NSRange)selectedRange
|
||||||
replacementRange:(NSRange)replacementRange
|
replacementRange:(NSRange)replacementRange
|
||||||
{
|
{
|
||||||
|
[markedText release];
|
||||||
if ([string isKindOfClass:[NSAttributedString class]])
|
if ([string isKindOfClass:[NSAttributedString class]])
|
||||||
[markedText initWithAttributedString:string];
|
markedText = [[NSMutableAttributedString alloc] initWithAttributedString:string];
|
||||||
else
|
else
|
||||||
[markedText initWithString:string];
|
markedText = [[NSMutableAttributedString alloc] initWithString:string];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)unmarkText
|
- (void)unmarkText
|
||||||
@@ -792,6 +828,11 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)canBecomeMainWindow
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
@@ -800,6 +841,10 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
|
|
||||||
@interface GLFWApplication : NSApplication
|
@interface GLFWApplication : NSApplication
|
||||||
|
{
|
||||||
|
NSArray* nibObjects;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GLFWApplication
|
@implementation GLFWApplication
|
||||||
@@ -824,53 +869,58 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
- (void)doNothing:(id)object
|
- (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
|
@end
|
||||||
|
|
||||||
#if defined(_GLFW_USE_MENUBAR)
|
// Set up the menu bar (manually)
|
||||||
|
// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
|
||||||
// Try to figure out what the calling application is called
|
// 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;
|
size_t i;
|
||||||
NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
|
NSString* appName = nil;
|
||||||
|
NSDictionary* bundleInfo = [[NSBundle mainBundle] infoDictionary];
|
||||||
// Keys to search for as potential application names
|
NSString* nameKeys[] =
|
||||||
NSString* GLFWNameKeys[] =
|
|
||||||
{
|
{
|
||||||
@"CFBundleDisplayName",
|
@"CFBundleDisplayName",
|
||||||
@"CFBundleName",
|
@"CFBundleName",
|
||||||
@"CFBundleExecutable",
|
@"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 &&
|
if (name &&
|
||||||
[name isKindOfClass:[NSString class]] &&
|
[name isKindOfClass:[NSString class]] &&
|
||||||
![name isEqualToString:@""])
|
![name isEqualToString:@""])
|
||||||
{
|
{
|
||||||
return name;
|
appName = name;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!appName)
|
||||||
|
{
|
||||||
char** progname = _NSGetProgname();
|
char** progname = _NSGetProgname();
|
||||||
if (progname && *progname)
|
if (progname && *progname)
|
||||||
return [NSString stringWithUTF8String:*progname];
|
appName = [NSString stringWithUTF8String:*progname];
|
||||||
|
else
|
||||||
// Really shouldn't get here
|
appName = @"GLFW Application";
|
||||||
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();
|
|
||||||
|
|
||||||
NSMenu* bar = [[NSMenu alloc] init];
|
NSMenu* bar = [[NSMenu alloc] init];
|
||||||
[NSApp setMainMenu:bar];
|
[NSApp setMainMenu:bar];
|
||||||
@@ -937,8 +987,6 @@ static void createMenuBar(void)
|
|||||||
[NSApp performSelector:setAppleMenuSelector withObject:appMenu];
|
[NSApp performSelector:setAppleMenuSelector withObject:appMenu];
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _GLFW_USE_MENUBAR */
|
|
||||||
|
|
||||||
// Initialize the Cocoa Application Kit
|
// Initialize the Cocoa Application Kit
|
||||||
//
|
//
|
||||||
static GLFWbool initializeAppKit(void)
|
static GLFWbool initializeAppKit(void)
|
||||||
@@ -954,15 +1002,20 @@ static GLFWbool initializeAppKit(void)
|
|||||||
toTarget:NSApp
|
toTarget:NSApp
|
||||||
withObject:nil];
|
withObject:nil];
|
||||||
|
|
||||||
|
if (_glfw.hints.init.ns.menubar)
|
||||||
|
{
|
||||||
// In case we are unbundled, make us a proper UI application
|
// In case we are unbundled, make us a proper UI application
|
||||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||||
|
|
||||||
#if defined(_GLFW_USE_MENUBAR)
|
|
||||||
// Menu bar setup must go between sharedApplication above and
|
// Menu bar setup must go between sharedApplication above and
|
||||||
// finishLaunching below, in order to properly emulate the behavior
|
// finishLaunching below, in order to properly emulate the behavior
|
||||||
// of NSApplicationMain
|
// of NSApplicationMain
|
||||||
|
|
||||||
|
if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
|
||||||
|
[NSApp loadMainMenu];
|
||||||
|
else
|
||||||
createMenuBar();
|
createMenuBar();
|
||||||
#endif
|
}
|
||||||
|
|
||||||
// There can only be one application delegate, but we allocate it the
|
// 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
|
// 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 setDelegate:_glfw.ns.delegate];
|
||||||
[NSApp run];
|
[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;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the Cocoa window
|
// Create the Cocoa window
|
||||||
//
|
//
|
||||||
static GLFWbool createNativeWindow(_GLFWwindow* window,
|
static GLFWbool createNativeWindow(_GLFWwindow* window,
|
||||||
const _GLFWwndconfig* wndconfig)
|
const _GLFWwndconfig* wndconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
window->ns.delegate = [[GLFWWindowDelegate alloc] initWithGlfwWindow:window];
|
window->ns.delegate = [[GLFWWindowDelegate alloc] initWithGlfwWindow:window];
|
||||||
if (window->ns.delegate == nil)
|
if (window->ns.delegate == nil)
|
||||||
@@ -1025,9 +1086,17 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
[window->ns.object center];
|
[window->ns.object center];
|
||||||
|
_glfw.ns.cascadePoint =
|
||||||
|
NSPointToCGPoint([window->ns.object cascadeTopLeftFromPoint:
|
||||||
|
NSPointFromCGPoint(_glfw.ns.cascadePoint)]);
|
||||||
|
|
||||||
if (wndconfig->resizable)
|
if (wndconfig->resizable)
|
||||||
[window->ns.object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
|
{
|
||||||
|
const NSWindowCollectionBehavior behavior =
|
||||||
|
NSWindowCollectionBehaviorFullScreenPrimary |
|
||||||
|
NSWindowCollectionBehaviorManaged;
|
||||||
|
[window->ns.object setCollectionBehavior:behavior];
|
||||||
|
}
|
||||||
|
|
||||||
if (wndconfig->floating)
|
if (wndconfig->floating)
|
||||||
[window->ns.object setLevel:NSFloatingWindowLevel];
|
[window->ns.object setLevel:NSFloatingWindowLevel];
|
||||||
@@ -1036,11 +1105,20 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
[window->ns.object zoom:nil];
|
[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];
|
window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
|
||||||
|
|
||||||
if (wndconfig->ns.retina)
|
if (wndconfig->ns.retina)
|
||||||
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
|
[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 setContentView:window->ns.view];
|
||||||
[window->ns.object makeFirstResponder:window->ns.view];
|
[window->ns.object makeFirstResponder:window->ns.view];
|
||||||
[window->ns.object setTitle:[NSString stringWithUTF8String:wndconfig->title]];
|
[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 setAcceptsMouseMovedEvents:YES];
|
||||||
[window->ns.object setRestorable:NO];
|
[window->ns.object setRestorable:NO];
|
||||||
|
|
||||||
|
_glfwPlatformGetWindowSize(window, &window->ns.width, &window->ns.height);
|
||||||
|
_glfwPlatformGetFramebufferSize(window, &window->ns.fbWidth, &window->ns.fbHeight);
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1064,7 +1145,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
if (!initializeAppKit())
|
if (!initializeAppKit())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
if (!createNativeWindow(window, wndconfig))
|
if (!createNativeWindow(window, wndconfig, fbconfig))
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
if (ctxconfig->client != GLFW_NO_API)
|
if (ctxconfig->client != GLFW_NO_API)
|
||||||
@@ -1076,9 +1157,18 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
if (!_glfwCreateContextNSGL(window, ctxconfig, fbconfig))
|
if (!_glfwCreateContextNSGL(window, ctxconfig, fbconfig))
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
else
|
else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Cocoa: EGL not available");
|
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_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1087,10 +1177,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwPlatformShowWindow(window);
|
_glfwPlatformShowWindow(window);
|
||||||
_glfwPlatformFocusWindow(window);
|
_glfwPlatformFocusWindow(window);
|
||||||
if (!acquireMonitor(window))
|
acquireMonitor(window);
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
centerCursor(window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
@@ -1125,7 +1212,11 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char *title)
|
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,
|
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
||||||
@@ -1227,6 +1318,18 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
|||||||
*bottom = contentRect.origin.y - frameRect.origin.y;
|
*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)
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
[window->ns.object miniaturize:nil];
|
[window->ns.object miniaturize:nil];
|
||||||
@@ -1256,6 +1359,11 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
|
|||||||
[window->ns.object orderOut:nil];
|
[window->ns.object orderOut:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
[NSApp requestUserAttention:NSInformationalRequest];
|
||||||
|
}
|
||||||
|
|
||||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
// Make us the active application
|
// Make us the active application
|
||||||
@@ -1297,34 +1405,17 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
|||||||
if (window->monitor)
|
if (window->monitor)
|
||||||
releaseMonitor(window);
|
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);
|
const NSUInteger styleMask = getStyleMask(window);
|
||||||
[window->ns.object setStyleMask:styleMask];
|
[window->ns.object setStyleMask:styleMask];
|
||||||
|
// HACK: Changing the style mask can cause the first responder to be cleared
|
||||||
[window->ns.object makeFirstResponder:window->ns.view];
|
[window->ns.object makeFirstResponder:window->ns.view];
|
||||||
|
|
||||||
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)
|
if (monitor)
|
||||||
{
|
{
|
||||||
[window->ns.object setLevel:NSMainMenuWindowLevel + 1];
|
[window->ns.object setLevel:NSMainMenuWindowLevel + 1];
|
||||||
@@ -1334,6 +1425,12 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
else
|
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 &&
|
if (window->numer != GLFW_DONT_CARE &&
|
||||||
window->denom != GLFW_DONT_CARE)
|
window->denom != GLFW_DONT_CARE)
|
||||||
{
|
{
|
||||||
@@ -1361,6 +1458,9 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
|||||||
[window->ns.object setLevel:NSNormalWindowLevel];
|
[window->ns.object setLevel:NSNormalWindowLevel];
|
||||||
|
|
||||||
[window->ns.object setHasShadow:YES];
|
[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];
|
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)
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||||
{
|
{
|
||||||
[window->ns.object setStyleMask:getStyleMask(window)];
|
[window->ns.object setStyleMask:getStyleMask(window)];
|
||||||
@@ -1403,6 +1522,16 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
|||||||
[window->ns.object setLevel:NSNormalWindowLevel];
|
[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)
|
void _glfwPlatformPollEvents(void)
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
@@ -1525,14 +1654,8 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
|||||||
updateCursorImage(window);
|
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;
|
UInt32 deadKeyState = 0;
|
||||||
UniChar characters[8];
|
UniChar characters[8];
|
||||||
UniCharCount characterCount = 0;
|
UniCharCount characterCount = 0;
|
||||||
@@ -1620,7 +1743,19 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
|||||||
if (!initializeAppKit())
|
if (!initializeAppKit())
|
||||||
return GLFW_FALSE;
|
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)
|
if (!cursor->ns.object)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
@@ -1644,7 +1779,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
|||||||
updateCursorImage(window);
|
updateCursorImage(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
|
void _glfwPlatformSetClipboardString(const char* string)
|
||||||
{
|
{
|
||||||
NSArray* types = [NSArray arrayWithObjects:NSStringPboardType, nil];
|
NSArray* types = [NSArray arrayWithObjects:NSStringPboardType, nil];
|
||||||
|
|
||||||
@@ -1654,7 +1789,7 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
|
|||||||
forType:NSStringPboardType];
|
forType:NSStringPboardType];
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
const char* _glfwPlatformGetClipboardString(void)
|
||||||
{
|
{
|
||||||
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
|
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
|
||||||
|
|
||||||
@@ -1674,7 +1809,7 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(_glfw.ns.clipboardString);
|
free(_glfw.ns.clipboardString);
|
||||||
_glfw.ns.clipboardString = strdup([object UTF8String]);
|
_glfw.ns.clipboardString = _glfw_strdup([object UTF8String]);
|
||||||
|
|
||||||
return _glfw.ns.clipboardString;
|
return _glfw.ns.clipboardString;
|
||||||
}
|
}
|
||||||
|
|||||||
+60
-22
@@ -38,13 +38,30 @@
|
|||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Checks whether the desired context attributes are valid
|
||||||
|
//
|
||||||
|
// This function checks things like whether the specified client API version
|
||||||
|
// exists and whether all relevant options have supported and non-conflicting
|
||||||
|
// values
|
||||||
|
//
|
||||||
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||||
{
|
{
|
||||||
|
if (ctxconfig->share)
|
||||||
|
{
|
||||||
|
if (ctxconfig->client == GLFW_NO_API ||
|
||||||
|
ctxconfig->share->context.client == GLFW_NO_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
|
if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
|
||||||
ctxconfig->source != GLFW_EGL_CONTEXT_API)
|
ctxconfig->source != GLFW_EGL_CONTEXT_API &&
|
||||||
|
ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
"Invalid context creation API %i",
|
"Invalid context creation API 0x%08X",
|
||||||
ctxconfig->source);
|
ctxconfig->source);
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
@@ -54,7 +71,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|||||||
ctxconfig->client != GLFW_OPENGL_ES_API)
|
ctxconfig->client != GLFW_OPENGL_ES_API)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
"Invalid client API %i",
|
"Invalid client API 0x%08X",
|
||||||
ctxconfig->client);
|
ctxconfig->client);
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
@@ -84,7 +101,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|||||||
ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE)
|
ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
"Invalid OpenGL profile %i",
|
"Invalid OpenGL profile 0x%08X",
|
||||||
ctxconfig->profile);
|
ctxconfig->profile);
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
@@ -133,7 +150,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|||||||
ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET)
|
ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
"Invalid context robustness mode %i",
|
"Invalid context robustness mode 0x%08X",
|
||||||
ctxconfig->robustness);
|
ctxconfig->robustness);
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
@@ -145,7 +162,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|||||||
ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH)
|
ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
"Invalid context release behavior %i",
|
"Invalid context release behavior 0x%08X",
|
||||||
ctxconfig->release);
|
ctxconfig->release);
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
@@ -154,6 +171,8 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Chooses the framebuffer config that best matches the desired one
|
||||||
|
//
|
||||||
const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
|
const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
|
||||||
const _GLFWfbconfig* alternatives,
|
const _GLFWfbconfig* alternatives,
|
||||||
unsigned int count)
|
unsigned int count)
|
||||||
@@ -207,6 +226,9 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
|
|||||||
// not important to us here, so we count them as one
|
// not important to us here, so we count them as one
|
||||||
missing++;
|
missing++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (desired->transparent != current->transparent)
|
||||||
|
missing++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// These polynomials make many small channel size differences matter
|
// These polynomials make many small channel size differences matter
|
||||||
@@ -317,10 +339,13 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
|
|||||||
return closest;
|
return closest;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
// Retrieves the attributes of the current context
|
||||||
|
//
|
||||||
|
GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
_GLFWwindow* window;
|
_GLFWwindow* previous;
|
||||||
const char* version;
|
const char* version;
|
||||||
const char* prefixes[] =
|
const char* prefixes[] =
|
||||||
{
|
{
|
||||||
@@ -330,11 +355,12 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
window = _glfwPlatformGetCurrentContext();
|
|
||||||
|
|
||||||
window->context.source = ctxconfig->source;
|
window->context.source = ctxconfig->source;
|
||||||
window->context.client = GLFW_OPENGL_API;
|
window->context.client = GLFW_OPENGL_API;
|
||||||
|
|
||||||
|
previous = _glfwPlatformGetTls(&_glfw.contextSlot);;
|
||||||
|
glfwMakeContextCurrent((GLFWwindow*) window);
|
||||||
|
|
||||||
window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
|
window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
|
||||||
window->context.getProcAddress("glGetIntegerv");
|
window->context.getProcAddress("glGetIntegerv");
|
||||||
window->context.GetString = (PFNGLGETSTRINGPROC)
|
window->context.GetString = (PFNGLGETSTRINGPROC)
|
||||||
@@ -342,6 +368,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
|||||||
if (!window->context.GetIntegerv || !window->context.GetString)
|
if (!window->context.GetIntegerv || !window->context.GetString)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
|
||||||
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,6 +386,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
|||||||
"OpenGL ES version string retrieval is broken");
|
"OpenGL ES version string retrieval is broken");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,6 +418,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
|||||||
"No version found in OpenGL ES version string");
|
"No version found in OpenGL ES version string");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -419,6 +448,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
|||||||
window->context.major, window->context.minor);
|
window->context.major, window->context.minor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,6 +464,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Entry point retrieval is broken");
|
"Entry point retrieval is broken");
|
||||||
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -540,9 +571,12 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
|||||||
window->context.swapBuffers(window);
|
window->context.swapBuffers(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Searches an extension string for the specified extension
|
||||||
|
//
|
||||||
GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions)
|
GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions)
|
||||||
{
|
{
|
||||||
const char* start = extensions;
|
const char* start = extensions;
|
||||||
@@ -577,13 +611,14 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions
|
|||||||
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
|
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
_GLFWwindow* previous = _glfwPlatformGetCurrentContext();
|
_GLFWwindow* previous = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
if (window && window->context.client == GLFW_NO_API)
|
if (window && window->context.client == GLFW_NO_API)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT,
|
||||||
|
"Cannot make current with a window that has no OpenGL or OpenGL ES context");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -600,7 +635,7 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
|
|||||||
GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
|
GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
return (GLFWwindow*) _glfwPlatformGetCurrentContext();
|
return _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
|
GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
|
||||||
@@ -612,7 +647,8 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
|
|||||||
|
|
||||||
if (window->context.client == GLFW_NO_API)
|
if (window->context.client == GLFW_NO_API)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT,
|
||||||
|
"Cannot swap buffers of a window that has no OpenGL or OpenGL ES context");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -625,10 +661,11 @@ GLFWAPI void glfwSwapInterval(int interval)
|
|||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
window = _glfwPlatformGetCurrentContext();
|
window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
_glfwInputError(GLFW_NO_CURRENT_CONTEXT,
|
||||||
|
"Cannot set swap interval without a current OpenGL or OpenGL ES context");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,21 +675,21 @@ GLFWAPI void glfwSwapInterval(int interval)
|
|||||||
GLFWAPI int glfwExtensionSupported(const char* extension)
|
GLFWAPI int glfwExtensionSupported(const char* extension)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window;
|
_GLFWwindow* window;
|
||||||
|
|
||||||
assert(extension != NULL);
|
assert(extension != NULL);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
|
|
||||||
window = _glfwPlatformGetCurrentContext();
|
window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
_glfwInputError(GLFW_NO_CURRENT_CONTEXT,
|
||||||
|
"Cannot query extension without a current OpenGL or OpenGL ES context");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*extension == '\0')
|
if (*extension == '\0')
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_VALUE, "Extension name is empty string");
|
_glfwInputError(GLFW_INVALID_VALUE, "Extension name cannot be an empty string");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -708,10 +745,11 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
|
|||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
window = _glfwPlatformGetCurrentContext();
|
window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
_glfwInputError(GLFW_NO_CURRENT_CONTEXT,
|
||||||
|
"Cannot query entry point without a current OpenGL or OpenGL ES context");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+78
-41
@@ -113,7 +113,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
|||||||
_GLFWfbconfig* u = usableConfigs + usableCount;
|
_GLFWfbconfig* u = usableConfigs + usableCount;
|
||||||
|
|
||||||
// Only consider RGB(A) EGLConfigs
|
// Only consider RGB(A) EGLConfigs
|
||||||
if (!(getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) & EGL_RGB_BUFFER))
|
if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Only consider window EGLConfigs
|
// Only consider window EGLConfigs
|
||||||
@@ -121,9 +121,25 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
#if defined(_GLFW_X11)
|
#if defined(_GLFW_X11)
|
||||||
|
XVisualInfo vi = {0};
|
||||||
|
|
||||||
// Only consider EGLConfigs with associated Visuals
|
// Only consider EGLConfigs with associated Visuals
|
||||||
if (!getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID))
|
vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
|
||||||
|
if (!vi.visualid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (desired->transparent)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
XVisualInfo* vis = XGetVisualInfo(_glfw.x11.display,
|
||||||
|
VisualIDMask, &vi,
|
||||||
|
&count);
|
||||||
|
if (vis)
|
||||||
|
{
|
||||||
|
u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
|
||||||
|
XFree(vis);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif // _GLFW_X11
|
#endif // _GLFW_X11
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||||
@@ -199,12 +215,12 @@ static void makeContextCurrentEGL(_GLFWwindow* window)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwPlatformSetCurrentContext(window);
|
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void swapBuffersEGL(_GLFWwindow* window)
|
static void swapBuffersEGL(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window != _glfwPlatformGetCurrentContext())
|
if (window != _glfwPlatformGetTls(&_glfw.contextSlot))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"EGL: The context must be current on the calling thread when swapping buffers");
|
"EGL: The context must be current on the calling thread when swapping buffers");
|
||||||
@@ -233,7 +249,7 @@ static int extensionSupportedEGL(const char* extension)
|
|||||||
|
|
||||||
static GLFWglproc getProcAddressEGL(const char* procname)
|
static GLFWglproc getProcAddressEGL(const char* procname)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
|
|
||||||
if (window->context.egl.client)
|
if (window->context.egl.client)
|
||||||
{
|
{
|
||||||
@@ -286,11 +302,15 @@ GLFWbool _glfwInitEGL(void)
|
|||||||
int i;
|
int i;
|
||||||
const char* sonames[] =
|
const char* sonames[] =
|
||||||
{
|
{
|
||||||
#if defined(_GLFW_WIN32)
|
#if defined(_GLFW_EGL_LIBRARY)
|
||||||
|
_GLFW_EGL_LIBRARY,
|
||||||
|
#elif defined(_GLFW_WIN32)
|
||||||
"libEGL.dll",
|
"libEGL.dll",
|
||||||
"EGL.dll",
|
"EGL.dll",
|
||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
"libEGL.dylib",
|
"libEGL.dylib",
|
||||||
|
#elif defined(__CYGWIN__)
|
||||||
|
"libEGL-1.so",
|
||||||
#else
|
#else
|
||||||
"libEGL.so.1",
|
"libEGL.so.1",
|
||||||
#endif
|
#endif
|
||||||
@@ -401,6 +421,8 @@ GLFWbool _glfwInitEGL(void)
|
|||||||
extensionSupportedEGL("EGL_KHR_gl_colorspace");
|
extensionSupportedEGL("EGL_KHR_gl_colorspace");
|
||||||
_glfw.egl.KHR_get_all_proc_addresses =
|
_glfw.egl.KHR_get_all_proc_addresses =
|
||||||
extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
|
extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
|
||||||
|
_glfw.egl.KHR_context_flush_control =
|
||||||
|
extensionSupportedEGL("EGL_KHR_context_flush_control");
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
@@ -422,11 +444,11 @@ void _glfwTerminateEGL(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define setEGLattrib(attribName, attribValue) \
|
#define setAttrib(a, v) \
|
||||||
{ \
|
{ \
|
||||||
attribs[index++] = attribName; \
|
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||||
attribs[index++] = attribValue; \
|
attribs[index++] = a; \
|
||||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
attribs[index++] = v; \
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the OpenGL or OpenGL ES context
|
// Create the OpenGL or OpenGL ES context
|
||||||
@@ -438,6 +460,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
EGLint attribs[40];
|
EGLint attribs[40];
|
||||||
EGLConfig config;
|
EGLConfig config;
|
||||||
EGLContext share = NULL;
|
EGLContext share = NULL;
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
if (!_glfw.egl.display)
|
if (!_glfw.egl.display)
|
||||||
{
|
{
|
||||||
@@ -478,7 +501,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (_glfw.egl.KHR_create_context)
|
if (_glfw.egl.KHR_create_context)
|
||||||
{
|
{
|
||||||
int index = 0, mask = 0, flags = 0;
|
int mask = 0, flags = 0;
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||||
{
|
{
|
||||||
@@ -489,12 +512,6 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
|
mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
|
||||||
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
||||||
mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
|
mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
|
||||||
|
|
||||||
if (_glfw.egl.KHR_create_context_no_error)
|
|
||||||
{
|
|
||||||
if (ctxconfig->noerror)
|
|
||||||
flags |= EGL_CONTEXT_OPENGL_NO_ERROR_KHR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig->debug)
|
if (ctxconfig->debug)
|
||||||
@@ -504,44 +521,57 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||||
{
|
{
|
||||||
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||||
EGL_NO_RESET_NOTIFICATION_KHR);
|
EGL_NO_RESET_NOTIFICATION_KHR);
|
||||||
}
|
}
|
||||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||||
{
|
{
|
||||||
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||||
EGL_LOSE_CONTEXT_ON_RESET_KHR);
|
EGL_LOSE_CONTEXT_ON_RESET_KHR);
|
||||||
}
|
}
|
||||||
|
|
||||||
flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
|
flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->noerror)
|
||||||
|
{
|
||||||
|
if (_glfw.egl.KHR_create_context_no_error)
|
||||||
|
setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||||
{
|
{
|
||||||
setEGLattrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
|
setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
|
||||||
setEGLattrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
|
setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mask)
|
if (mask)
|
||||||
setEGLattrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
|
setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
|
||||||
|
|
||||||
if (flags)
|
if (flags)
|
||||||
setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags);
|
setAttrib(EGL_CONTEXT_FLAGS_KHR, flags);
|
||||||
|
|
||||||
setEGLattrib(EGL_NONE, EGL_NONE);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||||
setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
|
setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
|
||||||
|
|
||||||
setEGLattrib(EGL_NONE, EGL_NONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Context release behaviors (GL_KHR_context_flush_control) are not yet
|
if (_glfw.egl.KHR_context_flush_control)
|
||||||
// supported on EGL but are not a hard constraint, so ignore and continue
|
{
|
||||||
|
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||||
|
{
|
||||||
|
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||||
|
EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
|
||||||
|
}
|
||||||
|
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||||
|
{
|
||||||
|
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||||
|
EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setAttrib(EGL_NONE, EGL_NONE);
|
||||||
|
|
||||||
window->context.egl.handle = eglCreateContext(_glfw.egl.display,
|
window->context.egl.handle = eglCreateContext(_glfw.egl.display,
|
||||||
config, share, attribs);
|
config, share, attribs);
|
||||||
@@ -561,12 +591,10 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
if (fbconfig->sRGB)
|
if (fbconfig->sRGB)
|
||||||
{
|
{
|
||||||
if (_glfw.egl.KHR_gl_colorspace)
|
if (_glfw.egl.KHR_gl_colorspace)
|
||||||
{
|
setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
||||||
setEGLattrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setEGLattrib(EGL_NONE, EGL_NONE);
|
setAttrib(EGL_NONE, EGL_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
window->context.egl.surface =
|
window->context.egl.surface =
|
||||||
@@ -591,7 +619,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
const char** sonames;
|
const char** sonames;
|
||||||
const char* es1sonames[] =
|
const char* es1sonames[] =
|
||||||
{
|
{
|
||||||
#if defined(_GLFW_WIN32)
|
#if defined(_GLFW_GLESV1_LIBRARY)
|
||||||
|
_GLFW_GLESV1_LIBRARY,
|
||||||
|
#elif defined(_GLFW_WIN32)
|
||||||
"GLESv1_CM.dll",
|
"GLESv1_CM.dll",
|
||||||
"libGLES_CM.dll",
|
"libGLES_CM.dll",
|
||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
@@ -604,11 +634,15 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
};
|
};
|
||||||
const char* es2sonames[] =
|
const char* es2sonames[] =
|
||||||
{
|
{
|
||||||
#if defined(_GLFW_WIN32)
|
#if defined(_GLFW_GLESV2_LIBRARY)
|
||||||
|
_GLFW_GLESV2_LIBRARY,
|
||||||
|
#elif defined(_GLFW_WIN32)
|
||||||
"GLESv2.dll",
|
"GLESv2.dll",
|
||||||
"libGLESv2.dll",
|
"libGLESv2.dll",
|
||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
"libGLESv2.dylib",
|
"libGLESv2.dylib",
|
||||||
|
#elif defined(__CYGWIN__)
|
||||||
|
"libGLESv2-2.so",
|
||||||
#else
|
#else
|
||||||
"libGLESv2.so.2",
|
"libGLESv2.so.2",
|
||||||
#endif
|
#endif
|
||||||
@@ -616,7 +650,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
};
|
};
|
||||||
const char* glsonames[] =
|
const char* glsonames[] =
|
||||||
{
|
{
|
||||||
#if defined(_GLFW_WIN32)
|
#if defined(_GLFW_OPENGL_LIBRARY)
|
||||||
|
_GLFW_OPENGL_LIBRARY,
|
||||||
|
#elif defined(_GLFW_WIN32)
|
||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
#else
|
#else
|
||||||
"libGL.so.1",
|
"libGL.so.1",
|
||||||
@@ -664,12 +700,13 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef setEGLattrib
|
#undef setAttrib
|
||||||
|
|
||||||
// Returns the Visual and depth of the chosen EGLConfig
|
// Returns the Visual and depth of the chosen EGLConfig
|
||||||
//
|
//
|
||||||
#if defined(_GLFW_X11)
|
#if defined(_GLFW_X11)
|
||||||
GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig,
|
GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig,
|
const _GLFWfbconfig* fbconfig,
|
||||||
Visual** visual, int* depth)
|
Visual** visual, int* depth)
|
||||||
{
|
{
|
||||||
|
|||||||
+10
-5
@@ -25,15 +25,16 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _glfw3_egl_context_h_
|
|
||||||
#define _glfw3_egl_context_h_
|
|
||||||
|
|
||||||
#if defined(_GLFW_USE_EGLPLATFORM_H)
|
#if defined(_GLFW_USE_EGLPLATFORM_H)
|
||||||
#include <EGL/eglplatform.h>
|
#include <EGL/eglplatform.h>
|
||||||
#elif defined(_GLFW_WIN32)
|
#elif defined(_GLFW_WIN32)
|
||||||
#define EGLAPIENTRY __stdcall
|
#define EGLAPIENTRY __stdcall
|
||||||
typedef HDC EGLNativeDisplayType;
|
typedef HDC EGLNativeDisplayType;
|
||||||
typedef HWND EGLNativeWindowType;
|
typedef HWND EGLNativeWindowType;
|
||||||
|
#elif defined(_GLFW_COCOA)
|
||||||
|
#define EGLAPIENTRY
|
||||||
|
typedef void* EGLNativeDisplayType;
|
||||||
|
typedef id EGLNativeWindowType;
|
||||||
#elif defined(_GLFW_X11)
|
#elif defined(_GLFW_X11)
|
||||||
#define EGLAPIENTRY
|
#define EGLAPIENTRY
|
||||||
typedef Display* EGLNativeDisplayType;
|
typedef Display* EGLNativeDisplayType;
|
||||||
@@ -106,6 +107,9 @@ typedef MirEGLNativeWindowType EGLNativeWindowType;
|
|||||||
#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3
|
#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3
|
||||||
#define EGL_GL_COLORSPACE_KHR 0x309d
|
#define EGL_GL_COLORSPACE_KHR 0x309d
|
||||||
#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
|
#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
|
||||||
|
#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
|
||||||
|
#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
|
||||||
|
#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
|
||||||
|
|
||||||
typedef int EGLint;
|
typedef int EGLint;
|
||||||
typedef unsigned int EGLBoolean;
|
typedef unsigned int EGLBoolean;
|
||||||
@@ -177,6 +181,7 @@ typedef struct _GLFWlibraryEGL
|
|||||||
GLFWbool KHR_create_context_no_error;
|
GLFWbool KHR_create_context_no_error;
|
||||||
GLFWbool KHR_gl_colorspace;
|
GLFWbool KHR_gl_colorspace;
|
||||||
GLFWbool KHR_get_all_proc_addresses;
|
GLFWbool KHR_get_all_proc_addresses;
|
||||||
|
GLFWbool KHR_context_flush_control;
|
||||||
|
|
||||||
void* handle;
|
void* handle;
|
||||||
|
|
||||||
@@ -206,9 +211,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig);
|
const _GLFWfbconfig* fbconfig);
|
||||||
#if defined(_GLFW_X11)
|
#if defined(_GLFW_X11)
|
||||||
GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig,
|
GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig,
|
const _GLFWfbconfig* fbconfig,
|
||||||
Visual** visual, int* depth);
|
Visual** visual, int* depth);
|
||||||
#endif /*_GLFW_X11*/
|
#endif /*_GLFW_X11*/
|
||||||
|
|
||||||
#endif // _glfw3_egl_context_h_
|
|
||||||
|
|||||||
@@ -55,8 +55,6 @@
|
|||||||
// Define this to 1 to force use of high-performance GPU on hybrid systems
|
// Define this to 1 to force use of high-performance GPU on hybrid systems
|
||||||
#cmakedefine _GLFW_USE_HYBRID_HPG
|
#cmakedefine _GLFW_USE_HYBRID_HPG
|
||||||
|
|
||||||
// Define this to 1 if glfwInit should change the current directory
|
// Define this to 1 if xkbcommon supports the compose key
|
||||||
#cmakedefine _GLFW_USE_CHDIR
|
#cmakedefine HAVE_XKBCOMMON_COMPOSE_H
|
||||||
// Define this to 1 if glfwCreateWindow should populate the menu bar
|
|
||||||
#cmakedefine _GLFW_USE_MENUBAR
|
|
||||||
|
|
||||||
|
|||||||
+62
-41
@@ -47,7 +47,8 @@ static int getGLXFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
|
|||||||
|
|
||||||
// Return the GLXFBConfig most closely matching the specified hints
|
// 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;
|
GLXFBConfig* nativeConfigs;
|
||||||
_GLFWfbconfig* usableConfigs;
|
_GLFWfbconfig* usableConfigs;
|
||||||
@@ -59,12 +60,12 @@ static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* res
|
|||||||
// HACK: This is a (hopefully temporary) workaround for Chromium
|
// HACK: This is a (hopefully temporary) workaround for Chromium
|
||||||
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
|
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
|
||||||
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
|
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
|
||||||
if (strcmp(vendor, "Chromium") == 0)
|
if (vendor && strcmp(vendor, "Chromium") == 0)
|
||||||
trustWindowBit = GLFW_FALSE;
|
trustWindowBit = GLFW_FALSE;
|
||||||
|
|
||||||
nativeConfigs =
|
nativeConfigs =
|
||||||
glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
|
glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
|
||||||
if (!nativeCount)
|
if (!nativeConfigs || !nativeCount)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
|
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
@@ -89,6 +90,16 @@ static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* res
|
|||||||
continue;
|
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->redBits = getGLXFBConfigAttrib(n, GLX_RED_SIZE);
|
||||||
u->greenBits = getGLXFBConfigAttrib(n, GLX_GREEN_SIZE);
|
u->greenBits = getGLXFBConfigAttrib(n, GLX_GREEN_SIZE);
|
||||||
u->blueBits = getGLXFBConfigAttrib(n, GLX_BLUE_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)
|
static void swapBuffersGLX(_GLFWwindow* window)
|
||||||
@@ -175,7 +186,7 @@ static void swapBuffersGLX(_GLFWwindow* window)
|
|||||||
|
|
||||||
static void swapIntervalGLX(int interval)
|
static void swapIntervalGLX(int interval)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
|
|
||||||
if (_glfw.glx.EXT_swap_control)
|
if (_glfw.glx.EXT_swap_control)
|
||||||
{
|
{
|
||||||
@@ -212,7 +223,7 @@ static GLFWglproc getProcAddressGLX(const char* procname)
|
|||||||
else if (_glfw.glx.GetProcAddressARB)
|
else if (_glfw.glx.GetProcAddressARB)
|
||||||
return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
|
return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
|
||||||
else
|
else
|
||||||
return dlsym(_glfw.glx.handle, procname);
|
return _glfw_dlsym(_glfw.glx.handle, procname);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy the OpenGL context
|
// Destroy the OpenGL context
|
||||||
@@ -244,7 +255,9 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
int i;
|
int i;
|
||||||
const char* sonames[] =
|
const char* sonames[] =
|
||||||
{
|
{
|
||||||
#if defined(__CYGWIN__)
|
#if defined(_GLFW_GLX_LIBRARY)
|
||||||
|
_GLFW_GLX_LIBRARY,
|
||||||
|
#elif defined(__CYGWIN__)
|
||||||
"libGL-1.so",
|
"libGL-1.so",
|
||||||
#else
|
#else
|
||||||
"libGL.so.1",
|
"libGL.so.1",
|
||||||
@@ -258,7 +271,7 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
|
|
||||||
for (i = 0; sonames[i]; i++)
|
for (i = 0; sonames[i]; i++)
|
||||||
{
|
{
|
||||||
_glfw.glx.handle = dlopen(sonames[i], RTLD_LAZY | RTLD_GLOBAL);
|
_glfw.glx.handle = _glfw_dlopen(sonames[i]);
|
||||||
if (_glfw.glx.handle)
|
if (_glfw.glx.handle)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -270,35 +283,35 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
_glfw.glx.GetFBConfigs =
|
_glfw.glx.GetFBConfigs =
|
||||||
dlsym(_glfw.glx.handle, "glXGetFBConfigs");
|
_glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigs");
|
||||||
_glfw.glx.GetFBConfigAttrib =
|
_glfw.glx.GetFBConfigAttrib =
|
||||||
dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib");
|
_glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib");
|
||||||
_glfw.glx.GetClientString =
|
_glfw.glx.GetClientString =
|
||||||
dlsym(_glfw.glx.handle, "glXGetClientString");
|
_glfw_dlsym(_glfw.glx.handle, "glXGetClientString");
|
||||||
_glfw.glx.QueryExtension =
|
_glfw.glx.QueryExtension =
|
||||||
dlsym(_glfw.glx.handle, "glXQueryExtension");
|
_glfw_dlsym(_glfw.glx.handle, "glXQueryExtension");
|
||||||
_glfw.glx.QueryVersion =
|
_glfw.glx.QueryVersion =
|
||||||
dlsym(_glfw.glx.handle, "glXQueryVersion");
|
_glfw_dlsym(_glfw.glx.handle, "glXQueryVersion");
|
||||||
_glfw.glx.DestroyContext =
|
_glfw.glx.DestroyContext =
|
||||||
dlsym(_glfw.glx.handle, "glXDestroyContext");
|
_glfw_dlsym(_glfw.glx.handle, "glXDestroyContext");
|
||||||
_glfw.glx.MakeCurrent =
|
_glfw.glx.MakeCurrent =
|
||||||
dlsym(_glfw.glx.handle, "glXMakeCurrent");
|
_glfw_dlsym(_glfw.glx.handle, "glXMakeCurrent");
|
||||||
_glfw.glx.SwapBuffers =
|
_glfw.glx.SwapBuffers =
|
||||||
dlsym(_glfw.glx.handle, "glXSwapBuffers");
|
_glfw_dlsym(_glfw.glx.handle, "glXSwapBuffers");
|
||||||
_glfw.glx.QueryExtensionsString =
|
_glfw.glx.QueryExtensionsString =
|
||||||
dlsym(_glfw.glx.handle, "glXQueryExtensionsString");
|
_glfw_dlsym(_glfw.glx.handle, "glXQueryExtensionsString");
|
||||||
_glfw.glx.CreateNewContext =
|
_glfw.glx.CreateNewContext =
|
||||||
dlsym(_glfw.glx.handle, "glXCreateNewContext");
|
_glfw_dlsym(_glfw.glx.handle, "glXCreateNewContext");
|
||||||
_glfw.glx.CreateWindow =
|
_glfw.glx.CreateWindow =
|
||||||
dlsym(_glfw.glx.handle, "glXCreateWindow");
|
_glfw_dlsym(_glfw.glx.handle, "glXCreateWindow");
|
||||||
_glfw.glx.DestroyWindow =
|
_glfw.glx.DestroyWindow =
|
||||||
dlsym(_glfw.glx.handle, "glXDestroyWindow");
|
_glfw_dlsym(_glfw.glx.handle, "glXDestroyWindow");
|
||||||
_glfw.glx.GetProcAddress =
|
_glfw.glx.GetProcAddress =
|
||||||
dlsym(_glfw.glx.handle, "glXGetProcAddress");
|
_glfw_dlsym(_glfw.glx.handle, "glXGetProcAddress");
|
||||||
_glfw.glx.GetProcAddressARB =
|
_glfw.glx.GetProcAddressARB =
|
||||||
dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
|
_glfw_dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
|
||||||
_glfw.glx.GetVisualFromFBConfig =
|
_glfw.glx.GetVisualFromFBConfig =
|
||||||
dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
|
_glfw_dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
|
||||||
|
|
||||||
if (!_glfw.glx.GetFBConfigs ||
|
if (!_glfw.glx.GetFBConfigs ||
|
||||||
!_glfw.glx.GetFBConfigAttrib ||
|
!_glfw.glx.GetFBConfigAttrib ||
|
||||||
@@ -397,6 +410,9 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))
|
if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))
|
||||||
_glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE;
|
_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"))
|
if (extensionSupportedGLX("GLX_ARB_context_flush_control"))
|
||||||
_glfw.glx.ARB_context_flush_control = GLFW_TRUE;
|
_glfw.glx.ARB_context_flush_control = GLFW_TRUE;
|
||||||
|
|
||||||
@@ -412,16 +428,16 @@ void _glfwTerminateGLX(void)
|
|||||||
|
|
||||||
if (_glfw.glx.handle)
|
if (_glfw.glx.handle)
|
||||||
{
|
{
|
||||||
dlclose(_glfw.glx.handle);
|
_glfw_dlclose(_glfw.glx.handle);
|
||||||
_glfw.glx.handle = NULL;
|
_glfw.glx.handle = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define setGLXattrib(attribName, attribValue) \
|
#define setAttrib(a, v) \
|
||||||
{ \
|
{ \
|
||||||
attribs[index++] = attribName; \
|
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||||
attribs[index++] = attribValue; \
|
attribs[index++] = a; \
|
||||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
attribs[index++] = v; \
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the OpenGL or OpenGL ES context
|
// Create the OpenGL or OpenGL ES context
|
||||||
@@ -498,8 +514,6 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (ctxconfig->debug)
|
if (ctxconfig->debug)
|
||||||
flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
|
flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
|
||||||
if (ctxconfig->noerror)
|
|
||||||
flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;
|
|
||||||
|
|
||||||
if (ctxconfig->robustness)
|
if (ctxconfig->robustness)
|
||||||
{
|
{
|
||||||
@@ -507,12 +521,12 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||||
{
|
{
|
||||||
setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||||
GLX_NO_RESET_NOTIFICATION_ARB);
|
GLX_NO_RESET_NOTIFICATION_ARB);
|
||||||
}
|
}
|
||||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||||
{
|
{
|
||||||
setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||||
GLX_LOSE_CONTEXT_ON_RESET_ARB);
|
GLX_LOSE_CONTEXT_ON_RESET_ARB);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,33 +540,39 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||||
{
|
{
|
||||||
setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||||
GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||||
}
|
}
|
||||||
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||||
{
|
{
|
||||||
setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||||
GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_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
|
// NOTE: Only request an explicitly versioned context when necessary, as
|
||||||
// explicitly requesting version 1.0 does not always return the
|
// explicitly requesting version 1.0 does not always return the
|
||||||
// highest version supported by the driver
|
// highest version supported by the driver
|
||||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||||
{
|
{
|
||||||
setGLXattrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
setAttrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||||
setGLXattrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
setAttrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mask)
|
if (mask)
|
||||||
setGLXattrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
|
setAttrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||||
|
|
||||||
if (flags)
|
if (flags)
|
||||||
setGLXattrib(GLX_CONTEXT_FLAGS_ARB, flags);
|
setAttrib(GLX_CONTEXT_FLAGS_ARB, flags);
|
||||||
|
|
||||||
setGLXattrib(None, None);
|
setAttrib(None, None);
|
||||||
|
|
||||||
window->context.glx.handle =
|
window->context.glx.handle =
|
||||||
_glfw.glx.CreateContextAttribsARB(_glfw.x11.display,
|
_glfw.glx.CreateContextAttribsARB(_glfw.x11.display,
|
||||||
@@ -609,11 +629,12 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef setGLXattrib
|
#undef setAttrib
|
||||||
|
|
||||||
// Returns the Visual and depth of the chosen GLXFBConfig
|
// 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,
|
const _GLFWfbconfig* fbconfig,
|
||||||
Visual** visual, int* depth)
|
Visual** visual, int* depth)
|
||||||
{
|
{
|
||||||
|
|||||||
+4
-6
@@ -25,9 +25,6 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _glfw3_glx_context_h_
|
|
||||||
#define _glfw3_glx_context_h_
|
|
||||||
|
|
||||||
#define GLX_VENDOR 1
|
#define GLX_VENDOR 1
|
||||||
#define GLX_RGBA_BIT 0x00000001
|
#define GLX_RGBA_BIT 0x00000001
|
||||||
#define GLX_WINDOW_BIT 0x00000001
|
#define GLX_WINDOW_BIT 0x00000001
|
||||||
@@ -67,6 +64,7 @@
|
|||||||
#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
|
#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
|
||||||
#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
|
#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
|
||||||
#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
|
#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
|
||||||
|
#define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
|
||||||
|
|
||||||
typedef XID GLXWindow;
|
typedef XID GLXWindow;
|
||||||
typedef XID GLXDrawable;
|
typedef XID GLXDrawable;
|
||||||
@@ -165,19 +163,19 @@ typedef struct _GLFWlibraryGLX
|
|||||||
GLFWbool ARB_create_context_profile;
|
GLFWbool ARB_create_context_profile;
|
||||||
GLFWbool ARB_create_context_robustness;
|
GLFWbool ARB_create_context_robustness;
|
||||||
GLFWbool EXT_create_context_es2_profile;
|
GLFWbool EXT_create_context_es2_profile;
|
||||||
|
GLFWbool ARB_create_context_no_error;
|
||||||
GLFWbool ARB_context_flush_control;
|
GLFWbool ARB_context_flush_control;
|
||||||
|
|
||||||
} _GLFWlibraryGLX;
|
} _GLFWlibraryGLX;
|
||||||
|
|
||||||
|
|
||||||
GLFWbool _glfwInitGLX(void);
|
GLFWbool _glfwInitGLX(void);
|
||||||
void _glfwTerminateGLX(void);
|
void _glfwTerminateGLX(void);
|
||||||
GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig);
|
const _GLFWfbconfig* fbconfig);
|
||||||
void _glfwDestroyContextGLX(_GLFWwindow* window);
|
void _glfwDestroyContextGLX(_GLFWwindow* window);
|
||||||
GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig,
|
GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig,
|
const _GLFWfbconfig* fbconfig,
|
||||||
Visual** visual, int* depth);
|
Visual** visual, int* depth);
|
||||||
|
|
||||||
#endif // _glfw3_glx_context_h_
|
|
||||||
|
|||||||
+206
-84
@@ -26,33 +26,42 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "mappings.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
// The three global variables below comprise all global data in GLFW.
|
// The global variables below comprise all mutable global data in GLFW
|
||||||
// Any other global variable is a bug.
|
//
|
||||||
|
// Any other global variable is a bug
|
||||||
|
|
||||||
// Global state shared between compilation units of GLFW
|
// Global state shared between compilation units of GLFW
|
||||||
// These are documented in internal.h
|
|
||||||
//
|
//
|
||||||
GLFWbool _glfwInitialized = GLFW_FALSE;
|
_GLFWlibrary _glfw = { GLFW_FALSE };
|
||||||
_GLFWlibrary _glfw;
|
|
||||||
|
|
||||||
// This is outside of _glfw so it can be initialized and usable before
|
// These are outside of _glfw so they can be used before initialization and
|
||||||
// glfwInit is called, which lets that function report errors
|
// after termination
|
||||||
//
|
//
|
||||||
static GLFWerrorfun _glfwErrorCallback = NULL;
|
static _GLFWerror _glfwMainThreadError;
|
||||||
|
static GLFWerrorfun _glfwErrorCallback;
|
||||||
|
static _GLFWinitconfig _glfwInitHints =
|
||||||
|
{
|
||||||
|
GLFW_TRUE, // hat buttons
|
||||||
|
{
|
||||||
|
GLFW_TRUE, // macOS menu bar
|
||||||
|
GLFW_TRUE // macOS bundle chdir
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Returns a generic string representation of the specified error
|
// 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:
|
case GLFW_NOT_INITIALIZED:
|
||||||
return "The GLFW library is not initialized";
|
return "The GLFW library is not initialized";
|
||||||
@@ -69,7 +78,7 @@ static const char* getErrorString(int error)
|
|||||||
case GLFW_VERSION_UNAVAILABLE:
|
case GLFW_VERSION_UNAVAILABLE:
|
||||||
return "The requested API version is unavailable";
|
return "The requested API version is unavailable";
|
||||||
case GLFW_PLATFORM_ERROR:
|
case GLFW_PLATFORM_ERROR:
|
||||||
return "A platform-specific error occurred";
|
return "An undocumented platform-specific error occurred";
|
||||||
case GLFW_FORMAT_UNAVAILABLE:
|
case GLFW_FORMAT_UNAVAILABLE:
|
||||||
return "The requested format is unavailable";
|
return "The requested format is unavailable";
|
||||||
case GLFW_NO_WINDOW_CONTEXT:
|
case GLFW_NO_WINDOW_CONTEXT:
|
||||||
@@ -79,75 +88,12 @@ static const char* getErrorString(int error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Terminate the library
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//
|
||||||
////// GLFW event API //////
|
static void terminate(void)
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void _glfwInputError(int error, const char* format, ...)
|
|
||||||
{
|
|
||||||
if (_glfwErrorCallback)
|
|
||||||
{
|
|
||||||
char buffer[8192];
|
|
||||||
const char* description;
|
|
||||||
|
|
||||||
if (format)
|
|
||||||
{
|
|
||||||
int count;
|
|
||||||
va_list vl;
|
|
||||||
|
|
||||||
va_start(vl, format);
|
|
||||||
count = vsnprintf(buffer, sizeof(buffer), format, vl);
|
|
||||||
va_end(vl);
|
|
||||||
|
|
||||||
if (count < 0)
|
|
||||||
buffer[sizeof(buffer) - 1] = '\0';
|
|
||||||
|
|
||||||
description = buffer;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
description = getErrorString(error);
|
|
||||||
|
|
||||||
_glfwErrorCallback(error, description);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW public API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWAPI int glfwInit(void)
|
|
||||||
{
|
|
||||||
if (_glfwInitialized)
|
|
||||||
return GLFW_TRUE;
|
|
||||||
|
|
||||||
memset(&_glfw, 0, sizeof(_glfw));
|
|
||||||
|
|
||||||
if (!_glfwPlatformInit())
|
|
||||||
{
|
|
||||||
_glfwPlatformTerminate();
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
|
|
||||||
_glfwInitialized = GLFW_TRUE;
|
|
||||||
|
|
||||||
_glfw.timerOffset = _glfwPlatformGetTimerValue();
|
|
||||||
|
|
||||||
// Not all window hints have zero as their default value
|
|
||||||
glfwDefaultWindowHints();
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwTerminate(void)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!_glfwInitialized)
|
|
||||||
return;
|
|
||||||
|
|
||||||
memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
|
memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
|
||||||
|
|
||||||
while (_glfw.windowListHead)
|
while (_glfw.windowListHead)
|
||||||
@@ -161,28 +107,180 @@ GLFWAPI void glfwTerminate(void)
|
|||||||
_GLFWmonitor* monitor = _glfw.monitors[i];
|
_GLFWmonitor* monitor = _glfw.monitors[i];
|
||||||
if (monitor->originalRamp.size)
|
if (monitor->originalRamp.size)
|
||||||
_glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
|
_glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
|
||||||
|
_glfwFreeMonitor(monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwTerminateVulkan();
|
free(_glfw.monitors);
|
||||||
|
|
||||||
_glfwFreeMonitors(_glfw.monitors, _glfw.monitorCount);
|
|
||||||
_glfw.monitors = NULL;
|
_glfw.monitors = NULL;
|
||||||
_glfw.monitorCount = 0;
|
_glfw.monitorCount = 0;
|
||||||
|
|
||||||
|
free(_glfw.mappings);
|
||||||
|
_glfw.mappings = NULL;
|
||||||
|
_glfw.mappingCount = 0;
|
||||||
|
|
||||||
|
_glfwTerminateVulkan();
|
||||||
_glfwPlatformTerminate();
|
_glfwPlatformTerminate();
|
||||||
|
|
||||||
|
_glfw.initialized = GLFW_FALSE;
|
||||||
|
|
||||||
|
while (_glfw.errorListHead)
|
||||||
|
{
|
||||||
|
_GLFWerror* error = _glfw.errorListHead;
|
||||||
|
_glfw.errorListHead = error->next;
|
||||||
|
free(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwPlatformDestroyTls(&_glfw.contextSlot);
|
||||||
|
_glfwPlatformDestroyTls(&_glfw.errorSlot);
|
||||||
|
_glfwPlatformDestroyMutex(&_glfw.errorLock);
|
||||||
|
|
||||||
memset(&_glfw, 0, sizeof(_glfw));
|
memset(&_glfw, 0, sizeof(_glfw));
|
||||||
_glfwInitialized = GLFW_FALSE;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
char* _glfw_strdup(const char* source)
|
||||||
|
{
|
||||||
|
const size_t length = strlen(source);
|
||||||
|
char* result = calloc(length + 1, 1);
|
||||||
|
strcpy(result, source);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// 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)
|
GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
|
||||||
{
|
{
|
||||||
if (major != NULL)
|
if (major != NULL)
|
||||||
*major = GLFW_VERSION_MAJOR;
|
*major = GLFW_VERSION_MAJOR;
|
||||||
|
|
||||||
if (minor != NULL)
|
if (minor != NULL)
|
||||||
*minor = GLFW_VERSION_MINOR;
|
*minor = GLFW_VERSION_MINOR;
|
||||||
|
|
||||||
if (rev != NULL)
|
if (rev != NULL)
|
||||||
*rev = GLFW_VERSION_REVISION;
|
*rev = GLFW_VERSION_REVISION;
|
||||||
}
|
}
|
||||||
@@ -192,6 +290,30 @@ GLFWAPI const char* glfwGetVersionString(void)
|
|||||||
return _glfwPlatformGetVersionString();
|
return _glfwPlatformGetVersionString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwGetError(const char** description)
|
||||||
|
{
|
||||||
|
_GLFWerror* error;
|
||||||
|
int code = GLFW_NO_ERROR;
|
||||||
|
|
||||||
|
if (description)
|
||||||
|
*description = NULL;
|
||||||
|
|
||||||
|
if (_glfw.initialized)
|
||||||
|
error = _glfwPlatformGetTls(&_glfw.errorSlot);
|
||||||
|
else
|
||||||
|
error = &_glfwMainThreadError;
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
code = error->code;
|
||||||
|
error->code = GLFW_NO_ERROR;
|
||||||
|
if (description && code)
|
||||||
|
*description = error->description;
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
|
GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
|
||||||
{
|
{
|
||||||
_GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
|
_GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
|
||||||
|
|||||||
+684
-48
@@ -29,16 +29,234 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
// Internal key state used for sticky keys
|
// Internal key state used for sticky keys
|
||||||
#define _GLFW_STICK 3
|
#define _GLFW_STICK 3
|
||||||
|
|
||||||
|
// Internal constants for gamepad mapping source types
|
||||||
|
#define _GLFW_JOYSTICK_AXIS 1
|
||||||
|
#define _GLFW_JOYSTICK_BUTTON 2
|
||||||
|
#define _GLFW_JOYSTICK_HATBIT 3
|
||||||
|
|
||||||
|
// Finds a mapping based on joystick GUID
|
||||||
|
//
|
||||||
|
static _GLFWmapping* findMapping(const char* guid)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < _glfw.mappingCount; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(_glfw.mappings[i].guid, guid) == 0)
|
||||||
|
return _glfw.mappings + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks whether a gamepad mapping element is present in the hardware
|
||||||
|
//
|
||||||
|
static GLFWbool isValidElementForJoystick(const _GLFWmapelement* e,
|
||||||
|
const _GLFWjoystick* js)
|
||||||
|
{
|
||||||
|
if (e->type == _GLFW_JOYSTICK_HATBIT && (e->index >> 4) >= js->hatCount)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
else if (e->type == _GLFW_JOYSTICK_BUTTON && e->index >= js->buttonCount)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
else if (e->type == _GLFW_JOYSTICK_AXIS && e->index >= js->axisCount)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finds a mapping based on joystick GUID and verifies element indices
|
||||||
|
//
|
||||||
|
static _GLFWmapping* findValidMapping(const _GLFWjoystick* js)
|
||||||
|
{
|
||||||
|
_GLFWmapping* mapping = findMapping(js->guid);
|
||||||
|
if (mapping)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++)
|
||||||
|
{
|
||||||
|
if (!isValidElementForJoystick(mapping->buttons + i, js))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"Invalid button in gamepad mapping %s (%s)",
|
||||||
|
mapping->guid,
|
||||||
|
mapping->name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++)
|
||||||
|
{
|
||||||
|
if (!isValidElementForJoystick(mapping->axes + i, js))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"Invalid axis in gamepad mapping %s (%s)",
|
||||||
|
mapping->guid,
|
||||||
|
mapping->name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parses an SDL_GameControllerDB line and adds it to the mapping list
|
||||||
|
//
|
||||||
|
static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
|
||||||
|
{
|
||||||
|
const char* c = string;
|
||||||
|
size_t i, length;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
_GLFWmapelement* element;
|
||||||
|
} fields[] =
|
||||||
|
{
|
||||||
|
{ "platform", NULL },
|
||||||
|
{ "a", mapping->buttons + GLFW_GAMEPAD_BUTTON_A },
|
||||||
|
{ "b", mapping->buttons + GLFW_GAMEPAD_BUTTON_B },
|
||||||
|
{ "x", mapping->buttons + GLFW_GAMEPAD_BUTTON_X },
|
||||||
|
{ "y", mapping->buttons + GLFW_GAMEPAD_BUTTON_Y },
|
||||||
|
{ "back", mapping->buttons + GLFW_GAMEPAD_BUTTON_BACK },
|
||||||
|
{ "start", mapping->buttons + GLFW_GAMEPAD_BUTTON_START },
|
||||||
|
{ "guide", mapping->buttons + GLFW_GAMEPAD_BUTTON_GUIDE },
|
||||||
|
{ "leftshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_BUMPER },
|
||||||
|
{ "rightshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER },
|
||||||
|
{ "leftstick", mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_THUMB },
|
||||||
|
{ "rightstick", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_THUMB },
|
||||||
|
{ "dpup", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_UP },
|
||||||
|
{ "dpright", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_RIGHT },
|
||||||
|
{ "dpdown", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_DOWN },
|
||||||
|
{ "dpleft", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_LEFT },
|
||||||
|
{ "lefttrigger", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_TRIGGER },
|
||||||
|
{ "righttrigger", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER },
|
||||||
|
{ "leftx", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_X },
|
||||||
|
{ "lefty", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_Y },
|
||||||
|
{ "rightx", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_X },
|
||||||
|
{ "righty", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_Y }
|
||||||
|
};
|
||||||
|
|
||||||
|
length = strcspn(c, ",");
|
||||||
|
if (length != 32 || c[length] != ',')
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE, NULL);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(mapping->guid, c, length);
|
||||||
|
c += length + 1;
|
||||||
|
|
||||||
|
length = strcspn(c, ",");
|
||||||
|
if (length >= sizeof(mapping->name) || c[length] != ',')
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE, NULL);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(mapping->name, c, length);
|
||||||
|
c += length + 1;
|
||||||
|
|
||||||
|
while (*c)
|
||||||
|
{
|
||||||
|
// TODO: Implement output modifiers
|
||||||
|
if (*c == '+' || *c == '-')
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(fields) / sizeof(fields[0]); i++)
|
||||||
|
{
|
||||||
|
length = strlen(fields[i].name);
|
||||||
|
if (strncmp(c, fields[i].name, length) != 0 || c[length] != ':')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
c += length + 1;
|
||||||
|
|
||||||
|
if (fields[i].element)
|
||||||
|
{
|
||||||
|
_GLFWmapelement* e = fields[i].element;
|
||||||
|
int8_t minimum = -1;
|
||||||
|
int8_t maximum = 1;
|
||||||
|
|
||||||
|
if (*c == '+')
|
||||||
|
{
|
||||||
|
minimum = 0;
|
||||||
|
c += 1;
|
||||||
|
}
|
||||||
|
else if (*c == '-')
|
||||||
|
{
|
||||||
|
maximum = 0;
|
||||||
|
c += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*c == 'a')
|
||||||
|
e->type = _GLFW_JOYSTICK_AXIS;
|
||||||
|
else if (*c == 'b')
|
||||||
|
e->type = _GLFW_JOYSTICK_BUTTON;
|
||||||
|
else if (*c == 'h')
|
||||||
|
e->type = _GLFW_JOYSTICK_HATBIT;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (e->type == _GLFW_JOYSTICK_HATBIT)
|
||||||
|
{
|
||||||
|
const unsigned long hat = strtoul(c + 1, (char**) &c, 10);
|
||||||
|
const unsigned long bit = strtoul(c + 1, (char**) &c, 10);
|
||||||
|
e->index = (uint8_t) ((hat << 4) | bit);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
e->index = (uint8_t) strtoul(c + 1, (char**) &c, 10);
|
||||||
|
|
||||||
|
if (e->type == _GLFW_JOYSTICK_AXIS)
|
||||||
|
{
|
||||||
|
e->axisScale = 2 / (maximum - minimum);
|
||||||
|
e->axisOffset = -(maximum + minimum);
|
||||||
|
|
||||||
|
if (*c == '~')
|
||||||
|
{
|
||||||
|
e->axisScale = -e->axisScale;
|
||||||
|
e->axisOffset = -e->axisOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
length = strlen(_GLFW_PLATFORM_MAPPING_NAME);
|
||||||
|
if (strncmp(c, _GLFW_PLATFORM_MAPPING_NAME, length) != 0)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
c += strcspn(c, ",");
|
||||||
|
c += strspn(c, ",");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
if (mapping->guid[i] >= 'A' && mapping->guid[i] <= 'F')
|
||||||
|
mapping->guid[i] += 'a' - 'A';
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwPlatformUpdateGamepadGUID(mapping->guid);
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW event API //////
|
////// GLFW event API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Notifies shared code of a physical key event
|
||||||
|
//
|
||||||
void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods)
|
void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||||
{
|
{
|
||||||
if (key >= 0 && key <= GLFW_KEY_LAST)
|
if (key >= 0 && key <= GLFW_KEY_LAST)
|
||||||
@@ -60,15 +278,24 @@ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int m
|
|||||||
action = GLFW_REPEAT;
|
action = GLFW_REPEAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!window->lockKeyMods)
|
||||||
|
mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
|
||||||
|
|
||||||
if (window->callbacks.key)
|
if (window->callbacks.key)
|
||||||
window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods);
|
window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code of a Unicode codepoint input event
|
||||||
|
// The 'plain' parameter determines whether to emit a regular character event
|
||||||
|
//
|
||||||
void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain)
|
void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain)
|
||||||
{
|
{
|
||||||
if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
|
if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!window->lockKeyMods)
|
||||||
|
mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
|
||||||
|
|
||||||
if (window->callbacks.charmods)
|
if (window->callbacks.charmods)
|
||||||
window->callbacks.charmods((GLFWwindow*) window, codepoint, mods);
|
window->callbacks.charmods((GLFWwindow*) window, codepoint, mods);
|
||||||
|
|
||||||
@@ -79,18 +306,24 @@ void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code of a scroll event
|
||||||
|
//
|
||||||
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
|
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
|
||||||
{
|
{
|
||||||
if (window->callbacks.scroll)
|
if (window->callbacks.scroll)
|
||||||
window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
|
window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code of a mouse button click event
|
||||||
|
//
|
||||||
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
|
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
|
||||||
{
|
{
|
||||||
if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
|
if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Register mouse button action
|
if (!window->lockKeyMods)
|
||||||
|
mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
|
||||||
|
|
||||||
if (action == GLFW_RELEASE && window->stickyMouseButtons)
|
if (action == GLFW_RELEASE && window->stickyMouseButtons)
|
||||||
window->mouseButtons[button] = _GLFW_STICK;
|
window->mouseButtons[button] = _GLFW_STICK;
|
||||||
else
|
else
|
||||||
@@ -100,6 +333,9 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
|
|||||||
window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods);
|
window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code of a cursor motion event
|
||||||
|
// The position is specified in client-area relative screen coordinates
|
||||||
|
//
|
||||||
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
|
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
|
||||||
{
|
{
|
||||||
if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)
|
if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)
|
||||||
@@ -112,34 +348,110 @@ void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
|
|||||||
window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos);
|
window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code of a cursor enter/leave event
|
||||||
|
//
|
||||||
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
|
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
|
||||||
{
|
{
|
||||||
if (window->callbacks.cursorEnter)
|
if (window->callbacks.cursorEnter)
|
||||||
window->callbacks.cursorEnter((GLFWwindow*) window, entered);
|
window->callbacks.cursorEnter((GLFWwindow*) window, entered);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code of files or directories dropped on a window
|
||||||
|
//
|
||||||
void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
|
void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
|
||||||
{
|
{
|
||||||
if (window->callbacks.drop)
|
if (window->callbacks.drop)
|
||||||
window->callbacks.drop((GLFWwindow*) window, count, paths);
|
window->callbacks.drop((GLFWwindow*) window, count, paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwInputJoystickChange(int jid, int event)
|
// Notifies shared code of a joystick connection or disconnection
|
||||||
|
//
|
||||||
|
void _glfwInputJoystick(_GLFWjoystick* js, int event)
|
||||||
{
|
{
|
||||||
|
const int jid = (int) (js - _glfw.joysticks);
|
||||||
|
|
||||||
if (_glfw.callbacks.joystick)
|
if (_glfw.callbacks.joystick)
|
||||||
_glfw.callbacks.joystick(jid, event);
|
_glfw.callbacks.joystick(jid, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code of the new value of a joystick axis
|
||||||
|
//
|
||||||
|
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value)
|
||||||
|
{
|
||||||
|
js->axes[axis] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notifies shared code of the new value of a joystick button
|
||||||
|
//
|
||||||
|
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value)
|
||||||
|
{
|
||||||
|
js->buttons[button] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notifies shared code of the new value of a joystick hat
|
||||||
|
//
|
||||||
|
void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
|
||||||
|
{
|
||||||
|
const int base = js->buttonCount + hat * 4;
|
||||||
|
|
||||||
|
js->buttons[base + 0] = (value & 0x01) ? GLFW_PRESS : GLFW_RELEASE;
|
||||||
|
js->buttons[base + 1] = (value & 0x02) ? GLFW_PRESS : GLFW_RELEASE;
|
||||||
|
js->buttons[base + 2] = (value & 0x04) ? GLFW_PRESS : GLFW_RELEASE;
|
||||||
|
js->buttons[base + 3] = (value & 0x08) ? GLFW_PRESS : GLFW_RELEASE;
|
||||||
|
|
||||||
|
js->hats[hat] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GLFWbool _glfwIsPrintable(int key)
|
// Returns an available joystick object with arrays and name allocated
|
||||||
|
//
|
||||||
|
_GLFWjoystick* _glfwAllocJoystick(const char* name,
|
||||||
|
const char* guid,
|
||||||
|
int axisCount,
|
||||||
|
int buttonCount,
|
||||||
|
int hatCount)
|
||||||
{
|
{
|
||||||
return (key >= GLFW_KEY_APOSTROPHE && key <= GLFW_KEY_WORLD_2) ||
|
int jid;
|
||||||
(key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD) ||
|
_GLFWjoystick* js;
|
||||||
key == GLFW_KEY_KP_EQUAL;
|
|
||||||
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
|
{
|
||||||
|
if (!_glfw.joysticks[jid].present)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jid > GLFW_JOYSTICK_LAST)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
js = _glfw.joysticks + jid;
|
||||||
|
js->present = GLFW_TRUE;
|
||||||
|
js->name = _glfw_strdup(name);
|
||||||
|
js->axes = calloc(axisCount, sizeof(float));
|
||||||
|
js->buttons = calloc(buttonCount + hatCount * 4, 1);
|
||||||
|
js->hats = calloc(hatCount, 1);
|
||||||
|
js->axisCount = axisCount;
|
||||||
|
js->buttonCount = buttonCount;
|
||||||
|
js->hatCount = hatCount;
|
||||||
|
|
||||||
|
strcpy(js->guid, guid);
|
||||||
|
js->mapping = findValidMapping(js);
|
||||||
|
|
||||||
|
return js;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frees arrays and name and flags the joystick object as unused
|
||||||
|
//
|
||||||
|
void _glfwFreeJoystick(_GLFWjoystick* js)
|
||||||
|
{
|
||||||
|
free(js->name);
|
||||||
|
free(js->axes);
|
||||||
|
free(js->buttons);
|
||||||
|
free(js->hats);
|
||||||
|
memset(js, 0, sizeof(_GLFWjoystick));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -162,10 +474,12 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
|
|||||||
return window->stickyKeys;
|
return window->stickyKeys;
|
||||||
case GLFW_STICKY_MOUSE_BUTTONS:
|
case GLFW_STICKY_MOUSE_BUTTONS:
|
||||||
return window->stickyMouseButtons;
|
return window->stickyMouseButtons;
|
||||||
default:
|
case GLFW_LOCK_KEY_MODS:
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode);
|
return window->lockKeyMods;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
||||||
@@ -175,16 +489,14 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
|||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
switch (mode)
|
if (mode == GLFW_CURSOR)
|
||||||
{
|
|
||||||
case GLFW_CURSOR:
|
|
||||||
{
|
{
|
||||||
if (value != GLFW_CURSOR_NORMAL &&
|
if (value != GLFW_CURSOR_NORMAL &&
|
||||||
value != GLFW_CURSOR_HIDDEN &&
|
value != GLFW_CURSOR_HIDDEN &&
|
||||||
value != GLFW_CURSOR_DISABLED)
|
value != GLFW_CURSOR_DISABLED)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
"Invalid cursor mode %i",
|
"Invalid cursor mode 0x%08X",
|
||||||
value);
|
value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -200,12 +512,10 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
|||||||
|
|
||||||
if (_glfwPlatformWindowFocused(window))
|
if (_glfwPlatformWindowFocused(window))
|
||||||
_glfwPlatformSetCursorMode(window, value);
|
_glfwPlatformSetCursorMode(window, value);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else if (mode == GLFW_STICKY_KEYS)
|
||||||
case GLFW_STICKY_KEYS:
|
|
||||||
{
|
{
|
||||||
|
value = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
if (window->stickyKeys == value)
|
if (window->stickyKeys == value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -221,12 +531,11 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window->stickyKeys = value ? GLFW_TRUE : GLFW_FALSE;
|
window->stickyKeys = value;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else if (mode == GLFW_STICKY_MOUSE_BUTTONS)
|
||||||
case GLFW_STICKY_MOUSE_BUTTONS:
|
|
||||||
{
|
{
|
||||||
|
value = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
if (window->stickyMouseButtons == value)
|
if (window->stickyMouseButtons == value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -242,18 +551,31 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window->stickyMouseButtons = value ? GLFW_TRUE : GLFW_FALSE;
|
window->stickyMouseButtons = value;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
else if (mode == GLFW_LOCK_KEY_MODS)
|
||||||
|
window->lockKeyMods = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode);
|
else
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI const char* glfwGetKeyName(int key, int scancode)
|
GLFWAPI const char* glfwGetKeyName(int key, int scancode)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
return _glfwPlatformGetKeyName(key, scancode);
|
|
||||||
|
if (key != GLFW_KEY_UNKNOWN)
|
||||||
|
{
|
||||||
|
if (key != GLFW_KEY_KP_EQUAL &&
|
||||||
|
(key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) &&
|
||||||
|
(key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_WORLD_2))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
scancode = _glfwPlatformGetKeyScancode(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _glfwPlatformGetScancodeName(scancode);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI int glfwGetKeyScancode(int key)
|
GLFWAPI int glfwGetKeyScancode(int key)
|
||||||
@@ -404,7 +726,7 @@ GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape)
|
|||||||
shape != GLFW_HRESIZE_CURSOR &&
|
shape != GLFW_HRESIZE_CURSOR &&
|
||||||
shape != GLFW_VRESIZE_CURSOR)
|
shape != GLFW_VRESIZE_CURSOR)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor %i", shape);
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor 0x%08X", shape);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,60 +877,197 @@ GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun)
|
|||||||
|
|
||||||
GLFWAPI int glfwJoystickPresent(int jid)
|
GLFWAPI int glfwJoystickPresent(int jid)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
_GLFWjoystick* js;
|
||||||
|
|
||||||
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
|
|
||||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", jid);
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||||
return 0;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _glfwPlatformJoystickPresent(jid);
|
js = _glfw.joysticks + jid;
|
||||||
|
if (!js->present)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
return _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
|
GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
|
||||||
{
|
{
|
||||||
|
_GLFWjoystick* js;
|
||||||
|
|
||||||
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
assert(count != NULL);
|
assert(count != NULL);
|
||||||
|
|
||||||
*count = 0;
|
*count = 0;
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", jid);
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _glfwPlatformGetJoystickAxes(jid, count);
|
js = _glfw.joysticks + jid;
|
||||||
|
if (!js->present)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_AXES))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*count = js->axisCount;
|
||||||
|
return js->axes;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
|
GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
|
||||||
{
|
{
|
||||||
|
_GLFWjoystick* js;
|
||||||
|
|
||||||
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
assert(count != NULL);
|
assert(count != NULL);
|
||||||
|
|
||||||
*count = 0;
|
*count = 0;
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", jid);
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _glfwPlatformGetJoystickButtons(jid, count);
|
js = _glfw.joysticks + jid;
|
||||||
|
if (!js->present)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (_glfw.hints.init.hatButtons)
|
||||||
|
*count = js->buttonCount + js->hatCount * 4;
|
||||||
|
else
|
||||||
|
*count = js->buttonCount;
|
||||||
|
|
||||||
|
return js->buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI const char* glfwGetJoystickName(int jid)
|
GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
|
||||||
{
|
{
|
||||||
|
_GLFWjoystick* js;
|
||||||
|
|
||||||
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
|
assert(count != NULL);
|
||||||
|
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", jid);
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _glfwPlatformGetJoystickName(jid);
|
js = _glfw.joysticks + jid;
|
||||||
|
if (!js->present)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*count = js->hatCount;
|
||||||
|
return js->hats;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI const char* glfwGetJoystickName(int jid)
|
||||||
|
{
|
||||||
|
_GLFWjoystick* js;
|
||||||
|
|
||||||
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
js = _glfw.joysticks + jid;
|
||||||
|
if (!js->present)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return js->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI const char* glfwGetJoystickGUID(int jid)
|
||||||
|
{
|
||||||
|
_GLFWjoystick* js;
|
||||||
|
|
||||||
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
js = _glfw.joysticks + jid;
|
||||||
|
if (!js->present)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return js->guid;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer)
|
||||||
|
{
|
||||||
|
_GLFWjoystick* js;
|
||||||
|
|
||||||
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
js = _glfw.joysticks + jid;
|
||||||
|
if (!js->present)
|
||||||
|
return;
|
||||||
|
|
||||||
|
js->userPointer = pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void* glfwGetJoystickUserPointer(int jid)
|
||||||
|
{
|
||||||
|
_GLFWjoystick* js;
|
||||||
|
|
||||||
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
js = _glfw.joysticks + jid;
|
||||||
|
if (!js->present)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return js->userPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
|
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
|
||||||
@@ -618,29 +1077,206 @@ GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
|
|||||||
return cbfun;
|
return cbfun;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwUpdateGamepadMappings(const char* string)
|
||||||
|
{
|
||||||
|
int jid;
|
||||||
|
const char* c = string;
|
||||||
|
|
||||||
|
assert(string != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
|
|
||||||
|
while (*c)
|
||||||
|
{
|
||||||
|
if (isxdigit(*c))
|
||||||
|
{
|
||||||
|
char line[1024];
|
||||||
|
|
||||||
|
const size_t length = strcspn(c, "\r\n");
|
||||||
|
if (length < sizeof(line))
|
||||||
|
{
|
||||||
|
_GLFWmapping mapping = {{0}};
|
||||||
|
|
||||||
|
memcpy(line, c, length);
|
||||||
|
line[length] = '\0';
|
||||||
|
|
||||||
|
if (parseMapping(&mapping, line))
|
||||||
|
{
|
||||||
|
_GLFWmapping* previous = findMapping(mapping.guid);
|
||||||
|
if (previous)
|
||||||
|
*previous = mapping;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_glfw.mappingCount++;
|
||||||
|
_glfw.mappings =
|
||||||
|
realloc(_glfw.mappings,
|
||||||
|
sizeof(_GLFWmapping) * _glfw.mappingCount);
|
||||||
|
_glfw.mappings[_glfw.mappingCount - 1] = mapping;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c += length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c += strcspn(c, "\r\n");
|
||||||
|
c += strspn(c, "\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
|
{
|
||||||
|
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||||
|
if (js->present)
|
||||||
|
js->mapping = findValidMapping(js);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwJoystickIsGamepad(int jid)
|
||||||
|
{
|
||||||
|
_GLFWjoystick* js;
|
||||||
|
|
||||||
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
|
|
||||||
|
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
js = _glfw.joysticks + jid;
|
||||||
|
if (!js->present)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
return js->mapping != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI const char* glfwGetGamepadName(int jid)
|
||||||
|
{
|
||||||
|
_GLFWjoystick* js;
|
||||||
|
|
||||||
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
js = _glfw.joysticks + jid;
|
||||||
|
if (!js->present)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!js->mapping)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return js->mapping->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
_GLFWjoystick* js;
|
||||||
|
|
||||||
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
|
assert(state != NULL);
|
||||||
|
|
||||||
|
memset(state, 0, sizeof(GLFWgamepadstate));
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
|
|
||||||
|
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
js = _glfw.joysticks + jid;
|
||||||
|
if (!js->present)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_ALL))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (!js->mapping)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++)
|
||||||
|
{
|
||||||
|
const _GLFWmapelement* e = js->mapping->buttons + i;
|
||||||
|
if (e->type == _GLFW_JOYSTICK_AXIS)
|
||||||
|
{
|
||||||
|
const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
|
||||||
|
if (value > 0.f)
|
||||||
|
state->buttons[i] = GLFW_PRESS;
|
||||||
|
}
|
||||||
|
else if (e->type == _GLFW_JOYSTICK_HATBIT)
|
||||||
|
{
|
||||||
|
const unsigned int hat = e->index >> 4;
|
||||||
|
const unsigned int bit = e->index & 0xf;
|
||||||
|
if (js->hats[hat] & bit)
|
||||||
|
state->buttons[i] = GLFW_PRESS;
|
||||||
|
}
|
||||||
|
else if (e->type == _GLFW_JOYSTICK_BUTTON)
|
||||||
|
state->buttons[i] = js->buttons[e->index];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++)
|
||||||
|
{
|
||||||
|
const _GLFWmapelement* e = js->mapping->axes + i;
|
||||||
|
if (e->type == _GLFW_JOYSTICK_AXIS)
|
||||||
|
{
|
||||||
|
const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
|
||||||
|
state->axes[i] = fminf(fmaxf(value, -1.f), 1.f);
|
||||||
|
}
|
||||||
|
else if (e->type == _GLFW_JOYSTICK_HATBIT)
|
||||||
|
{
|
||||||
|
const unsigned int hat = e->index >> 4;
|
||||||
|
const unsigned int bit = e->index & 0xf;
|
||||||
|
if (js->hats[hat] & bit)
|
||||||
|
state->axes[i] = 1.f;
|
||||||
|
}
|
||||||
|
else if (e->type == _GLFW_JOYSTICK_BUTTON)
|
||||||
|
state->axes[i] = (float) js->buttons[e->index];
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
|
GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
||||||
assert(window != NULL);
|
|
||||||
assert(string != NULL);
|
assert(string != NULL);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
_glfwPlatformSetClipboardString(window, string);
|
_glfwPlatformSetClipboardString(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
|
GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
||||||
assert(window != NULL);
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
return _glfwPlatformGetClipboardString(window);
|
return _glfwPlatformGetClipboardString();
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI double glfwGetTime(void)
|
GLFWAPI double glfwGetTime(void)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(0.0);
|
_GLFW_REQUIRE_INIT_OR_RETURN(0.0);
|
||||||
return (double) (_glfwPlatformGetTimerValue() - _glfw.timerOffset) /
|
return (double) (_glfwPlatformGetTimerValue() - _glfw.timer.offset) /
|
||||||
_glfwPlatformGetTimerFrequency();
|
_glfwPlatformGetTimerFrequency();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -654,7 +1290,7 @@ GLFWAPI void glfwSetTime(double time)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.timerOffset = _glfwPlatformGetTimerValue() -
|
_glfw.timer.offset = _glfwPlatformGetTimerValue() -
|
||||||
(uint64_t) (time * _glfwPlatformGetTimerFrequency());
|
(uint64_t) (time * _glfwPlatformGetTimerFrequency());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+251
-578
File diff suppressed because it is too large
Load Diff
+271
-178
@@ -27,9 +27,6 @@
|
|||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#if defined(__linux__)
|
|
||||||
#include <linux/joystick.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/inotify.h>
|
#include <sys/inotify.h>
|
||||||
@@ -40,129 +37,225 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.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
|
// Attempt to open the specified joystick device
|
||||||
//
|
//
|
||||||
#if defined(__linux__)
|
|
||||||
static GLFWbool openJoystickDevice(const char* path)
|
static GLFWbool openJoystickDevice(const char* path)
|
||||||
{
|
{
|
||||||
char axisCount, buttonCount;
|
int jid, code;
|
||||||
char name[256] = "";
|
char name[256] = "";
|
||||||
int jid, fd, version;
|
char guid[33] = "";
|
||||||
_GLFWjoystickLinux* js;
|
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;
|
continue;
|
||||||
|
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
|
||||||
if (strcmp(_glfw.linux_js.js[jid].path, path) == 0)
|
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
linjs.fd = open(path, O_RDONLY | O_NONBLOCK);
|
||||||
|
if (linjs.fd == -1)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
if (!_glfw.linux_js.js[jid].present)
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
break;
|
"Linux: Failed to query input device: %s",
|
||||||
|
strerror(errno));
|
||||||
|
close(linjs.fd);
|
||||||
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jid > GLFW_JOYSTICK_LAST)
|
// Ensure this device supports the events expected of a joystick
|
||||||
return GLFW_FALSE;
|
if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits))
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
// It's an old 0.x interface (we don't support it)
|
close(linjs.fd);
|
||||||
close(fd);
|
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0)
|
if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0)
|
||||||
strncpy(name, "Unknown", sizeof(name));
|
strncpy(name, "Unknown", sizeof(name));
|
||||||
|
|
||||||
js = _glfw.linux_js.js + jid;
|
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
||||||
js->present = GLFW_TRUE;
|
if (id.vendor && id.product && id.version)
|
||||||
js->name = strdup(name);
|
{
|
||||||
js->path = strdup(path);
|
sprintf(guid, "%02x%02x0000%02x%02x0000%02x%02x0000%02x%02x0000",
|
||||||
js->fd = fd;
|
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);
|
for (code = BTN_MISC; code < KEY_CNT; code++)
|
||||||
js->axisCount = (int) axisCount;
|
{
|
||||||
js->axes = calloc(axisCount, sizeof(float));
|
if (!isBitSet(code, keyBits))
|
||||||
|
continue;
|
||||||
|
|
||||||
ioctl(fd, JSIOCGBUTTONS, &buttonCount);
|
linjs.keyMap[code - BTN_MISC] = buttonCount;
|
||||||
js->buttonCount = (int) buttonCount;
|
buttonCount++;
|
||||||
js->buttons = calloc(buttonCount, 1);
|
}
|
||||||
|
|
||||||
_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;
|
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__)
|
close(js->linjs.fd);
|
||||||
_glfwPollJoystickEvents();
|
_glfwFreeJoystick(js);
|
||||||
|
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lexically compare joysticks by name; used by qsort
|
// Lexically compare joysticks by name; used by qsort
|
||||||
//
|
//
|
||||||
#if defined(__linux__)
|
|
||||||
static int compareJoysticks(const void* fp, const void* sp)
|
static int compareJoysticks(const void* fp, const void* sp)
|
||||||
{
|
{
|
||||||
const _GLFWjoystickLinux* fj = fp;
|
const _GLFWjoystick* fj = fp;
|
||||||
const _GLFWjoystickLinux* sj = sp;
|
const _GLFWjoystick* sj = sp;
|
||||||
return strcmp(fj->path, sj->path);
|
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)
|
GLFWbool _glfwInitJoysticksLinux(void)
|
||||||
{
|
{
|
||||||
#if defined(__linux__)
|
|
||||||
DIR* dir;
|
DIR* dir;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
const char* dirname = "/dev/input";
|
const char* dirname = "/dev/input";
|
||||||
|
|
||||||
_glfw.linux_js.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
_glfw.linjs.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||||
if (_glfw.linux_js.inotify == -1)
|
if (_glfw.linjs.inotify > 0)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
// HACK: Register for IN_ATTRIB to get notified when udev is done
|
||||||
"Linux: Failed to initialize inotify: %s",
|
|
||||||
strerror(errno));
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
// This works well in practice but the true way is libudev
|
||||||
|
|
||||||
_glfw.linux_js.watch = inotify_add_watch(_glfw.linux_js.inotify,
|
_glfw.linjs.watch = inotify_add_watch(_glfw.linjs.inotify,
|
||||||
dirname,
|
dirname,
|
||||||
IN_CREATE | IN_ATTRIB);
|
IN_CREATE | IN_ATTRIB | IN_DELETE);
|
||||||
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)
|
// Continue without device connection notifications if inotify fails
|
||||||
|
|
||||||
|
if (regcomp(&_glfw.linjs.regex, "^event[0-9]\\+$", 0) != 0)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
@@ -215,31 +296,25 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
|||||||
|
|
||||||
while ((entry = readdir(dir)))
|
while ((entry = readdir(dir)))
|
||||||
{
|
{
|
||||||
char path[20];
|
|
||||||
regmatch_t match;
|
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;
|
continue;
|
||||||
|
|
||||||
|
char path[PATH_MAX];
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
|
snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
|
||||||
|
|
||||||
if (openJoystickDevice(path))
|
if (openJoystickDevice(path))
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(dir);
|
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);
|
// Continue with no joysticks if enumeration fails
|
||||||
#endif // __linux__
|
|
||||||
|
|
||||||
|
qsort(_glfw.joysticks, count, sizeof(_GLFWjoystick), compareJoysticks);
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,56 +322,65 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
|||||||
//
|
//
|
||||||
void _glfwTerminateJoysticksLinux(void)
|
void _glfwTerminateJoysticksLinux(void)
|
||||||
{
|
{
|
||||||
#if defined(__linux__)
|
int jid;
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i <= GLFW_JOYSTICK_LAST; i++)
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
{
|
{
|
||||||
if (_glfw.linux_js.js[i].present)
|
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||||
{
|
if (js->present)
|
||||||
close(_glfw.linux_js.js[i].fd);
|
closeJoystick(js);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
if (_glfw.linjs.watch > 0)
|
||||||
inotify_rm_watch(_glfw.linux_js.inotify, _glfw.linux_js.watch);
|
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;
|
ssize_t offset = 0;
|
||||||
char buffer[16384];
|
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)
|
while (size > offset)
|
||||||
{
|
{
|
||||||
regmatch_t match;
|
regmatch_t match;
|
||||||
const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
|
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;
|
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 //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int _glfwPlatformJoystickPresent(int jid)
|
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||||
{
|
{
|
||||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + jid;
|
// Read all queued events (non-blocking)
|
||||||
return pollJoystickEvents(js);
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-20
@@ -24,45 +24,39 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _glfw3_linux_joystick_h_
|
#include <linux/input.h>
|
||||||
#define _glfw3_linux_joystick_h_
|
#include <linux/limits.h>
|
||||||
|
|
||||||
#include <regex.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
|
// Linux-specific joystick data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWjoystickLinux
|
typedef struct _GLFWjoystickLinux
|
||||||
{
|
{
|
||||||
GLFWbool present;
|
|
||||||
int fd;
|
int fd;
|
||||||
float* axes;
|
char path[PATH_MAX];
|
||||||
int axisCount;
|
int keyMap[KEY_CNT - BTN_MISC];
|
||||||
unsigned char* buttons;
|
int absMap[ABS_CNT];
|
||||||
int buttonCount;
|
struct input_absinfo absInfo[ABS_CNT];
|
||||||
char* name;
|
int hats[4][2];
|
||||||
char* path;
|
|
||||||
} _GLFWjoystickLinux;
|
} _GLFWjoystickLinux;
|
||||||
|
|
||||||
// Linux-specific joystick API data
|
// Linux-specific joystick API data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWjoylistLinux
|
typedef struct _GLFWlibraryLinux
|
||||||
{
|
{
|
||||||
_GLFWjoystickLinux js[GLFW_JOYSTICK_LAST + 1];
|
|
||||||
|
|
||||||
#if defined(__linux__)
|
|
||||||
int inotify;
|
int inotify;
|
||||||
int watch;
|
int watch;
|
||||||
regex_t regex;
|
regex_t regex;
|
||||||
#endif /*__linux__*/
|
GLFWbool dropped;
|
||||||
} _GLFWjoylistLinux;
|
} _GLFWlibraryLinux;
|
||||||
|
|
||||||
|
|
||||||
GLFWbool _glfwInitJoysticksLinux(void);
|
GLFWbool _glfwInitJoysticksLinux(void);
|
||||||
void _glfwTerminateJoysticksLinux(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
|
// 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
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -51,6 +51,7 @@ static void createKeyTables(void)
|
|||||||
_glfw.mir.keycodes[KEY_8] = GLFW_KEY_8;
|
_glfw.mir.keycodes[KEY_8] = GLFW_KEY_8;
|
||||||
_glfw.mir.keycodes[KEY_9] = GLFW_KEY_9;
|
_glfw.mir.keycodes[KEY_9] = GLFW_KEY_9;
|
||||||
_glfw.mir.keycodes[KEY_0] = GLFW_KEY_0;
|
_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_MINUS] = GLFW_KEY_MINUS;
|
||||||
_glfw.mir.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL;
|
_glfw.mir.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL;
|
||||||
_glfw.mir.keycodes[KEY_Q] = GLFW_KEY_Q;
|
_glfw.mir.keycodes[KEY_Q] = GLFW_KEY_Q;
|
||||||
@@ -189,18 +190,11 @@ int _glfwPlatformInit(void)
|
|||||||
|
|
||||||
createKeyTables();
|
createKeyTables();
|
||||||
|
|
||||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
if (!_glfwInitJoysticksLinux())
|
if (!_glfwInitJoysticksLinux())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
_glfwInitTimerPOSIX();
|
_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));
|
_glfw.mir.eventQueue = calloc(1, sizeof(EventQueue));
|
||||||
_glfwInitEventQueueMir(_glfw.mir.eventQueue);
|
_glfwInitEventQueueMir(_glfw.mir.eventQueue);
|
||||||
|
|
||||||
@@ -213,6 +207,7 @@ int _glfwPlatformInit(void)
|
|||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_glfwPollMonitorsMir();
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,7 +215,6 @@ void _glfwPlatformTerminate(void)
|
|||||||
{
|
{
|
||||||
_glfwTerminateEGL();
|
_glfwTerminateEGL();
|
||||||
_glfwTerminateJoysticksLinux();
|
_glfwTerminateJoysticksLinux();
|
||||||
_glfwTerminateThreadLocalStoragePOSIX();
|
|
||||||
|
|
||||||
_glfwDeleteEventQueueMir(_glfw.mir.eventQueue);
|
_glfwDeleteEventQueueMir(_glfw.mir.eventQueue);
|
||||||
|
|
||||||
@@ -237,9 +231,7 @@ const char* _glfwPlatformGetVersionString(void)
|
|||||||
#else
|
#else
|
||||||
" gettimeofday"
|
" gettimeofday"
|
||||||
#endif
|
#endif
|
||||||
#if defined(__linux__)
|
" evdev"
|
||||||
" /dev/js"
|
|
||||||
#endif
|
|
||||||
#if defined(_GLFW_BUILD_DLL)
|
#if defined(_GLFW_BUILD_DLL)
|
||||||
" shared"
|
" shared"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+79
-47
@@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 Mir - www.glfw.org
|
// 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
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -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;
|
int i;
|
||||||
_GLFWmonitor** monitors = NULL;
|
MirDisplayConfig* displayConfig =
|
||||||
MirDisplayConfiguration* displayConfig =
|
mir_connection_create_display_configuration(_glfw.mir.connection);
|
||||||
mir_connection_create_display_config(_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 &&
|
if (enabled && state == mir_output_connection_state_connected)
|
||||||
out->connected &&
|
|
||||||
out->num_modes &&
|
|
||||||
out->current_mode < out->num_modes)
|
|
||||||
{
|
{
|
||||||
found++;
|
int widthMM = mir_output_get_physical_width_mm(output);
|
||||||
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
|
int heightMM = mir_output_get_physical_height_mm(output);
|
||||||
monitors[i] = _glfwAllocMonitor("Unknown",
|
int x = mir_output_get_position_x(output);
|
||||||
out->physical_width_mm,
|
int y = mir_output_get_position_y(output);
|
||||||
out->physical_height_mm);
|
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;
|
_GLFWmonitor* monitor = _glfwAllocMonitor(name,
|
||||||
monitors[i]->mir.y = out->position_y;
|
widthMM,
|
||||||
monitors[i]->mir.outputId = out->output_id;
|
heightMM);
|
||||||
monitors[i]->mir.curMode = out->current_mode;
|
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],
|
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
||||||
&monitors[i]->modeCount);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mir_display_config_destroy(displayConfig);
|
mir_display_config_release(displayConfig);
|
||||||
|
|
||||||
*count = found;
|
|
||||||
return monitors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
|
|
||||||
{
|
//////////////////////////////////////////////////////////////////////////
|
||||||
return first->mir.outputId == second->mir.outputId;
|
////// GLFW platform API //////
|
||||||
}
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||||
{
|
{
|
||||||
@@ -86,7 +88,16 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
|||||||
*ypos = monitor->mir.y;
|
*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)
|
switch (pf)
|
||||||
{
|
{
|
||||||
@@ -123,30 +134,52 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
GLFWvidmode* modes = NULL;
|
GLFWvidmode* modes = NULL;
|
||||||
MirDisplayConfiguration* displayConfig =
|
MirDisplayConfig* displayConfig =
|
||||||
mir_connection_create_display_config(_glfw.mir.connection);
|
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;
|
const MirOutput* output = mir_display_config_get_output(displayConfig, i);
|
||||||
if (out->output_id != monitor->mir.outputId)
|
int id = mir_output_get_id(output);
|
||||||
|
|
||||||
|
if (id != monitor->mir.outputId)
|
||||||
continue;
|
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;
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
modes[*found].height = out->modes[*found].vertical_resolution;
|
"Mir: Monitor no longer connected");
|
||||||
modes[*found].refreshRate = out->modes[*found].refresh_rate;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mir_display_config_destroy(displayConfig);
|
mir_display_config_release(displayConfig);
|
||||||
|
|
||||||
return modes;
|
return modes;
|
||||||
}
|
}
|
||||||
@@ -179,4 +212,3 @@ GLFWAPI int glfwGetMirMonitor(GLFWmonitor* handle)
|
|||||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||||
return monitor->mir.outputId;
|
return monitor->mir.outputId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-17
@@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 Mir - www.glfw.org
|
// 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
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,40 +24,38 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _glfw3_mir_platform_h_
|
|
||||||
#define _glfw3_mir_platform_h_
|
|
||||||
|
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
#include <mir_toolkit/mir_client_library.h>
|
#include <mir_toolkit/mir_client_library.h>
|
||||||
|
|
||||||
typedef VkFlags VkMirSurfaceCreateFlagsKHR;
|
typedef VkFlags VkMirWindowCreateFlagsKHR;
|
||||||
|
|
||||||
typedef struct VkMirSurfaceCreateInfoKHR
|
typedef struct VkMirWindowCreateInfoKHR
|
||||||
{
|
{
|
||||||
VkStructureType sType;
|
VkStructureType sType;
|
||||||
const void* pNext;
|
const void* pNext;
|
||||||
VkMirSurfaceCreateFlagsKHR flags;
|
VkMirWindowCreateFlagsKHR flags;
|
||||||
MirConnection* connection;
|
MirConnection* connection;
|
||||||
MirSurface* mirSurface;
|
MirWindow* mirWindow;
|
||||||
} VkMirSurfaceCreateInfoKHR;
|
} 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*);
|
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(VkPhysicalDevice,uint32_t,MirConnection*);
|
||||||
|
|
||||||
#include "posix_tls.h"
|
#include "posix_thread.h"
|
||||||
#include "posix_time.h"
|
#include "posix_time.h"
|
||||||
#include "linux_joystick.h"
|
#include "linux_joystick.h"
|
||||||
#include "xkb_unicode.h"
|
#include "xkb_unicode.h"
|
||||||
#include "egl_context.h"
|
#include "egl_context.h"
|
||||||
|
#include "osmesa_context.h"
|
||||||
|
|
||||||
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||||
#define _glfw_dlclose(handle) dlclose(handle)
|
#define _glfw_dlclose(handle) dlclose(handle)
|
||||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
#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_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.mir.display)
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowMir mir
|
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowMir mir
|
||||||
@@ -80,10 +78,10 @@ typedef struct EventQueue
|
|||||||
//
|
//
|
||||||
typedef struct _GLFWwindowMir
|
typedef struct _GLFWwindowMir
|
||||||
{
|
{
|
||||||
MirSurface* surface;
|
MirWindow* window;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
MirEGLNativeWindowType window;
|
MirEGLNativeWindowType nativeWindow;
|
||||||
_GLFWcursor* currentCursor;
|
_GLFWcursor* currentCursor;
|
||||||
|
|
||||||
} _GLFWwindowMir;
|
} _GLFWwindowMir;
|
||||||
@@ -105,8 +103,6 @@ typedef struct _GLFWlibraryMir
|
|||||||
{
|
{
|
||||||
MirConnection* connection;
|
MirConnection* connection;
|
||||||
MirEGLNativeDisplayType display;
|
MirEGLNativeDisplayType display;
|
||||||
MirCursorConfiguration* defaultConf;
|
|
||||||
MirCursorConfiguration* disabledConf;
|
|
||||||
EventQueue* eventQueue;
|
EventQueue* eventQueue;
|
||||||
|
|
||||||
short int keycodes[256];
|
short int keycodes[256];
|
||||||
@@ -127,10 +123,11 @@ typedef struct _GLFWcursorMir
|
|||||||
{
|
{
|
||||||
MirCursorConfiguration* conf;
|
MirCursorConfiguration* conf;
|
||||||
MirBufferStream* customCursor;
|
MirBufferStream* customCursor;
|
||||||
|
char const* cursorName; // only needed for system cursors
|
||||||
} _GLFWcursorMir;
|
} _GLFWcursorMir;
|
||||||
|
|
||||||
|
|
||||||
|
extern void _glfwPollMonitorsMir(void);
|
||||||
extern void _glfwInitEventQueueMir(EventQueue* queue);
|
extern void _glfwInitEventQueueMir(EventQueue* queue);
|
||||||
extern void _glfwDeleteEventQueueMir(EventQueue* queue);
|
extern void _glfwDeleteEventQueueMir(EventQueue* queue);
|
||||||
|
|
||||||
#endif // _glfw3_mir_platform_h_
|
|
||||||
|
|||||||
+183
-136
@@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 Mir - www.glfw.org
|
// 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
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -89,9 +89,6 @@ static EventNode* dequeueEvent(EventQueue* queue)
|
|||||||
return node;
|
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)
|
static MirPixelFormat findValidPixelFormat(void)
|
||||||
{
|
{
|
||||||
unsigned int i, validFormats, mirPixelFormats = 32;
|
unsigned int i, validFormats, mirPixelFormats = 32;
|
||||||
@@ -120,12 +117,16 @@ static int mirModToGLFWMod(uint32_t mods)
|
|||||||
|
|
||||||
if (mods & mir_input_event_modifier_alt)
|
if (mods & mir_input_event_modifier_alt)
|
||||||
publicMods |= GLFW_MOD_ALT;
|
publicMods |= GLFW_MOD_ALT;
|
||||||
else if (mods & mir_input_event_modifier_shift)
|
if (mods & mir_input_event_modifier_shift)
|
||||||
publicMods |= GLFW_MOD_SHIFT;
|
publicMods |= GLFW_MOD_SHIFT;
|
||||||
else if (mods & mir_input_event_modifier_ctrl)
|
if (mods & mir_input_event_modifier_ctrl)
|
||||||
publicMods |= GLFW_MOD_CONTROL;
|
publicMods |= GLFW_MOD_CONTROL;
|
||||||
else if (mods & mir_input_event_modifier_meta)
|
if (mods & mir_input_event_modifier_meta)
|
||||||
publicMods |= GLFW_MOD_SUPER;
|
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;
|
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);
|
enqueueEvent(event, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLFWbool createSurface(_GLFWwindow* window)
|
static GLFWbool createWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
MirSurfaceSpec* spec;
|
MirWindowSpec* spec;
|
||||||
MirBufferUsage buffer_usage = mir_buffer_usage_hardware;
|
MirBufferUsage buffer_usage = mir_buffer_usage_hardware;
|
||||||
MirPixelFormat pixel_format = findValidPixelFormat();
|
MirPixelFormat pixel_format = findValidPixelFormat();
|
||||||
|
|
||||||
@@ -301,40 +302,39 @@ static GLFWbool createSurface(_GLFWwindow* window)
|
|||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
spec = mir_connection_create_spec_for_normal_surface(_glfw.mir.connection,
|
spec = mir_create_normal_window_spec(_glfw.mir.connection,
|
||||||
window->mir.width,
|
window->mir.width,
|
||||||
window->mir.height,
|
window->mir.height);
|
||||||
pixel_format);
|
|
||||||
|
|
||||||
mir_surface_spec_set_buffer_usage(spec, buffer_usage);
|
mir_window_spec_set_pixel_format(spec, pixel_format);
|
||||||
mir_surface_spec_set_name(spec, "MirSurface");
|
mir_window_spec_set_buffer_usage(spec, buffer_usage);
|
||||||
|
|
||||||
window->mir.surface = mir_surface_create_sync(spec);
|
window->mir.window = mir_create_window_sync(spec);
|
||||||
mir_surface_spec_release(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,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Mir: Unable to create surface: %s",
|
"Mir: Unable to create window: %s",
|
||||||
mir_surface_get_error_message(window->mir.surface));
|
mir_window_get_error_message(window->mir.window));
|
||||||
|
|
||||||
return GLFW_FALSE;
|
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;
|
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);
|
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||||
mir_surface_spec_set_pointer_confinement(spec, state);
|
mir_window_spec_set_pointer_confinement(spec, state);
|
||||||
|
|
||||||
mir_surface_apply_spec(window->mir.surface, spec);
|
mir_window_apply_spec(window->mir.window, spec);
|
||||||
mir_surface_spec_release(spec);
|
mir_window_spec_release(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -381,12 +381,12 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
GLFWvidmode mode;
|
GLFWvidmode mode;
|
||||||
_glfwPlatformGetVideoMode(window->monitor, &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)
|
if (wndconfig->width > mode.width || wndconfig->height > mode.height)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Mir: Requested surface size too large: %ix%i",
|
"Mir: Requested window size too large: %ix%i",
|
||||||
wndconfig->width, wndconfig->height);
|
wndconfig->width, wndconfig->height);
|
||||||
|
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
@@ -397,19 +397,30 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
window->mir.height = wndconfig->height;
|
window->mir.height = wndconfig->height;
|
||||||
window->mir.currentCursor = NULL;
|
window->mir.currentCursor = NULL;
|
||||||
|
|
||||||
if (!createSurface(window))
|
if (!createWindow(window))
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
window->mir.window = mir_buffer_stream_get_egl_native_window(
|
window->mir.nativeWindow = mir_buffer_stream_get_egl_native_window(
|
||||||
mir_surface_get_buffer_stream(window->mir.surface));
|
mir_window_get_buffer_stream(window->mir.window));
|
||||||
|
|
||||||
if (ctxconfig->client != GLFW_NO_API)
|
if (ctxconfig->client != GLFW_NO_API)
|
||||||
|
{
|
||||||
|
if (ctxconfig->source == GLFW_EGL_CONTEXT_API ||
|
||||||
|
ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
|
||||||
{
|
{
|
||||||
if (!_glfwInitEGL())
|
if (!_glfwInitEGL())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
||||||
return GLFW_FALSE;
|
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;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
@@ -419,10 +430,10 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
|||||||
if (_glfw.mir.disabledCursorWindow == window)
|
if (_glfw.mir.disabledCursorWindow == window)
|
||||||
_glfw.mir.disabledCursorWindow = NULL;
|
_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);
|
mir_window_release_sync(window->mir.window);
|
||||||
window->mir.surface = NULL;
|
window->mir.window= NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->context.destroy)
|
if (window->context.destroy)
|
||||||
@@ -431,14 +442,12 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
||||||
{
|
{
|
||||||
MirSurfaceSpec* spec;
|
MirWindowSpec* spec;
|
||||||
const char* e_title = title ? title : "";
|
|
||||||
|
|
||||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||||
mir_surface_spec_set_name(spec, e_title);
|
mir_window_spec_set_name(spec, title);
|
||||||
|
mir_window_apply_spec(window->mir.window, spec);
|
||||||
mir_surface_apply_spec(window->mir.surface, spec);
|
mir_window_spec_release(spec);
|
||||||
mir_surface_spec_release(spec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
||||||
@@ -450,22 +459,30 @@ void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
|||||||
|
|
||||||
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
||||||
{
|
{
|
||||||
MirSurfaceSpec* spec;
|
MirWindowSpec* spec;
|
||||||
|
|
||||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||||
mir_surface_spec_set_width (spec, width);
|
mir_window_spec_set_width (spec, width);
|
||||||
mir_surface_spec_set_height(spec, height);
|
mir_window_spec_set_height(spec, height);
|
||||||
|
|
||||||
mir_surface_apply_spec(window->mir.surface, spec);
|
mir_window_apply_spec(window->mir.window, spec);
|
||||||
mir_surface_spec_release(spec);
|
mir_window_spec_release(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||||
int minwidth, int minheight,
|
int minwidth, int minheight,
|
||||||
int maxwidth, int maxheight)
|
int maxwidth, int maxheight)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
MirWindowSpec* spec;
|
||||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
|
||||||
|
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)
|
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
|
||||||
@@ -502,59 +519,74 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
|||||||
*height = window->mir.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)
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
MirSurfaceSpec* spec;
|
MirWindowSpec* spec;
|
||||||
|
|
||||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||||
mir_surface_spec_set_state(spec, mir_surface_state_minimized);
|
mir_window_spec_set_state(spec, mir_window_state_minimized);
|
||||||
|
|
||||||
mir_surface_apply_spec(window->mir.surface, spec);
|
mir_window_apply_spec(window->mir.window, spec);
|
||||||
mir_surface_spec_release(spec);
|
mir_window_spec_release(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
MirSurfaceSpec* spec;
|
MirWindowSpec* spec;
|
||||||
|
|
||||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||||
mir_surface_spec_set_state(spec, mir_surface_state_restored);
|
mir_window_spec_set_state(spec, mir_window_state_restored);
|
||||||
|
|
||||||
mir_surface_apply_spec(window->mir.surface, spec);
|
mir_window_apply_spec(window->mir.window, spec);
|
||||||
mir_surface_spec_release(spec);
|
mir_window_spec_release(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
MirSurfaceSpec* spec;
|
MirWindowSpec* spec;
|
||||||
|
|
||||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||||
mir_surface_spec_set_state(spec, mir_surface_state_maximized);
|
mir_window_spec_set_state(spec, mir_window_state_maximized);
|
||||||
|
|
||||||
mir_surface_apply_spec(window->mir.surface, spec);
|
mir_window_apply_spec(window->mir.window, spec);
|
||||||
mir_surface_spec_release(spec);
|
mir_window_spec_release(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
MirSurfaceSpec* spec;
|
MirWindowSpec* spec;
|
||||||
|
|
||||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||||
mir_surface_spec_set_state(spec, mir_surface_state_hidden);
|
mir_window_spec_set_state(spec, mir_window_state_hidden);
|
||||||
|
|
||||||
mir_surface_apply_spec(window->mir.surface, spec);
|
mir_window_apply_spec(window->mir.window, spec);
|
||||||
mir_surface_spec_release(spec);
|
mir_window_spec_release(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
MirSurfaceSpec* spec;
|
MirWindowSpec* spec;
|
||||||
|
|
||||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||||
mir_surface_spec_set_state(spec, mir_surface_state_restored);
|
mir_window_spec_set_state(spec, mir_window_state_restored);
|
||||||
|
|
||||||
mir_surface_apply_spec(window->mir.surface, spec);
|
mir_window_apply_spec(window->mir.window, spec);
|
||||||
mir_surface_spec_release(spec);
|
mir_window_spec_release(spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||||
@@ -575,7 +607,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
|||||||
|
|
||||||
int _glfwPlatformWindowFocused(_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)
|
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||||
@@ -587,12 +619,26 @@ int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
|||||||
|
|
||||||
int _glfwPlatformWindowVisible(_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)
|
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)
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||||
@@ -613,6 +659,15 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
|||||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void _glfwPlatformPollEvents(void)
|
void _glfwPlatformPollEvents(void)
|
||||||
{
|
{
|
||||||
EventNode* node = NULL;
|
EventNode* node = NULL;
|
||||||
@@ -628,7 +683,7 @@ void _glfwPlatformWaitEvents(void)
|
|||||||
{
|
{
|
||||||
pthread_mutex_lock(&_glfw.mir.eventMutex);
|
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_cond_wait(&_glfw.mir.eventCond, &_glfw.mir.eventMutex);
|
||||||
|
|
||||||
pthread_mutex_unlock(&_glfw.mir.eventMutex);
|
pthread_mutex_unlock(&_glfw.mir.eventMutex);
|
||||||
@@ -671,54 +726,40 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
|||||||
int xhot, int yhot)
|
int xhot, int yhot)
|
||||||
{
|
{
|
||||||
MirBufferStream* stream;
|
MirBufferStream* stream;
|
||||||
MirPixelFormat pixel_format = findValidPixelFormat();
|
|
||||||
|
|
||||||
int i_w = image->width;
|
int i_w = image->width;
|
||||||
int i_h = image->height;
|
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,
|
stream = mir_connection_create_buffer_stream_sync(_glfw.mir.connection,
|
||||||
i_w, i_h,
|
i_w, i_h,
|
||||||
pixel_format,
|
mir_pixel_format_argb_8888,
|
||||||
mir_buffer_usage_software);
|
mir_buffer_usage_software);
|
||||||
|
|
||||||
cursor->mir.conf = mir_cursor_configuration_from_buffer_stream(stream, xhot, yhot);
|
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;
|
MirGraphicsRegion region;
|
||||||
mir_buffer_stream_get_graphics_region(stream, ®ion);
|
mir_buffer_stream_get_graphics_region(stream, ®ion);
|
||||||
|
|
||||||
// FIXME Figure this out based on the current_pf
|
unsigned char* pixels = image->pixels;
|
||||||
bytes_per_pixel = 4;
|
char* dest = region.vaddr;
|
||||||
bytes_per_row = bytes_per_pixel * i_w;
|
int i;
|
||||||
|
|
||||||
dest = region.vaddr;
|
for (i = 0; i < i_w * i_h; i++, pixels += 4)
|
||||||
pixels = image->pixels;
|
|
||||||
|
|
||||||
r_stride = region.stride;
|
|
||||||
|
|
||||||
for (i = 0; i < i_h; i++)
|
|
||||||
{
|
{
|
||||||
memcpy(dest, pixels, bytes_per_row);
|
unsigned int alpha = pixels[3];
|
||||||
dest += r_stride;
|
*dest++ = (char)(pixels[2] * alpha / 255);
|
||||||
pixels += r_stride;
|
*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;
|
cursor->mir.customCursor = stream;
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* getSystemCursorName(int shape)
|
static const char* getSystemCursorName(int shape)
|
||||||
{
|
{
|
||||||
switch (shape)
|
switch (shape)
|
||||||
{
|
{
|
||||||
@@ -741,17 +782,11 @@ const char* getSystemCursorName(int shape)
|
|||||||
|
|
||||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||||
{
|
{
|
||||||
const char* cursor_name = getSystemCursorName(shape);
|
cursor->mir.conf = NULL;
|
||||||
|
|
||||||
if (cursor_name)
|
|
||||||
{
|
|
||||||
cursor->mir.conf = mir_cursor_configuration_from_name(cursor_name);
|
|
||||||
cursor->mir.customCursor = NULL;
|
cursor->mir.customCursor = NULL;
|
||||||
|
cursor->mir.cursorName = getSystemCursorName(shape);
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return cursor->mir.cursorName != NULL;
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
||||||
@@ -762,21 +797,32 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
|||||||
mir_buffer_stream_release_sync(cursor->mir.customCursor);
|
mir_buffer_stream_release_sync(cursor->mir.customCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setCursorNameForWindow(MirWindow* window, char const* name)
|
||||||
|
{
|
||||||
|
MirWindowSpec* spec = mir_create_window_spec(_glfw.mir.connection);
|
||||||
|
mir_window_spec_set_cursor_name(spec, name);
|
||||||
|
mir_window_apply_spec(window, spec);
|
||||||
|
mir_window_spec_release(spec);
|
||||||
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
||||||
{
|
{
|
||||||
if (cursor && cursor->mir.conf)
|
if (cursor)
|
||||||
{
|
{
|
||||||
window->mir.currentCursor = cursor;
|
window->mir.currentCursor = cursor;
|
||||||
|
|
||||||
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, cursor->mir.conf));
|
if (cursor->mir.cursorName)
|
||||||
if (cursor->mir.customCursor)
|
|
||||||
{
|
{
|
||||||
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
|
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)
|
if (mode == GLFW_CURSOR_DISABLED)
|
||||||
{
|
{
|
||||||
_glfw.mir.disabledCursorWindow = window;
|
_glfw.mir.disabledCursorWindow = window;
|
||||||
setSurfaceConfinement(window, mir_pointer_confined_to_surface);
|
setWindowConfinement(window, mir_pointer_confined_to_window);
|
||||||
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, _glfw.mir.disabledConf));
|
setCursorNameForWindow(window->mir.window, mir_disabled_cursor_name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -806,7 +852,7 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
|||||||
if (_glfw.mir.disabledCursorWindow == window)
|
if (_glfw.mir.disabledCursorWindow == window)
|
||||||
{
|
{
|
||||||
_glfw.mir.disabledCursorWindow = NULL;
|
_glfw.mir.disabledCursorWindow = NULL;
|
||||||
setSurfaceConfinement(window, mir_pointer_unconfined);
|
setWindowConfinement(window, mir_pointer_unconfined);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
||||||
@@ -815,12 +861,12 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
|||||||
}
|
}
|
||||||
else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
|
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,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||||
@@ -832,13 +878,13 @@ int _glfwPlatformGetKeyScancode(int key)
|
|||||||
return _glfw.mir.scancodes[key];
|
return _glfw.mir.scancodes[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
|
void _glfwPlatformSetClipboardString(const char* string)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
const char* _glfwPlatformGetClipboardString(void)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||||
@@ -859,7 +905,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
|||||||
VkPhysicalDevice device,
|
VkPhysicalDevice device,
|
||||||
uint32_t queuefamily)
|
uint32_t queuefamily)
|
||||||
{
|
{
|
||||||
PFN_vkGetPhysicalDeviceMirPresentationSupportKHR vkGetPhysicalDeviceMirPresentationSupportKHR =
|
PFN_vkGetPhysicalDeviceMirPresentationSupportKHR
|
||||||
|
vkGetPhysicalDeviceMirPresentationSupportKHR =
|
||||||
(PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)
|
(PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)
|
||||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
|
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
|
||||||
if (!vkGetPhysicalDeviceMirPresentationSupportKHR)
|
if (!vkGetPhysicalDeviceMirPresentationSupportKHR)
|
||||||
@@ -880,12 +927,12 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
|||||||
VkSurfaceKHR* surface)
|
VkSurfaceKHR* surface)
|
||||||
{
|
{
|
||||||
VkResult err;
|
VkResult err;
|
||||||
VkMirSurfaceCreateInfoKHR sci;
|
VkMirWindowCreateInfoKHR sci;
|
||||||
PFN_vkCreateMirSurfaceKHR vkCreateMirSurfaceKHR;
|
PFN_vkCreateMirWindowKHR vkCreateMirWindowKHR;
|
||||||
|
|
||||||
vkCreateMirSurfaceKHR = (PFN_vkCreateMirSurfaceKHR)
|
vkCreateMirWindowKHR = (PFN_vkCreateMirWindowKHR)
|
||||||
vkGetInstanceProcAddr(instance, "vkCreateMirSurfaceKHR");
|
vkGetInstanceProcAddr(instance, "vkCreateMirWindowKHR");
|
||||||
if (!vkCreateMirSurfaceKHR)
|
if (!vkCreateMirWindowKHR)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"Mir: Vulkan instance missing VK_KHR_mir_surface extension");
|
"Mir: Vulkan instance missing VK_KHR_mir_surface extension");
|
||||||
@@ -895,9 +942,9 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
|||||||
memset(&sci, 0, sizeof(sci));
|
memset(&sci, 0, sizeof(sci));
|
||||||
sci.sType = VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR;
|
sci.sType = VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR;
|
||||||
sci.connection = _glfw.mir.connection;
|
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)
|
if (err)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
@@ -919,10 +966,10 @@ GLFWAPI MirConnection* glfwGetMirDisplay(void)
|
|||||||
return _glfw.mir.connection;
|
return _glfw.mir.connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* handle)
|
GLFWAPI MirWindow* glfwGetMirWindow(GLFWwindow* handle)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
return window->mir.surface;
|
return window->mir.window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+94
-67
@@ -86,83 +86,67 @@ static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
|
|||||||
////// GLFW event API //////
|
////// GLFW event API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void _glfwInputMonitorChange(void)
|
// Notifies shared code of a monitor connection or disconnection
|
||||||
|
//
|
||||||
|
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
|
||||||
{
|
{
|
||||||
int i, j, monitorCount = _glfw.monitorCount;
|
if (action == GLFW_CONNECTED)
|
||||||
_GLFWmonitor** monitors = _glfw.monitors;
|
|
||||||
|
|
||||||
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
|
|
||||||
|
|
||||||
// Re-use still connected monitor objects
|
|
||||||
|
|
||||||
for (i = 0; i < _glfw.monitorCount; i++)
|
|
||||||
{
|
{
|
||||||
for (j = 0; j < monitorCount; j++)
|
_glfw.monitorCount++;
|
||||||
|
_glfw.monitors =
|
||||||
|
realloc(_glfw.monitors, sizeof(_GLFWmonitor*) * _glfw.monitorCount);
|
||||||
|
|
||||||
|
if (placement == _GLFW_INSERT_FIRST)
|
||||||
{
|
{
|
||||||
if (_glfwPlatformIsSameMonitor(_glfw.monitors[i], monitors[j]))
|
memmove(_glfw.monitors + 1,
|
||||||
{
|
_glfw.monitors,
|
||||||
_glfwFreeMonitor(_glfw.monitors[i]);
|
(_glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
|
||||||
_glfw.monitors[i] = monitors[j];
|
_glfw.monitors[0] = monitor;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
_glfw.monitors[_glfw.monitorCount - 1] = monitor;
|
||||||
}
|
}
|
||||||
}
|
else if (action == GLFW_DISCONNECTED)
|
||||||
|
|
||||||
// Find and report disconnected monitors (not in the new list)
|
|
||||||
|
|
||||||
for (i = 0; i < monitorCount; i++)
|
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
_GLFWwindow* window;
|
_GLFWwindow* window;
|
||||||
|
|
||||||
for (j = 0; j < _glfw.monitorCount; j++)
|
|
||||||
{
|
|
||||||
if (monitors[i] == _glfw.monitors[j])
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j < _glfw.monitorCount)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (window = _glfw.windowListHead; window; window = window->next)
|
for (window = _glfw.windowListHead; window; window = window->next)
|
||||||
{
|
{
|
||||||
if (window->monitor == monitors[i])
|
if (window->monitor == monitor)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height, xoff, yoff;
|
||||||
_glfwPlatformGetWindowSize(window, &width, &height);
|
_glfwPlatformGetWindowSize(window, &width, &height);
|
||||||
_glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0);
|
_glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0);
|
||||||
|
_glfwPlatformGetWindowFrameSize(window, &xoff, &yoff, NULL, NULL);
|
||||||
|
_glfwPlatformSetWindowPos(window, xoff, yoff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfw.callbacks.monitor)
|
|
||||||
_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 (i = 0; i < _glfw.monitorCount; i++)
|
||||||
{
|
{
|
||||||
for (j = 0; j < monitorCount; j++)
|
if (_glfw.monitors[i] == monitor)
|
||||||
{
|
{
|
||||||
if (_glfw.monitors[i] == monitors[j])
|
_glfw.monitorCount--;
|
||||||
{
|
memmove(_glfw.monitors + i,
|
||||||
monitors[j] = NULL;
|
_glfw.monitors + i + 1,
|
||||||
|
(_glfw.monitorCount - i) * sizeof(_GLFWmonitor*));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (j < monitorCount)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (_glfw.callbacks.monitor)
|
|
||||||
_glfw.callbacks.monitor((GLFWmonitor*) _glfw.monitors[i], GLFW_CONNECTED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwFreeMonitors(monitors, monitorCount);
|
if (_glfw.callbacks.monitor)
|
||||||
|
_glfw.callbacks.monitor((GLFWmonitor*) monitor, action);
|
||||||
|
|
||||||
|
if (action == GLFW_DISCONNECTED)
|
||||||
|
_glfwFreeMonitor(monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window)
|
// Notifies shared code that a full screen window has acquired or released
|
||||||
|
// a monitor
|
||||||
|
//
|
||||||
|
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
|
||||||
{
|
{
|
||||||
monitor->window = window;
|
monitor->window = window;
|
||||||
}
|
}
|
||||||
@@ -172,6 +156,8 @@ void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window)
|
|||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Allocates and returns a monitor object with the specified name and dimensions
|
||||||
|
//
|
||||||
_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
|
_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
|
||||||
{
|
{
|
||||||
_GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor));
|
_GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor));
|
||||||
@@ -179,11 +165,13 @@ _GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
|
|||||||
monitor->heightMM = heightMM;
|
monitor->heightMM = heightMM;
|
||||||
|
|
||||||
if (name)
|
if (name)
|
||||||
monitor->name = strdup(name);
|
monitor->name = _glfw_strdup(name);
|
||||||
|
|
||||||
return monitor;
|
return monitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Frees a monitor object and any data associated with it
|
||||||
|
//
|
||||||
void _glfwFreeMonitor(_GLFWmonitor* monitor)
|
void _glfwFreeMonitor(_GLFWmonitor* monitor)
|
||||||
{
|
{
|
||||||
if (monitor == NULL)
|
if (monitor == NULL)
|
||||||
@@ -197,6 +185,8 @@ void _glfwFreeMonitor(_GLFWmonitor* monitor)
|
|||||||
free(monitor);
|
free(monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allocates red, green and blue value arrays of the specified size
|
||||||
|
//
|
||||||
void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size)
|
void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size)
|
||||||
{
|
{
|
||||||
ramp->red = calloc(size, sizeof(unsigned short));
|
ramp->red = calloc(size, sizeof(unsigned short));
|
||||||
@@ -205,6 +195,8 @@ void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size)
|
|||||||
ramp->size = size;
|
ramp->size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Frees the red, green and blue value arrays and clears the struct
|
||||||
|
//
|
||||||
void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
|
void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
|
||||||
{
|
{
|
||||||
free(ramp->red);
|
free(ramp->red);
|
||||||
@@ -214,16 +206,8 @@ void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
|
|||||||
memset(ramp, 0, sizeof(GLFWgammaramp));
|
memset(ramp, 0, sizeof(GLFWgammaramp));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwFreeMonitors(_GLFWmonitor** monitors, int count)
|
// Chooses the video mode most closely matching the desired one
|
||||||
{
|
//
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
_glfwFreeMonitor(monitors[i]);
|
|
||||||
|
|
||||||
free(monitors);
|
|
||||||
}
|
|
||||||
|
|
||||||
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
|
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
|
||||||
const GLFWvidmode* desired)
|
const GLFWvidmode* desired)
|
||||||
{
|
{
|
||||||
@@ -274,11 +258,15 @@ const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
|
|||||||
return closest;
|
return closest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Performs lexical comparison between two @ref GLFWvidmode structures
|
||||||
|
//
|
||||||
int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm)
|
int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm)
|
||||||
{
|
{
|
||||||
return compareVideoModes(fm, sm);
|
return compareVideoModes(fm, sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Splits a color depth into red, green and blue bit depths
|
||||||
|
//
|
||||||
void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
|
void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
|
||||||
{
|
{
|
||||||
int delta;
|
int delta;
|
||||||
@@ -306,6 +294,7 @@ void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
|
|||||||
GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
|
GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
|
||||||
{
|
{
|
||||||
assert(count != NULL);
|
assert(count != NULL);
|
||||||
|
|
||||||
*count = 0;
|
*count = 0;
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
@@ -357,6 +346,21 @@ GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int*
|
|||||||
*heightMM = monitor->heightMM;
|
*heightMM = monitor->heightMM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* handle,
|
||||||
|
float* xscale, float* yscale)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
|
||||||
|
if (xscale)
|
||||||
|
*xscale = 0.f;
|
||||||
|
if (yscale)
|
||||||
|
*yscale = 0.f;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
_glfwPlatformGetMonitorContentScale(monitor, xscale, yscale);
|
||||||
|
}
|
||||||
|
|
||||||
GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
|
GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
|
||||||
{
|
{
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
@@ -366,6 +370,24 @@ GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
|
|||||||
return monitor->name;
|
return monitor->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* handle, void* pointer)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
monitor->userPointer = pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* handle)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
return monitor->userPointer;
|
||||||
|
}
|
||||||
|
|
||||||
GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun)
|
GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
@@ -406,6 +428,10 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
|
|||||||
int i;
|
int i;
|
||||||
unsigned short values[256];
|
unsigned short values[256];
|
||||||
GLFWgammaramp ramp;
|
GLFWgammaramp ramp;
|
||||||
|
assert(handle != NULL);
|
||||||
|
assert(gamma == gamma);
|
||||||
|
assert(gamma >= 0.f);
|
||||||
|
assert(gamma <= FLT_MAX);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
@@ -417,16 +443,16 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
|
|||||||
|
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
{
|
{
|
||||||
double value;
|
float value;
|
||||||
|
|
||||||
// Calculate intensity
|
// Calculate intensity
|
||||||
value = i / 255.0;
|
value = i / 255.f;
|
||||||
// Apply gamma curve
|
// Apply gamma curve
|
||||||
value = pow(value, 1.0 / gamma) * 65535.0 + 0.5;
|
value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
|
||||||
|
|
||||||
// Clamp to value range
|
// Clamp to value range
|
||||||
if (value > 65535.0)
|
if (value > 65535.f)
|
||||||
value = 65535.0;
|
value = 65535.f;
|
||||||
|
|
||||||
values[i] = (unsigned short) value;
|
values[i] = (unsigned short) value;
|
||||||
}
|
}
|
||||||
@@ -457,6 +483,7 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
|
|||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
assert(monitor != NULL);
|
assert(monitor != NULL);
|
||||||
assert(ramp != NULL);
|
assert(ramp != NULL);
|
||||||
|
assert(ramp->size > 0);
|
||||||
assert(ramp->red != NULL);
|
assert(ramp->red != NULL);
|
||||||
assert(ramp->green != NULL);
|
assert(ramp->green != NULL);
|
||||||
assert(ramp->blue != NULL);
|
assert(ramp->blue != NULL);
|
||||||
|
|||||||
@@ -24,9 +24,6 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _glfw3_nsgl_context_h_
|
|
||||||
#define _glfw3_nsgl_context_h_
|
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl
|
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl
|
||||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl
|
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl
|
||||||
|
|
||||||
@@ -57,4 +54,3 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
const _GLFWfbconfig* fbconfig);
|
const _GLFWfbconfig* fbconfig);
|
||||||
void _glfwDestroyContextNSGL(_GLFWwindow* window);
|
void _glfwDestroyContextNSGL(_GLFWwindow* window);
|
||||||
|
|
||||||
#endif // _glfw3_nsgl_context_h_
|
|
||||||
|
|||||||
+55
-29
@@ -34,7 +34,7 @@ static void makeContextCurrentNSGL(_GLFWwindow* window)
|
|||||||
else
|
else
|
||||||
[NSOpenGLContext clearCurrentContext];
|
[NSOpenGLContext clearCurrentContext];
|
||||||
|
|
||||||
_glfwPlatformSetCurrentContext(window);
|
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void swapBuffersNSGL(_GLFWwindow* window)
|
static void swapBuffersNSGL(_GLFWwindow* window)
|
||||||
@@ -45,7 +45,7 @@ static void swapBuffersNSGL(_GLFWwindow* window)
|
|||||||
|
|
||||||
static void swapIntervalNSGL(int interval)
|
static void swapIntervalNSGL(int interval)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
|
|
||||||
GLint sync = interval;
|
GLint sync = interval;
|
||||||
[window->context.nsgl.object setValues:&sync
|
[window->context.nsgl.object setValues:&sync
|
||||||
@@ -119,8 +119,6 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig)
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
unsigned int attributeCount = 0;
|
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_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
|
// macOS but are not a hard constraint, so ignore and continue
|
||||||
|
|
||||||
// Context release behaviors (GL_KHR_context_flush_control) are not yet
|
// 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; }
|
// Debug contexts (GL_KHR_debug) are not yet supported by macOS but are not
|
||||||
#define ADD_ATTR2(x, y) { ADD_ATTR(x); ADD_ATTR(y); }
|
// a hard constraint, so ignore and continue
|
||||||
|
|
||||||
// Arbitrary array size here
|
// No-error contexts (GL_KHR_no_error) are not yet supported by macOS but
|
||||||
NSOpenGLPixelFormatAttribute attributes[40];
|
// are not a hard constraint, so ignore and continue
|
||||||
|
|
||||||
ADD_ATTR(NSOpenGLPFAAccelerated);
|
#define addAttrib(a) \
|
||||||
ADD_ATTR(NSOpenGLPFAClosestPolicy);
|
{ \
|
||||||
|
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 MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
|
||||||
if (ctxconfig->major >= 4)
|
if (ctxconfig->major >= 4)
|
||||||
{
|
{
|
||||||
ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
|
setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
||||||
if (ctxconfig->major >= 3)
|
if (ctxconfig->major >= 3)
|
||||||
{
|
{
|
||||||
ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
|
setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig->major <= 2)
|
if (ctxconfig->major <= 2)
|
||||||
{
|
{
|
||||||
if (fbconfig->auxBuffers != GLFW_DONT_CARE)
|
if (fbconfig->auxBuffers != GLFW_DONT_CARE)
|
||||||
ADD_ATTR2(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
|
setAttrib(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
|
||||||
|
|
||||||
if (fbconfig->accumRedBits != GLFW_DONT_CARE &&
|
if (fbconfig->accumRedBits != GLFW_DONT_CARE &&
|
||||||
fbconfig->accumGreenBits != GLFW_DONT_CARE &&
|
fbconfig->accumGreenBits != GLFW_DONT_CARE &&
|
||||||
@@ -187,7 +207,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
fbconfig->accumBlueBits +
|
fbconfig->accumBlueBits +
|
||||||
fbconfig->accumAlphaBits;
|
fbconfig->accumAlphaBits;
|
||||||
|
|
||||||
ADD_ATTR2(NSOpenGLPFAAccumSize, accumBits);
|
setAttrib(NSOpenGLPFAAccumSize, accumBits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,17 +225,17 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
else if (colorBits < 15)
|
else if (colorBits < 15)
|
||||||
colorBits = 15;
|
colorBits = 15;
|
||||||
|
|
||||||
ADD_ATTR2(NSOpenGLPFAColorSize, colorBits);
|
setAttrib(NSOpenGLPFAColorSize, colorBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fbconfig->alphaBits != GLFW_DONT_CARE)
|
if (fbconfig->alphaBits != GLFW_DONT_CARE)
|
||||||
ADD_ATTR2(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
|
setAttrib(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
|
||||||
|
|
||||||
if (fbconfig->depthBits != GLFW_DONT_CARE)
|
if (fbconfig->depthBits != GLFW_DONT_CARE)
|
||||||
ADD_ATTR2(NSOpenGLPFADepthSize, fbconfig->depthBits);
|
setAttrib(NSOpenGLPFADepthSize, fbconfig->depthBits);
|
||||||
|
|
||||||
if (fbconfig->stencilBits != GLFW_DONT_CARE)
|
if (fbconfig->stencilBits != GLFW_DONT_CARE)
|
||||||
ADD_ATTR2(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
|
setAttrib(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
|
||||||
|
|
||||||
if (fbconfig->stereo)
|
if (fbconfig->stereo)
|
||||||
{
|
{
|
||||||
@@ -224,36 +244,36 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
"NSGL: Stereo rendering is deprecated");
|
"NSGL: Stereo rendering is deprecated");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
#else
|
#else
|
||||||
ADD_ATTR(NSOpenGLPFAStereo);
|
addAttrib(NSOpenGLPFAStereo);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fbconfig->doublebuffer)
|
if (fbconfig->doublebuffer)
|
||||||
ADD_ATTR(NSOpenGLPFADoubleBuffer);
|
addAttrib(NSOpenGLPFADoubleBuffer);
|
||||||
|
|
||||||
if (fbconfig->samples != GLFW_DONT_CARE)
|
if (fbconfig->samples != GLFW_DONT_CARE)
|
||||||
{
|
{
|
||||||
if (fbconfig->samples == 0)
|
if (fbconfig->samples == 0)
|
||||||
{
|
{
|
||||||
ADD_ATTR2(NSOpenGLPFASampleBuffers, 0);
|
setAttrib(NSOpenGLPFASampleBuffers, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ADD_ATTR2(NSOpenGLPFASampleBuffers, 1);
|
setAttrib(NSOpenGLPFASampleBuffers, 1);
|
||||||
ADD_ATTR2(NSOpenGLPFASamples, fbconfig->samples);
|
setAttrib(NSOpenGLPFASamples, fbconfig->samples);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB
|
// NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB
|
||||||
// framebuffer, so there's no need (and no way) to request it
|
// framebuffer, so there's no need (and no way) to request it
|
||||||
|
|
||||||
ADD_ATTR(0);
|
addAttrib(0);
|
||||||
|
|
||||||
#undef ADD_ATTR
|
#undef addAttrib
|
||||||
#undef ADD_ATTR2
|
#undef setAttrib
|
||||||
|
|
||||||
window->context.nsgl.pixelFormat =
|
window->context.nsgl.pixelFormat =
|
||||||
[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
|
[[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
|
||||||
if (window->context.nsgl.pixelFormat == nil)
|
if (window->context.nsgl.pixelFormat == nil)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
@@ -276,6 +296,12 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
return GLFW_FALSE;
|
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.nsgl.object setView:window->ns.view];
|
||||||
|
|
||||||
window->context.makeCurrent = makeContextCurrentNSGL;
|
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) 2016 Google Inc.
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||||
@@ -34,9 +34,6 @@
|
|||||||
|
|
||||||
int _glfwPlatformInit(void)
|
int _glfwPlatformInit(void)
|
||||||
{
|
{
|
||||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
_glfwInitTimerPOSIX();
|
_glfwInitTimerPOSIX();
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
@@ -44,11 +41,10 @@ int _glfwPlatformInit(void)
|
|||||||
void _glfwPlatformTerminate(void)
|
void _glfwPlatformTerminate(void)
|
||||||
{
|
{
|
||||||
_glfwTerminateOSMesa();
|
_glfwTerminateOSMesa();
|
||||||
_glfwTerminateThreadLocalStoragePOSIX();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
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>
|
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
@@ -28,41 +27,16 @@
|
|||||||
#include "internal.h"
|
#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 //////
|
////// 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) 2016 Google Inc.
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||||
@@ -32,22 +32,19 @@
|
|||||||
////// GLFW platform API //////
|
////// 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 _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)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||||
{
|
{
|
||||||
return NULL;
|
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) 2016 Google Inc.
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// 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>
|
#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_MONITOR_STATE
|
||||||
#define _GLFW_PLATFORM_CURSOR_STATE
|
#define _GLFW_PLATFORM_CURSOR_STATE
|
||||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_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_CONTEXT_STATE
|
||||||
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE
|
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE
|
||||||
|
|
||||||
#include "osmesa_context.h"
|
#include "osmesa_context.h"
|
||||||
#include "posix_time.h"
|
#include "posix_time.h"
|
||||||
#include "posix_tls.h"
|
#include "posix_thread.h"
|
||||||
|
#include "null_joystick.h"
|
||||||
|
|
||||||
#if defined(_GLFW_WIN32)
|
#if defined(_GLFW_WIN32)
|
||||||
#define _glfw_dlopen(name) LoadLibraryA(name)
|
#define _glfw_dlopen(name) LoadLibraryA(name)
|
||||||
@@ -53,13 +52,11 @@
|
|||||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// OSMesa-specific per-window data
|
// Null-specific per-window data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWwindowOSMesa
|
typedef struct _GLFWwindowNull
|
||||||
{
|
{
|
||||||
int width;
|
int width;
|
||||||
int height;
|
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) 2016 Google Inc.
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||||
@@ -31,8 +31,8 @@
|
|||||||
static int createNativeWindow(_GLFWwindow* window,
|
static int createNativeWindow(_GLFWwindow* window,
|
||||||
const _GLFWwndconfig* wndconfig)
|
const _GLFWwndconfig* wndconfig)
|
||||||
{
|
{
|
||||||
window->osmesa.width = wndconfig->width;
|
window->null.width = wndconfig->width;
|
||||||
window->osmesa.height = wndconfig->height;
|
window->null.height = wndconfig->height;
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (ctxconfig->client != GLFW_NO_API)
|
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())
|
if (!_glfwInitOSMesa())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
@@ -61,7 +62,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: EGL not available");
|
_glfwInputError(GLFW_API_UNAVAILABLE, "Null: EGL not available");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,15 +104,15 @@ void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
|
|||||||
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
||||||
{
|
{
|
||||||
if (width)
|
if (width)
|
||||||
*width = window->osmesa.width;
|
*width = window->null.width;
|
||||||
if (height)
|
if (height)
|
||||||
*height = window->osmesa.height;
|
*height = window->null.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
||||||
{
|
{
|
||||||
window->osmesa.width = width;
|
window->null.width = width;
|
||||||
window->osmesa.height = height;
|
window->null.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||||
@@ -127,19 +128,24 @@ void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int n, int d)
|
|||||||
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
|
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
|
||||||
{
|
{
|
||||||
if (width)
|
if (width)
|
||||||
*width = window->osmesa.width;
|
*width = window->null.width;
|
||||||
if (height)
|
if (height)
|
||||||
*height = window->osmesa.height;
|
*height = window->null.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||||
int* left, int* top,
|
int* left, int* top,
|
||||||
int* right, int* bottom)
|
int* right, int* bottom)
|
||||||
{
|
{
|
||||||
if (right)
|
}
|
||||||
*right = window->osmesa.width;
|
|
||||||
if (bottom)
|
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
||||||
*top = window->osmesa.height;
|
float* xscale, float* yscale)
|
||||||
|
{
|
||||||
|
if (xscale)
|
||||||
|
*xscale = 1.f;
|
||||||
|
if (yscale)
|
||||||
|
*yscale = 1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||||
@@ -159,6 +165,16 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
|||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
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 _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
|
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -230,10 +260,6 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformApplyCursorMode(_GLFWwindow* window)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||||
const GLFWimage* image,
|
const GLFWimage* image,
|
||||||
int xhot, int yhot)
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetKeyName(int key, int scancode)
|
const char* _glfwPlatformGetScancodeName(int scancode)
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -273,26 +299,6 @@ int _glfwPlatformGetKeyScancode(int key)
|
|||||||
return -1;
|
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)
|
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
+17
-14
@@ -36,25 +36,26 @@ static void makeContextCurrentOSMesa(_GLFWwindow* window)
|
|||||||
{
|
{
|
||||||
if (window)
|
if (window)
|
||||||
{
|
{
|
||||||
|
int width, height;
|
||||||
|
_glfwPlatformGetFramebufferSize(window, &width, &height);
|
||||||
|
|
||||||
// Check to see if we need to allocate a new buffer
|
// Check to see if we need to allocate a new buffer
|
||||||
if ((window->context.osmesa.buffer == NULL) ||
|
if ((window->context.osmesa.buffer == NULL) ||
|
||||||
(window->osmesa.width != window->context.osmesa.width) ||
|
(width != window->context.osmesa.width) ||
|
||||||
(window->osmesa.height != window->context.osmesa.height))
|
(height != window->context.osmesa.height))
|
||||||
{
|
{
|
||||||
free(window->context.osmesa.buffer);
|
free(window->context.osmesa.buffer);
|
||||||
|
|
||||||
// Allocate the new buffer (width * height * 8-bit RGBA)
|
// Allocate the new buffer (width * height * 8-bit RGBA)
|
||||||
window->context.osmesa.buffer =
|
window->context.osmesa.buffer = calloc(4, width * height);
|
||||||
calloc(4, window->osmesa.width * window->osmesa.height);
|
window->context.osmesa.width = width;
|
||||||
|
window->context.osmesa.height = height;
|
||||||
window->context.osmesa.width = window->osmesa.width;
|
|
||||||
window->context.osmesa.height = window->osmesa.height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!OSMesaMakeCurrent(window->context.osmesa.handle,
|
if (!OSMesaMakeCurrent(window->context.osmesa.handle,
|
||||||
window->context.osmesa.buffer,
|
window->context.osmesa.buffer,
|
||||||
GL_UNSIGNED_BYTE,
|
GL_UNSIGNED_BYTE,
|
||||||
window->osmesa.width, window->osmesa.height))
|
width, height))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"OSMesa: Failed to make context current");
|
"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)
|
static GLFWglproc getProcAddressOSMesa(const char* procname)
|
||||||
@@ -112,7 +113,9 @@ GLFWbool _glfwInitOSMesa(void)
|
|||||||
int i;
|
int i;
|
||||||
const char* sonames[] =
|
const char* sonames[] =
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_GLFW_OSMESA_LIBRARY)
|
||||||
|
_GLFW_OSMESA_LIBRARY,
|
||||||
|
#elif defined(_WIN32)
|
||||||
"libOSMesa.dll",
|
"libOSMesa.dll",
|
||||||
"OSMesa.dll",
|
"OSMesa.dll",
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
@@ -183,11 +186,11 @@ void _glfwTerminateOSMesa(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define setAttrib(attribName, attribValue) \
|
#define setAttrib(a, v) \
|
||||||
{ \
|
{ \
|
||||||
attribs[index++] = attribName; \
|
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||||
attribs[index++] = attribValue; \
|
attribs[index++] = a; \
|
||||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
attribs[index++] = v; \
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||||
|
|||||||
@@ -25,9 +25,6 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _glfw3_osmesa_context_h_
|
|
||||||
#define _glfw3_osmesa_context_h_
|
|
||||||
|
|
||||||
#define OSMESA_RGBA 0x1908
|
#define OSMESA_RGBA 0x1908
|
||||||
#define OSMESA_FORMAT 0x22
|
#define OSMESA_FORMAT 0x22
|
||||||
#define OSMESA_DEPTH_BITS 0x30
|
#define OSMESA_DEPTH_BITS 0x30
|
||||||
@@ -40,7 +37,7 @@
|
|||||||
#define OSMESA_CONTEXT_MINOR_VERSION 0x37
|
#define OSMESA_CONTEXT_MINOR_VERSION 0x37
|
||||||
|
|
||||||
typedef void* OSMesaContext;
|
typedef void* OSMesaContext;
|
||||||
typedef void (*OSMESAproc)();
|
typedef void (*OSMESAproc)(void);
|
||||||
|
|
||||||
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextExt)(GLenum,GLint,GLint,GLint,OSMesaContext);
|
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextExt)(GLenum,GLint,GLint,GLint,OSMesaContext);
|
||||||
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextAttribs)(const int*,OSMesaContext);
|
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextAttribs)(const int*,OSMesaContext);
|
||||||
@@ -57,8 +54,8 @@ typedef GLFWglproc (GLAPIENTRY * PFN_OSMesaGetProcAddress)(const char*);
|
|||||||
#define OSMesaGetDepthBuffer _glfw.osmesa.GetDepthBuffer
|
#define OSMesaGetDepthBuffer _glfw.osmesa.GetDepthBuffer
|
||||||
#define OSMesaGetProcAddress _glfw.osmesa.GetProcAddress
|
#define OSMesaGetProcAddress _glfw.osmesa.GetProcAddress
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextOSMesa osmesa
|
#define _GLFW_OSMESA_CONTEXT_STATE _GLFWcontextOSMesa osmesa
|
||||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryOSMesa osmesa
|
#define _GLFW_OSMESA_LIBRARY_CONTEXT_STATE _GLFWlibraryOSMesa osmesa
|
||||||
|
|
||||||
|
|
||||||
// OSMesa-specific per-context data
|
// OSMesa-specific per-context data
|
||||||
@@ -95,4 +92,3 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
|||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig);
|
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>
|
#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
|
typedef struct _GLFWtlsPOSIX
|
||||||
{
|
{
|
||||||
GLFWbool allocated;
|
GLFWbool allocated;
|
||||||
pthread_key_t context;
|
pthread_key_t key;
|
||||||
|
|
||||||
} _GLFWtlsPOSIX;
|
} _GLFWtlsPOSIX;
|
||||||
|
|
||||||
|
// POSIX-specific mutex data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWmutexPOSIX
|
||||||
|
{
|
||||||
|
GLFWbool allocated;
|
||||||
|
pthread_mutex_t handle;
|
||||||
|
|
||||||
GLFWbool _glfwInitThreadLocalStoragePOSIX(void);
|
} _GLFWmutexPOSIX;
|
||||||
void _glfwTerminateThreadLocalStoragePOSIX(void);
|
|
||||||
|
|
||||||
#endif // _glfw3_posix_tls_h_
|
|
||||||
+6
-6
@@ -44,14 +44,14 @@ void _glfwInitTimerPOSIX(void)
|
|||||||
|
|
||||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
||||||
{
|
{
|
||||||
_glfw.posix_time.monotonic = GLFW_TRUE;
|
_glfw.timer.posix.monotonic = GLFW_TRUE;
|
||||||
_glfw.posix_time.frequency = 1000000000;
|
_glfw.timer.posix.frequency = 1000000000;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
_glfw.posix_time.monotonic = GLFW_FALSE;
|
_glfw.timer.posix.monotonic = GLFW_FALSE;
|
||||||
_glfw.posix_time.frequency = 1000000;
|
_glfw.timer.posix.frequency = 1000000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ void _glfwInitTimerPOSIX(void)
|
|||||||
uint64_t _glfwPlatformGetTimerValue(void)
|
uint64_t _glfwPlatformGetTimerValue(void)
|
||||||
{
|
{
|
||||||
#if defined(CLOCK_MONOTONIC)
|
#if defined(CLOCK_MONOTONIC)
|
||||||
if (_glfw.posix_time.monotonic)
|
if (_glfw.timer.posix.monotonic)
|
||||||
{
|
{
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
@@ -80,6 +80,6 @@ uint64_t _glfwPlatformGetTimerValue(void)
|
|||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerFrequency(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 _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerPOSIX posix
|
||||||
#define _glfw3_posix_time_h_
|
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimePOSIX posix_time
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
// POSIX-specific global timer data
|
// POSIX-specific global timer data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWtimePOSIX
|
typedef struct _GLFWtimerPOSIX
|
||||||
{
|
{
|
||||||
GLFWbool monotonic;
|
GLFWbool monotonic;
|
||||||
uint64_t frequency;
|
uint64_t frequency;
|
||||||
|
|
||||||
} _GLFWtimePOSIX;
|
} _GLFWtimerPOSIX;
|
||||||
|
|
||||||
|
|
||||||
void _glfwInitTimerPOSIX(void);
|
void _glfwInitTimerPOSIX(void);
|
||||||
|
|
||||||
#endif // _glfw3_posix_time_h_
|
|
||||||
|
|||||||
+24
-13
@@ -49,11 +49,12 @@ GLFWbool _glfwInitVulkan(int mode)
|
|||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
|
|
||||||
#if !defined(_GLFW_VULKAN_STATIC)
|
#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");
|
_glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
|
||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
// NULL maps to RTLD_DEFAULT, which searches all loaded binaries
|
_glfw.vk.handle = _glfw_dlopen("libMoltenVK.dylib");
|
||||||
_glfw.vk.handle = _glfw_dlopen(NULL);
|
|
||||||
#else
|
#else
|
||||||
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
|
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
|
||||||
#endif
|
#endif
|
||||||
@@ -69,16 +70,8 @@ GLFWbool _glfwInitVulkan(int mode)
|
|||||||
_glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
|
_glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
|
||||||
if (!_glfw.vk.GetInstanceProcAddr)
|
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,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"Vulkan: Loader does not export vkGetInstanceProcAddr");
|
"Vulkan: Loader does not export vkGetInstanceProcAddr");
|
||||||
#endif
|
|
||||||
|
|
||||||
_glfwTerminateVulkan();
|
_glfwTerminateVulkan();
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
@@ -99,9 +92,13 @@ GLFWbool _glfwInitVulkan(int mode)
|
|||||||
err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
|
err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
// NOTE: This happens on systems with a loader but without any Vulkan ICD
|
||||||
|
if (mode == _GLFW_REQUIRE_LOADER)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"Vulkan: Failed to query instance extension count: %s",
|
"Vulkan: Failed to query instance extension count: %s",
|
||||||
_glfwGetVulkanResultString(err));
|
_glfwGetVulkanResultString(err));
|
||||||
|
}
|
||||||
|
|
||||||
_glfwTerminateVulkan();
|
_glfwTerminateVulkan();
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
@@ -112,7 +109,7 @@ GLFWbool _glfwInitVulkan(int mode)
|
|||||||
err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep);
|
err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"Vulkan: Failed to query instance extensions: %s",
|
"Vulkan: Failed to query instance extensions: %s",
|
||||||
_glfwGetVulkanResultString(err));
|
_glfwGetVulkanResultString(err));
|
||||||
|
|
||||||
@@ -230,6 +227,8 @@ GLFWAPI int glfwVulkanSupported(void)
|
|||||||
|
|
||||||
GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
|
GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
|
||||||
{
|
{
|
||||||
|
assert(count != NULL);
|
||||||
|
|
||||||
*count = 0;
|
*count = 0;
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
@@ -248,6 +247,7 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
|
|||||||
const char* procname)
|
const char* procname)
|
||||||
{
|
{
|
||||||
GLFWvkproc proc;
|
GLFWvkproc proc;
|
||||||
|
assert(procname != NULL);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
@@ -273,6 +273,9 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
|
|||||||
VkPhysicalDevice device,
|
VkPhysicalDevice device,
|
||||||
uint32_t queuefamily)
|
uint32_t queuefamily)
|
||||||
{
|
{
|
||||||
|
assert(instance != VK_NULL_HANDLE);
|
||||||
|
assert(device != VK_NULL_HANDLE);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
|
|
||||||
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||||
@@ -296,6 +299,7 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
|
|||||||
VkSurfaceKHR* surface)
|
VkSurfaceKHR* surface)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(instance != VK_NULL_HANDLE);
|
||||||
assert(window != NULL);
|
assert(window != NULL);
|
||||||
assert(surface != NULL);
|
assert(surface != NULL);
|
||||||
|
|
||||||
@@ -313,6 +317,13 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
|
|||||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window->context.client != GLFW_NO_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"Vulkan: Window surface creation requires the window to have the client API set to GLFW_NO_API");
|
||||||
|
return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
|
||||||
|
}
|
||||||
|
|
||||||
return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface);
|
return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+113
-103
@@ -44,9 +44,8 @@ static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib
|
|||||||
pixelFormat,
|
pixelFormat,
|
||||||
0, 1, &attrib, &value))
|
0, 1, &attrib, &value))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"WGL: Failed to retrieve pixel format attribute %i",
|
"WGL: Failed to retrieve pixel format attribute");
|
||||||
attrib);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +54,9 @@ static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib
|
|||||||
|
|
||||||
// Return a list of available and usable framebuffer configs
|
// Return a list of available and usable framebuffer configs
|
||||||
//
|
//
|
||||||
static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired)
|
static int choosePixelFormat(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
_GLFWfbconfig* usableConfigs;
|
_GLFWfbconfig* usableConfigs;
|
||||||
const _GLFWfbconfig* closest;
|
const _GLFWfbconfig* closest;
|
||||||
@@ -128,6 +129,8 @@ static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired)
|
|||||||
if (_glfw.wgl.ARB_multisample)
|
if (_glfw.wgl.ARB_multisample)
|
||||||
u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
|
u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
|
||||||
|
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||||
|
{
|
||||||
if (_glfw.wgl.ARB_framebuffer_sRGB ||
|
if (_glfw.wgl.ARB_framebuffer_sRGB ||
|
||||||
_glfw.wgl.EXT_framebuffer_sRGB)
|
_glfw.wgl.EXT_framebuffer_sRGB)
|
||||||
{
|
{
|
||||||
@@ -137,10 +140,22 @@ static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PIXELFORMATDESCRIPTOR pfd;
|
if (_glfw.wgl.EXT_colorspace)
|
||||||
|
{
|
||||||
|
if (getPixelFormatAttrib(window, n, WGL_COLORSPACE_EXT) ==
|
||||||
|
WGL_COLORSPACE_SRGB_EXT)
|
||||||
|
{
|
||||||
|
u->sRGB = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Get pixel format attributes through legacy PFDs
|
// Get pixel format attributes through legacy PFDs
|
||||||
|
|
||||||
|
PIXELFORMATDESCRIPTOR pfd;
|
||||||
|
|
||||||
if (!DescribePixelFormat(window->context.wgl.dc,
|
if (!DescribePixelFormat(window->context.wgl.dc,
|
||||||
n,
|
n,
|
||||||
sizeof(PIXELFORMATDESCRIPTOR),
|
sizeof(PIXELFORMATDESCRIPTOR),
|
||||||
@@ -198,7 +213,7 @@ static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
|
closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);
|
||||||
if (!closest)
|
if (!closest)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
@@ -214,54 +229,39 @@ static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired)
|
|||||||
return pixelFormat;
|
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)
|
static void makeContextCurrentWGL(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window)
|
if (window)
|
||||||
{
|
{
|
||||||
if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
|
if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
|
||||||
_glfwPlatformSetCurrentContext(window);
|
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"WGL: Failed to make context current");
|
"WGL: Failed to make context current");
|
||||||
_glfwPlatformSetCurrentContext(NULL);
|
_glfwPlatformSetTls(&_glfw.contextSlot, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!wglMakeCurrent(NULL, NULL))
|
if (!wglMakeCurrent(NULL, NULL))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"WGL: Failed to clear current context");
|
"WGL: Failed to clear current context");
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwPlatformSetCurrentContext(NULL);
|
_glfwPlatformSetTls(&_glfw.contextSlot, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void swapBuffersWGL(_GLFWwindow* window)
|
static void swapBuffersWGL(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
// HACK: Use DwmFlush when desktop composition is enabled
|
// HACK: Use DwmFlush when desktop composition is enabled
|
||||||
if (isCompositionEnabled() && !window->monitor)
|
if (_glfwIsCompositionEnabledWin32() && !window->monitor)
|
||||||
{
|
{
|
||||||
int count = abs(window->context.wgl.interval);
|
int count = abs(window->context.wgl.interval);
|
||||||
while (count--)
|
while (count--)
|
||||||
_glfw_DwmFlush();
|
DwmFlush();
|
||||||
}
|
}
|
||||||
|
|
||||||
SwapBuffers(window->context.wgl.dc);
|
SwapBuffers(window->context.wgl.dc);
|
||||||
@@ -269,13 +269,13 @@ static void swapBuffersWGL(_GLFWwindow* window)
|
|||||||
|
|
||||||
static void swapIntervalWGL(int interval)
|
static void swapIntervalWGL(int interval)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
|
|
||||||
window->context.wgl.interval = interval;
|
window->context.wgl.interval = interval;
|
||||||
|
|
||||||
// HACK: Disable WGL swap interval when desktop composition is enabled to
|
// HACK: Disable WGL swap interval when desktop composition is enabled to
|
||||||
// avoid interfering with DWM vsync
|
// avoid interfering with DWM vsync
|
||||||
if (isCompositionEnabled() && !window->monitor)
|
if (_glfwIsCompositionEnabledWin32() && !window->monitor)
|
||||||
interval = 0;
|
interval = 0;
|
||||||
|
|
||||||
if (_glfw.wgl.EXT_swap_control)
|
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;
|
PIXELFORMATDESCRIPTOR pfd;
|
||||||
HGLRC rc;
|
HGLRC prc, rc;
|
||||||
HDC dc = GetDC(_glfw.win32.helperWindowHandle);;
|
HDC pdc, dc;
|
||||||
|
|
||||||
_glfw.wgl.extensionsLoaded = GLFW_TRUE;
|
if (_glfw.wgl.instance)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
_glfw.wgl.instance = LoadLibraryA("opengl32.dll");
|
||||||
|
if (!_glfw.wgl.instance)
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to load opengl32.dll");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.wgl.CreateContext = (PFN_wglCreateContext)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
|
||||||
|
_glfw.wgl.DeleteContext = (PFN_wglDeleteContext)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
|
||||||
|
_glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
|
||||||
|
_glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
|
||||||
|
_glfw.wgl.GetCurrentContext = (PFN_wglGetCurrentContext)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentContext");
|
||||||
|
_glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
|
||||||
|
_glfw.wgl.ShareLists = (PFN_wglShareLists)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglShareLists");
|
||||||
|
|
||||||
// NOTE: A dummy context has to be created for opengl32.dll to load the
|
// NOTE: A dummy context has to be created for opengl32.dll to load the
|
||||||
// OpenGL ICD, from which we can then query WGL extensions
|
// OpenGL ICD, from which we can then query WGL extensions
|
||||||
// NOTE: This code will accept the Microsoft GDI ICD; accelerated context
|
// NOTE: This code will accept the Microsoft GDI ICD; accelerated context
|
||||||
// creation failure occurs during manual pixel format enumeration
|
// creation failure occurs during manual pixel format enumeration
|
||||||
|
|
||||||
|
dc = GetDC(_glfw.win32.helperWindowHandle);;
|
||||||
|
|
||||||
ZeroMemory(&pfd, sizeof(pfd));
|
ZeroMemory(&pfd, sizeof(pfd));
|
||||||
pfd.nSize = sizeof(pfd);
|
pfd.nSize = sizeof(pfd);
|
||||||
pfd.nVersion = 1;
|
pfd.nVersion = 1;
|
||||||
@@ -353,26 +384,29 @@ static void loadWGLExtensions(void)
|
|||||||
|
|
||||||
if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd))
|
if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"WGL: Failed to set pixel format for dummy context");
|
"WGL: Failed to set pixel format for dummy context");
|
||||||
return;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = wglCreateContext(dc);
|
rc = wglCreateContext(dc);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"WGL: Failed to create dummy context");
|
"WGL: Failed to create dummy context");
|
||||||
return;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pdc = wglGetCurrentDC();
|
||||||
|
prc = wglGetCurrentContext();
|
||||||
|
|
||||||
if (!wglMakeCurrent(dc, rc))
|
if (!wglMakeCurrent(dc, rc))
|
||||||
{
|
{
|
||||||
wglDeleteContext(rc);
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to make dummy context current");
|
"WGL: Failed to make dummy context current");
|
||||||
return;
|
wglMakeCurrent(pdc, prc);
|
||||||
|
wglDeleteContext(rc);
|
||||||
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Functions must be loaded first as they're needed to retrieve the
|
// NOTE: Functions must be loaded first as they're needed to retrieve the
|
||||||
@@ -404,49 +438,19 @@ static void loadWGLExtensions(void)
|
|||||||
extensionSupportedWGL("WGL_EXT_create_context_es2_profile");
|
extensionSupportedWGL("WGL_EXT_create_context_es2_profile");
|
||||||
_glfw.wgl.ARB_create_context_robustness =
|
_glfw.wgl.ARB_create_context_robustness =
|
||||||
extensionSupportedWGL("WGL_ARB_create_context_robustness");
|
extensionSupportedWGL("WGL_ARB_create_context_robustness");
|
||||||
|
_glfw.wgl.ARB_create_context_no_error =
|
||||||
|
extensionSupportedWGL("WGL_ARB_create_context_no_error");
|
||||||
_glfw.wgl.EXT_swap_control =
|
_glfw.wgl.EXT_swap_control =
|
||||||
extensionSupportedWGL("WGL_EXT_swap_control");
|
extensionSupportedWGL("WGL_EXT_swap_control");
|
||||||
|
_glfw.wgl.EXT_colorspace =
|
||||||
|
extensionSupportedWGL("WGL_EXT_colorspace");
|
||||||
_glfw.wgl.ARB_pixel_format =
|
_glfw.wgl.ARB_pixel_format =
|
||||||
extensionSupportedWGL("WGL_ARB_pixel_format");
|
extensionSupportedWGL("WGL_ARB_pixel_format");
|
||||||
_glfw.wgl.ARB_context_flush_control =
|
_glfw.wgl.ARB_context_flush_control =
|
||||||
extensionSupportedWGL("WGL_ARB_context_flush_control");
|
extensionSupportedWGL("WGL_ARB_context_flush_control");
|
||||||
|
|
||||||
wglMakeCurrent(dc, NULL);
|
wglMakeCurrent(pdc, prc);
|
||||||
wglDeleteContext(rc);
|
wglDeleteContext(rc);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Initialize WGL
|
|
||||||
//
|
|
||||||
GLFWbool _glfwInitWGL(void)
|
|
||||||
{
|
|
||||||
if (_glfw.wgl.instance)
|
|
||||||
return GLFW_TRUE;
|
|
||||||
|
|
||||||
_glfw.wgl.instance = LoadLibraryA("opengl32.dll");
|
|
||||||
if (!_glfw.wgl.instance)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "WGL: Failed to load opengl32.dll");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.wgl.CreateContext = (PFN_wglCreateContext)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
|
|
||||||
_glfw.wgl.DeleteContext = (PFN_wglDeleteContext)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
|
|
||||||
_glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
|
|
||||||
_glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
|
|
||||||
_glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
|
|
||||||
_glfw.wgl.ShareLists = (PFN_wglShareLists)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglShareLists");
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,11 +462,11 @@ void _glfwTerminateWGL(void)
|
|||||||
FreeLibrary(_glfw.wgl.instance);
|
FreeLibrary(_glfw.wgl.instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define setWGLattrib(attribName, attribValue) \
|
#define setAttrib(a, v) \
|
||||||
{ \
|
{ \
|
||||||
attribs[index++] = attribName; \
|
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||||
attribs[index++] = attribValue; \
|
attribs[index++] = a; \
|
||||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
attribs[index++] = v; \
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the OpenGL or OpenGL ES context
|
// Create the OpenGL or OpenGL ES context
|
||||||
@@ -476,9 +480,6 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
PIXELFORMATDESCRIPTOR pfd;
|
PIXELFORMATDESCRIPTOR pfd;
|
||||||
HGLRC share = NULL;
|
HGLRC share = NULL;
|
||||||
|
|
||||||
if (!_glfw.wgl.extensionsLoaded)
|
|
||||||
loadWGLExtensions();
|
|
||||||
|
|
||||||
if (ctxconfig->share)
|
if (ctxconfig->share)
|
||||||
share = ctxconfig->share->context.wgl.handle;
|
share = ctxconfig->share->context.wgl.handle;
|
||||||
|
|
||||||
@@ -490,21 +491,21 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixelFormat = choosePixelFormat(window, fbconfig);
|
pixelFormat = choosePixelFormat(window, ctxconfig, fbconfig);
|
||||||
if (!pixelFormat)
|
if (!pixelFormat)
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
if (!DescribePixelFormat(window->context.wgl.dc,
|
if (!DescribePixelFormat(window->context.wgl.dc,
|
||||||
pixelFormat, sizeof(pfd), &pfd))
|
pixelFormat, sizeof(pfd), &pfd))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"WGL: Failed to retrieve PFD for selected pixel format");
|
"WGL: Failed to retrieve PFD for selected pixel format");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
|
if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"WGL: Failed to set selected pixel format");
|
"WGL: Failed to set selected pixel format");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
@@ -562,8 +563,6 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (ctxconfig->debug)
|
if (ctxconfig->debug)
|
||||||
flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
|
flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
|
||||||
if (ctxconfig->noerror)
|
|
||||||
flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;
|
|
||||||
|
|
||||||
if (ctxconfig->robustness)
|
if (ctxconfig->robustness)
|
||||||
{
|
{
|
||||||
@@ -571,12 +570,12 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||||
{
|
{
|
||||||
setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||||
WGL_NO_RESET_NOTIFICATION_ARB);
|
WGL_NO_RESET_NOTIFICATION_ARB);
|
||||||
}
|
}
|
||||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||||
{
|
{
|
||||||
setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||||
WGL_LOSE_CONTEXT_ON_RESET_ARB);
|
WGL_LOSE_CONTEXT_ON_RESET_ARB);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,33 +589,39 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||||
{
|
{
|
||||||
setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||||
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||||
}
|
}
|
||||||
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||||
{
|
{
|
||||||
setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||||
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->noerror)
|
||||||
|
{
|
||||||
|
if (_glfw.wgl.ARB_create_context_no_error)
|
||||||
|
setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: Only request an explicitly versioned context when necessary, as
|
// NOTE: Only request an explicitly versioned context when necessary, as
|
||||||
// explicitly requesting version 1.0 does not always return the
|
// explicitly requesting version 1.0 does not always return the
|
||||||
// highest version supported by the driver
|
// highest version supported by the driver
|
||||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||||
{
|
{
|
||||||
setWGLattrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
setAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||||
setWGLattrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
setAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags)
|
if (flags)
|
||||||
setWGLattrib(WGL_CONTEXT_FLAGS_ARB, flags);
|
setAttrib(WGL_CONTEXT_FLAGS_ARB, flags);
|
||||||
|
|
||||||
if (mask)
|
if (mask)
|
||||||
setWGLattrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
|
setAttrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||||
|
|
||||||
setWGLattrib(0, 0);
|
setAttrib(0, 0);
|
||||||
|
|
||||||
window->context.wgl.handle =
|
window->context.wgl.handle =
|
||||||
_glfw.wgl.CreateContextAttribsARB(window->context.wgl.dc,
|
_glfw.wgl.CreateContextAttribsARB(window->context.wgl.dc,
|
||||||
@@ -647,6 +652,11 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
"WGL: Driver does not support the requested OpenGL profile");
|
"WGL: Driver does not support the requested OpenGL profile");
|
||||||
}
|
}
|
||||||
|
else if (error == (0xc0070000 | ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"WGL: The share context is not compatible with the requested context");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||||
@@ -669,7 +679,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
window->context.wgl.handle = wglCreateContext(window->context.wgl.dc);
|
window->context.wgl.handle = wglCreateContext(window->context.wgl.dc);
|
||||||
if (!window->context.wgl.handle)
|
if (!window->context.wgl.handle)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
|
||||||
"WGL: Failed to create OpenGL context");
|
"WGL: Failed to create OpenGL context");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
@@ -678,7 +688,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
if (!wglShareLists(share, window->context.wgl.handle))
|
if (!wglShareLists(share, window->context.wgl.handle))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"WGL: Failed to enable sharing with specified OpenGL context");
|
"WGL: Failed to enable sharing with specified OpenGL context");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
@@ -695,7 +705,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
return GLFW_TRUE;
|
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_NUMBER_PIXEL_FORMATS_ARB 0x2000
|
||||||
#define WGL_SUPPORT_OPENGL_ARB 0x2010
|
#define WGL_SUPPORT_OPENGL_ARB 0x2010
|
||||||
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
|
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
|
||||||
@@ -72,9 +68,13 @@
|
|||||||
#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
|
#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
|
||||||
#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
|
#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
|
||||||
#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
|
#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
|
||||||
|
#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
|
||||||
|
#define WGL_COLORSPACE_EXT 0x309d
|
||||||
|
#define WGL_COLORSPACE_SRGB_EXT 0x3089
|
||||||
|
|
||||||
#define ERROR_INVALID_VERSION_ARB 0x2095
|
#define ERROR_INVALID_VERSION_ARB 0x2095
|
||||||
#define ERROR_INVALID_PROFILE_ARB 0x2096
|
#define ERROR_INVALID_PROFILE_ARB 0x2096
|
||||||
|
#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
|
||||||
|
|
||||||
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
|
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
|
||||||
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);
|
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);
|
||||||
@@ -86,6 +86,7 @@ typedef HGLRC (WINAPI * PFN_wglCreateContext)(HDC);
|
|||||||
typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC);
|
typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC);
|
||||||
typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR);
|
typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR);
|
||||||
typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void);
|
typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void);
|
||||||
|
typedef HGLRC (WINAPI * PFN_wglGetCurrentContext)(void);
|
||||||
typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC);
|
typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC);
|
||||||
typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
|
typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
|
||||||
|
|
||||||
@@ -94,6 +95,7 @@ typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
|
|||||||
#define wglDeleteContext _glfw.wgl.DeleteContext
|
#define wglDeleteContext _glfw.wgl.DeleteContext
|
||||||
#define wglGetProcAddress _glfw.wgl.GetProcAddress
|
#define wglGetProcAddress _glfw.wgl.GetProcAddress
|
||||||
#define wglGetCurrentDC _glfw.wgl.GetCurrentDC
|
#define wglGetCurrentDC _glfw.wgl.GetCurrentDC
|
||||||
|
#define wglGetCurrentContext _glfw.wgl.GetCurrentContext
|
||||||
#define wglMakeCurrent _glfw.wgl.MakeCurrent
|
#define wglMakeCurrent _glfw.wgl.MakeCurrent
|
||||||
#define wglShareLists _glfw.wgl.ShareLists
|
#define wglShareLists _glfw.wgl.ShareLists
|
||||||
|
|
||||||
@@ -124,17 +126,17 @@ typedef struct _GLFWlibraryWGL
|
|||||||
PFN_wglDeleteContext DeleteContext;
|
PFN_wglDeleteContext DeleteContext;
|
||||||
PFN_wglGetProcAddress GetProcAddress;
|
PFN_wglGetProcAddress GetProcAddress;
|
||||||
PFN_wglGetCurrentDC GetCurrentDC;
|
PFN_wglGetCurrentDC GetCurrentDC;
|
||||||
|
PFN_wglGetCurrentContext GetCurrentContext;
|
||||||
PFN_wglMakeCurrent MakeCurrent;
|
PFN_wglMakeCurrent MakeCurrent;
|
||||||
PFN_wglShareLists ShareLists;
|
PFN_wglShareLists ShareLists;
|
||||||
|
|
||||||
GLFWbool extensionsLoaded;
|
|
||||||
|
|
||||||
PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;
|
PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;
|
||||||
PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB;
|
PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB;
|
||||||
PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;
|
PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;
|
||||||
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
|
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
|
||||||
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
|
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
|
||||||
GLFWbool EXT_swap_control;
|
GLFWbool EXT_swap_control;
|
||||||
|
GLFWbool EXT_colorspace;
|
||||||
GLFWbool ARB_multisample;
|
GLFWbool ARB_multisample;
|
||||||
GLFWbool ARB_framebuffer_sRGB;
|
GLFWbool ARB_framebuffer_sRGB;
|
||||||
GLFWbool EXT_framebuffer_sRGB;
|
GLFWbool EXT_framebuffer_sRGB;
|
||||||
@@ -143,6 +145,7 @@ typedef struct _GLFWlibraryWGL
|
|||||||
GLFWbool ARB_create_context_profile;
|
GLFWbool ARB_create_context_profile;
|
||||||
GLFWbool EXT_create_context_es2_profile;
|
GLFWbool EXT_create_context_es2_profile;
|
||||||
GLFWbool ARB_create_context_robustness;
|
GLFWbool ARB_create_context_robustness;
|
||||||
|
GLFWbool ARB_create_context_no_error;
|
||||||
GLFWbool ARB_context_flush_control;
|
GLFWbool ARB_context_flush_control;
|
||||||
|
|
||||||
} _GLFWlibraryWGL;
|
} _GLFWlibraryWGL;
|
||||||
@@ -154,4 +157,3 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig);
|
const _GLFWfbconfig* fbconfig);
|
||||||
|
|
||||||
#endif // _glfw3_wgl_context_h_
|
|
||||||
|
|||||||
+149
-40
@@ -30,8 +30,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
|
||||||
#include <initguid.h>
|
static const GUID _glfw_GUID_DEVINTERFACE_HID =
|
||||||
DEFINE_GUID(GUID_DEVINTERFACE_HID,0x4d1e55b2,0xf16f,0x11cf,0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30);
|
{0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}};
|
||||||
|
|
||||||
|
#define GUID_DEVINTERFACE_HID _glfw_GUID_DEVINTERFACE_HID
|
||||||
|
|
||||||
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
|
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
|
||||||
|
|
||||||
@@ -60,6 +62,17 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
|
|||||||
|
|
||||||
#endif // _GLFW_BUILD_DLL
|
#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)
|
// Load necessary libraries (DLLs)
|
||||||
//
|
//
|
||||||
static GLFWbool loadLibraries(void)
|
static GLFWbool loadLibraries(void)
|
||||||
@@ -67,29 +80,31 @@ static GLFWbool loadLibraries(void)
|
|||||||
_glfw.win32.winmm.instance = LoadLibraryA("winmm.dll");
|
_glfw.win32.winmm.instance = LoadLibraryA("winmm.dll");
|
||||||
if (!_glfw.win32.winmm.instance)
|
if (!_glfw.win32.winmm.instance)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load winmm.dll");
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to load winmm.dll");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.win32.winmm.timeGetTime = (PFN_timeGetTime)
|
_glfw.win32.winmm.GetTime = (PFN_timeGetTime)
|
||||||
GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");
|
GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");
|
||||||
|
|
||||||
_glfw.win32.user32.instance = LoadLibraryA("user32.dll");
|
_glfw.win32.user32.instance = LoadLibraryA("user32.dll");
|
||||||
if (!_glfw.win32.user32.instance)
|
if (!_glfw.win32.user32.instance)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load user32.dll");
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to load user32.dll");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.win32.user32.SetProcessDPIAware = (PFN_SetProcessDPIAware)
|
_glfw.win32.user32.SetProcessDPIAware_ = (PFN_SetProcessDPIAware)
|
||||||
GetProcAddress(_glfw.win32.user32.instance, "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");
|
GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
|
||||||
|
|
||||||
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
|
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
|
||||||
if (_glfw.win32.dinput8.instance)
|
if (_glfw.win32.dinput8.instance)
|
||||||
{
|
{
|
||||||
_glfw.win32.dinput8.DirectInput8Create = (PFN_DirectInput8Create)
|
_glfw.win32.dinput8.Create = (PFN_DirectInput8Create)
|
||||||
GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create");
|
GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,9 +125,9 @@ static GLFWbool loadLibraries(void)
|
|||||||
_glfw.win32.xinput.instance = LoadLibraryA(names[i]);
|
_glfw.win32.xinput.instance = LoadLibraryA(names[i]);
|
||||||
if (_glfw.win32.xinput.instance)
|
if (_glfw.win32.xinput.instance)
|
||||||
{
|
{
|
||||||
_glfw.win32.xinput.XInputGetCapabilities = (PFN_XInputGetCapabilities)
|
_glfw.win32.xinput.GetCapabilities = (PFN_XInputGetCapabilities)
|
||||||
GetProcAddress(_glfw.win32.xinput.instance, "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");
|
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -123,17 +138,21 @@ static GLFWbool loadLibraries(void)
|
|||||||
_glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
|
_glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
|
||||||
if (_glfw.win32.dwmapi.instance)
|
if (_glfw.win32.dwmapi.instance)
|
||||||
{
|
{
|
||||||
_glfw.win32.dwmapi.DwmIsCompositionEnabled = (PFN_DwmIsCompositionEnabled)
|
_glfw.win32.dwmapi.IsCompositionEnabled = (PFN_DwmIsCompositionEnabled)
|
||||||
GetProcAddress(_glfw.win32.dwmapi.instance, "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");
|
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
|
||||||
|
_glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow)
|
||||||
|
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
|
_glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
|
||||||
if (_glfw.win32.shcore.instance)
|
if (_glfw.win32.shcore.instance)
|
||||||
{
|
{
|
||||||
_glfw.win32.shcore.SetProcessDpiAwareness = (PFN_SetProcessDpiAwareness)
|
_glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness)
|
||||||
GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
|
GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
|
||||||
|
_glfw.win32.shcore.GetDpiForMonitor_ = (PFN_GetDpiForMonitor)
|
||||||
|
GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor");
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
@@ -307,15 +326,15 @@ static HWND createHelperWindow(void)
|
|||||||
MSG msg;
|
MSG msg;
|
||||||
HWND window = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
|
HWND window = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
|
||||||
_GLFW_WNDCLASSNAME,
|
_GLFW_WNDCLASSNAME,
|
||||||
L"GLFW helper window",
|
L"GLFW message window",
|
||||||
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
|
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
|
||||||
0, 0, 1, 1,
|
0, 0, 1, 1,
|
||||||
HWND_MESSAGE, NULL,
|
NULL, NULL,
|
||||||
GetModuleHandleW(NULL),
|
GetModuleHandleW(NULL),
|
||||||
NULL);
|
NULL);
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"Win32: Failed to create helper window");
|
"Win32: Failed to create helper window");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -332,6 +351,7 @@ static HWND createHelperWindow(void)
|
|||||||
dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
||||||
dbi.dbcc_classguid = GUID_DEVINTERFACE_HID;
|
dbi.dbcc_classguid = GUID_DEVINTERFACE_HID;
|
||||||
|
|
||||||
|
_glfw.win32.deviceNotificationHandle =
|
||||||
RegisterDeviceNotificationW(window,
|
RegisterDeviceNotificationW(window,
|
||||||
(DEV_BROADCAST_HDR*) &dbi,
|
(DEV_BROADCAST_HDR*) &dbi,
|
||||||
DEVICE_NOTIFY_WINDOW_HANDLE);
|
DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||||
@@ -356,16 +376,22 @@ static HWND createHelperWindow(void)
|
|||||||
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
|
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
|
||||||
{
|
{
|
||||||
WCHAR* target;
|
WCHAR* target;
|
||||||
int length;
|
int count;
|
||||||
|
|
||||||
length = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
|
count = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
|
||||||
if (!length)
|
if (!count)
|
||||||
return NULL;
|
|
||||||
|
|
||||||
target = calloc(length, sizeof(WCHAR));
|
|
||||||
|
|
||||||
if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, length))
|
|
||||||
{
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to convert string from UTF-8");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
target = calloc(count, sizeof(WCHAR));
|
||||||
|
|
||||||
|
if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, count))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to convert string from UTF-8");
|
||||||
free(target);
|
free(target);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -378,16 +404,22 @@ WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
|
|||||||
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
|
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
|
||||||
{
|
{
|
||||||
char* target;
|
char* target;
|
||||||
int length;
|
int size;
|
||||||
|
|
||||||
length = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
|
size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
|
||||||
if (!length)
|
if (!size)
|
||||||
return NULL;
|
|
||||||
|
|
||||||
target = calloc(length, 1);
|
|
||||||
|
|
||||||
if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, length, NULL, NULL))
|
|
||||||
{
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to convert string to UTF-8");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
target = calloc(size, 1);
|
||||||
|
|
||||||
|
if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to convert string to UTF-8");
|
||||||
free(target);
|
free(target);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -395,6 +427,81 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reports the specified error, appending information about the last Win32 error
|
||||||
|
//
|
||||||
|
void _glfwInputErrorWin32(int error, const char* description)
|
||||||
|
{
|
||||||
|
WCHAR buffer[_GLFW_MESSAGE_SIZE] = L"";
|
||||||
|
char message[_GLFW_MESSAGE_SIZE] = "";
|
||||||
|
|
||||||
|
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
|
FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||||
|
FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||||||
|
NULL,
|
||||||
|
GetLastError() & 0xffff,
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
buffer,
|
||||||
|
sizeof(buffer),
|
||||||
|
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 //////
|
////// GLFW platform API //////
|
||||||
@@ -402,9 +509,6 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
|
|||||||
|
|
||||||
int _glfwPlatformInit(void)
|
int _glfwPlatformInit(void)
|
||||||
{
|
{
|
||||||
if (!_glfwInitThreadLocalStorageWin32())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
// To make SetForegroundWindow work as we want, we need to fiddle
|
// To make SetForegroundWindow work as we want, we need to fiddle
|
||||||
// with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
|
// with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
|
||||||
// as possible in the hope of still being the foreground process)
|
// as possible in the hope of still being the foreground process)
|
||||||
@@ -417,11 +521,12 @@ int _glfwPlatformInit(void)
|
|||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
createKeyTables();
|
createKeyTables();
|
||||||
|
_glfwUpdateKeyNamesWin32();
|
||||||
|
|
||||||
if (_glfw_SetProcessDpiAwareness)
|
if (IsWindows8Point1OrGreater())
|
||||||
_glfw_SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||||
else if (_glfw_SetProcessDPIAware)
|
else if (IsWindowsVistaOrGreater())
|
||||||
_glfw_SetProcessDPIAware();
|
SetProcessDPIAware();
|
||||||
|
|
||||||
if (!_glfwRegisterWindowClassWin32())
|
if (!_glfwRegisterWindowClassWin32())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
@@ -433,11 +538,15 @@ int _glfwPlatformInit(void)
|
|||||||
_glfwInitTimerWin32();
|
_glfwInitTimerWin32();
|
||||||
_glfwInitJoysticksWin32();
|
_glfwInitJoysticksWin32();
|
||||||
|
|
||||||
|
_glfwPollMonitorsWin32();
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformTerminate(void)
|
void _glfwPlatformTerminate(void)
|
||||||
{
|
{
|
||||||
|
if (_glfw.win32.deviceNotificationHandle)
|
||||||
|
UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
|
||||||
|
|
||||||
if (_glfw.win32.helperWindowHandle)
|
if (_glfw.win32.helperWindowHandle)
|
||||||
DestroyWindow(_glfw.win32.helperWindowHandle);
|
DestroyWindow(_glfw.win32.helperWindowHandle);
|
||||||
|
|
||||||
@@ -449,12 +558,12 @@ void _glfwPlatformTerminate(void)
|
|||||||
SPIF_SENDCHANGE);
|
SPIF_SENDCHANGE);
|
||||||
|
|
||||||
free(_glfw.win32.clipboardString);
|
free(_glfw.win32.clipboardString);
|
||||||
|
free(_glfw.win32.rawInput);
|
||||||
|
|
||||||
_glfwTerminateWGL();
|
_glfwTerminateWGL();
|
||||||
_glfwTerminateEGL();
|
_glfwTerminateEGL();
|
||||||
|
|
||||||
_glfwTerminateJoysticksWin32();
|
_glfwTerminateJoysticksWin32();
|
||||||
_glfwTerminateThreadLocalStorageWin32();
|
|
||||||
|
|
||||||
freeLibraries();
|
freeLibraries();
|
||||||
}
|
}
|
||||||
|
|||||||
+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) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||||
@@ -27,13 +27,9 @@
|
|||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <initguid.h>
|
|
||||||
|
|
||||||
#define _GLFW_PRESENCE_ONLY 1
|
|
||||||
#define _GLFW_UPDATE_STATE 2
|
|
||||||
|
|
||||||
#define _GLFW_TYPE_AXIS 0
|
#define _GLFW_TYPE_AXIS 0
|
||||||
#define _GLFW_TYPE_SLIDER 1
|
#define _GLFW_TYPE_SLIDER 1
|
||||||
#define _GLFW_TYPE_BUTTON 2
|
#define _GLFW_TYPE_BUTTON 2
|
||||||
@@ -52,18 +48,36 @@ typedef struct _GLFWobjenumWin32
|
|||||||
int povCount;
|
int povCount;
|
||||||
} _GLFWobjenumWin32;
|
} _GLFWobjenumWin32;
|
||||||
|
|
||||||
// Define only the necessary GUIDs (it's bad enough that we're exporting these)
|
// Define local copies of the necessary GUIDs
|
||||||
//
|
//
|
||||||
DEFINE_GUID(IID_IDirectInput8W,0xbf798031,0x483a,0x4da2,0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00);
|
static const GUID _glfw_IID_IDirectInput8W =
|
||||||
DEFINE_GUID(GUID_XAxis,0xa36d02e0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
{0xbf798031,0x483a,0x4da2,{0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00}};
|
||||||
DEFINE_GUID(GUID_YAxis,0xa36d02e1,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
static const GUID _glfw_GUID_XAxis =
|
||||||
DEFINE_GUID(GUID_ZAxis,0xa36d02e2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
{0xa36d02e0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||||
DEFINE_GUID(GUID_RxAxis,0xa36d02f4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
static const GUID _glfw_GUID_YAxis =
|
||||||
DEFINE_GUID(GUID_RyAxis,0xa36d02f5,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
{0xa36d02e1,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||||
DEFINE_GUID(GUID_RzAxis,0xa36d02e3,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
static const GUID _glfw_GUID_ZAxis =
|
||||||
DEFINE_GUID(GUID_Slider,0xa36d02e4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
{0xa36d02e2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||||
DEFINE_GUID(GUID_Button,0xa36d02f0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
static const GUID _glfw_GUID_RxAxis =
|
||||||
DEFINE_GUID(GUID_POV,0xa36d02f2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
{0xa36d02f4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||||
|
static const GUID _glfw_GUID_RyAxis =
|
||||||
|
{0xa36d02f5,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||||
|
static const GUID _glfw_GUID_RzAxis =
|
||||||
|
{0xa36d02e3,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||||
|
static const GUID _glfw_GUID_Slider =
|
||||||
|
{0xa36d02e4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||||
|
static const GUID _glfw_GUID_POV =
|
||||||
|
{0xa36d02f2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||||
|
|
||||||
|
#define IID_IDirectInput8W _glfw_IID_IDirectInput8W
|
||||||
|
#define GUID_XAxis _glfw_GUID_XAxis
|
||||||
|
#define GUID_YAxis _glfw_GUID_YAxis
|
||||||
|
#define GUID_ZAxis _glfw_GUID_ZAxis
|
||||||
|
#define GUID_RxAxis _glfw_GUID_RxAxis
|
||||||
|
#define GUID_RyAxis _glfw_GUID_RyAxis
|
||||||
|
#define GUID_RzAxis _glfw_GUID_RzAxis
|
||||||
|
#define GUID_Slider _glfw_GUID_Slider
|
||||||
|
#define GUID_POV _glfw_GUID_POV
|
||||||
|
|
||||||
// Object data array for our clone of c_dfDIJoystick
|
// Object data array for our clone of c_dfDIJoystick
|
||||||
// Generated with https://github.com/elmindreda/c_dfDIJoystick2
|
// Generated with https://github.com/elmindreda/c_dfDIJoystick2
|
||||||
@@ -149,9 +163,9 @@ static const char* getDeviceDescription(const XINPUT_CAPABILITIES* xic)
|
|||||||
case XINPUT_DEVSUBTYPE_GAMEPAD:
|
case XINPUT_DEVSUBTYPE_GAMEPAD:
|
||||||
{
|
{
|
||||||
if (xic->Flags & XINPUT_CAPS_WIRELESS)
|
if (xic->Flags & XINPUT_CAPS_WIRELESS)
|
||||||
return "Wireless Xbox 360 Controller";
|
return "Wireless Xbox Controller";
|
||||||
else
|
else
|
||||||
return "Xbox 360 Controller";
|
return "Xbox Controller";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,25 +252,20 @@ static GLFWbool supportsXInput(const GUID* guid)
|
|||||||
|
|
||||||
// Frees all resources associated with the specified joystick
|
// Frees all resources associated with the specified joystick
|
||||||
//
|
//
|
||||||
static void closeJoystick(_GLFWjoystickWin32* js)
|
static void closeJoystick(_GLFWjoystick* js)
|
||||||
{
|
{
|
||||||
if (js->device)
|
if (js->win32.device)
|
||||||
{
|
{
|
||||||
IDirectInputDevice8_Unacquire(js->device);
|
IDirectInputDevice8_Unacquire(js->win32.device);
|
||||||
IDirectInputDevice8_Release(js->device);
|
IDirectInputDevice8_Release(js->win32.device);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(js->name);
|
_glfwFreeJoystick(js);
|
||||||
free(js->axes);
|
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
||||||
free(js->buttons);
|
|
||||||
free(js->objects);
|
|
||||||
memset(js, 0, sizeof(_GLFWjoystickWin32));
|
|
||||||
|
|
||||||
_glfwInputJoystickChange((int) (js - _glfw.win32_js), GLFW_DISCONNECTED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DirectInput device object enumeration callback
|
// DirectInput device object enumeration callback
|
||||||
// Insights gleaned from SDL2
|
// Insights gleaned from SDL
|
||||||
//
|
//
|
||||||
static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
|
static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
|
||||||
void* user)
|
void* user)
|
||||||
@@ -337,23 +346,20 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
|||||||
DIPROPDWORD dipd;
|
DIPROPDWORD dipd;
|
||||||
IDirectInputDevice8* device;
|
IDirectInputDevice8* device;
|
||||||
_GLFWobjenumWin32 data;
|
_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)
|
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||||
|
if (js->present)
|
||||||
|
{
|
||||||
|
if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||||
return DIENUM_CONTINUE;
|
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))
|
if (supportsXInput(&di->guidProduct))
|
||||||
return DIENUM_CONTINUE;
|
return DIENUM_CONTINUE;
|
||||||
|
|
||||||
@@ -426,228 +432,56 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
|||||||
sizeof(_GLFWjoyobjectWin32),
|
sizeof(_GLFWjoyobjectWin32),
|
||||||
compareJoystickObjects);
|
compareJoystickObjects);
|
||||||
|
|
||||||
js = _glfw.win32_js + jid;
|
if (!WideCharToMultiByte(CP_UTF8, 0,
|
||||||
js->device = device;
|
di->tszInstanceName, -1,
|
||||||
js->guid = di->guidInstance;
|
name, sizeof(name),
|
||||||
js->axisCount = data.axisCount + data.sliderCount;
|
NULL, NULL))
|
||||||
js->axes = calloc(js->axisCount, sizeof(float));
|
{
|
||||||
js->buttonCount += data.buttonCount + data.povCount * 4;
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
js->buttons = calloc(js->buttonCount, 1);
|
"Win32: Failed to convert joystick name to UTF-8");
|
||||||
js->objects = data.objects;
|
|
||||||
js->objectCount = data.objectCount;
|
|
||||||
js->name = _glfwCreateUTF8FromWideStringWin32(di->tszInstanceName);
|
|
||||||
js->present = GLFW_TRUE;
|
|
||||||
|
|
||||||
_glfwInputJoystickChange(jid, GLFW_CONNECTED);
|
IDirectInputDevice8_Release(device);
|
||||||
|
free(data.objects);
|
||||||
|
return DIENUM_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
||||||
|
if (memcmp(&di->guidProduct.Data4[2], "PIDVID", 6) == 0)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
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;
|
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 (_glfw.win32_js[jid].present &&
|
|
||||||
_glfw.win32_js[jid].device == NULL &&
|
|
||||||
_glfw.win32_js[jid].index == index)
|
|
||||||
{
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
@@ -659,7 +493,7 @@ void _glfwInitJoysticksWin32(void)
|
|||||||
{
|
{
|
||||||
if (_glfw.win32.dinput8.instance)
|
if (_glfw.win32.dinput8.instance)
|
||||||
{
|
{
|
||||||
if (FAILED(_glfw_DirectInput8Create(GetModuleHandle(NULL),
|
if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
|
||||||
DIRECTINPUT_VERSION,
|
DIRECTINPUT_VERSION,
|
||||||
&IID_IDirectInput8W,
|
&IID_IDirectInput8W,
|
||||||
(void**) &_glfw.win32.dinput8.api,
|
(void**) &_glfw.win32.dinput8.api,
|
||||||
@@ -680,7 +514,7 @@ void _glfwTerminateJoysticksWin32(void)
|
|||||||
int jid;
|
int jid;
|
||||||
|
|
||||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; 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)
|
if (_glfw.win32.dinput8.api)
|
||||||
IDirectInput8_Release(_glfw.win32.dinput8.api);
|
IDirectInput8_Release(_glfw.win32.dinput8.api);
|
||||||
@@ -692,10 +526,43 @@ void _glfwDetectJoystickConnectionWin32(void)
|
|||||||
{
|
{
|
||||||
if (_glfw.win32.xinput.instance)
|
if (_glfw.win32.xinput.instance)
|
||||||
{
|
{
|
||||||
DWORD i;
|
DWORD index;
|
||||||
|
|
||||||
for (i = 0; i < XUSER_MAX_COUNT; i++)
|
for (index = 0; index < XUSER_MAX_COUNT; index++)
|
||||||
openXinputDevice(i);
|
{
|
||||||
|
int jid;
|
||||||
|
char guid[33];
|
||||||
|
XINPUT_CAPABILITIES xic;
|
||||||
|
_GLFWjoystick* js;
|
||||||
|
|
||||||
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
|
{
|
||||||
|
if (_glfw.joysticks[jid].present &&
|
||||||
|
_glfw.joysticks[jid].win32.device == NULL &&
|
||||||
|
_glfw.joysticks[jid].win32.index == index)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jid <= GLFW_JOYSTICK_LAST)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
||||||
|
sprintf(guid, "78696e707574%02x000000000000000000",
|
||||||
|
xic.SubType & 0xff);
|
||||||
|
|
||||||
|
js = _glfwAllocJoystick(getDeviceDescription(&xic), guid, 6, 10, 1);
|
||||||
|
if (!js)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
js->win32.index = index;
|
||||||
|
|
||||||
|
_glfwInputJoystick(js, GLFW_CONNECTED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfw.win32.dinput8.api)
|
if (_glfw.win32.dinput8.api)
|
||||||
@@ -719,8 +586,12 @@ void _glfwDetectJoystickDisconnectionWin32(void)
|
|||||||
{
|
{
|
||||||
int jid;
|
int jid;
|
||||||
|
|
||||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
pollJoystickState(_glfw.win32_js + jid, _GLFW_PRESENCE_ONLY);
|
{
|
||||||
|
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||||
|
if (js->present)
|
||||||
|
_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -728,38 +599,153 @@ void _glfwDetectJoystickDisconnectionWin32(void)
|
|||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int _glfwPlatformJoystickPresent(int jid)
|
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||||
{
|
{
|
||||||
_GLFWjoystickWin32* js = _glfw.win32_js + jid;
|
if (js->win32.device)
|
||||||
return pollJoystickState(js, _GLFW_PRESENCE_ONLY);
|
{
|
||||||
|
int i, ai = 0, bi = 0, pi = 0;
|
||||||
|
HRESULT result;
|
||||||
|
DIJOYSTATE state;
|
||||||
|
|
||||||
|
IDirectInputDevice8_Poll(js->win32.device);
|
||||||
|
result = IDirectInputDevice8_GetDeviceState(js->win32.device,
|
||||||
|
sizeof(state),
|
||||||
|
&state);
|
||||||
|
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
|
||||||
|
{
|
||||||
|
IDirectInputDevice8_Acquire(js->win32.device);
|
||||||
|
IDirectInputDevice8_Poll(js->win32.device);
|
||||||
|
result = IDirectInputDevice8_GetDeviceState(js->win32.device,
|
||||||
|
sizeof(state),
|
||||||
|
&state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
closeJoystick(js);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == _GLFW_POLL_PRESENCE)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
for (i = 0; i < js->win32.objectCount; i++)
|
||||||
|
{
|
||||||
|
const void* data = (char*) &state + js->win32.objects[i].offset;
|
||||||
|
|
||||||
|
switch (js->win32.objects[i].type)
|
||||||
|
{
|
||||||
|
case _GLFW_TYPE_AXIS:
|
||||||
|
case _GLFW_TYPE_SLIDER:
|
||||||
|
{
|
||||||
|
const float value = (*((LONG*) data) + 0.5f) / 32767.5f;
|
||||||
|
_glfwInputJoystickAxis(js, ai, value);
|
||||||
|
ai++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _GLFW_TYPE_BUTTON:
|
||||||
|
{
|
||||||
|
const char value = (*((BYTE*) data) & 0x80) != 0;
|
||||||
|
_glfwInputJoystickButton(js, bi, value);
|
||||||
|
bi++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _GLFW_TYPE_POV:
|
||||||
|
{
|
||||||
|
const int states[9] =
|
||||||
|
{
|
||||||
|
GLFW_HAT_UP,
|
||||||
|
GLFW_HAT_RIGHT_UP,
|
||||||
|
GLFW_HAT_RIGHT,
|
||||||
|
GLFW_HAT_RIGHT_DOWN,
|
||||||
|
GLFW_HAT_DOWN,
|
||||||
|
GLFW_HAT_LEFT_DOWN,
|
||||||
|
GLFW_HAT_LEFT,
|
||||||
|
GLFW_HAT_LEFT_UP,
|
||||||
|
GLFW_HAT_CENTERED
|
||||||
|
};
|
||||||
|
|
||||||
|
// Screams of horror are appropriate at this point
|
||||||
|
int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
||||||
|
if (state < 0 || state > 8)
|
||||||
|
state = 8;
|
||||||
|
|
||||||
|
_glfwInputJoystickHat(js, pi, states[state]);
|
||||||
|
pi++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i, dpad = 0;
|
||||||
|
DWORD result;
|
||||||
|
XINPUT_STATE xis;
|
||||||
|
const WORD buttons[10] =
|
||||||
|
{
|
||||||
|
XINPUT_GAMEPAD_A,
|
||||||
|
XINPUT_GAMEPAD_B,
|
||||||
|
XINPUT_GAMEPAD_X,
|
||||||
|
XINPUT_GAMEPAD_Y,
|
||||||
|
XINPUT_GAMEPAD_LEFT_SHOULDER,
|
||||||
|
XINPUT_GAMEPAD_RIGHT_SHOULDER,
|
||||||
|
XINPUT_GAMEPAD_BACK,
|
||||||
|
XINPUT_GAMEPAD_START,
|
||||||
|
XINPUT_GAMEPAD_LEFT_THUMB,
|
||||||
|
XINPUT_GAMEPAD_RIGHT_THUMB
|
||||||
|
};
|
||||||
|
|
||||||
|
result = XInputGetState(js->win32.index, &xis);
|
||||||
|
if (result != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
if (result == ERROR_DEVICE_NOT_CONNECTED)
|
||||||
|
closeJoystick(js);
|
||||||
|
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == _GLFW_POLL_PRESENCE)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
_glfwInputJoystickAxis(js, 0, (xis.Gamepad.sThumbLX + 0.5f) / 32767.5f);
|
||||||
|
_glfwInputJoystickAxis(js, 1, -(xis.Gamepad.sThumbLY + 0.5f) / 32767.5f);
|
||||||
|
_glfwInputJoystickAxis(js, 2, (xis.Gamepad.sThumbRX + 0.5f) / 32767.5f);
|
||||||
|
_glfwInputJoystickAxis(js, 3, -(xis.Gamepad.sThumbRY + 0.5f) / 32767.5f);
|
||||||
|
_glfwInputJoystickAxis(js, 4, xis.Gamepad.bLeftTrigger / 127.5f - 1.f);
|
||||||
|
_glfwInputJoystickAxis(js, 5, xis.Gamepad.bRightTrigger / 127.5f - 1.f);
|
||||||
|
|
||||||
|
for (i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
const char value = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
|
||||||
|
_glfwInputJoystickButton(js, i, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
|
||||||
|
dpad |= GLFW_HAT_UP;
|
||||||
|
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
|
||||||
|
dpad |= GLFW_HAT_RIGHT;
|
||||||
|
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
|
||||||
|
dpad |= GLFW_HAT_DOWN;
|
||||||
|
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
|
||||||
|
dpad |= GLFW_HAT_LEFT;
|
||||||
|
|
||||||
|
_glfwInputJoystickHat(js, 0, dpad);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float* _glfwPlatformGetJoystickAxes(int jid, int* count)
|
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
||||||
{
|
{
|
||||||
_GLFWjoystickWin32* js = _glfw.win32_js + jid;
|
if (strcmp(guid + 20, "504944564944") == 0)
|
||||||
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
|
{
|
||||||
return NULL;
|
char original[33];
|
||||||
|
strcpy(original, guid);
|
||||||
*count = js->axisCount;
|
sprintf(guid, "03000000%.4s0000%.4s000000000000",
|
||||||
return js->axes;
|
original, original + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-11
@@ -24,11 +24,10 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _glfw3_win32_joystick_h_
|
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickWin32 win32
|
||||||
#define _glfw3_win32_joystick_h_
|
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE int dummy
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
|
#define _GLFW_PLATFORM_MAPPING_NAME "Windows"
|
||||||
_GLFWjoystickWin32 win32_js[GLFW_JOYSTICK_LAST + 1]
|
|
||||||
|
|
||||||
// Joystick element (axis, button or slider)
|
// Joystick element (axis, button or slider)
|
||||||
//
|
//
|
||||||
@@ -42,14 +41,8 @@ typedef struct _GLFWjoyobjectWin32
|
|||||||
//
|
//
|
||||||
typedef struct _GLFWjoystickWin32
|
typedef struct _GLFWjoystickWin32
|
||||||
{
|
{
|
||||||
GLFWbool present;
|
|
||||||
float* axes;
|
|
||||||
int axisCount;
|
|
||||||
unsigned char* buttons;
|
|
||||||
int buttonCount;
|
|
||||||
_GLFWjoyobjectWin32* objects;
|
_GLFWjoyobjectWin32* objects;
|
||||||
int objectCount;
|
int objectCount;
|
||||||
char* name;
|
|
||||||
IDirectInputDevice8W* device;
|
IDirectInputDevice8W* device;
|
||||||
DWORD index;
|
DWORD index;
|
||||||
GUID guid;
|
GUID guid;
|
||||||
@@ -61,4 +54,3 @@ void _glfwTerminateJoysticksWin32(void);
|
|||||||
void _glfwDetectJoystickConnectionWin32(void);
|
void _glfwDetectJoystickConnectionWin32(void);
|
||||||
void _glfwDetectJoystickDisconnectionWin32(void);
|
void _glfwDetectJoystickDisconnectionWin32(void);
|
||||||
|
|
||||||
#endif // _glfw3_win32_joystick_h_
|
|
||||||
|
|||||||
+222
-114
@@ -33,33 +33,66 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Callback for EnumDisplayMonitors in createMonitor
|
||||||
|
//
|
||||||
|
static BOOL CALLBACK monitorCallback(HMONITOR handle,
|
||||||
|
HDC dc,
|
||||||
|
RECT* rect,
|
||||||
|
LPARAM data)
|
||||||
|
{
|
||||||
|
MONITORINFOEXW mi;
|
||||||
|
ZeroMemory(&mi, sizeof(mi));
|
||||||
|
mi.cbSize = sizeof(mi);
|
||||||
|
|
||||||
|
if (GetMonitorInfoW(handle, (MONITORINFO*) &mi))
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) data;
|
||||||
|
if (wcscmp(mi.szDevice, monitor->win32.adapterName) == 0)
|
||||||
|
monitor->win32.handle = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
// Create monitor from an adapter and (optionally) a display
|
// Create monitor from an adapter and (optionally) a display
|
||||||
//
|
//
|
||||||
static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
||||||
DISPLAY_DEVICEW* display)
|
DISPLAY_DEVICEW* display)
|
||||||
{
|
{
|
||||||
_GLFWmonitor* monitor;
|
_GLFWmonitor* monitor;
|
||||||
|
int widthMM, heightMM;
|
||||||
char* name;
|
char* name;
|
||||||
HDC dc;
|
HDC dc;
|
||||||
|
DEVMODEW dm;
|
||||||
|
RECT rect;
|
||||||
|
|
||||||
if (display)
|
if (display)
|
||||||
name = _glfwCreateUTF8FromWideStringWin32(display->DeviceString);
|
name = _glfwCreateUTF8FromWideStringWin32(display->DeviceString);
|
||||||
else
|
else
|
||||||
name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString);
|
name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString);
|
||||||
if (!name)
|
if (!name)
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to convert string to UTF-8");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
ZeroMemory(&dm, sizeof(dm));
|
||||||
|
dm.dmSize = sizeof(dm);
|
||||||
|
EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm);
|
||||||
|
|
||||||
dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
|
dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
|
||||||
|
|
||||||
monitor = _glfwAllocMonitor(name,
|
if (IsWindows8Point1OrGreater())
|
||||||
GetDeviceCaps(dc, HORZSIZE),
|
{
|
||||||
GetDeviceCaps(dc, VERTSIZE));
|
widthMM = GetDeviceCaps(dc, HORZSIZE);
|
||||||
|
heightMM = GetDeviceCaps(dc, VERTSIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
widthMM = (int) (dm.dmPelsWidth * 25.4f / GetDeviceCaps(dc, LOGPIXELSX));
|
||||||
|
heightMM = (int) (dm.dmPelsHeight * 25.4f / GetDeviceCaps(dc, LOGPIXELSY));
|
||||||
|
}
|
||||||
|
|
||||||
DeleteDC(dc);
|
DeleteDC(dc);
|
||||||
|
|
||||||
|
monitor = _glfwAllocMonitor(name, widthMM, heightMM);
|
||||||
free(name);
|
free(name);
|
||||||
|
|
||||||
if (adapter->StateFlags & DISPLAY_DEVICE_MODESPRUNED)
|
if (adapter->StateFlags & DISPLAY_DEVICE_MODESPRUNED)
|
||||||
@@ -82,6 +115,12 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
|||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rect.left = dm.dmPosition.x;
|
||||||
|
rect.top = dm.dmPosition.y;
|
||||||
|
rect.right = dm.dmPosition.x + dm.dmPelsWidth;
|
||||||
|
rect.bottom = dm.dmPosition.y + dm.dmPelsHeight;
|
||||||
|
|
||||||
|
EnumDisplayMonitors(NULL, &rect, monitorCallback, (LPARAM) monitor);
|
||||||
return monitor;
|
return monitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,21 +129,132 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
|||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Poll for changes in the set of connected monitors
|
||||||
|
//
|
||||||
|
void _glfwPollMonitorsWin32(void)
|
||||||
|
{
|
||||||
|
int i, disconnectedCount;
|
||||||
|
_GLFWmonitor** disconnected = NULL;
|
||||||
|
DWORD adapterIndex, displayIndex;
|
||||||
|
DISPLAY_DEVICEW adapter, display;
|
||||||
|
_GLFWmonitor* monitor;
|
||||||
|
|
||||||
|
disconnectedCount = _glfw.monitorCount;
|
||||||
|
if (disconnectedCount)
|
||||||
|
{
|
||||||
|
disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
|
||||||
|
memcpy(disconnected,
|
||||||
|
_glfw.monitors,
|
||||||
|
_glfw.monitorCount * sizeof(_GLFWmonitor*));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (adapterIndex = 0; ; adapterIndex++)
|
||||||
|
{
|
||||||
|
int type = _GLFW_INSERT_LAST;
|
||||||
|
|
||||||
|
ZeroMemory(&adapter, sizeof(adapter));
|
||||||
|
adapter.cb = sizeof(adapter);
|
||||||
|
|
||||||
|
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
|
||||||
|
type = _GLFW_INSERT_FIRST;
|
||||||
|
|
||||||
|
for (displayIndex = 0; ; displayIndex++)
|
||||||
|
{
|
||||||
|
ZeroMemory(&display, sizeof(display));
|
||||||
|
display.cb = sizeof(display);
|
||||||
|
|
||||||
|
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!(display.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (i = 0; i < disconnectedCount; i++)
|
||||||
|
{
|
||||||
|
if (disconnected[i] &&
|
||||||
|
wcscmp(disconnected[i]->win32.displayName,
|
||||||
|
display.DeviceName) == 0)
|
||||||
|
{
|
||||||
|
disconnected[i] = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < disconnectedCount)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
monitor = createMonitor(&adapter, &display);
|
||||||
|
if (!monitor)
|
||||||
|
{
|
||||||
|
free(disconnected);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
|
||||||
|
|
||||||
|
type = _GLFW_INSERT_LAST;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK: If an active adapter does not have any display devices
|
||||||
|
// (as sometimes happens), add it directly as a monitor
|
||||||
|
if (displayIndex == 0)
|
||||||
|
{
|
||||||
|
for (i = 0; i < disconnectedCount; i++)
|
||||||
|
{
|
||||||
|
if (disconnected[i] &&
|
||||||
|
wcscmp(disconnected[i]->win32.adapterName,
|
||||||
|
adapter.DeviceName) == 0)
|
||||||
|
{
|
||||||
|
disconnected[i] = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < disconnectedCount)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
monitor = createMonitor(&adapter, NULL);
|
||||||
|
if (!monitor)
|
||||||
|
{
|
||||||
|
free(disconnected);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < disconnectedCount; i++)
|
||||||
|
{
|
||||||
|
if (disconnected[i])
|
||||||
|
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(disconnected);
|
||||||
|
}
|
||||||
|
|
||||||
// Change the current video mode
|
// Change the current video mode
|
||||||
//
|
//
|
||||||
GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
||||||
{
|
{
|
||||||
GLFWvidmode current;
|
GLFWvidmode current;
|
||||||
const GLFWvidmode* best;
|
const GLFWvidmode* best;
|
||||||
DEVMODEW dm;
|
DEVMODEW dm;
|
||||||
|
LONG result;
|
||||||
|
|
||||||
best = _glfwChooseVideoMode(monitor, desired);
|
best = _glfwChooseVideoMode(monitor, desired);
|
||||||
_glfwPlatformGetVideoMode(monitor, ¤t);
|
_glfwPlatformGetVideoMode(monitor, ¤t);
|
||||||
if (_glfwCompareVideoModes(¤t, best) == 0)
|
if (_glfwCompareVideoModes(¤t, best) == 0)
|
||||||
return GLFW_TRUE;
|
return;
|
||||||
|
|
||||||
ZeroMemory(&dm, sizeof(dm));
|
ZeroMemory(&dm, sizeof(dm));
|
||||||
dm.dmSize = sizeof(DEVMODEW);
|
dm.dmSize = sizeof(dm);
|
||||||
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL |
|
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL |
|
||||||
DM_DISPLAYFREQUENCY;
|
DM_DISPLAYFREQUENCY;
|
||||||
dm.dmPelsWidth = best->width;
|
dm.dmPelsWidth = best->width;
|
||||||
@@ -115,18 +265,36 @@ GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desire
|
|||||||
if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24)
|
if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24)
|
||||||
dm.dmBitsPerPel = 32;
|
dm.dmBitsPerPel = 32;
|
||||||
|
|
||||||
if (ChangeDisplaySettingsExW(monitor->win32.adapterName,
|
result = ChangeDisplaySettingsExW(monitor->win32.adapterName,
|
||||||
&dm,
|
&dm,
|
||||||
NULL,
|
NULL,
|
||||||
CDS_FULLSCREEN,
|
CDS_FULLSCREEN,
|
||||||
NULL) != DISP_CHANGE_SUCCESSFUL)
|
NULL);
|
||||||
{
|
if (result == DISP_CHANGE_SUCCESSFUL)
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to set video mode");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
monitor->win32.modeChanged = GLFW_TRUE;
|
monitor->win32.modeChanged = GLFW_TRUE;
|
||||||
return GLFW_TRUE;
|
else
|
||||||
|
{
|
||||||
|
const char* description = "Unknown error";
|
||||||
|
|
||||||
|
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
|
// 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 //////
|
////// 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)
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||||
{
|
{
|
||||||
DEVMODEW settings;
|
DEVMODEW dm;
|
||||||
ZeroMemory(&settings, sizeof(DEVMODEW));
|
ZeroMemory(&dm, sizeof(dm));
|
||||||
settings.dmSize = sizeof(DEVMODEW);
|
dm.dmSize = sizeof(dm);
|
||||||
|
|
||||||
EnumDisplaySettingsExW(monitor->win32.adapterName,
|
EnumDisplaySettingsExW(monitor->win32.adapterName,
|
||||||
ENUM_CURRENT_SETTINGS,
|
ENUM_CURRENT_SETTINGS,
|
||||||
&settings,
|
&dm,
|
||||||
EDS_ROTATEDMODE);
|
EDS_ROTATEDMODE);
|
||||||
|
|
||||||
if (xpos)
|
if (xpos)
|
||||||
*xpos = settings.dmPosition.x;
|
*xpos = dm.dmPosition.x;
|
||||||
if (ypos)
|
if (ypos)
|
||||||
*ypos = settings.dmPosition.y;
|
*ypos = dm.dmPosition.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||||
|
float* xscale, float* yscale)
|
||||||
|
{
|
||||||
|
_glfwGetMonitorContentScaleWin32(monitor->win32.handle, xscale, yscale);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||||
@@ -261,8 +370,8 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
|||||||
GLFWvidmode mode;
|
GLFWvidmode mode;
|
||||||
DEVMODEW dm;
|
DEVMODEW dm;
|
||||||
|
|
||||||
ZeroMemory(&dm, sizeof(DEVMODEW));
|
ZeroMemory(&dm, sizeof(dm));
|
||||||
dm.dmSize = sizeof(DEVMODEW);
|
dm.dmSize = sizeof(dm);
|
||||||
|
|
||||||
if (!EnumDisplaySettingsW(monitor->win32.adapterName, modeIndex, &dm))
|
if (!EnumDisplaySettingsW(monitor->win32.adapterName, modeIndex, &dm))
|
||||||
break;
|
break;
|
||||||
@@ -328,9 +437,8 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
|||||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||||
{
|
{
|
||||||
DEVMODEW dm;
|
DEVMODEW dm;
|
||||||
|
ZeroMemory(&dm, sizeof(dm));
|
||||||
ZeroMemory(&dm, sizeof(DEVMODEW));
|
dm.dmSize = sizeof(dm);
|
||||||
dm.dmSize = sizeof(DEVMODEW);
|
|
||||||
|
|
||||||
EnumDisplaySettingsW(monitor->win32.adapterName, ENUM_CURRENT_SETTINGS, &dm);
|
EnumDisplaySettingsW(monitor->win32.adapterName, ENUM_CURRENT_SETTINGS, &dm);
|
||||||
|
|
||||||
|
|||||||
+99
-46
@@ -25,9 +25,6 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _glfw3_win32_platform_h_
|
|
||||||
#define _glfw3_win32_platform_h_
|
|
||||||
|
|
||||||
// We don't need all the fancy stuff
|
// We don't need all the fancy stuff
|
||||||
#ifndef NOMINMAX
|
#ifndef NOMINMAX
|
||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
@@ -66,16 +63,10 @@
|
|||||||
|
|
||||||
#include <wctype.h>
|
#include <wctype.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <mmsystem.h>
|
|
||||||
#include <dinput.h>
|
#include <dinput.h>
|
||||||
#include <xinput.h>
|
#include <xinput.h>
|
||||||
#include <dbt.h>
|
#include <dbt.h>
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#include <malloc.h>
|
|
||||||
#define strdup _strdup
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// HACK: Define macros that some windows.h variants don't
|
// HACK: Define macros that some windows.h variants don't
|
||||||
#ifndef WM_MOUSEHWHEEL
|
#ifndef WM_MOUSEHWHEEL
|
||||||
#define WM_MOUSEHWHEEL 0x020E
|
#define WM_MOUSEHWHEEL 0x020E
|
||||||
@@ -104,28 +95,64 @@
|
|||||||
#ifndef DISPLAY_DEVICE_ACTIVE
|
#ifndef DISPLAY_DEVICE_ACTIVE
|
||||||
#define DISPLAY_DEVICE_ACTIVE 0x00000001
|
#define DISPLAY_DEVICE_ACTIVE 0x00000001
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef _WIN32_WINNT_WINBLUE
|
||||||
|
#define _WIN32_WINNT_WINBLUE 0x0602
|
||||||
|
#endif
|
||||||
|
|
||||||
#if WINVER < 0x0601
|
#if WINVER < 0x0601
|
||||||
typedef struct tagCHANGEFILTERSTRUCT
|
typedef struct
|
||||||
{
|
{
|
||||||
DWORD cbSize;
|
DWORD cbSize;
|
||||||
DWORD ExtStatus;
|
DWORD ExtStatus;
|
||||||
|
} CHANGEFILTERSTRUCT;
|
||||||
} CHANGEFILTERSTRUCT, *PCHANGEFILTERSTRUCT;
|
|
||||||
#ifndef MSGFLT_ALLOW
|
#ifndef MSGFLT_ALLOW
|
||||||
#define MSGFLT_ALLOW 1
|
#define MSGFLT_ALLOW 1
|
||||||
#endif
|
#endif
|
||||||
#endif /*Windows 7*/
|
#endif /*Windows 7*/
|
||||||
|
|
||||||
|
#if WINVER < 0x0600
|
||||||
|
#define DWM_BB_ENABLE 0x00000001
|
||||||
|
#define DWM_BB_BLURREGION 0x00000002
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
DWORD dwFlags;
|
||||||
|
BOOL fEnable;
|
||||||
|
HRGN hRgnBlur;
|
||||||
|
BOOL fTransitionOnMaximized;
|
||||||
|
} DWM_BLURBEHIND;
|
||||||
|
#endif /*Windows Vista*/
|
||||||
|
|
||||||
#ifndef DPI_ENUMS_DECLARED
|
#ifndef DPI_ENUMS_DECLARED
|
||||||
typedef enum PROCESS_DPI_AWARENESS
|
typedef enum
|
||||||
{
|
{
|
||||||
PROCESS_DPI_UNAWARE = 0,
|
PROCESS_DPI_UNAWARE = 0,
|
||||||
PROCESS_SYSTEM_DPI_AWARE = 1,
|
PROCESS_SYSTEM_DPI_AWARE = 1,
|
||||||
PROCESS_PER_MONITOR_DPI_AWARE = 2
|
PROCESS_PER_MONITOR_DPI_AWARE = 2
|
||||||
} PROCESS_DPI_AWARENESS;
|
} PROCESS_DPI_AWARENESS;
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MDT_EFFECTIVE_DPI = 0,
|
||||||
|
MDT_ANGULAR_DPI = 1,
|
||||||
|
MDT_RAW_DPI = 2,
|
||||||
|
MDT_DEFAULT = MDT_EFFECTIVE_DPI
|
||||||
|
} MONITOR_DPI_TYPE;
|
||||||
#endif /*DPI_ENUMS_DECLARED*/
|
#endif /*DPI_ENUMS_DECLARED*/
|
||||||
|
|
||||||
|
// 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
|
// HACK: Define macros that some xinput.h variants don't
|
||||||
#ifndef XINPUT_CAPS_WIRELESS
|
#ifndef XINPUT_CAPS_WIRELESS
|
||||||
#define XINPUT_CAPS_WIRELESS 0x0002
|
#define XINPUT_CAPS_WIRELESS 0x0002
|
||||||
@@ -162,33 +189,37 @@ typedef enum PROCESS_DPI_AWARENESS
|
|||||||
|
|
||||||
// winmm.dll function pointer typedefs
|
// winmm.dll function pointer typedefs
|
||||||
typedef DWORD (WINAPI * PFN_timeGetTime)(void);
|
typedef DWORD (WINAPI * PFN_timeGetTime)(void);
|
||||||
#define _glfw_timeGetTime _glfw.win32.winmm.timeGetTime
|
#define timeGetTime _glfw.win32.winmm.GetTime
|
||||||
|
|
||||||
// xinput.dll function pointer typedefs
|
// xinput.dll function pointer typedefs
|
||||||
typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*);
|
typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*);
|
||||||
typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
|
typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
|
||||||
#define _glfw_XInputGetCapabilities _glfw.win32.xinput.XInputGetCapabilities
|
#define XInputGetCapabilities _glfw.win32.xinput.GetCapabilities
|
||||||
#define _glfw_XInputGetState _glfw.win32.xinput.XInputGetState
|
#define XInputGetState _glfw.win32.xinput.GetState
|
||||||
|
|
||||||
// dinput8.dll function pointer typedefs
|
// dinput8.dll function pointer typedefs
|
||||||
typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
|
typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
|
||||||
#define _glfw_DirectInput8Create _glfw.win32.dinput8.DirectInput8Create
|
#define DirectInput8Create _glfw.win32.dinput8.Create
|
||||||
|
|
||||||
// user32.dll function pointer typedefs
|
// user32.dll function pointer typedefs
|
||||||
typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void);
|
typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void);
|
||||||
typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,PCHANGEFILTERSTRUCT);
|
typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,CHANGEFILTERSTRUCT*);
|
||||||
#define _glfw_SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware
|
#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
|
||||||
#define _glfw_ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx
|
#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
|
||||||
|
|
||||||
// dwmapi.dll function pointer typedefs
|
// dwmapi.dll function pointer typedefs
|
||||||
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
||||||
typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
|
typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
|
||||||
#define _glfw_DwmIsCompositionEnabled _glfw.win32.dwmapi.DwmIsCompositionEnabled
|
typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*);
|
||||||
#define _glfw_DwmFlush _glfw.win32.dwmapi.DwmFlush
|
#define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled
|
||||||
|
#define DwmFlush _glfw.win32.dwmapi.Flush
|
||||||
|
#define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow
|
||||||
|
|
||||||
// shcore.dll function pointer typedefs
|
// shcore.dll function pointer typedefs
|
||||||
typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
|
typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
|
||||||
#define _glfw_SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness
|
typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);
|
||||||
|
#define SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness_
|
||||||
|
#define GetDpiForMonitor _glfw.win32.shcore.GetDpiForMonitor_
|
||||||
|
|
||||||
typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
|
typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
|
||||||
|
|
||||||
@@ -207,6 +238,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
|
|||||||
#include "win32_joystick.h"
|
#include "win32_joystick.h"
|
||||||
#include "wgl_context.h"
|
#include "wgl_context.h"
|
||||||
#include "egl_context.h"
|
#include "egl_context.h"
|
||||||
|
#include "osmesa_context.h"
|
||||||
|
|
||||||
#define _GLFW_WNDCLASSNAME L"GLFW30"
|
#define _GLFW_WNDCLASSNAME L"GLFW30"
|
||||||
|
|
||||||
@@ -219,10 +251,11 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
|
|||||||
|
|
||||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
|
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
|
||||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
|
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
|
||||||
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time
|
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerWin32 win32
|
||||||
#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsWin32 win32_tls
|
|
||||||
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 win32
|
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 win32
|
||||||
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWin32 win32
|
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWin32 win32
|
||||||
|
#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsWin32 win32
|
||||||
|
#define _GLFW_PLATFORM_MUTEX_STATE _GLFWmutexWin32 win32
|
||||||
|
|
||||||
|
|
||||||
// Win32-specific per-window data
|
// Win32-specific per-window data
|
||||||
@@ -234,8 +267,11 @@ typedef struct _GLFWwindowWin32
|
|||||||
HICON smallIcon;
|
HICON smallIcon;
|
||||||
|
|
||||||
GLFWbool cursorTracked;
|
GLFWbool cursorTracked;
|
||||||
|
GLFWbool frameAction;
|
||||||
GLFWbool iconified;
|
GLFWbool iconified;
|
||||||
GLFWbool maximized;
|
GLFWbool maximized;
|
||||||
|
// Whether to enable framebuffer transparency on DWM
|
||||||
|
GLFWbool transparent;
|
||||||
|
|
||||||
// The last received cursor position, regardless of source
|
// The last received cursor position, regardless of source
|
||||||
int lastCursorPosX, lastCursorPosY;
|
int lastCursorPosX, lastCursorPosY;
|
||||||
@@ -247,48 +283,54 @@ typedef struct _GLFWwindowWin32
|
|||||||
typedef struct _GLFWlibraryWin32
|
typedef struct _GLFWlibraryWin32
|
||||||
{
|
{
|
||||||
HWND helperWindowHandle;
|
HWND helperWindowHandle;
|
||||||
|
HDEVNOTIFY deviceNotificationHandle;
|
||||||
DWORD foregroundLockTimeout;
|
DWORD foregroundLockTimeout;
|
||||||
|
int acquiredMonitorCount;
|
||||||
char* clipboardString;
|
char* clipboardString;
|
||||||
char keyName[64];
|
|
||||||
short int keycodes[512];
|
short int keycodes[512];
|
||||||
short int scancodes[GLFW_KEY_LAST + 1];
|
short int scancodes[GLFW_KEY_LAST + 1];
|
||||||
|
char keynames[GLFW_KEY_LAST + 1][5];
|
||||||
// Where to place the cursor when re-enabled
|
// Where to place the cursor when re-enabled
|
||||||
double restoreCursorPosX, restoreCursorPosY;
|
double restoreCursorPosX, restoreCursorPosY;
|
||||||
// The window whose disabled cursor mode is active
|
// The window whose disabled cursor mode is active
|
||||||
_GLFWwindow* disabledCursorWindow;
|
_GLFWwindow* disabledCursorWindow;
|
||||||
|
RAWINPUT* rawInput;
|
||||||
|
int rawInputSize;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
PFN_timeGetTime timeGetTime;
|
PFN_timeGetTime GetTime;
|
||||||
} winmm;
|
} winmm;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
PFN_DirectInput8Create DirectInput8Create;
|
PFN_DirectInput8Create Create;
|
||||||
IDirectInput8W* api;
|
IDirectInput8W* api;
|
||||||
} dinput8;
|
} dinput8;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
PFN_XInputGetCapabilities XInputGetCapabilities;
|
PFN_XInputGetCapabilities GetCapabilities;
|
||||||
PFN_XInputGetState XInputGetState;
|
PFN_XInputGetState GetState;
|
||||||
} xinput;
|
} xinput;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
PFN_SetProcessDPIAware SetProcessDPIAware;
|
PFN_SetProcessDPIAware SetProcessDPIAware_;
|
||||||
PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx;
|
PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx_;
|
||||||
} user32;
|
} user32;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
PFN_DwmIsCompositionEnabled DwmIsCompositionEnabled;
|
PFN_DwmIsCompositionEnabled IsCompositionEnabled;
|
||||||
PFN_DwmFlush DwmFlush;
|
PFN_DwmFlush Flush;
|
||||||
|
PFN_DwmEnableBlurBehindWindow EnableBlurBehindWindow;
|
||||||
} dwmapi;
|
} dwmapi;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
PFN_SetProcessDpiAwareness SetProcessDpiAwareness;
|
PFN_SetProcessDpiAwareness SetProcessDpiAwareness_;
|
||||||
|
PFN_GetDpiForMonitor GetDpiForMonitor_;
|
||||||
} shcore;
|
} shcore;
|
||||||
|
|
||||||
} _GLFWlibraryWin32;
|
} _GLFWlibraryWin32;
|
||||||
@@ -297,11 +339,12 @@ typedef struct _GLFWlibraryWin32
|
|||||||
//
|
//
|
||||||
typedef struct _GLFWmonitorWin32
|
typedef struct _GLFWmonitorWin32
|
||||||
{
|
{
|
||||||
|
HMONITOR handle;
|
||||||
// This size matches the static size of DISPLAY_DEVICE.DeviceName
|
// This size matches the static size of DISPLAY_DEVICE.DeviceName
|
||||||
WCHAR adapterName[32];
|
WCHAR adapterName[32];
|
||||||
WCHAR displayName[32];
|
WCHAR displayName[32];
|
||||||
char publicAdapterName[64];
|
char publicAdapterName[32];
|
||||||
char publicDisplayName[64];
|
char publicDisplayName[32];
|
||||||
GLFWbool modesPruned;
|
GLFWbool modesPruned;
|
||||||
GLFWbool modeChanged;
|
GLFWbool modeChanged;
|
||||||
|
|
||||||
@@ -317,35 +360,45 @@ typedef struct _GLFWcursorWin32
|
|||||||
|
|
||||||
// Win32-specific global timer data
|
// Win32-specific global timer data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWtimeWin32
|
typedef struct _GLFWtimerWin32
|
||||||
{
|
{
|
||||||
GLFWbool hasPC;
|
GLFWbool hasPC;
|
||||||
uint64_t frequency;
|
uint64_t frequency;
|
||||||
|
|
||||||
} _GLFWtimeWin32;
|
} _GLFWtimerWin32;
|
||||||
|
|
||||||
// Win32-specific global TLS data
|
// Win32-specific thread local storage data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWtlsWin32
|
typedef struct _GLFWtlsWin32
|
||||||
{
|
{
|
||||||
GLFWbool allocated;
|
GLFWbool allocated;
|
||||||
DWORD context;
|
DWORD index;
|
||||||
|
|
||||||
} _GLFWtlsWin32;
|
} _GLFWtlsWin32;
|
||||||
|
|
||||||
|
// Win32-specific mutex data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWmutexWin32
|
||||||
|
{
|
||||||
|
GLFWbool allocated;
|
||||||
|
CRITICAL_SECTION section;
|
||||||
|
|
||||||
|
} _GLFWmutexWin32;
|
||||||
|
|
||||||
|
|
||||||
GLFWbool _glfwRegisterWindowClassWin32(void);
|
GLFWbool _glfwRegisterWindowClassWin32(void);
|
||||||
void _glfwUnregisterWindowClassWin32(void);
|
void _glfwUnregisterWindowClassWin32(void);
|
||||||
|
GLFWbool _glfwIsCompositionEnabledWin32(void);
|
||||||
GLFWbool _glfwInitThreadLocalStorageWin32(void);
|
|
||||||
void _glfwTerminateThreadLocalStorageWin32(void);
|
|
||||||
|
|
||||||
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
|
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
|
||||||
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
|
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
|
||||||
|
void _glfwInputErrorWin32(int error, const char* description);
|
||||||
|
void _glfwUpdateKeyNamesWin32(void);
|
||||||
|
|
||||||
void _glfwInitTimerWin32(void);
|
void _glfwInitTimerWin32(void);
|
||||||
|
|
||||||
GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
void _glfwPollMonitorsWin32(void);
|
||||||
|
void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||||
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
|
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
|
||||||
|
void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale);
|
||||||
|
|
||||||
#endif // _glfw3_win32_platform_h_
|
|
||||||
|
|||||||
@@ -27,43 +27,71 @@
|
|||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWbool _glfwInitThreadLocalStorageWin32(void)
|
|
||||||
{
|
|
||||||
_glfw.win32_tls.context = TlsAlloc();
|
|
||||||
if (_glfw.win32_tls.context == TLS_OUT_OF_INDEXES)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to allocate TLS index");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.win32_tls.allocated = GLFW_TRUE;
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwTerminateThreadLocalStorageWin32(void)
|
|
||||||
{
|
|
||||||
if (_glfw.win32_tls.allocated)
|
|
||||||
TlsFree(_glfw.win32_tls.context);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW platform API //////
|
////// 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))
|
if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
|
||||||
{
|
{
|
||||||
_glfw.win32_time.hasPC = GLFW_TRUE;
|
_glfw.timer.win32.hasPC = GLFW_TRUE;
|
||||||
_glfw.win32_time.frequency = frequency;
|
_glfw.timer.win32.frequency = frequency;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_glfw.win32_time.hasPC = GLFW_FALSE;
|
_glfw.timer.win32.hasPC = GLFW_FALSE;
|
||||||
_glfw.win32_time.frequency = 1000;
|
_glfw.timer.win32.frequency = 1000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,18 +57,18 @@ void _glfwInitTimerWin32(void)
|
|||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerValue(void)
|
uint64_t _glfwPlatformGetTimerValue(void)
|
||||||
{
|
{
|
||||||
if (_glfw.win32_time.hasPC)
|
if (_glfw.timer.win32.hasPC)
|
||||||
{
|
{
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
QueryPerformanceCounter((LARGE_INTEGER*) &value);
|
QueryPerformanceCounter((LARGE_INTEGER*) &value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return (uint64_t) _glfw_timeGetTime();
|
return (uint64_t) timeGetTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerFrequency(void)
|
uint64_t _glfwPlatformGetTimerFrequency(void)
|
||||||
{
|
{
|
||||||
return _glfw.win32_time.frequency;
|
return _glfw.timer.win32.frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+438
-182
File diff suppressed because it is too large
Load Diff
+224
-104
@@ -38,72 +38,96 @@
|
|||||||
////// GLFW event API //////
|
////// GLFW event API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Notifies shared code that a window has lost or received input focus
|
||||||
|
//
|
||||||
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
|
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
|
||||||
{
|
{
|
||||||
if (focused)
|
|
||||||
{
|
|
||||||
if (window->callbacks.focus)
|
|
||||||
window->callbacks.focus((GLFWwindow*) window, focused);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (window->callbacks.focus)
|
if (window->callbacks.focus)
|
||||||
window->callbacks.focus((GLFWwindow*) window, focused);
|
window->callbacks.focus((GLFWwindow*) window, focused);
|
||||||
|
|
||||||
// Release all pressed keyboard keys
|
if (!focused)
|
||||||
for (i = 0; i <= GLFW_KEY_LAST; i++)
|
|
||||||
{
|
{
|
||||||
if (window->keys[i] == GLFW_PRESS)
|
int key, button;
|
||||||
_glfwInputKey(window, i, 0, GLFW_RELEASE, 0);
|
|
||||||
|
for (key = 0; key <= GLFW_KEY_LAST; key++)
|
||||||
|
{
|
||||||
|
if (window->keys[key] == GLFW_PRESS)
|
||||||
|
{
|
||||||
|
const int scancode = _glfwPlatformGetKeyScancode(key);
|
||||||
|
_glfwInputKey(window, key, scancode, GLFW_RELEASE, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release all pressed mouse buttons
|
for (button = 0; button <= GLFW_MOUSE_BUTTON_LAST; button++)
|
||||||
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
|
|
||||||
{
|
{
|
||||||
if (window->mouseButtons[i] == GLFW_PRESS)
|
if (window->mouseButtons[button] == GLFW_PRESS)
|
||||||
_glfwInputMouseClick(window, i, GLFW_RELEASE, 0);
|
_glfwInputMouseClick(window, button, GLFW_RELEASE, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code that a window has moved
|
||||||
|
// The position is specified in client-area relative screen coordinates
|
||||||
|
//
|
||||||
void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
|
void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
|
||||||
{
|
{
|
||||||
if (window->callbacks.pos)
|
if (window->callbacks.pos)
|
||||||
window->callbacks.pos((GLFWwindow*) window, x, y);
|
window->callbacks.pos((GLFWwindow*) window, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code that a window has been resized
|
||||||
|
// The size is specified in screen coordinates
|
||||||
|
//
|
||||||
void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
|
void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
|
||||||
{
|
{
|
||||||
if (window->callbacks.size)
|
if (window->callbacks.size)
|
||||||
window->callbacks.size((GLFWwindow*) window, width, height);
|
window->callbacks.size((GLFWwindow*) window, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code that a window has been iconified or restored
|
||||||
|
//
|
||||||
void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
|
void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
|
||||||
{
|
{
|
||||||
if (window->callbacks.iconify)
|
if (window->callbacks.iconify)
|
||||||
window->callbacks.iconify((GLFWwindow*) window, iconified);
|
window->callbacks.iconify((GLFWwindow*) window, iconified);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code that a window has been maximized or restored
|
||||||
|
//
|
||||||
void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)
|
void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)
|
||||||
{
|
{
|
||||||
if (window->callbacks.maximize)
|
if (window->callbacks.maximize)
|
||||||
window->callbacks.maximize((GLFWwindow*) window, maximized);
|
window->callbacks.maximize((GLFWwindow*) window, maximized);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code that a window framebuffer has been resized
|
||||||
|
// The size is specified in pixels
|
||||||
|
//
|
||||||
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
|
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
|
||||||
{
|
{
|
||||||
if (window->callbacks.fbsize)
|
if (window->callbacks.fbsize)
|
||||||
window->callbacks.fbsize((GLFWwindow*) window, width, height);
|
window->callbacks.fbsize((GLFWwindow*) window, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code that a window content scale has changed
|
||||||
|
// The scale is specified as the ratio between the current and default DPI
|
||||||
|
//
|
||||||
|
void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale)
|
||||||
|
{
|
||||||
|
if (window->callbacks.scale)
|
||||||
|
window->callbacks.scale((GLFWwindow*) window, xscale, yscale);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notifies shared code that the window contents needs updating
|
||||||
|
//
|
||||||
void _glfwInputWindowDamage(_GLFWwindow* window)
|
void _glfwInputWindowDamage(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window->callbacks.refresh)
|
if (window->callbacks.refresh)
|
||||||
window->callbacks.refresh((GLFWwindow*) window);
|
window->callbacks.refresh((GLFWwindow*) window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code that the user wishes to close a window
|
||||||
|
//
|
||||||
void _glfwInputWindowCloseRequest(_GLFWwindow* window)
|
void _glfwInputWindowCloseRequest(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
window->shouldClose = GLFW_TRUE;
|
window->shouldClose = GLFW_TRUE;
|
||||||
@@ -112,7 +136,9 @@ void _glfwInputWindowCloseRequest(_GLFWwindow* window)
|
|||||||
window->callbacks.close((GLFWwindow*) window);
|
window->callbacks.close((GLFWwindow*) window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor)
|
// Notifies shared code that a window has changed its desired monitor
|
||||||
|
//
|
||||||
|
void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor)
|
||||||
{
|
{
|
||||||
window->monitor = monitor;
|
window->monitor = monitor;
|
||||||
}
|
}
|
||||||
@@ -131,9 +157,10 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
|||||||
_GLFWctxconfig ctxconfig;
|
_GLFWctxconfig ctxconfig;
|
||||||
_GLFWwndconfig wndconfig;
|
_GLFWwndconfig wndconfig;
|
||||||
_GLFWwindow* window;
|
_GLFWwindow* window;
|
||||||
_GLFWwindow* previous;
|
|
||||||
|
|
||||||
assert(title != NULL);
|
assert(title != NULL);
|
||||||
|
assert(width >= 0);
|
||||||
|
assert(height >= 0);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
@@ -155,16 +182,6 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
|||||||
wndconfig.title = title;
|
wndconfig.title = title;
|
||||||
ctxconfig.share = (_GLFWwindow*) share;
|
ctxconfig.share = (_GLFWwindow*) share;
|
||||||
|
|
||||||
if (ctxconfig.share)
|
|
||||||
{
|
|
||||||
if (ctxconfig.client == GLFW_NO_API ||
|
|
||||||
ctxconfig.share->context.client == GLFW_NO_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_glfwIsValidContextConfig(&ctxconfig))
|
if (!_glfwIsValidContextConfig(&ctxconfig))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -193,36 +210,32 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
|||||||
window->numer = GLFW_DONT_CARE;
|
window->numer = GLFW_DONT_CARE;
|
||||||
window->denom = GLFW_DONT_CARE;
|
window->denom = GLFW_DONT_CARE;
|
||||||
|
|
||||||
// Save the currently current context so it can be restored later
|
|
||||||
previous = _glfwPlatformGetCurrentContext();
|
|
||||||
if (ctxconfig.client != GLFW_NO_API)
|
|
||||||
glfwMakeContextCurrent(NULL);
|
|
||||||
|
|
||||||
// Open the actual window and create its context
|
// Open the actual window and create its context
|
||||||
if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig))
|
if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig))
|
||||||
{
|
{
|
||||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
|
||||||
glfwDestroyWindow((GLFWwindow*) window);
|
glfwDestroyWindow((GLFWwindow*) window);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig.client != GLFW_NO_API)
|
if (ctxconfig.client != GLFW_NO_API)
|
||||||
{
|
{
|
||||||
window->context.makeCurrent(window);
|
if (!_glfwRefreshContextAttribs(window, &ctxconfig))
|
||||||
|
|
||||||
// Retrieve the actual (as opposed to requested) context attributes
|
|
||||||
if (!_glfwRefreshContextAttribs(&ctxconfig))
|
|
||||||
{
|
{
|
||||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
|
||||||
glfwDestroyWindow((GLFWwindow*) window);
|
glfwDestroyWindow((GLFWwindow*) window);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore the previously current context (or NULL)
|
|
||||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!window->monitor)
|
if (window->monitor)
|
||||||
|
{
|
||||||
|
if (wndconfig.centerCursor)
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
_glfwPlatformGetWindowSize(window, &width, &height);
|
||||||
|
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (wndconfig.visible)
|
if (wndconfig.visible)
|
||||||
{
|
{
|
||||||
@@ -239,23 +252,25 @@ void glfwDefaultWindowHints(void)
|
|||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
memset(&_glfw.hints, 0, sizeof(_glfw.hints));
|
|
||||||
|
|
||||||
// The default is OpenGL with minimum version 1.0
|
// The default is OpenGL with minimum version 1.0
|
||||||
|
memset(&_glfw.hints.context, 0, sizeof(_glfw.hints.context));
|
||||||
_glfw.hints.context.client = GLFW_OPENGL_API;
|
_glfw.hints.context.client = GLFW_OPENGL_API;
|
||||||
_glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API;
|
_glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API;
|
||||||
_glfw.hints.context.major = 1;
|
_glfw.hints.context.major = 1;
|
||||||
_glfw.hints.context.minor = 0;
|
_glfw.hints.context.minor = 0;
|
||||||
|
|
||||||
// The default is a focused, visible, resizable window with decorations
|
// The default is a focused, visible, resizable window with decorations
|
||||||
|
memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
|
||||||
_glfw.hints.window.resizable = GLFW_TRUE;
|
_glfw.hints.window.resizable = GLFW_TRUE;
|
||||||
_glfw.hints.window.visible = GLFW_TRUE;
|
_glfw.hints.window.visible = GLFW_TRUE;
|
||||||
_glfw.hints.window.decorated = GLFW_TRUE;
|
_glfw.hints.window.decorated = GLFW_TRUE;
|
||||||
_glfw.hints.window.focused = GLFW_TRUE;
|
_glfw.hints.window.focused = GLFW_TRUE;
|
||||||
_glfw.hints.window.autoIconify = 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,
|
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
|
||||||
// double buffered
|
// double buffered
|
||||||
|
memset(&_glfw.hints.framebuffer, 0, sizeof(_glfw.hints.framebuffer));
|
||||||
_glfw.hints.framebuffer.redBits = 8;
|
_glfw.hints.framebuffer.redBits = 8;
|
||||||
_glfw.hints.framebuffer.greenBits = 8;
|
_glfw.hints.framebuffer.greenBits = 8;
|
||||||
_glfw.hints.framebuffer.blueBits = 8;
|
_glfw.hints.framebuffer.blueBits = 8;
|
||||||
@@ -279,110 +294,143 @@ GLFWAPI void glfwWindowHint(int hint, int value)
|
|||||||
{
|
{
|
||||||
case GLFW_RED_BITS:
|
case GLFW_RED_BITS:
|
||||||
_glfw.hints.framebuffer.redBits = value;
|
_glfw.hints.framebuffer.redBits = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_GREEN_BITS:
|
case GLFW_GREEN_BITS:
|
||||||
_glfw.hints.framebuffer.greenBits = value;
|
_glfw.hints.framebuffer.greenBits = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_BLUE_BITS:
|
case GLFW_BLUE_BITS:
|
||||||
_glfw.hints.framebuffer.blueBits = value;
|
_glfw.hints.framebuffer.blueBits = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_ALPHA_BITS:
|
case GLFW_ALPHA_BITS:
|
||||||
_glfw.hints.framebuffer.alphaBits = value;
|
_glfw.hints.framebuffer.alphaBits = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_DEPTH_BITS:
|
case GLFW_DEPTH_BITS:
|
||||||
_glfw.hints.framebuffer.depthBits = value;
|
_glfw.hints.framebuffer.depthBits = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_STENCIL_BITS:
|
case GLFW_STENCIL_BITS:
|
||||||
_glfw.hints.framebuffer.stencilBits = value;
|
_glfw.hints.framebuffer.stencilBits = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_ACCUM_RED_BITS:
|
case GLFW_ACCUM_RED_BITS:
|
||||||
_glfw.hints.framebuffer.accumRedBits = value;
|
_glfw.hints.framebuffer.accumRedBits = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_ACCUM_GREEN_BITS:
|
case GLFW_ACCUM_GREEN_BITS:
|
||||||
_glfw.hints.framebuffer.accumGreenBits = value;
|
_glfw.hints.framebuffer.accumGreenBits = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_ACCUM_BLUE_BITS:
|
case GLFW_ACCUM_BLUE_BITS:
|
||||||
_glfw.hints.framebuffer.accumBlueBits = value;
|
_glfw.hints.framebuffer.accumBlueBits = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_ACCUM_ALPHA_BITS:
|
case GLFW_ACCUM_ALPHA_BITS:
|
||||||
_glfw.hints.framebuffer.accumAlphaBits = value;
|
_glfw.hints.framebuffer.accumAlphaBits = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_AUX_BUFFERS:
|
case GLFW_AUX_BUFFERS:
|
||||||
_glfw.hints.framebuffer.auxBuffers = value;
|
_glfw.hints.framebuffer.auxBuffers = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_STEREO:
|
case GLFW_STEREO:
|
||||||
_glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
break;
|
return;
|
||||||
case GLFW_DOUBLEBUFFER:
|
case GLFW_DOUBLEBUFFER:
|
||||||
_glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
break;
|
return;
|
||||||
|
case GLFW_TRANSPARENT_FRAMEBUFFER:
|
||||||
|
_glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
return;
|
||||||
case GLFW_SAMPLES:
|
case GLFW_SAMPLES:
|
||||||
_glfw.hints.framebuffer.samples = value;
|
_glfw.hints.framebuffer.samples = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_SRGB_CAPABLE:
|
case GLFW_SRGB_CAPABLE:
|
||||||
_glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
break;
|
return;
|
||||||
case GLFW_RESIZABLE:
|
case GLFW_RESIZABLE:
|
||||||
_glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
break;
|
return;
|
||||||
case GLFW_DECORATED:
|
case GLFW_DECORATED:
|
||||||
_glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
break;
|
return;
|
||||||
case GLFW_FOCUSED:
|
case GLFW_FOCUSED:
|
||||||
_glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
break;
|
return;
|
||||||
case GLFW_AUTO_ICONIFY:
|
case GLFW_AUTO_ICONIFY:
|
||||||
_glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
break;
|
return;
|
||||||
case GLFW_FLOATING:
|
case GLFW_FLOATING:
|
||||||
_glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
break;
|
return;
|
||||||
case GLFW_MAXIMIZED:
|
case GLFW_MAXIMIZED:
|
||||||
_glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
break;
|
return;
|
||||||
case GLFW_VISIBLE:
|
case GLFW_VISIBLE:
|
||||||
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
break;
|
return;
|
||||||
case GLFW_COCOA_RETINA_FRAMEBUFFER:
|
case GLFW_COCOA_RETINA_FRAMEBUFFER:
|
||||||
_glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
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:
|
case GLFW_CLIENT_API:
|
||||||
_glfw.hints.context.client = value;
|
_glfw.hints.context.client = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_CONTEXT_CREATION_API:
|
case GLFW_CONTEXT_CREATION_API:
|
||||||
_glfw.hints.context.source = value;
|
_glfw.hints.context.source = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_CONTEXT_VERSION_MAJOR:
|
case GLFW_CONTEXT_VERSION_MAJOR:
|
||||||
_glfw.hints.context.major = value;
|
_glfw.hints.context.major = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_CONTEXT_VERSION_MINOR:
|
case GLFW_CONTEXT_VERSION_MINOR:
|
||||||
_glfw.hints.context.minor = value;
|
_glfw.hints.context.minor = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_CONTEXT_ROBUSTNESS:
|
case GLFW_CONTEXT_ROBUSTNESS:
|
||||||
_glfw.hints.context.robustness = value;
|
_glfw.hints.context.robustness = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_OPENGL_FORWARD_COMPAT:
|
case GLFW_OPENGL_FORWARD_COMPAT:
|
||||||
_glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
break;
|
return;
|
||||||
case GLFW_OPENGL_DEBUG_CONTEXT:
|
case GLFW_OPENGL_DEBUG_CONTEXT:
|
||||||
_glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
break;
|
return;
|
||||||
case GLFW_CONTEXT_NO_ERROR:
|
case GLFW_CONTEXT_NO_ERROR:
|
||||||
_glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
break;
|
return;
|
||||||
case GLFW_OPENGL_PROFILE:
|
case GLFW_OPENGL_PROFILE:
|
||||||
_glfw.hints.context.profile = value;
|
_glfw.hints.context.profile = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_CONTEXT_RELEASE_BEHAVIOR:
|
case GLFW_CONTEXT_RELEASE_BEHAVIOR:
|
||||||
_glfw.hints.context.release = value;
|
_glfw.hints.context.release = value;
|
||||||
break;
|
return;
|
||||||
case GLFW_REFRESH_RATE:
|
case GLFW_REFRESH_RATE:
|
||||||
_glfw.hints.refreshRate = value;
|
_glfw.hints.refreshRate = value;
|
||||||
break;
|
return;
|
||||||
default:
|
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint %i", hint);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwWindowHintString(int hint, const char* value)
|
||||||
|
{
|
||||||
|
assert(value != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
switch (hint)
|
||||||
|
{
|
||||||
|
case GLFW_COCOA_FRAME_NAME:
|
||||||
|
strncpy(_glfw.hints.window.ns.frameName, value,
|
||||||
|
sizeof(_glfw.hints.window.ns.frameName) - 1);
|
||||||
|
return;
|
||||||
|
case GLFW_X11_CLASS_NAME:
|
||||||
|
strncpy(_glfw.hints.window.x11.className, value,
|
||||||
|
sizeof(_glfw.hints.window.x11.className) - 1);
|
||||||
|
return;
|
||||||
|
case GLFW_X11_INSTANCE_NAME:
|
||||||
|
strncpy(_glfw.hints.window.x11.instanceName, value,
|
||||||
|
sizeof(_glfw.hints.window.x11.instanceName) - 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint string 0x%08X", hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
|
GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
|
||||||
@@ -400,7 +448,7 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
|
|||||||
|
|
||||||
// The window's context must not be current on another thread when the
|
// The window's context must not be current on another thread when the
|
||||||
// window is destroyed
|
// window is destroyed
|
||||||
if (window == _glfwPlatformGetCurrentContext())
|
if (window == _glfwPlatformGetTls(&_glfw.contextSlot))
|
||||||
glfwMakeContextCurrent(NULL);
|
glfwMakeContextCurrent(NULL);
|
||||||
|
|
||||||
_glfwPlatformDestroyWindow(window);
|
_glfwPlatformDestroyWindow(window);
|
||||||
@@ -440,7 +488,6 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title)
|
|||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
assert(window != NULL);
|
assert(window != NULL);
|
||||||
|
|
||||||
assert(title != NULL);
|
assert(title != NULL);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
@@ -504,6 +551,8 @@ GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height)
|
|||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
assert(window != NULL);
|
assert(window != NULL);
|
||||||
|
assert(width >= 0);
|
||||||
|
assert(height >= 0);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
@@ -562,6 +611,8 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)
|
|||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
assert(window != NULL);
|
assert(window != NULL);
|
||||||
|
assert(numer != 0);
|
||||||
|
assert(denom != 0);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
@@ -619,6 +670,49 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle,
|
|||||||
_glfwPlatformGetWindowFrameSize(window, left, top, right, bottom);
|
_glfwPlatformGetWindowFrameSize(window, left, top, right, bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle,
|
||||||
|
float* xscale, float* yscale)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
if (xscale)
|
||||||
|
*xscale = 0.f;
|
||||||
|
if (yscale)
|
||||||
|
*yscale = 0.f;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
_glfwPlatformGetWindowContentScale(window, xscale, yscale);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(1.f);
|
||||||
|
return _glfwPlatformGetWindowOpacity(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
assert(opacity == opacity);
|
||||||
|
assert(opacity >= 0.f);
|
||||||
|
assert(opacity <= 1.f);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (opacity != opacity || opacity < 0.f || opacity > 1.f)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE, "Invalid window opacity %f", opacity);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwPlatformSetWindowOpacity(window, opacity);
|
||||||
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwIconifyWindow(GLFWwindow* handle)
|
GLFWAPI void glfwIconifyWindow(GLFWwindow* handle)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
@@ -664,6 +758,16 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle)
|
|||||||
_glfwPlatformFocusWindow(window);
|
_glfwPlatformFocusWindow(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
_glfwPlatformRequestWindowAttention(window);
|
||||||
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwHideWindow(GLFWwindow* handle)
|
GLFWAPI void glfwHideWindow(GLFWwindow* handle)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
@@ -704,6 +808,10 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
|
|||||||
return _glfwPlatformWindowVisible(window);
|
return _glfwPlatformWindowVisible(window);
|
||||||
case GLFW_MAXIMIZED:
|
case GLFW_MAXIMIZED:
|
||||||
return _glfwPlatformWindowMaximized(window);
|
return _glfwPlatformWindowMaximized(window);
|
||||||
|
case GLFW_HOVERED:
|
||||||
|
return _glfwPlatformWindowHovered(window);
|
||||||
|
case GLFW_TRANSPARENT_FRAMEBUFFER:
|
||||||
|
return _glfwPlatformFramebufferTransparent(window);
|
||||||
case GLFW_RESIZABLE:
|
case GLFW_RESIZABLE:
|
||||||
return window->resizable;
|
return window->resizable;
|
||||||
case GLFW_DECORATED:
|
case GLFW_DECORATED:
|
||||||
@@ -736,7 +844,7 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
|
|||||||
return window->context.noerror;
|
return window->context.noerror;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute %i", attrib);
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -749,41 +857,37 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
|
|||||||
|
|
||||||
value = value ? GLFW_TRUE : GLFW_FALSE;
|
value = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
|
||||||
switch (attrib)
|
if (attrib == GLFW_AUTO_ICONIFY)
|
||||||
{
|
window->autoIconify = value;
|
||||||
case GLFW_RESIZABLE:
|
else if (attrib == GLFW_RESIZABLE)
|
||||||
if (window->resizable != value)
|
|
||||||
{
|
{
|
||||||
|
if (window->resizable == value)
|
||||||
|
return;
|
||||||
|
|
||||||
window->resizable = value;
|
window->resizable = value;
|
||||||
if (!window->monitor)
|
if (!window->monitor)
|
||||||
_glfwPlatformSetWindowResizable(window, value);
|
_glfwPlatformSetWindowResizable(window, value);
|
||||||
}
|
}
|
||||||
|
else if (attrib == GLFW_DECORATED)
|
||||||
|
{
|
||||||
|
if (window->decorated == value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case GLFW_DECORATED:
|
|
||||||
if (window->decorated != value)
|
|
||||||
{
|
|
||||||
window->decorated = value;
|
window->decorated = value;
|
||||||
if (!window->monitor)
|
if (!window->monitor)
|
||||||
_glfwPlatformSetWindowDecorated(window, value);
|
_glfwPlatformSetWindowDecorated(window, value);
|
||||||
}
|
}
|
||||||
|
else if (attrib == GLFW_FLOATING)
|
||||||
|
{
|
||||||
|
if (window->floating == value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case GLFW_FLOATING:
|
|
||||||
if (window->floating != value)
|
|
||||||
{
|
|
||||||
window->floating = value;
|
window->floating = value;
|
||||||
if (!window->monitor)
|
if (!window->monitor)
|
||||||
_glfwPlatformSetWindowFloating(window, value);
|
_glfwPlatformSetWindowFloating(window, value);
|
||||||
}
|
}
|
||||||
return;
|
else
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
|
||||||
case GLFW_AUTO_ICONIFY:
|
|
||||||
window->autoIconify = value;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute %i", attrib);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle)
|
GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle)
|
||||||
@@ -804,6 +908,8 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,
|
|||||||
_GLFWwindow* window = (_GLFWwindow*) wh;
|
_GLFWwindow* window = (_GLFWwindow*) wh;
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) mh;
|
_GLFWmonitor* monitor = (_GLFWmonitor*) mh;
|
||||||
assert(window != NULL);
|
assert(window != NULL);
|
||||||
|
assert(width >= 0);
|
||||||
|
assert(height >= 0);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
@@ -938,6 +1044,17 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle
|
|||||||
return cbfun;
|
return cbfun;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* handle,
|
||||||
|
GLFWwindowcontentscalefun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.scale, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwPollEvents(void)
|
GLFWAPI void glfwPollEvents(void)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
@@ -957,6 +1074,9 @@ GLFWAPI void glfwWaitEvents(void)
|
|||||||
GLFWAPI void glfwWaitEventsTimeout(double timeout)
|
GLFWAPI void glfwWaitEventsTimeout(double timeout)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
|
assert(timeout == timeout);
|
||||||
|
assert(timeout >= 0.0);
|
||||||
|
assert(timeout <= DBL_MAX);
|
||||||
|
|
||||||
if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)
|
if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)
|
||||||
{
|
{
|
||||||
|
|||||||
+177
-31
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -33,7 +34,6 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include <wayland-cursor.h>
|
|
||||||
|
|
||||||
|
|
||||||
static inline int min(int n1, int n2)
|
static inline int min(int n1, int n2)
|
||||||
@@ -48,11 +48,17 @@ static void pointerHandleEnter(void* data,
|
|||||||
wl_fixed_t sx,
|
wl_fixed_t sx,
|
||||||
wl_fixed_t sy)
|
wl_fixed_t sy)
|
||||||
{
|
{
|
||||||
|
// Happens in the case we just destroyed the surface.
|
||||||
|
if (!surface)
|
||||||
|
return;
|
||||||
|
|
||||||
_GLFWwindow* window = wl_surface_get_user_data(surface);
|
_GLFWwindow* window = wl_surface_get_user_data(surface);
|
||||||
|
|
||||||
_glfw.wl.pointerSerial = serial;
|
_glfw.wl.pointerSerial = serial;
|
||||||
_glfw.wl.pointerFocus = window;
|
_glfw.wl.pointerFocus = window;
|
||||||
|
|
||||||
|
window->wl.hovered = GLFW_TRUE;
|
||||||
|
|
||||||
_glfwPlatformSetCursor(window, window->wl.currentCursor);
|
_glfwPlatformSetCursor(window, window->wl.currentCursor);
|
||||||
_glfwInputCursorEnter(window, GLFW_TRUE);
|
_glfwInputCursorEnter(window, GLFW_TRUE);
|
||||||
}
|
}
|
||||||
@@ -67,6 +73,8 @@ static void pointerHandleLeave(void* data,
|
|||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
window->wl.hovered = GLFW_FALSE;
|
||||||
|
|
||||||
_glfw.wl.pointerSerial = serial;
|
_glfw.wl.pointerSerial = serial;
|
||||||
_glfw.wl.pointerFocus = NULL;
|
_glfw.wl.pointerFocus = NULL;
|
||||||
_glfwInputCursorEnter(window, GLFW_FALSE);
|
_glfwInputCursorEnter(window, GLFW_FALSE);
|
||||||
@@ -109,6 +117,8 @@ static void pointerHandleButton(void* data,
|
|||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
_glfw.wl.pointerSerial = serial;
|
||||||
|
|
||||||
/* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
|
/* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
|
||||||
* codes. */
|
* codes. */
|
||||||
glfwButton = button - BTN_LEFT;
|
glfwButton = button - BTN_LEFT;
|
||||||
@@ -128,30 +138,22 @@ static void pointerHandleAxis(void* data,
|
|||||||
wl_fixed_t value)
|
wl_fixed_t value)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
||||||
double scrollFactor;
|
double x = 0.0, y = 0.0;
|
||||||
double x, y;
|
// Wayland scroll events are in pointer motion coordinate space (think two
|
||||||
|
// finger scroll). The factor 10 is commonly used to convert to "scroll
|
||||||
|
// step means 1.0.
|
||||||
|
const double scrollFactor = 1.0 / 10.0;
|
||||||
|
|
||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Wayland scroll events are in pointer motion coordinate space (think
|
assert(axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL ||
|
||||||
* two finger scroll). The factor 10 is commonly used to convert to
|
axis == WL_POINTER_AXIS_VERTICAL_SCROLL);
|
||||||
* "scroll step means 1.0. */
|
|
||||||
scrollFactor = 1.0/10.0;
|
|
||||||
|
|
||||||
switch (axis)
|
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
|
||||||
{
|
|
||||||
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
|
|
||||||
x = wl_fixed_to_double(value) * scrollFactor;
|
x = wl_fixed_to_double(value) * scrollFactor;
|
||||||
y = 0.0;
|
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
|
||||||
break;
|
|
||||||
case WL_POINTER_AXIS_VERTICAL_SCROLL:
|
|
||||||
x = 0.0;
|
|
||||||
y = wl_fixed_to_double(value) * scrollFactor;
|
y = wl_fixed_to_double(value) * scrollFactor;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwInputScroll(window, x, y);
|
_glfwInputScroll(window, x, y);
|
||||||
}
|
}
|
||||||
@@ -172,8 +174,12 @@ static void keyboardHandleKeymap(void* data,
|
|||||||
{
|
{
|
||||||
struct xkb_keymap* keymap;
|
struct xkb_keymap* keymap;
|
||||||
struct xkb_state* state;
|
struct xkb_state* state;
|
||||||
|
|
||||||
|
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||||
struct xkb_compose_table* composeTable;
|
struct xkb_compose_table* composeTable;
|
||||||
struct xkb_compose_state* composeState;
|
struct xkb_compose_state* composeState;
|
||||||
|
#endif
|
||||||
|
|
||||||
char* mapStr;
|
char* mapStr;
|
||||||
const char* locale;
|
const char* locale;
|
||||||
|
|
||||||
@@ -221,6 +227,7 @@ static void keyboardHandleKeymap(void* data,
|
|||||||
if (!locale)
|
if (!locale)
|
||||||
locale = "C";
|
locale = "C";
|
||||||
|
|
||||||
|
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||||
composeTable =
|
composeTable =
|
||||||
xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
|
xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
|
||||||
XKB_COMPOSE_COMPILE_NO_FLAGS);
|
XKB_COMPOSE_COMPILE_NO_FLAGS);
|
||||||
@@ -240,6 +247,7 @@ static void keyboardHandleKeymap(void* data,
|
|||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Failed to create XKB compose table");
|
"Wayland: Failed to create XKB compose table");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
||||||
xkb_state_unref(_glfw.wl.xkb.state);
|
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");
|
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
|
||||||
_glfw.wl.xkb.superMask =
|
_glfw.wl.xkb.superMask =
|
||||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
|
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,
|
static void keyboardHandleEnter(void* data,
|
||||||
@@ -262,6 +274,10 @@ static void keyboardHandleEnter(void* data,
|
|||||||
struct wl_surface* surface,
|
struct wl_surface* surface,
|
||||||
struct wl_array* keys)
|
struct wl_array* keys)
|
||||||
{
|
{
|
||||||
|
// Happens in the case we just destroyed the surface.
|
||||||
|
if (!surface)
|
||||||
|
return;
|
||||||
|
|
||||||
_GLFWwindow* window = wl_surface_get_user_data(surface);
|
_GLFWwindow* window = wl_surface_get_user_data(surface);
|
||||||
|
|
||||||
_glfw.wl.keyboardFocus = window;
|
_glfw.wl.keyboardFocus = window;
|
||||||
@@ -290,9 +306,10 @@ static int toGLFWKeyCode(uint32_t key)
|
|||||||
return GLFW_KEY_UNKNOWN;
|
return GLFW_KEY_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||||
static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
|
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;
|
return sym;
|
||||||
if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym)
|
if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym)
|
||||||
!= XKB_COMPOSE_FEED_ACCEPTED)
|
!= XKB_COMPOSE_FEED_ACCEPTED)
|
||||||
@@ -309,6 +326,7 @@ static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
|
|||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void inputChar(_GLFWwindow* window, uint32_t key)
|
static void inputChar(_GLFWwindow* window, uint32_t key)
|
||||||
{
|
{
|
||||||
@@ -322,7 +340,11 @@ static void inputChar(_GLFWwindow* window, uint32_t key)
|
|||||||
|
|
||||||
if (numSyms == 1)
|
if (numSyms == 1)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||||
sym = composeSymbol(syms[0]);
|
sym = composeSymbol(syms[0]);
|
||||||
|
#else
|
||||||
|
sym = syms[0];
|
||||||
|
#endif
|
||||||
cp = _glfwKeySym2Unicode(sym);
|
cp = _glfwKeySym2Unicode(sym);
|
||||||
if (cp != -1)
|
if (cp != -1)
|
||||||
{
|
{
|
||||||
@@ -393,6 +415,10 @@ static void keyboardHandleModifiers(void* data,
|
|||||||
modifiers |= GLFW_MOD_SHIFT;
|
modifiers |= GLFW_MOD_SHIFT;
|
||||||
if (mask & _glfw.wl.xkb.superMask)
|
if (mask & _glfw.wl.xkb.superMask)
|
||||||
modifiers |= GLFW_MOD_SUPER;
|
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;
|
_glfw.wl.xkb.modifiers = modifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,6 +461,17 @@ static const struct wl_seat_listener seatListener = {
|
|||||||
seatHandleCapabilities
|
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,
|
static void registryHandleGlobal(void* data,
|
||||||
struct wl_registry* registry,
|
struct wl_registry* registry,
|
||||||
uint32_t name,
|
uint32_t name,
|
||||||
@@ -471,6 +508,12 @@ static void registryHandleGlobal(void* data,
|
|||||||
wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL);
|
wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (strcmp(interface, "xdg_wm_base") == 0)
|
||||||
|
{
|
||||||
|
_glfw.wl.wmBase =
|
||||||
|
wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
|
||||||
|
xdg_wm_base_add_listener(_glfw.wl.wmBase, &wmBaseListener, NULL);
|
||||||
|
}
|
||||||
else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0)
|
else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0)
|
||||||
{
|
{
|
||||||
_glfw.wl.relativePointerManager =
|
_glfw.wl.relativePointerManager =
|
||||||
@@ -485,6 +528,13 @@ static void registryHandleGlobal(void* data,
|
|||||||
&zwp_pointer_constraints_v1_interface,
|
&zwp_pointer_constraints_v1_interface,
|
||||||
1);
|
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,
|
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_8] = GLFW_KEY_8;
|
||||||
_glfw.wl.keycodes[KEY_9] = GLFW_KEY_9;
|
_glfw.wl.keycodes[KEY_9] = GLFW_KEY_9;
|
||||||
_glfw.wl.keycodes[KEY_0] = GLFW_KEY_0;
|
_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_MINUS] = GLFW_KEY_MINUS;
|
||||||
_glfw.wl.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL;
|
_glfw.wl.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL;
|
||||||
_glfw.wl.keycodes[KEY_Q] = GLFW_KEY_Q;
|
_glfw.wl.keycodes[KEY_Q] = GLFW_KEY_Q;
|
||||||
@@ -639,6 +690,84 @@ static void createKeyTables(void)
|
|||||||
|
|
||||||
int _glfwPlatformInit(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);
|
_glfw.wl.display = wl_display_connect(NULL);
|
||||||
if (!_glfw.wl.display)
|
if (!_glfw.wl.display)
|
||||||
{
|
{
|
||||||
@@ -650,9 +779,6 @@ int _glfwPlatformInit(void)
|
|||||||
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
||||||
wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
|
wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
|
||||||
|
|
||||||
_glfw.wl.monitors = calloc(4, sizeof(_GLFWmonitor*));
|
|
||||||
_glfw.wl.monitorsSize = 4;
|
|
||||||
|
|
||||||
createKeyTables();
|
createKeyTables();
|
||||||
|
|
||||||
_glfw.wl.xkb.context = xkb_context_new(0);
|
_glfw.wl.xkb.context = xkb_context_new(0);
|
||||||
@@ -669,9 +795,6 @@ int _glfwPlatformInit(void)
|
|||||||
// Sync so we got all initial output events
|
// Sync so we got all initial output events
|
||||||
wl_display_roundtrip(_glfw.wl.display);
|
wl_display_roundtrip(_glfw.wl.display);
|
||||||
|
|
||||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
if (!_glfwInitJoysticksLinux())
|
if (!_glfwInitJoysticksLinux())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
@@ -683,7 +806,7 @@ int _glfwPlatformInit(void)
|
|||||||
if (!_glfw.wl.cursorTheme)
|
if (!_glfw.wl.cursorTheme)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Unable to load default cursor theme\n");
|
"Wayland: Unable to load default cursor theme");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
_glfw.wl.cursorSurface =
|
_glfw.wl.cursorSurface =
|
||||||
@@ -695,17 +818,38 @@ int _glfwPlatformInit(void)
|
|||||||
|
|
||||||
void _glfwPlatformTerminate(void)
|
void _glfwPlatformTerminate(void)
|
||||||
{
|
{
|
||||||
_glfwTerminateEGL();
|
|
||||||
_glfwTerminateJoysticksLinux();
|
_glfwTerminateJoysticksLinux();
|
||||||
_glfwTerminateThreadLocalStoragePOSIX();
|
_glfwTerminateEGL();
|
||||||
|
if (_glfw.wl.egl.handle)
|
||||||
|
{
|
||||||
|
_glfw_dlclose(_glfw.wl.egl.handle);
|
||||||
|
_glfw.wl.egl.handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||||
|
if (_glfw.wl.xkb.composeState)
|
||||||
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
|
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
|
||||||
|
#endif
|
||||||
|
if (_glfw.wl.xkb.keymap)
|
||||||
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
||||||
|
if (_glfw.wl.xkb.state)
|
||||||
xkb_state_unref(_glfw.wl.xkb.state);
|
xkb_state_unref(_glfw.wl.xkb.state);
|
||||||
|
if (_glfw.wl.xkb.context)
|
||||||
xkb_context_unref(_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)
|
if (_glfw.wl.cursorTheme)
|
||||||
wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
|
wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
|
||||||
|
if (_glfw.wl.cursor.handle)
|
||||||
|
{
|
||||||
|
_glfw_dlclose(_glfw.wl.cursor.handle);
|
||||||
|
_glfw.wl.cursor.handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (_glfw.wl.cursorSurface)
|
if (_glfw.wl.cursorSurface)
|
||||||
wl_surface_destroy(_glfw.wl.cursorSurface);
|
wl_surface_destroy(_glfw.wl.cursorSurface);
|
||||||
if (_glfw.wl.compositor)
|
if (_glfw.wl.compositor)
|
||||||
@@ -714,6 +858,8 @@ void _glfwPlatformTerminate(void)
|
|||||||
wl_shm_destroy(_glfw.wl.shm);
|
wl_shm_destroy(_glfw.wl.shm);
|
||||||
if (_glfw.wl.shell)
|
if (_glfw.wl.shell)
|
||||||
wl_shell_destroy(_glfw.wl.shell);
|
wl_shell_destroy(_glfw.wl.shell);
|
||||||
|
if (_glfw.wl.wmBase)
|
||||||
|
xdg_wm_base_destroy(_glfw.wl.wmBase);
|
||||||
if (_glfw.wl.pointer)
|
if (_glfw.wl.pointer)
|
||||||
wl_pointer_destroy(_glfw.wl.pointer);
|
wl_pointer_destroy(_glfw.wl.pointer);
|
||||||
if (_glfw.wl.keyboard)
|
if (_glfw.wl.keyboard)
|
||||||
@@ -724,6 +870,8 @@ void _glfwPlatformTerminate(void)
|
|||||||
zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager);
|
zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager);
|
||||||
if (_glfw.wl.pointerConstraints)
|
if (_glfw.wl.pointerConstraints)
|
||||||
zwp_pointer_constraints_v1_destroy(_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)
|
if (_glfw.wl.registry)
|
||||||
wl_registry_destroy(_glfw.wl.registry);
|
wl_registry_destroy(_glfw.wl.registry);
|
||||||
if (_glfw.wl.display)
|
if (_glfw.wl.display)
|
||||||
@@ -741,9 +889,7 @@ const char* _glfwPlatformGetVersionString(void)
|
|||||||
#else
|
#else
|
||||||
" gettimeofday"
|
" gettimeofday"
|
||||||
#endif
|
#endif
|
||||||
#if defined(__linux__)
|
" evdev"
|
||||||
" /dev/js"
|
|
||||||
#endif
|
|
||||||
#if defined(_GLFW_BUILD_DLL)
|
#if defined(_GLFW_BUILD_DLL)
|
||||||
" shared"
|
" shared"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+31
-106
@@ -32,12 +32,6 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
struct _GLFWvidmodeWayland
|
|
||||||
{
|
|
||||||
GLFWvidmode base;
|
|
||||||
uint32_t flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void geometry(void* data,
|
static void geometry(void* data,
|
||||||
struct wl_output* output,
|
struct wl_output* output,
|
||||||
int32_t x,
|
int32_t x,
|
||||||
@@ -50,21 +44,15 @@ static void geometry(void* data,
|
|||||||
int32_t transform)
|
int32_t transform)
|
||||||
{
|
{
|
||||||
struct _GLFWmonitor *monitor = data;
|
struct _GLFWmonitor *monitor = data;
|
||||||
char* name;
|
char name[1024];
|
||||||
size_t nameLength;
|
|
||||||
|
|
||||||
monitor->wl.x = x;
|
monitor->wl.x = x;
|
||||||
monitor->wl.y = y;
|
monitor->wl.y = y;
|
||||||
monitor->widthMM = physicalWidth;
|
monitor->widthMM = physicalWidth;
|
||||||
monitor->heightMM = physicalHeight;
|
monitor->heightMM = physicalHeight;
|
||||||
|
|
||||||
nameLength = strlen(make) + 1 + strlen(model) + 1;
|
snprintf(name, sizeof(name), "%s %s", make, model);
|
||||||
name = realloc(monitor->name, nameLength);
|
monitor->name = _glfw_strdup(name);
|
||||||
if (name)
|
|
||||||
{
|
|
||||||
sprintf(name, "%s %s", make, model);
|
|
||||||
monitor->name = name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mode(void* data,
|
static void mode(void* data,
|
||||||
@@ -75,32 +63,29 @@ static void mode(void* data,
|
|||||||
int32_t refresh)
|
int32_t refresh)
|
||||||
{
|
{
|
||||||
struct _GLFWmonitor *monitor = data;
|
struct _GLFWmonitor *monitor = data;
|
||||||
_GLFWvidmodeWayland mode = { { 0 }, };
|
GLFWvidmode mode;
|
||||||
|
|
||||||
mode.base.width = width;
|
mode.width = width;
|
||||||
mode.base.height = height;
|
mode.height = height;
|
||||||
mode.base.refreshRate = refresh / 1000;
|
mode.redBits = 8;
|
||||||
mode.flags = flags;
|
mode.greenBits = 8;
|
||||||
|
mode.blueBits = 8;
|
||||||
|
mode.refreshRate = refresh / 1000;
|
||||||
|
|
||||||
if (monitor->wl.modesCount + 1 >= monitor->wl.modesSize)
|
monitor->modeCount++;
|
||||||
{
|
monitor->modes =
|
||||||
int size = monitor->wl.modesSize * 2;
|
realloc(monitor->modes, monitor->modeCount * sizeof(GLFWvidmode));
|
||||||
_GLFWvidmodeWayland* modes =
|
monitor->modes[monitor->modeCount - 1] = mode;
|
||||||
realloc(monitor->wl.modes,
|
|
||||||
size * sizeof(_GLFWvidmodeWayland));
|
|
||||||
monitor->wl.modes = modes;
|
|
||||||
monitor->wl.modesSize = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
monitor->wl.modes[monitor->wl.modesCount++] = mode;
|
if (flags & WL_OUTPUT_MODE_CURRENT)
|
||||||
|
monitor->wl.currentMode = monitor->modeCount - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void done(void* data,
|
static void done(void* data, struct wl_output* output)
|
||||||
struct wl_output* output)
|
|
||||||
{
|
{
|
||||||
struct _GLFWmonitor *monitor = data;
|
struct _GLFWmonitor *monitor = data;
|
||||||
|
|
||||||
monitor->wl.done = GLFW_TRUE;
|
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scale(void* data,
|
static void scale(void* data,
|
||||||
@@ -149,26 +134,10 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
monitor->wl.modes = calloc(4, sizeof(_GLFWvidmodeWayland));
|
|
||||||
monitor->wl.modesSize = 4;
|
|
||||||
|
|
||||||
monitor->wl.scale = 1;
|
monitor->wl.scale = 1;
|
||||||
|
|
||||||
monitor->wl.output = output;
|
monitor->wl.output = output;
|
||||||
|
|
||||||
wl_output_add_listener(output, &outputListener, monitor);
|
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 //////
|
////// 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)
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||||
{
|
{
|
||||||
if (xpos)
|
if (xpos)
|
||||||
@@ -220,32 +153,24 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
|||||||
*ypos = monitor->wl.y;
|
*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* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||||
{
|
{
|
||||||
GLFWvidmode *modes;
|
*found = monitor->modeCount;
|
||||||
int i, modesCount = monitor->wl.modesCount;
|
return monitor->modes;
|
||||||
|
|
||||||
modes = calloc(modesCount, sizeof(GLFWvidmode));
|
|
||||||
|
|
||||||
for (i = 0; i < modesCount; i++)
|
|
||||||
modes[i] = monitor->wl.modes[i].base;
|
|
||||||
|
|
||||||
*found = modesCount;
|
|
||||||
return modes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||||
{
|
{
|
||||||
int i;
|
*mode = monitor->modes[monitor->wl.currentMode];
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
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 <wayland-client.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||||
#include <xkbcommon/xkbcommon-compose.h>
|
#include <xkbcommon/xkbcommon-compose.h>
|
||||||
|
#endif
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
|
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
|
||||||
@@ -46,14 +45,17 @@ typedef struct VkWaylandSurfaceCreateInfoKHR
|
|||||||
typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWaylandSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWaylandSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);
|
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);
|
||||||
|
|
||||||
#include "posix_tls.h"
|
#include "posix_thread.h"
|
||||||
#include "posix_time.h"
|
#include "posix_time.h"
|
||||||
#include "linux_joystick.h"
|
#include "linux_joystick.h"
|
||||||
#include "xkb_unicode.h"
|
#include "xkb_unicode.h"
|
||||||
#include "egl_context.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-relative-pointer-unstable-v1-client-protocol.h"
|
||||||
#include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
|
#include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
|
||||||
|
#include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
|
||||||
|
|
||||||
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||||
#define _glfw_dlclose(handle) dlclose(handle)
|
#define _glfw_dlclose(handle) dlclose(handle)
|
||||||
@@ -70,10 +72,72 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
|
|||||||
#define _GLFW_PLATFORM_CONTEXT_STATE
|
#define _GLFW_PLATFORM_CONTEXT_STATE
|
||||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
|
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
|
||||||
|
|
||||||
|
struct wl_cursor_image {
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
uint32_t hotspot_x;
|
||||||
|
uint32_t hotspot_y;
|
||||||
|
uint32_t delay;
|
||||||
|
};
|
||||||
|
struct wl_cursor {
|
||||||
|
unsigned int image_count;
|
||||||
|
struct wl_cursor_image** images;
|
||||||
|
char* name;
|
||||||
|
};
|
||||||
|
typedef struct wl_cursor_theme* (* PFN_wl_cursor_theme_load)(const char*, int, struct wl_shm*);
|
||||||
|
typedef void (* PFN_wl_cursor_theme_destroy)(struct wl_cursor_theme*);
|
||||||
|
typedef struct wl_cursor* (* PFN_wl_cursor_theme_get_cursor)(struct wl_cursor_theme*, const char*);
|
||||||
|
typedef struct wl_buffer* (* PFN_wl_cursor_image_get_buffer)(struct wl_cursor_image*);
|
||||||
|
#define wl_cursor_theme_load _glfw.wl.cursor.theme_load
|
||||||
|
#define wl_cursor_theme_destroy _glfw.wl.cursor.theme_destroy
|
||||||
|
#define wl_cursor_theme_get_cursor _glfw.wl.cursor.theme_get_cursor
|
||||||
|
#define wl_cursor_image_get_buffer _glfw.wl.cursor.image_get_buffer
|
||||||
|
|
||||||
|
typedef struct wl_egl_window* (* PFN_wl_egl_window_create)(struct wl_surface*, int, int);
|
||||||
|
typedef void (* PFN_wl_egl_window_destroy)(struct wl_egl_window*);
|
||||||
|
typedef void (* PFN_wl_egl_window_resize)(struct wl_egl_window*, int, int, int, int);
|
||||||
|
#define wl_egl_window_create _glfw.wl.egl.window_create
|
||||||
|
#define wl_egl_window_destroy _glfw.wl.egl.window_destroy
|
||||||
|
#define wl_egl_window_resize _glfw.wl.egl.window_resize
|
||||||
|
|
||||||
|
typedef struct xkb_context* (* PFN_xkb_context_new)(enum xkb_context_flags);
|
||||||
|
typedef 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
|
// Wayland-specific per-window data
|
||||||
//
|
//
|
||||||
@@ -82,11 +146,18 @@ typedef struct _GLFWwindowWayland
|
|||||||
int width, height;
|
int width, height;
|
||||||
GLFWbool visible;
|
GLFWbool visible;
|
||||||
GLFWbool maximized;
|
GLFWbool maximized;
|
||||||
|
GLFWbool hovered;
|
||||||
|
GLFWbool transparent;
|
||||||
struct wl_surface* surface;
|
struct wl_surface* surface;
|
||||||
struct wl_egl_window* native;
|
struct wl_egl_window* native;
|
||||||
struct wl_shell_surface* shellSurface;
|
struct wl_shell_surface* shellSurface;
|
||||||
struct wl_callback* callback;
|
struct wl_callback* callback;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct xdg_surface* surface;
|
||||||
|
struct xdg_toplevel* toplevel;
|
||||||
|
} xdg;
|
||||||
|
|
||||||
_GLFWcursor* currentCursor;
|
_GLFWcursor* currentCursor;
|
||||||
double cursorPosX, cursorPosY;
|
double cursorPosX, cursorPosY;
|
||||||
|
|
||||||
@@ -103,6 +174,12 @@ typedef struct _GLFWwindowWayland
|
|||||||
struct zwp_relative_pointer_v1* relativePointer;
|
struct zwp_relative_pointer_v1* relativePointer;
|
||||||
struct zwp_locked_pointer_v1* lockedPointer;
|
struct zwp_locked_pointer_v1* lockedPointer;
|
||||||
} pointerLock;
|
} pointerLock;
|
||||||
|
|
||||||
|
struct zwp_idle_inhibitor_v1* idleInhibitor;
|
||||||
|
|
||||||
|
// This is a hack to prevent auto-iconification on creation.
|
||||||
|
GLFWbool justCreated;
|
||||||
|
|
||||||
} _GLFWwindowWayland;
|
} _GLFWwindowWayland;
|
||||||
|
|
||||||
// Wayland-specific global data
|
// Wayland-specific global data
|
||||||
@@ -117,8 +194,10 @@ typedef struct _GLFWlibraryWayland
|
|||||||
struct wl_seat* seat;
|
struct wl_seat* seat;
|
||||||
struct wl_pointer* pointer;
|
struct wl_pointer* pointer;
|
||||||
struct wl_keyboard* keyboard;
|
struct wl_keyboard* keyboard;
|
||||||
|
struct xdg_wm_base* wmBase;
|
||||||
struct zwp_relative_pointer_manager_v1* relativePointerManager;
|
struct zwp_relative_pointer_manager_v1* relativePointerManager;
|
||||||
struct zwp_pointer_constraints_v1* pointerConstraints;
|
struct zwp_pointer_constraints_v1* pointerConstraints;
|
||||||
|
struct zwp_idle_inhibit_manager_v1* idleInhibitManager;
|
||||||
|
|
||||||
int compositorVersion;
|
int compositorVersion;
|
||||||
|
|
||||||
@@ -126,28 +205,69 @@ typedef struct _GLFWlibraryWayland
|
|||||||
struct wl_surface* cursorSurface;
|
struct wl_surface* cursorSurface;
|
||||||
uint32_t pointerSerial;
|
uint32_t pointerSerial;
|
||||||
|
|
||||||
_GLFWmonitor** monitors;
|
|
||||||
int monitorsCount;
|
|
||||||
int monitorsSize;
|
|
||||||
|
|
||||||
short int keycodes[256];
|
short int keycodes[256];
|
||||||
short int scancodes[GLFW_KEY_LAST + 1];
|
short int scancodes[GLFW_KEY_LAST + 1];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
void* handle;
|
||||||
struct xkb_context* context;
|
struct xkb_context* context;
|
||||||
struct xkb_keymap* keymap;
|
struct xkb_keymap* keymap;
|
||||||
struct xkb_state* state;
|
struct xkb_state* state;
|
||||||
|
|
||||||
|
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||||
struct xkb_compose_state* composeState;
|
struct xkb_compose_state* composeState;
|
||||||
|
#endif
|
||||||
|
|
||||||
xkb_mod_mask_t controlMask;
|
xkb_mod_mask_t controlMask;
|
||||||
xkb_mod_mask_t altMask;
|
xkb_mod_mask_t altMask;
|
||||||
xkb_mod_mask_t shiftMask;
|
xkb_mod_mask_t shiftMask;
|
||||||
xkb_mod_mask_t superMask;
|
xkb_mod_mask_t superMask;
|
||||||
|
xkb_mod_mask_t capsLockMask;
|
||||||
|
xkb_mod_mask_t numLockMask;
|
||||||
unsigned int modifiers;
|
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;
|
} xkb;
|
||||||
|
|
||||||
_GLFWwindow* pointerFocus;
|
_GLFWwindow* pointerFocus;
|
||||||
_GLFWwindow* keyboardFocus;
|
_GLFWwindow* keyboardFocus;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
void* handle;
|
||||||
|
|
||||||
|
PFN_wl_cursor_theme_load theme_load;
|
||||||
|
PFN_wl_cursor_theme_destroy theme_destroy;
|
||||||
|
PFN_wl_cursor_theme_get_cursor theme_get_cursor;
|
||||||
|
PFN_wl_cursor_image_get_buffer image_get_buffer;
|
||||||
|
} cursor;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
void* handle;
|
||||||
|
|
||||||
|
PFN_wl_egl_window_create window_create;
|
||||||
|
PFN_wl_egl_window_destroy window_destroy;
|
||||||
|
PFN_wl_egl_window_resize window_resize;
|
||||||
|
} egl;
|
||||||
|
|
||||||
} _GLFWlibraryWayland;
|
} _GLFWlibraryWayland;
|
||||||
|
|
||||||
// Wayland-specific per-monitor data
|
// Wayland-specific per-monitor data
|
||||||
@@ -155,15 +275,12 @@ typedef struct _GLFWlibraryWayland
|
|||||||
typedef struct _GLFWmonitorWayland
|
typedef struct _GLFWmonitorWayland
|
||||||
{
|
{
|
||||||
struct wl_output* output;
|
struct wl_output* output;
|
||||||
|
int currentMode;
|
||||||
_GLFWvidmodeWayland* modes;
|
|
||||||
int modesCount;
|
|
||||||
int modesSize;
|
|
||||||
GLFWbool done;
|
|
||||||
|
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
int scale;
|
int scale;
|
||||||
|
|
||||||
} _GLFWmonitorWayland;
|
} _GLFWmonitorWayland;
|
||||||
|
|
||||||
// Wayland-specific per-cursor data
|
// Wayland-specific per-cursor data
|
||||||
@@ -179,4 +296,3 @@ typedef struct _GLFWcursorWayland
|
|||||||
|
|
||||||
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
|
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
|
||||||
|
|
||||||
#endif // _glfw3_wayland_platform_h_
|
|
||||||
|
|||||||
+333
-30
@@ -37,9 +37,6 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
|
||||||
#include <wayland-egl.h>
|
|
||||||
#include <wayland-cursor.h>
|
|
||||||
|
|
||||||
|
|
||||||
static void handlePing(void* data,
|
static void handlePing(void* data,
|
||||||
struct wl_shell_surface* shellSurface,
|
struct wl_shell_surface* shellSurface,
|
||||||
@@ -125,6 +122,7 @@ static void checkScaleChange(_GLFWwindow* window)
|
|||||||
wl_surface_set_buffer_scale(window->wl.surface, scale);
|
wl_surface_set_buffer_scale(window->wl.surface, scale);
|
||||||
wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
|
wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
|
||||||
_glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
|
_glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
|
||||||
|
_glfwInputWindowContentScale(window, scale, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,6 +187,24 @@ static void setOpaqueRegion(_GLFWwindow* window)
|
|||||||
wl_region_destroy(region);
|
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,
|
static GLFWbool createSurface(_GLFWwindow* window,
|
||||||
const _GLFWwndconfig* wndconfig)
|
const _GLFWwndconfig* wndconfig)
|
||||||
{
|
{
|
||||||
@@ -212,7 +228,7 @@ static GLFWbool createSurface(_GLFWwindow* window,
|
|||||||
window->wl.height = wndconfig->height;
|
window->wl.height = wndconfig->height;
|
||||||
window->wl.scale = 1;
|
window->wl.scale = 1;
|
||||||
|
|
||||||
// TODO: make this optional once issue #197 is fixed.
|
if (!window->wl.transparent)
|
||||||
setOpaqueRegion(window);
|
setOpaqueRegion(window);
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
@@ -220,10 +236,21 @@ static GLFWbool createSurface(_GLFWwindow* window,
|
|||||||
|
|
||||||
static GLFWbool createShellSurface(_GLFWwindow* window)
|
static GLFWbool createShellSurface(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
|
if (!_glfw.wl.shell)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland: wl_shell protocol not available");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
window->wl.shellSurface = wl_shell_get_shell_surface(_glfw.wl.shell,
|
window->wl.shellSurface = wl_shell_get_shell_surface(_glfw.wl.shell,
|
||||||
window->wl.surface);
|
window->wl.surface);
|
||||||
if (!window->wl.shellSurface)
|
if (!window->wl.shellSurface)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland: Shell surface creation failed");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
wl_shell_surface_add_listener(window->wl.shellSurface,
|
wl_shell_surface_add_listener(window->wl.shellSurface,
|
||||||
&shellSurfaceListener,
|
&shellSurfaceListener,
|
||||||
@@ -239,16 +266,161 @@ static GLFWbool createShellSurface(_GLFWwindow* window)
|
|||||||
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
|
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
|
||||||
0,
|
0,
|
||||||
window->monitor->wl.output);
|
window->monitor->wl.output);
|
||||||
|
setIdleInhibitor(window, GLFW_TRUE);
|
||||||
}
|
}
|
||||||
else if (window->wl.maximized)
|
else if (window->wl.maximized)
|
||||||
{
|
{
|
||||||
wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
|
wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
|
||||||
|
setIdleInhibitor(window, GLFW_FALSE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wl_shell_surface_set_toplevel(window->wl.shellSurface);
|
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;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,29 +560,53 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig)
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
|
window->wl.justCreated = GLFW_TRUE;
|
||||||
|
window->wl.transparent = fbconfig->transparent;
|
||||||
|
|
||||||
if (!createSurface(window, wndconfig))
|
if (!createSurface(window, wndconfig))
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
if (ctxconfig->client != GLFW_NO_API)
|
if (ctxconfig->client != GLFW_NO_API)
|
||||||
|
{
|
||||||
|
if (ctxconfig->source == GLFW_EGL_CONTEXT_API ||
|
||||||
|
ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
|
||||||
{
|
{
|
||||||
if (!_glfwInitEGL())
|
if (!_glfwInitEGL())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
||||||
return GLFW_FALSE;
|
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)
|
if (wndconfig->title)
|
||||||
window->wl.title = strdup(wndconfig->title);
|
window->wl.title = _glfw_strdup(wndconfig->title);
|
||||||
|
|
||||||
if (wndconfig->visible)
|
if (wndconfig->visible)
|
||||||
|
{
|
||||||
|
if (_glfw.wl.wmBase)
|
||||||
|
{
|
||||||
|
if (!createXdgSurface(window))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (!createShellSurface(window))
|
if (!createShellSurface(window))
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
window->wl.visible = GLFW_TRUE;
|
window->wl.visible = GLFW_TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
window->wl.xdg.surface = NULL;
|
||||||
|
window->wl.xdg.toplevel = NULL;
|
||||||
window->wl.shellSurface = NULL;
|
window->wl.shellSurface = NULL;
|
||||||
window->wl.visible = GLFW_FALSE;
|
window->wl.visible = GLFW_FALSE;
|
||||||
}
|
}
|
||||||
@@ -437,6 +633,9 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
|||||||
_glfwInputWindowFocus(window, GLFW_FALSE);
|
_glfwInputWindowFocus(window, GLFW_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window->wl.idleInhibitor)
|
||||||
|
zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);
|
||||||
|
|
||||||
if (window->context.destroy)
|
if (window->context.destroy)
|
||||||
window->context.destroy(window);
|
window->context.destroy(window);
|
||||||
|
|
||||||
@@ -446,6 +645,12 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
|||||||
if (window->wl.shellSurface)
|
if (window->wl.shellSurface)
|
||||||
wl_shell_surface_destroy(window->wl.shellSurface);
|
wl_shell_surface_destroy(window->wl.shellSurface);
|
||||||
|
|
||||||
|
if (window->wl.xdg.toplevel)
|
||||||
|
xdg_toplevel_destroy(window->wl.xdg.toplevel);
|
||||||
|
|
||||||
|
if (window->wl.xdg.surface)
|
||||||
|
xdg_surface_destroy(window->wl.xdg.surface);
|
||||||
|
|
||||||
if (window->wl.surface)
|
if (window->wl.surface)
|
||||||
wl_surface_destroy(window->wl.surface);
|
wl_surface_destroy(window->wl.surface);
|
||||||
|
|
||||||
@@ -457,8 +662,10 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
|||||||
{
|
{
|
||||||
if (window->wl.title)
|
if (window->wl.title)
|
||||||
free(window->wl.title);
|
free(window->wl.title);
|
||||||
window->wl.title = strdup(title);
|
window->wl.title = _glfw_strdup(title);
|
||||||
if (window->wl.shellSurface)
|
if (window->wl.xdg.toplevel)
|
||||||
|
xdg_toplevel_set_title(window->wl.xdg.toplevel, title);
|
||||||
|
else if (window->wl.shellSurface)
|
||||||
wl_shell_surface_set_title(window->wl.shellSurface, title);
|
wl_shell_surface_set_title(window->wl.shellSurface, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,6 +708,7 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
|||||||
window->wl.width = width;
|
window->wl.width = width;
|
||||||
window->wl.height = height;
|
window->wl.height = height;
|
||||||
wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
|
wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
|
||||||
|
if (!window->wl.transparent)
|
||||||
setOpaqueRegion(window);
|
setOpaqueRegion(window);
|
||||||
_glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
|
_glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
|
||||||
}
|
}
|
||||||
@@ -509,8 +717,24 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
|||||||
int minwidth, int minheight,
|
int minwidth, int minheight,
|
||||||
int maxwidth, int maxheight)
|
int maxwidth, int maxheight)
|
||||||
{
|
{
|
||||||
|
if (_glfw.wl.wmBase)
|
||||||
|
{
|
||||||
|
if (window->wl.xdg.toplevel)
|
||||||
|
{
|
||||||
|
if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
|
||||||
|
minwidth = minheight = 0;
|
||||||
|
if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)
|
||||||
|
maxwidth = maxheight = 0;
|
||||||
|
xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight);
|
||||||
|
xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight);
|
||||||
|
wl_surface_commit(window->wl.surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// TODO: find out how to trigger a resize.
|
// TODO: find out how to trigger a resize.
|
||||||
// The actual limits are checked in the wl_shell_surface::configure handler.
|
// The actual limits are checked in the wl_shell_surface::configure handler.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
|
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
|
||||||
@@ -534,43 +758,70 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
|||||||
// implemented, but for now just leave everything as 0.
|
// 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)
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
// TODO: move to xdg_shell instead of wl_shell.
|
if (_glfw.wl.wmBase)
|
||||||
|
{
|
||||||
|
if (window->wl.xdg.toplevel)
|
||||||
|
xdg_toplevel_set_minimized(window->wl.xdg.toplevel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Iconify window not supported");
|
"Wayland: Iconify window not supported on wl_shell");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
// TODO: also do the same for iconified.
|
if (window->wl.xdg.toplevel)
|
||||||
if (window->monitor || window->wl.maximized)
|
|
||||||
{
|
{
|
||||||
if (window->wl.shellSurface)
|
if (window->monitor)
|
||||||
wl_shell_surface_set_toplevel(window->wl.shellSurface);
|
xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
|
||||||
|
if (window->wl.maximized)
|
||||||
window->wl.maximized = GLFW_FALSE;
|
xdg_toplevel_unset_maximized(window->wl.xdg.toplevel);
|
||||||
|
// There is no way to unset minimized, or even to know if we are
|
||||||
|
// minimized, so there is nothing to do here.
|
||||||
}
|
}
|
||||||
|
else if (window->wl.shellSurface)
|
||||||
|
{
|
||||||
|
if (window->monitor || window->wl.maximized)
|
||||||
|
wl_shell_surface_set_toplevel(window->wl.shellSurface);
|
||||||
|
}
|
||||||
|
_glfwInputWindowMonitor(window, NULL);
|
||||||
|
window->wl.maximized = GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (!window->monitor && !window->wl.maximized)
|
if (window->wl.xdg.toplevel)
|
||||||
{
|
{
|
||||||
if (window->wl.shellSurface)
|
xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
|
||||||
|
}
|
||||||
|
else if (window->wl.shellSurface)
|
||||||
{
|
{
|
||||||
// Let the compositor select the best output.
|
// Let the compositor select the best output.
|
||||||
wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
|
wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
|
||||||
}
|
}
|
||||||
window->wl.maximized = GLFW_TRUE;
|
window->wl.maximized = GLFW_TRUE;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (!window->monitor)
|
if (!window->wl.visible)
|
||||||
{
|
{
|
||||||
if (!window->wl.shellSurface)
|
if (_glfw.wl.wmBase)
|
||||||
|
createXdgSurface(window);
|
||||||
|
else if (!window->wl.shellSurface)
|
||||||
createShellSurface(window);
|
createShellSurface(window);
|
||||||
window->wl.visible = GLFW_TRUE;
|
window->wl.visible = GLFW_TRUE;
|
||||||
}
|
}
|
||||||
@@ -578,12 +829,26 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (!window->monitor)
|
if (window->wl.xdg.toplevel)
|
||||||
{
|
{
|
||||||
if (window->wl.shellSurface)
|
xdg_toplevel_destroy(window->wl.xdg.toplevel);
|
||||||
wl_shell_surface_destroy(window->wl.shellSurface);
|
xdg_surface_destroy(window->wl.xdg.surface);
|
||||||
window->wl.visible = GLFW_FALSE;
|
window->wl.xdg.toplevel = NULL;
|
||||||
|
window->wl.xdg.surface = NULL;
|
||||||
}
|
}
|
||||||
|
else if (window->wl.shellSurface)
|
||||||
|
{
|
||||||
|
wl_shell_surface_destroy(window->wl.shellSurface);
|
||||||
|
window->wl.shellSurface = NULL;
|
||||||
|
}
|
||||||
|
window->wl.visible = GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland: Window attention request not implemented yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||||
@@ -598,6 +863,21 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
|||||||
int width, int height,
|
int width, int height,
|
||||||
int refreshRate)
|
int refreshRate)
|
||||||
{
|
{
|
||||||
|
if (window->wl.xdg.toplevel)
|
||||||
|
{
|
||||||
|
if (monitor)
|
||||||
|
{
|
||||||
|
xdg_toplevel_set_fullscreen(
|
||||||
|
window->wl.xdg.toplevel,
|
||||||
|
monitor->wl.output);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (window->wl.shellSurface)
|
||||||
|
{
|
||||||
if (monitor)
|
if (monitor)
|
||||||
{
|
{
|
||||||
wl_shell_surface_set_fullscreen(
|
wl_shell_surface_set_fullscreen(
|
||||||
@@ -610,7 +890,9 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
wl_shell_surface_set_toplevel(window->wl.shellSurface);
|
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)
|
int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
||||||
@@ -620,7 +902,8 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
|||||||
|
|
||||||
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
// TODO: move to xdg_shell, wl_shell doesn't have any iconified concept.
|
// wl_shell doesn't have any iconified concept, and xdg-shell doesn’t give
|
||||||
|
// any way to request whether a surface is iconified.
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,6 +917,16 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
|||||||
return window->wl.maximized;
|
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)
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
@@ -655,6 +948,15 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
|||||||
"Wayland: Window attribute setting not implemented yet");
|
"Wayland: Window attribute setting not implemented yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void _glfwPlatformPollEvents(void)
|
void _glfwPlatformPollEvents(void)
|
||||||
{
|
{
|
||||||
handleEvents(0);
|
handleEvents(0);
|
||||||
@@ -701,7 +1003,7 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
|||||||
_glfwPlatformSetCursor(window, window->wl.currentCursor);
|
_glfwPlatformSetCursor(window, window->wl.currentCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetKeyName(int key, int scancode)
|
const char* _glfwPlatformGetScancodeName(int scancode)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
return NULL;
|
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
|
// TODO
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Clipboard setting not implemented yet");
|
"Wayland: Clipboard setting not implemented yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
const char* _glfwPlatformGetClipboardString(void)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
@@ -999,7 +1301,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
|||||||
VkPhysicalDevice device,
|
VkPhysicalDevice device,
|
||||||
uint32_t queuefamily)
|
uint32_t queuefamily)
|
||||||
{
|
{
|
||||||
PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR =
|
PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
|
||||||
|
vkGetPhysicalDeviceWaylandPresentationSupportKHR =
|
||||||
(PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)
|
(PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)
|
||||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
|
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
|
||||||
if (!vkGetPhysicalDeviceWaylandPresentationSupportKHR)
|
if (!vkGetPhysicalDeviceWaylandPresentationSupportKHR)
|
||||||
|
|||||||
+314
-56
@@ -237,8 +237,8 @@ static void createKeyTables(void)
|
|||||||
|
|
||||||
if (_glfw.x11.xkb.available)
|
if (_glfw.x11.xkb.available)
|
||||||
{
|
{
|
||||||
// Use XKB to determine physical key locations independently of the current
|
// Use XKB to determine physical key locations independently of the
|
||||||
// keyboard layout
|
// current keyboard layout
|
||||||
|
|
||||||
char name[XkbKeyNameLength + 1];
|
char name[XkbKeyNameLength + 1];
|
||||||
XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd);
|
XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd);
|
||||||
@@ -381,13 +381,11 @@ static void detectEWMH(void)
|
|||||||
XInternAtom(_glfw.x11.display, "_NET_SUPPORTED", False);
|
XInternAtom(_glfw.x11.display, "_NET_SUPPORTED", False);
|
||||||
|
|
||||||
// Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window
|
// Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window
|
||||||
if (_glfwGetWindowPropertyX11(_glfw.x11.root,
|
if (!_glfwGetWindowPropertyX11(_glfw.x11.root,
|
||||||
supportingWmCheck,
|
supportingWmCheck,
|
||||||
XA_WINDOW,
|
XA_WINDOW,
|
||||||
(unsigned char**) &windowFromRoot) != 1)
|
(unsigned char**) &windowFromRoot))
|
||||||
{
|
{
|
||||||
if (windowFromRoot)
|
|
||||||
XFree(windowFromRoot);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,14 +393,12 @@ static void detectEWMH(void)
|
|||||||
|
|
||||||
// It should be the ID of a child window (of the root)
|
// It should be the ID of a child window (of the root)
|
||||||
// Then we look for the same property on the child window
|
// Then we look for the same property on the child window
|
||||||
if (_glfwGetWindowPropertyX11(*windowFromRoot,
|
if (!_glfwGetWindowPropertyX11(*windowFromRoot,
|
||||||
supportingWmCheck,
|
supportingWmCheck,
|
||||||
XA_WINDOW,
|
XA_WINDOW,
|
||||||
(unsigned char**) &windowFromChild) != 1)
|
(unsigned char**) &windowFromChild))
|
||||||
{
|
{
|
||||||
XFree(windowFromRoot);
|
XFree(windowFromRoot);
|
||||||
if (windowFromChild)
|
|
||||||
XFree(windowFromChild);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,6 +438,8 @@ static void detectEWMH(void)
|
|||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_VERT");
|
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_VERT");
|
||||||
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ =
|
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_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 =
|
_glfw.x11.NET_WM_FULLSCREEN_MONITORS =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS");
|
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS");
|
||||||
_glfw.x11.NET_WM_WINDOW_TYPE =
|
_glfw.x11.NET_WM_WINDOW_TYPE =
|
||||||
@@ -455,24 +453,25 @@ static void detectEWMH(void)
|
|||||||
_glfw.x11.NET_REQUEST_FRAME_EXTENTS =
|
_glfw.x11.NET_REQUEST_FRAME_EXTENTS =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");
|
getSupportedAtom(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");
|
||||||
|
|
||||||
|
if (supportedAtoms)
|
||||||
XFree(supportedAtoms);
|
XFree(supportedAtoms);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize X11 display and look for supported X11 extensions
|
// Look for and initialize supported X11 extensions
|
||||||
//
|
//
|
||||||
static GLFWbool initExtensions(void)
|
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)
|
if (_glfw.x11.vidmode.handle)
|
||||||
{
|
{
|
||||||
_glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension)
|
_glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension)
|
||||||
dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension");
|
_glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension");
|
||||||
_glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp)
|
_glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp)
|
||||||
dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp");
|
_glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp");
|
||||||
_glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp)
|
_glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp)
|
||||||
dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp");
|
_glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp");
|
||||||
_glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize)
|
_glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize)
|
||||||
dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize");
|
_glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize");
|
||||||
|
|
||||||
_glfw.x11.vidmode.available =
|
_glfw.x11.vidmode.available =
|
||||||
XF86VidModeQueryExtension(_glfw.x11.display,
|
XF86VidModeQueryExtension(_glfw.x11.display,
|
||||||
@@ -480,7 +479,72 @@ static GLFWbool initExtensions(void)
|
|||||||
&_glfw.x11.vidmode.errorBase);
|
&_glfw.x11.vidmode.errorBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for RandR extension
|
_glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6");
|
||||||
|
if (_glfw.x11.xi.handle)
|
||||||
|
{
|
||||||
|
_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))
|
||||||
|
{
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_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,
|
if (XRRQueryExtension(_glfw.x11.display,
|
||||||
&_glfw.x11.randr.eventBase,
|
&_glfw.x11.randr.eventBase,
|
||||||
&_glfw.x11.randr.errorBase))
|
&_glfw.x11.randr.errorBase))
|
||||||
@@ -499,6 +563,7 @@ static GLFWbool initExtensions(void)
|
|||||||
"X11: Failed to query RandR version");
|
"X11: Failed to query RandR version");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_glfw.x11.randr.available)
|
if (_glfw.x11.randr.available)
|
||||||
{
|
{
|
||||||
@@ -507,21 +572,48 @@ static GLFWbool initExtensions(void)
|
|||||||
|
|
||||||
if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0]))
|
if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0]))
|
||||||
{
|
{
|
||||||
// This is either a headless system or an older Nvidia binary driver
|
// This is likely an older Nvidia driver with broken gamma support
|
||||||
// with broken gamma support
|
// Flag it as useless and fall back to xf86vm gamma, if available
|
||||||
// Flag it as useless and fall back to Xf86VidMode gamma, if
|
|
||||||
// available
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"X11: RandR gamma ramp support seems broken");
|
|
||||||
_glfw.x11.randr.gammaBroken = GLFW_TRUE;
|
_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,
|
XRRSelectInput(_glfw.x11.display, _glfw.x11.root,
|
||||||
RROutputChangeNotifyMask);
|
RROutputChangeNotifyMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1");
|
||||||
|
if (_glfw.x11.xcursor.handle)
|
||||||
|
{
|
||||||
|
_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,
|
if (XineramaQueryExtension(_glfw.x11.display,
|
||||||
&_glfw.x11.xinerama.major,
|
&_glfw.x11.xinerama.major,
|
||||||
&_glfw.x11.xinerama.minor))
|
&_glfw.x11.xinerama.minor))
|
||||||
@@ -529,6 +621,23 @@ static GLFWbool initExtensions(void)
|
|||||||
if (XineramaIsActive(_glfw.x11.display))
|
if (XineramaIsActive(_glfw.x11.display))
|
||||||
_glfw.x11.xinerama.available = GLFW_TRUE;
|
_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
|
// Check if Xkb is supported on this display
|
||||||
_glfw.x11.xkb.major = 1;
|
_glfw.x11.xkb.major = 1;
|
||||||
@@ -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)
|
if (_glfw.x11.x11xcb.handle)
|
||||||
{
|
{
|
||||||
_glfw.x11.x11xcb.XGetXCBConnection = (PFN_XGetXCBConnection)
|
_glfw.x11.x11xcb.GetXCBConnection = (PFN_XGetXCBConnection)
|
||||||
dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection");
|
_glfw_dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection");
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.x11.xrender.handle = _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
|
// Update the key code LUT
|
||||||
@@ -569,10 +740,7 @@ static GLFWbool initExtensions(void)
|
|||||||
|
|
||||||
// String format atoms
|
// String format atoms
|
||||||
_glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False);
|
_glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False);
|
||||||
_glfw.x11.UTF8_STRING =
|
_glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
|
||||||
XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
|
|
||||||
_glfw.x11.COMPOUND_STRING =
|
|
||||||
XInternAtom(_glfw.x11.display, "COMPOUND_STRING", False);
|
|
||||||
_glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False);
|
_glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False);
|
||||||
|
|
||||||
// Custom selection property atom
|
// Custom selection property atom
|
||||||
@@ -582,6 +750,8 @@ static GLFWbool initExtensions(void)
|
|||||||
// ICCCM standard clipboard atoms
|
// ICCCM standard clipboard atoms
|
||||||
_glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False);
|
_glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False);
|
||||||
_glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", 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);
|
_glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False);
|
||||||
|
|
||||||
// Clipboard manager atoms
|
// Clipboard manager atoms
|
||||||
@@ -597,9 +767,10 @@ static GLFWbool initExtensions(void)
|
|||||||
_glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", False);
|
_glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", False);
|
||||||
_glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False);
|
_glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False);
|
||||||
_glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", 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.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False);
|
||||||
_glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", 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
|
// ICCCM, EWMH and Motif window property atoms
|
||||||
// These can be set safely even without WM support
|
// 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);
|
XInternAtom(_glfw.x11.display, "_NET_WM_ICON_NAME", False);
|
||||||
_glfw.x11.NET_WM_BYPASS_COMPOSITOR =
|
_glfw.x11.NET_WM_BYPASS_COMPOSITOR =
|
||||||
XInternAtom(_glfw.x11.display, "_NET_WM_BYPASS_COMPOSITOR", False);
|
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 =
|
_glfw.x11.MOTIF_WM_HINTS =
|
||||||
XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False);
|
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;
|
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
|
// Create a blank cursor for hidden and disabled cursor modes
|
||||||
//
|
//
|
||||||
static Cursor createHiddenCursor(void)
|
static Cursor createHiddenCursor(void)
|
||||||
{
|
{
|
||||||
unsigned char pixels[16 * 16 * 4];
|
unsigned char pixels[16 * 16 * 4] = { 0 };
|
||||||
GLFWimage image = { 16, 16, pixels };
|
GLFWimage image = { 16, 16, pixels };
|
||||||
|
|
||||||
memset(pixels, 0, sizeof(pixels));
|
|
||||||
|
|
||||||
return _glfwCreateCursorX11(&image, 0, 0);
|
return _glfwCreateCursorX11(&image, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -688,7 +902,7 @@ void _glfwReleaseErrorHandlerX11(void)
|
|||||||
//
|
//
|
||||||
void _glfwInputErrorX11(int error, const char* message)
|
void _glfwInputErrorX11(int error, const char* message)
|
||||||
{
|
{
|
||||||
char buffer[8192];
|
char buffer[_GLFW_MESSAGE_SIZE];
|
||||||
XGetErrorText(_glfw.x11.display, _glfw.x11.errorCode,
|
XGetErrorText(_glfw.x11.display, _glfw.x11.errorCode,
|
||||||
buffer, sizeof(buffer));
|
buffer, sizeof(buffer));
|
||||||
|
|
||||||
@@ -702,6 +916,9 @@ Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot)
|
|||||||
int i;
|
int i;
|
||||||
Cursor cursor;
|
Cursor cursor;
|
||||||
|
|
||||||
|
if (!_glfw.x11.xcursor.handle)
|
||||||
|
return None;
|
||||||
|
|
||||||
XcursorImage* native = XcursorImageCreate(image->width, image->height);
|
XcursorImage* native = XcursorImageCreate(image->width, image->height);
|
||||||
if (native == NULL)
|
if (native == NULL)
|
||||||
return None;
|
return None;
|
||||||
@@ -736,13 +953,17 @@ Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot)
|
|||||||
int _glfwPlatformInit(void)
|
int _glfwPlatformInit(void)
|
||||||
{
|
{
|
||||||
#if !defined(X_HAVE_UTF8_STRING)
|
#if !defined(X_HAVE_UTF8_STRING)
|
||||||
// HACK: If the current locale is C, apply the environment's locale
|
// HACK: If the current locale is "C" and the Xlib UTF-8 functions are
|
||||||
// This is done because the C locale breaks wide character input
|
// 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)
|
if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0)
|
||||||
setlocale(LC_CTYPE, "");
|
setlocale(LC_CTYPE, "");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
XInitThreads();
|
XInitThreads();
|
||||||
|
XrmInitialize();
|
||||||
|
|
||||||
_glfw.x11.display = XOpenDisplay(NULL);
|
_glfw.x11.display = XOpenDisplay(NULL);
|
||||||
if (!_glfw.x11.display)
|
if (!_glfw.x11.display)
|
||||||
@@ -765,12 +986,15 @@ int _glfwPlatformInit(void)
|
|||||||
_glfw.x11.screen = DefaultScreen(_glfw.x11.display);
|
_glfw.x11.screen = DefaultScreen(_glfw.x11.display);
|
||||||
_glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen);
|
_glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen);
|
||||||
_glfw.x11.context = XUniqueContext();
|
_glfw.x11.context = XUniqueContext();
|
||||||
_glfw.x11.helperWindowHandle = createHelperWindow();
|
|
||||||
_glfw.x11.hiddenCursorHandle = createHiddenCursor();
|
getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY);
|
||||||
|
|
||||||
if (!initExtensions())
|
if (!initExtensions())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
_glfw.x11.helperWindowHandle = createHelperWindow();
|
||||||
|
_glfw.x11.hiddenCursorHandle = createHiddenCursor();
|
||||||
|
|
||||||
if (XSupportsLocale())
|
if (XSupportsLocale())
|
||||||
{
|
{
|
||||||
XSetLocaleModifiers("");
|
XSetLocaleModifiers("");
|
||||||
@@ -786,25 +1010,19 @@ int _glfwPlatformInit(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
#if defined(__linux__)
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
if (!_glfwInitJoysticksLinux())
|
if (!_glfwInitJoysticksLinux())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
_glfwInitTimerPOSIX();
|
_glfwInitTimerPOSIX();
|
||||||
|
|
||||||
|
_glfwPollMonitorsX11();
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformTerminate(void)
|
void _glfwPlatformTerminate(void)
|
||||||
{
|
{
|
||||||
if (_glfw.x11.x11xcb.handle)
|
|
||||||
{
|
|
||||||
dlclose(_glfw.x11.x11xcb.handle);
|
|
||||||
_glfw.x11.x11xcb.handle = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.x11.helperWindowHandle)
|
if (_glfw.x11.helperWindowHandle)
|
||||||
{
|
{
|
||||||
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) ==
|
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) ==
|
||||||
@@ -823,6 +1041,7 @@ void _glfwPlatformTerminate(void)
|
|||||||
_glfw.x11.hiddenCursorHandle = (Cursor) 0;
|
_glfw.x11.hiddenCursorHandle = (Cursor) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(_glfw.x11.primarySelectionString);
|
||||||
free(_glfw.x11.clipboardString);
|
free(_glfw.x11.clipboardString);
|
||||||
|
|
||||||
if (_glfw.x11.im)
|
if (_glfw.x11.im)
|
||||||
@@ -831,20 +1050,59 @@ void _glfwPlatformTerminate(void)
|
|||||||
_glfw.x11.im = NULL;
|
_glfw.x11.im = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwTerminateEGL();
|
|
||||||
|
|
||||||
if (_glfw.x11.display)
|
if (_glfw.x11.display)
|
||||||
{
|
{
|
||||||
XCloseDisplay(_glfw.x11.display);
|
XCloseDisplay(_glfw.x11.display);
|
||||||
_glfw.x11.display = NULL;
|
_glfw.x11.display = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: This needs to be done after XCloseDisplay, as libGL registers
|
if (_glfw.x11.x11xcb.handle)
|
||||||
// cleanup callbacks that get called by it
|
{
|
||||||
|
_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();
|
_glfwTerminateGLX();
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
_glfwTerminateJoysticksLinux();
|
_glfwTerminateJoysticksLinux();
|
||||||
_glfwTerminateThreadLocalStoragePOSIX();
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
@@ -856,7 +1114,7 @@ const char* _glfwPlatformGetVersionString(void)
|
|||||||
" gettimeofday"
|
" gettimeofday"
|
||||||
#endif
|
#endif
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
" /dev/js"
|
" evdev"
|
||||||
#endif
|
#endif
|
||||||
#if defined(_GLFW_BUILD_DLL)
|
#if defined(_GLFW_BUILD_DLL)
|
||||||
" shared"
|
" shared"
|
||||||
|
|||||||
+137
-124
@@ -95,9 +95,128 @@ static GLFWvidmode vidmodeFromModeInfo(const XRRModeInfo* mi,
|
|||||||
////// GLFW internal API //////
|
////// 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
|
// Set the current video mode for the specified monitor
|
||||||
//
|
//
|
||||||
GLFWbool _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
||||||
{
|
{
|
||||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
{
|
{
|
||||||
@@ -112,7 +231,7 @@ GLFWbool _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
|||||||
best = _glfwChooseVideoMode(monitor, desired);
|
best = _glfwChooseVideoMode(monitor, desired);
|
||||||
_glfwPlatformGetVideoMode(monitor, ¤t);
|
_glfwPlatformGetVideoMode(monitor, ¤t);
|
||||||
if (_glfwCompareVideoModes(¤t, best) == 0)
|
if (_glfwCompareVideoModes(¤t, best) == 0)
|
||||||
return GLFW_TRUE;
|
return;
|
||||||
|
|
||||||
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
@@ -150,16 +269,7 @@ GLFWbool _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
|||||||
XRRFreeOutputInfo(oi);
|
XRRFreeOutputInfo(oi);
|
||||||
XRRFreeCrtcInfo(ci);
|
XRRFreeCrtcInfo(ci);
|
||||||
XRRFreeScreenResources(sr);
|
XRRFreeScreenResources(sr);
|
||||||
|
|
||||||
if (!native)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"X11: Monitor mode list changed");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore the saved (original) video mode for the specified monitor
|
// Restore the saved (original) video mode for the specified monitor
|
||||||
@@ -198,119 +308,6 @@ void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor)
|
|||||||
////// GLFW platform API //////
|
////// 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)
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||||
{
|
{
|
||||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
@@ -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* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||||
{
|
{
|
||||||
GLFWvidmode* result;
|
GLFWvidmode* result;
|
||||||
@@ -446,6 +452,13 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
|||||||
{
|
{
|
||||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
|
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);
|
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));
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user