mirror of
https://github.com/glfw/glfw.git
synced 2026-09-18 22:55:46 +00:00
Compare commits
52 Commits
drag-window
...
egldevice
| Author | SHA1 | Date | |
|---|---|---|---|
| 4e1d7e9266 | |||
| 243db302bf | |||
| 5b1a187f71 | |||
| 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 |
+2
-2
@@ -19,5 +19,5 @@ notifications:
|
||||
- provider: Email
|
||||
to:
|
||||
- ci@glfw.org
|
||||
- on_build_failure: true
|
||||
- on_build_success: false
|
||||
on_build_failure: true
|
||||
on_build_success: false
|
||||
|
||||
@@ -0,0 +1,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\"\n")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
configure_file("${template_path}" "${target_path}" @ONLY NEWLINE_STYLE UNIX)
|
||||
file(REMOVE "${source_path}")
|
||||
|
||||
+33
-22
@@ -41,8 +41,9 @@ if (WIN32)
|
||||
endif()
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF)
|
||||
option(GLFW_USE_MIR "Use Mir for window creation" OFF)
|
||||
option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF)
|
||||
option(GLFW_USE_MIR "Use Mir for window creation" OFF)
|
||||
option(GLFW_USE_EGLDEVICE "Use EGLDevice for window creation" OFF)
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
@@ -163,6 +164,9 @@ elseif (GLFW_USE_MIR)
|
||||
elseif (GLFW_USE_OSMESA)
|
||||
set(_GLFW_OSMESA 1)
|
||||
message(STATUS "Using OSMesa for headless context creation")
|
||||
elseif (GLFW_USE_EGLDEVICE)
|
||||
set(_GLFW_EGLDEVICE 1)
|
||||
message(STATUS "Using EGLDevice for window creation")
|
||||
elseif (WIN32)
|
||||
set(_GLFW_WIN32 1)
|
||||
message(STATUS "Using Win32 for window creation")
|
||||
@@ -181,7 +185,7 @@ endif()
|
||||
#--------------------------------------------------------------------
|
||||
if (GLFW_VULKAN_STATIC)
|
||||
if (VULKAN_FOUND AND VULKAN_STATIC_LIBRARY)
|
||||
list(APPEND glfw_LIBRARIES ${VULKAN_STATIC_LIBRARY} ${GLFW_VULKAN_DEPS})
|
||||
list(APPEND glfw_LIBRARIES "${VULKAN_STATIC_LIBRARY}" ${GLFW_VULKAN_DEPS})
|
||||
if (BUILD_SHARED_LIBS)
|
||||
message(WARNING "Linking Vulkan loader static library into GLFW")
|
||||
endif()
|
||||
@@ -245,38 +249,28 @@ if (_GLFW_X11)
|
||||
|
||||
# Check for XRandR (modern resolution switching and gamma control)
|
||||
if (NOT X11_Xrandr_FOUND)
|
||||
message(FATAL_ERROR "The RandR library and headers were not found")
|
||||
message(FATAL_ERROR "The RandR headers were not found")
|
||||
endif()
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIRS "${X11_Xrandr_INCLUDE_PATH}")
|
||||
list(APPEND glfw_LIBRARIES "${X11_Xrandr_LIB}")
|
||||
list(APPEND glfw_PKG_DEPS "xrandr")
|
||||
|
||||
# Check for Xinerama (legacy multi-monitor support)
|
||||
if (NOT X11_Xinerama_FOUND)
|
||||
message(FATAL_ERROR "The Xinerama library and headers were not found")
|
||||
message(FATAL_ERROR "The Xinerama headers were not found")
|
||||
endif()
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIRS "${X11_Xinerama_INCLUDE_PATH}")
|
||||
list(APPEND glfw_LIBRARIES "${X11_Xinerama_LIB}")
|
||||
list(APPEND glfw_PKG_DEPS "xinerama")
|
||||
|
||||
# Check for Xkb (X keyboard extension)
|
||||
if (NOT X11_Xkb_FOUND)
|
||||
message(FATAL_ERROR "The X keyboard extension headers were not found")
|
||||
endif()
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIR "${X11_Xkb_INCLUDE_PATH}")
|
||||
|
||||
# Check for Xcursor
|
||||
# Check for Xcursor (cursor creation from RGBA images)
|
||||
if (NOT X11_Xcursor_FOUND)
|
||||
message(FATAL_ERROR "The Xcursor libraries and headers were not found")
|
||||
message(FATAL_ERROR "The Xcursor headers were not found")
|
||||
endif()
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIR "${X11_Xcursor_INCLUDE_PATH}")
|
||||
list(APPEND glfw_LIBRARIES "${X11_Xcursor_LIB}")
|
||||
list(APPEND glfw_PKG_DEPS "xcursor")
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIRS "${X11_Xrandr_INCLUDE_PATH}"
|
||||
"${X11_Xinerama_INCLUDE_PATH}"
|
||||
"${X11_Xkb_INCLUDE_PATH}"
|
||||
"${X11_Xcursor_INCLUDE_PATH}")
|
||||
endif()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
@@ -284,7 +278,7 @@ endif()
|
||||
#--------------------------------------------------------------------
|
||||
if (_GLFW_WAYLAND)
|
||||
find_package(ECM REQUIRED NO_MODULE)
|
||||
list(APPEND CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
|
||||
list(APPEND CMAKE_MODULE_PATH "${ECM_MODULE_PATH}")
|
||||
|
||||
find_package(Wayland REQUIRED)
|
||||
find_package(WaylandScanner REQUIRED)
|
||||
@@ -301,6 +295,23 @@ if (_GLFW_WAYLAND)
|
||||
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
|
||||
endif()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Use EGLDevice for window creation
|
||||
#--------------------------------------------------------------------
|
||||
if (_GLFW_EGLDEVICE)
|
||||
|
||||
find_path(DRM_INCLUDE_DIR NAMES drm.h PATH_SUFFIXES drm libdrm)
|
||||
if (NOT DRM_INCLUDE_DIR)
|
||||
message(FATAL_ERROR "The libdrm headers were not found")
|
||||
endif()
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIRS "${DRM_INCLUDE_DIR}")
|
||||
|
||||
list(APPEND glfw_LIBRARIES "-ldrm")
|
||||
list(APPEND glfw_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}")
|
||||
|
||||
endif()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Use Mir for window creation
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
@@ -11,8 +11,9 @@ application development. It provides a simple, platform-independent API for
|
||||
creating windows, contexts and surfaces, reading input, handling events, etc.
|
||||
|
||||
GLFW natively supports Windows, macOS and Linux and other Unix-like systems.
|
||||
Experimental implementations for the Wayland protocol and the Mir display server
|
||||
are available but not yet officially supported.
|
||||
Experimental implementations for the Wayland protocol, the Mir display server
|
||||
and direct rendering via EGLDevice are available but not yet officially
|
||||
supported.
|
||||
|
||||
GLFW is licensed under the [zlib/libpng
|
||||
license](http://www.glfw.org/license.html).
|
||||
@@ -45,8 +46,8 @@ guide](http://www.glfw.org/docs/latest/moving.html) for moving to the GLFW
|
||||
## Compiling GLFW
|
||||
|
||||
GLFW itself requires only the headers and libraries for your window system. It
|
||||
does not need the headers for any context creation API (WGL, GLX, EGL, NSGL) or
|
||||
rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them.
|
||||
does not need the headers for any context creation API (WGL, GLX, EGL, NSGL,
|
||||
OSMesa) or rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them.
|
||||
|
||||
GLFW supports compilation on Windows with Visual C++ 2010 and later, MinGW and
|
||||
MinGW-w64, on macOS with Clang and on Linux and other Unix-like systems with GCC
|
||||
@@ -91,6 +92,9 @@ 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 (experimental) EGLDevice backend also depends on the `libdrm-dev`
|
||||
development package.
|
||||
|
||||
The examples and test programs depend on a number of tiny libraries. These are
|
||||
located in the `deps/` directory.
|
||||
|
||||
@@ -146,6 +150,8 @@ information on what to include when reporting a bug.
|
||||
- Added `glfwGetJoystickHats` function for querying joystick hats
|
||||
(#889,#906,#934)
|
||||
- Added `glfwInitHint` and `glfwInitHintString` for setting initialization hints
|
||||
- Added `glfwGetX11SelectionString` and `glfwSetX11SelectionString`
|
||||
functions for accessing X11 primary selection (#894,#1056)
|
||||
- Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#850)
|
||||
- Added definition of `GLAPIENTRY` to public header
|
||||
- Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering
|
||||
@@ -161,6 +167,7 @@ information on what to include when reporting a bug.
|
||||
- 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
|
||||
- Removed `GLFW_USE_RETINA` compile-time option
|
||||
- Removed `GLFW_USE_CHDIR` compile-time option
|
||||
- Removed `GLFW_USE_MENUBAR` compile-time option
|
||||
@@ -173,6 +180,7 @@ information on what to include when reporting a bug.
|
||||
- Bugfix: The scancode for synthetic key release events was always zero
|
||||
- [Win32] Added system error strings to relevant GLFW error descriptions (#733)
|
||||
- [Win32] Moved to `WM_INPUT` for disabled cursor mode motion input (#125)
|
||||
- [Win32] Removed XInput circular deadzone from joystick axis data (#1045)
|
||||
- [Win32] Bugfix: Undecorated windows could not be iconified by the user (#861)
|
||||
- [Win32] Bugfix: Deadzone logic could underflow with some controllers (#910)
|
||||
- [Win32] Bugfix: Bitness test in `FindVulkan.cmake` was VS specific (#928)
|
||||
@@ -186,6 +194,11 @@ information on what to include when reporting a bug.
|
||||
- [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)
|
||||
- [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125)
|
||||
- [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading
|
||||
- [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X
|
||||
@@ -196,9 +209,15 @@ information on what to include when reporting a bug.
|
||||
- [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
|
||||
- [Linux] Added experimental support for direct rendering via EGLDevice (#786)
|
||||
- [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
|
||||
@@ -216,6 +235,10 @@ information on what to include when reporting a bug.
|
||||
- [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)
|
||||
- [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`
|
||||
@@ -249,9 +272,8 @@ GLFW exists because people around the world donated their time and lent their
|
||||
skills.
|
||||
|
||||
- Bobyshev Alexander
|
||||
- artblanc
|
||||
- arturo
|
||||
- Matt Arsenault
|
||||
- David Avedissian
|
||||
- Keith Bauer
|
||||
- John Bartholomew
|
||||
- Niklas Behrens
|
||||
@@ -260,11 +282,17 @@ skills.
|
||||
- Doug Binks
|
||||
- blanco
|
||||
- Kyle Brenneman
|
||||
- Rok Breulj
|
||||
- Martin Capitanio
|
||||
- David Carlier
|
||||
- Arturo Castro
|
||||
- Chi-kwan Chan
|
||||
- Kamal Chandra
|
||||
- Ian Clarkson
|
||||
- Michał Cichoń
|
||||
- Lambert Clara
|
||||
- Yaron Cohen-Tal
|
||||
- Omar Cornut
|
||||
- Andrew Corrigan
|
||||
- Noel Cower
|
||||
- Jason Daly
|
||||
@@ -276,6 +304,8 @@ skills.
|
||||
- Mario Dorn
|
||||
- Jonathan Dummer
|
||||
- Ralph Eastwood
|
||||
- Fredrik Ehnbom
|
||||
- Robin Eklind
|
||||
- Siavash Eliasi
|
||||
- Felipe Ferreira
|
||||
- Michael Fogleman
|
||||
@@ -285,6 +315,7 @@ skills.
|
||||
- Marcus Geelnard
|
||||
- Eloi Marín Gratacós
|
||||
- Stefan Gustavson
|
||||
- Jonathan Hale
|
||||
- Sylvain Hellegouarch
|
||||
- Matthew Henry
|
||||
- heromyth
|
||||
@@ -297,20 +328,22 @@ skills.
|
||||
- Toni Jovanoski
|
||||
- Arseny Kapoulkine
|
||||
- Osman Keskin
|
||||
- Josh Kilmer
|
||||
- Cameron King
|
||||
- Peter Knut
|
||||
- Christoph Kubisch
|
||||
- Yuri Kunde Schlesner
|
||||
- Konstantin Käfer
|
||||
- Eric Larson
|
||||
- Robin Leffmann
|
||||
- Glenn Lewis
|
||||
- Shane Liesegang
|
||||
- Eyal Lotem
|
||||
- Дмитри Малышев
|
||||
- Martins Mozeiko
|
||||
- Tristam MacDonald
|
||||
- Hans Mackowiak
|
||||
- Дмитри Малышев
|
||||
- Zbigniew Mandziejewicz
|
||||
- Célestin Marot
|
||||
- Kyle McDonald
|
||||
- David Medlock
|
||||
- Bryce Mehring
|
||||
@@ -322,10 +355,15 @@ skills.
|
||||
- Bruce Mitchener
|
||||
- Jack Moffitt
|
||||
- Jeff Molofee
|
||||
- Pierre Morel
|
||||
- Jon Morton
|
||||
- Pierre Moulon
|
||||
- Martins Mozeiko
|
||||
- Julian Møller
|
||||
- ndogxj
|
||||
- Kristian Nielsen
|
||||
- Kamil Nowakowski
|
||||
- Denis Ovod
|
||||
- Ozzy
|
||||
- Andri Pálsson
|
||||
- Peoro
|
||||
@@ -335,28 +373,34 @@ skills.
|
||||
- Orson Peters
|
||||
- Emmanuel Gil Peyrot
|
||||
- Cyril Pichard
|
||||
- Pieroman
|
||||
- Keith Pitt
|
||||
- Stanislav Podgorskiy
|
||||
- Alexandre Pretyman
|
||||
- Philip Rideout
|
||||
- Eddie Ringle
|
||||
- Jorge Rodriguez
|
||||
- Ed Ropple
|
||||
- Aleksey Rybalkin
|
||||
- Riku Salminen
|
||||
- Brandon Schaefer
|
||||
- Sebastian Schuberth
|
||||
- Christian Sdunek
|
||||
- Matt Sealey
|
||||
- SephiRok
|
||||
- Steve Sexton
|
||||
- Systemcluster
|
||||
- Arkady Shapkin
|
||||
- Yoshiki Shibukawa
|
||||
- Dmitri Shuralyov
|
||||
- Daniel Skorupski
|
||||
- Bradley Smith
|
||||
- Patrick Snape
|
||||
- Erlend Sogge Heggen
|
||||
- Julian Squires
|
||||
- Johannes Stein
|
||||
- Pontus Stenetorp
|
||||
- Michael Stocker
|
||||
- Justin Stoecker
|
||||
- Elviss Strazdins
|
||||
- Paul Sultana
|
||||
- Nathan Sweet
|
||||
- TTK-Bandit
|
||||
- Sergey Tikhomirov
|
||||
@@ -366,6 +410,7 @@ skills.
|
||||
- Matthew Turner
|
||||
- urraka
|
||||
- Elias Vanderstuyft
|
||||
- Stef Velzel
|
||||
- Jari Vetoniemi
|
||||
- Ricardo Vieira
|
||||
- Nicholas Vitovitch
|
||||
@@ -375,8 +420,8 @@ skills.
|
||||
- Xo Wang
|
||||
- Jay Weisskopf
|
||||
- Frank Wille
|
||||
- yuriks
|
||||
- Ryogo Yoshimura
|
||||
- Andrey Zholos
|
||||
- Santi Zupancic
|
||||
- Jonas Ådahl
|
||||
- Lasse Öörni
|
||||
|
||||
@@ -257,6 +257,7 @@ ramps and clipboard. The options are:
|
||||
- @b _GLFW_WAYLAND to use the Wayland API (experimental and incomplete)
|
||||
- @b _GLFW_MIR to use the Mir API (experimental and incomplete)
|
||||
- @b _GLFW_OSMESA to use the OSMesa API (headless and non-interactive)
|
||||
- @b _GLFW_EGLDEVICE to use the EGLDevice API (experimental and incomplete)
|
||||
|
||||
If you are building GLFW as a shared library / dynamic library / DLL then you
|
||||
must also define @b _GLFW_BUILD_DLL. Otherwise, you must not define it.
|
||||
@@ -265,6 +266,12 @@ If you are linking the Vulkan loader statically into your application then you
|
||||
must also define @b _GLFW_VULKAN_STATIC. Otherwise, GLFW will attempt to use the
|
||||
external version.
|
||||
|
||||
If you are using a custom name for the Vulkan, EGL, GLX, OSMesa, OpenGL, GLESv1
|
||||
or GLESv2 library, you can override the default names by defining those you need
|
||||
of @b _GLFW_VULKAN_LIBRARY, @b _GLFW_EGL_LIBRARY, @b _GLFW_GLX_LIBRARY, @b
|
||||
_GLFW_OSMESA_LIBRARY, @b _GLFW_OPENGL_LIBRARY, @b _GLFW_GLESV1_LIBRARY and @b
|
||||
_GLFW_GLESV2_LIBRARY. Otherwise, GLFW will use the built-in default names.
|
||||
|
||||
For the EGL context creation API, the following options are available:
|
||||
|
||||
- @b _GLFW_USE_EGLPLATFORM_H to use `EGL/eglplatform.h` for native handle
|
||||
|
||||
@@ -25,7 +25,6 @@ $extrastylesheet
|
||||
<ul class="glfwnavbar">
|
||||
<li><a href="http://www.glfw.org/documentation.html">Documentation</a></li>
|
||||
<li><a href="http://www.glfw.org/download.html">Download</a></li>
|
||||
<li><a href="http://www.glfw.org/media.html">Media</a></li>
|
||||
<li><a href="http://www.glfw.org/community.html">Community</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
+32
-28
@@ -82,6 +82,9 @@ Some hints are platform specific. These may be set on any platform but they
|
||||
will only affect their specific platform. Other platforms will simply ignore
|
||||
them. Setting these hints requires no platform specific headers or 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
|
||||
@@ -112,7 +115,7 @@ Set this with @ref glfwInitHintString.
|
||||
|
||||
@subsubsection init_hints_values Supported and default values
|
||||
|
||||
Init hint | Default value | Supported 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`
|
||||
@@ -299,35 +302,39 @@ functions not on this list will not be made non-reentrant.
|
||||
|
||||
@subsection thread_safety Thread safety
|
||||
|
||||
Most GLFW functions must only be called from the main thread, but some may be
|
||||
called from any thread. However, no GLFW function may be called from any thread
|
||||
but the main thread until GLFW has been successfully initialized, including
|
||||
functions that may called before initialization.
|
||||
Most GLFW functions must only be called from the main thread (the thread that
|
||||
calls main), but some may be called from any thread once the library has been
|
||||
initialized. Before initialization the whole library is thread-unsafe.
|
||||
|
||||
The reference documentation for every GLFW function states whether it is limited
|
||||
to the main thread.
|
||||
|
||||
Initialization and termination, event processing and the creation and
|
||||
destruction of windows, contexts and cursors are all limited to the main thread
|
||||
due to limitations of one or several platforms.
|
||||
Initialization, termination, event processing and the creation and
|
||||
destruction of windows, cursors and OpenGL and OpenGL ES contexts are all
|
||||
restricted to the main thread due to limitations of one or several platforms.
|
||||
|
||||
Because event processing must be performed on the main thread, all callbacks
|
||||
except for the error callback will only be called on that thread. The error
|
||||
callback may be called on any thread, as any GLFW function may generate errors.
|
||||
|
||||
The posting of empty events may be done from any thread. The window user
|
||||
pointer and close flag may also be accessed and modified from any thread, but
|
||||
this is not synchronized by GLFW. The following window related functions may
|
||||
be called from any thread:
|
||||
The error code and description may be queried from any thread.
|
||||
|
||||
- @ref glfwGetError
|
||||
|
||||
Empty events may be posted from any thread.
|
||||
|
||||
- @ref glfwPostEmptyEvent
|
||||
|
||||
The window user pointer and close flag may be read and written from any thread,
|
||||
but this is not synchronized by GLFW.
|
||||
|
||||
- @ref glfwGetWindowUserPointer
|
||||
- @ref glfwSetWindowUserPointer
|
||||
- @ref glfwWindowShouldClose
|
||||
- @ref glfwSetWindowShouldClose
|
||||
|
||||
Rendering may be done on any thread. The following context related functions
|
||||
may be called from any thread:
|
||||
These functions for working with OpenGL and OpenGL ES contexts may be called
|
||||
from any thread, but the window object is not synchronized by GLFW.
|
||||
|
||||
- @ref glfwMakeContextCurrent
|
||||
- @ref glfwGetCurrentContext
|
||||
@@ -336,27 +343,23 @@ may be called from any thread:
|
||||
- @ref glfwExtensionSupported
|
||||
- @ref glfwGetProcAddress
|
||||
|
||||
The raw timer may be queried from any thread. The following raw timer related
|
||||
functions may be called from any thread:
|
||||
The raw timer functions may be called from any thread.
|
||||
|
||||
- @ref glfwGetTimerFrequency
|
||||
- @ref glfwGetTimerValue
|
||||
|
||||
The regular timer may be used from any thread, but the reading and writing of
|
||||
the timer offset is not synchronized by GLFW. The following timer related
|
||||
functions may be called from any thread:
|
||||
The regular timer may be used from any thread, but reading and writing the timer
|
||||
offset is not synchronized by GLFW.
|
||||
|
||||
- @ref glfwGetTime
|
||||
- @ref glfwSetTime
|
||||
|
||||
Library version information may be queried from any thread. The following
|
||||
version related functions may be called from any thread:
|
||||
Library version information may be queried from any thread.
|
||||
|
||||
- @ref glfwGetVersion
|
||||
- @ref glfwGetVersionString
|
||||
|
||||
Vulkan objects may be created and information queried from any thread. The
|
||||
following Vulkan related functions may be called from any thread:
|
||||
All Vulkan related functions may be called from any thread.
|
||||
|
||||
- @ref glfwVulkanSupported
|
||||
- @ref glfwGetRequiredInstanceExtensions
|
||||
@@ -364,9 +367,9 @@ following Vulkan related functions may be called from any thread:
|
||||
- @ref glfwGetPhysicalDevicePresentationSupport
|
||||
- @ref glfwCreateWindowSurface
|
||||
|
||||
GLFW uses no synchronization objects internally except for thread-local storage
|
||||
to keep track of the current context for each thread. Synchronization is left
|
||||
to the application.
|
||||
GLFW uses synchronization objects internally only to manage the per-thread
|
||||
context and error states. Additional synchronization is left to the
|
||||
application.
|
||||
|
||||
Functions that may currently be called from any thread will always remain so,
|
||||
but functions that are currently limited to the main thread may be updated to
|
||||
@@ -388,8 +391,9 @@ Undocumented behavior, i.e. behavior that is not described in the documentation,
|
||||
may change at any time until it is documented.
|
||||
|
||||
If the reference documentation and the implementation differ, the reference
|
||||
documentation is correct and the implementation will be fixed in the next
|
||||
release.
|
||||
documentation will almost always take precedence and the implementation will be
|
||||
fixed in the next release. The reference documentation will also take
|
||||
precedence over anything stated in a guide.
|
||||
|
||||
|
||||
@subsection event_order Event order
|
||||
|
||||
@@ -118,6 +118,13 @@ creation API, intended for automated testing. This backend does not provide
|
||||
input.
|
||||
|
||||
|
||||
@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
|
||||
|
||||
|
||||
|
||||
+28
-17
@@ -105,6 +105,7 @@ extern "C" {
|
||||
#else
|
||||
#define APIENTRY
|
||||
#endif
|
||||
#define GLFW_APIENTRY_DEFINED
|
||||
#endif /* APIENTRY */
|
||||
|
||||
/* Some Windows OpenGL headers need this.
|
||||
@@ -4203,6 +4204,10 @@ GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun);
|
||||
*
|
||||
* This function returns whether the specified joystick is present.
|
||||
*
|
||||
* There is no need to call this function before other functions that accept
|
||||
* a joystick ID, as they all check for presence before performing any other
|
||||
* work.
|
||||
*
|
||||
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||
* @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise.
|
||||
*
|
||||
@@ -4225,8 +4230,8 @@ GLFWAPI int glfwJoystickPresent(int jid);
|
||||
* Each element in the array is a value between -1.0 and 1.0.
|
||||
*
|
||||
* If the specified joystick is not present this function will return `NULL`
|
||||
* but will not generate an error. Call @ref glfwJoystickPresent to check
|
||||
* device presence.
|
||||
* but will not generate an error. This can be used instead of first calling
|
||||
* @ref glfwJoystickPresent.
|
||||
*
|
||||
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||
* @param[out] count Where to store the number of axis values in the returned
|
||||
@@ -4265,8 +4270,8 @@ GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count);
|
||||
* GLFW_JOYSTICK_HAT_BUTTONS init hint before initialization.
|
||||
*
|
||||
* If the specified joystick is not present this function will return `NULL`
|
||||
* but will not generate an error. Call @ref glfwJoystickPresent to check
|
||||
* device presence.
|
||||
* but will not generate an error. This can be used instead of first calling
|
||||
* @ref glfwJoystickPresent.
|
||||
*
|
||||
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||
* @param[out] count Where to store the number of button states in the returned
|
||||
@@ -4322,8 +4327,8 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count);
|
||||
* @endcode
|
||||
*
|
||||
* If the specified joystick is not present this function will return `NULL`
|
||||
* but will not generate an error. Call @ref glfwJoystickPresent to check
|
||||
* device presence.
|
||||
* but will not generate an error. This can be used instead of first calling
|
||||
* @ref glfwJoystickPresent.
|
||||
*
|
||||
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||
* @param[out] count Where to store the number of hat states in the returned
|
||||
@@ -4357,8 +4362,8 @@ GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count);
|
||||
* yourself.
|
||||
*
|
||||
* If the specified joystick is not present this function will return `NULL`
|
||||
* but will not generate an error. Call @ref glfwJoystickPresent to check
|
||||
* device presence.
|
||||
* but will not generate an error. This can be used instead of first calling
|
||||
* @ref glfwJoystickPresent.
|
||||
*
|
||||
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||
* @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick
|
||||
@@ -4387,9 +4392,13 @@ GLFWAPI const char* glfwGetJoystickName(int jid);
|
||||
* hexadecimal string, of the specified joystick. The returned string is
|
||||
* allocated and freed by GLFW. You should not free it yourself.
|
||||
*
|
||||
* The GUID is what connects a joystick to a gamepad mapping. A connected
|
||||
* joystick will always have a GUID even if there is no gamepad mapping
|
||||
* assigned to it.
|
||||
*
|
||||
* If the specified joystick is not present this function will return `NULL`
|
||||
* but will not generate an error. Call @ref glfwJoystickPresent to check
|
||||
* device presence.
|
||||
* but will not generate an error. This can be used instead of first calling
|
||||
* @ref glfwJoystickPresent.
|
||||
*
|
||||
* The GUID uses the format introduced in SDL 2.0.5. This GUID tries to
|
||||
* uniquely identify the make and model of a joystick but does not identify
|
||||
@@ -4425,7 +4434,8 @@ GLFWAPI const char* glfwGetJoystickGUID(int jid);
|
||||
*
|
||||
* If the specified joystick is present but does not have a gamepad mapping
|
||||
* this function will return `GLFW_FALSE` but will not generate an error. Call
|
||||
* @ref glfwJoystickPresent to only check device presence.
|
||||
* @ref glfwJoystickPresent to check if a joystick is present regardless of
|
||||
* whether it has a mapping.
|
||||
*
|
||||
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||
* @return `GLFW_TRUE` if a joystick is both present and has a gamepad mapping,
|
||||
@@ -4514,8 +4524,9 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string);
|
||||
* gamepad mapping assigned to the specified joystick.
|
||||
*
|
||||
* If the specified joystick is not present or does not have a gamepad mapping
|
||||
* this function will return `NULL` but will not generate an error. Call @ref
|
||||
* glfwJoystickIsGamepad to check whether it is present and has a gamepad mapping.
|
||||
* this function will return `NULL` but will not generate an error. Call
|
||||
* @ref glfwJoystickPresent to check whether it is present regardless of
|
||||
* whether it has a mapping.
|
||||
*
|
||||
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||
* @return The UTF-8 encoded name of the gamepad, or `NULL` if the
|
||||
@@ -4542,10 +4553,10 @@ GLFWAPI const char* glfwGetGamepadName(int jid);
|
||||
* This function retrives the state of the specified joystick remapped to
|
||||
* an Xbox-like gamepad.
|
||||
*
|
||||
* If the specified joystick is not present this function will return
|
||||
* `GLFW_FALSE` but will not generate an error. Call @ref
|
||||
* glfwJoystickIsGamepad to check whether it is present and has a gamepad
|
||||
* mapping.
|
||||
* If the specified joystick is not present or does not have a gamepad mapping
|
||||
* this function will return `GLFW_FALSE` but will not generate an error. Call
|
||||
* @ref glfwJoystickPresent to check whether it is present regardless of
|
||||
* whether it has a mapping.
|
||||
*
|
||||
* The Guide button may not be available for input as it is often hooked by the
|
||||
* system or the Steam client.
|
||||
|
||||
@@ -86,7 +86,10 @@ extern "C" {
|
||||
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
|
||||
// example to allow applications to correctly declare a GL_ARB_debug_output
|
||||
// callback) but windows.h assumes no one will define APIENTRY before it does
|
||||
#undef APIENTRY
|
||||
#if defined(GLFW_APIENTRY_DEFINED)
|
||||
#undef APIENTRY
|
||||
#undef GLFW_APIENTRY_DEFINED
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_COCOA)
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
@@ -289,6 +292,56 @@ GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
|
||||
|
||||
/*! @brief Sets the current primary selection to the specified string.
|
||||
*
|
||||
* @param[in] string A UTF-8 encoded string.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @pointer_lifetime The specified string is copied before this function
|
||||
* returns.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref clipboard
|
||||
* @sa glfwGetX11SelectionString
|
||||
* @sa glfwSetClipboardString
|
||||
*
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI void glfwSetX11SelectionString(const char* string);
|
||||
|
||||
/*! @brief Returns the contents of the current primary selection as a string.
|
||||
*
|
||||
* If the selection is empty or if its contents cannot be converted, `NULL`
|
||||
* is returned and a @ref GLFW_FORMAT_UNAVAILABLE error is generated.
|
||||
*
|
||||
* @return The contents of the selection as a UTF-8 encoded string, or `NULL`
|
||||
* if an [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @pointer_lifetime The returned string is allocated and freed by GLFW. You
|
||||
* should not free it yourself. It is valid until the next call to @ref
|
||||
* glfwGetX11SelectionString or @ref glfwSetX11SelectionString, or until the
|
||||
* library is terminated.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref clipboard
|
||||
* @sa glfwSetX11SelectionString
|
||||
* @sa glfwGetClipboardString
|
||||
*
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI const char* glfwGetX11SelectionString(void);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||
|
||||
+27
-7
@@ -7,7 +7,7 @@ set(common_SOURCES context.c init.c input.c monitor.c vulkan.c window.c)
|
||||
|
||||
if (_GLFW_COCOA)
|
||||
set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h cocoa_joystick.h
|
||||
posix_thread.h nsgl_context.h egl_context.h osmesa_context.c)
|
||||
posix_thread.h nsgl_context.h egl_context.h osmesa_context.h)
|
||||
set(glfw_SOURCES ${common_SOURCES} cocoa_init.m cocoa_joystick.m
|
||||
cocoa_monitor.m cocoa_window.m cocoa_time.c posix_thread.c
|
||||
nsgl_context.m egl_context.c osmesa_context.c)
|
||||
@@ -41,12 +41,18 @@ elseif (_GLFW_WAYLAND)
|
||||
|
||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
||||
PROTOCOL
|
||||
${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml
|
||||
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml"
|
||||
BASENAME relative-pointer-unstable-v1)
|
||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
||||
PROTOCOL
|
||||
${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml
|
||||
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml"
|
||||
BASENAME pointer-constraints-unstable-v1)
|
||||
elseif(_GLFW_EGLDEVICE)
|
||||
set(glfw_HEADERS ${common_HEADERS} egldevice_platform.h linux_joystick.h
|
||||
posix_time.h posix_thread.h xkb_unicode.h egl_context.h)
|
||||
set(glfw_SOURCES ${common_SOURCES} egldevice_init.c egldevice_monitor.c egldevice_window.c
|
||||
linux_joystick.c posix_time.c posix_thread.c xkb_unicode.c
|
||||
egl_context.c)
|
||||
elseif (_GLFW_MIR)
|
||||
set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
|
||||
posix_time.h posix_thread.h xkb_unicode.h egl_context.h
|
||||
@@ -66,6 +72,18 @@ if (APPLE)
|
||||
set_source_files_properties(${glfw_SOURCES} PROPERTIES LANGUAGE C)
|
||||
endif()
|
||||
|
||||
# Make GCC and Clang warn about declarations that VS 2010 and 2012 won't accept
|
||||
# for all source files that VS will build
|
||||
if (${CMAKE_C_COMPILER_ID} STREQUAL GNU OR ${CMAKE_C_COMPILER_ID} STREQUAL Clang)
|
||||
if (WIN32)
|
||||
set(windows_SOURCES ${glfw_SOURCES})
|
||||
else()
|
||||
set(windows_SOURCES ${common_SOURCES})
|
||||
endif()
|
||||
set_source_files_properties(${windows_SOURCES} PROPERTIES
|
||||
COMPILE_FLAGS -Wdeclaration-after-statement)
|
||||
endif()
|
||||
|
||||
add_library(glfw ${glfw_SOURCES} ${glfw_HEADERS})
|
||||
set_target_properties(glfw PROPERTIES
|
||||
OUTPUT_NAME ${GLFW_LIB_NAME}
|
||||
@@ -74,10 +92,12 @@ set_target_properties(glfw PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
FOLDER "GLFW3")
|
||||
|
||||
target_compile_definitions(glfw PRIVATE -D_GLFW_USE_CONFIG_H)
|
||||
target_compile_definitions(glfw PRIVATE
|
||||
_GLFW_USE_CONFIG_H
|
||||
$<$<BOOL:${UNIX}>:_POSIX_C_SOURCE=200809L>)
|
||||
target_include_directories(glfw PUBLIC
|
||||
$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>)
|
||||
"$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>")
|
||||
target_include_directories(glfw PRIVATE
|
||||
"${GLFW_SOURCE_DIR}/src"
|
||||
"${GLFW_BINARY_DIR}/src"
|
||||
@@ -118,7 +138,7 @@ if (BUILD_SHARED_LIBS)
|
||||
target_compile_options(glfw PRIVATE "-fvisibility=hidden")
|
||||
endif()
|
||||
|
||||
target_compile_definitions(glfw INTERFACE -DGLFW_DLL)
|
||||
target_compile_definitions(glfw INTERFACE GLFW_DLL)
|
||||
target_link_libraries(glfw PRIVATE ${glfw_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(glfw INTERFACE ${glfw_LIBRARIES})
|
||||
|
||||
+5
-6
@@ -215,8 +215,9 @@ static GLFWbool updateUnicodeDataNS(void)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.ns.unicodeData = TISGetInputSourceProperty(_glfw.ns.inputSource,
|
||||
kTISPropertyUnicodeKeyLayoutData);
|
||||
_glfw.ns.unicodeData =
|
||||
TISGetInputSourceProperty(_glfw.ns.inputSource,
|
||||
kTISPropertyUnicodeKeyLayoutData);
|
||||
if (!_glfw.ns.unicodeData)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
@@ -232,7 +233,8 @@ static GLFWbool updateUnicodeDataNS(void)
|
||||
static GLFWbool initializeTIS(void)
|
||||
{
|
||||
// This works only because Cocoa has already loaded it properly
|
||||
_glfw.ns.tis.bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
|
||||
_glfw.ns.tis.bundle =
|
||||
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
|
||||
if (!_glfw.ns.tis.bundle)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
@@ -352,9 +354,6 @@ void _glfwPlatformTerminate(void)
|
||||
_glfw.ns.listener = nil;
|
||||
}
|
||||
|
||||
[_glfw.ns.cursor release];
|
||||
_glfw.ns.cursor = nil;
|
||||
|
||||
free(_glfw.ns.clipboardString);
|
||||
|
||||
_glfwTerminateNSGL();
|
||||
|
||||
@@ -73,7 +73,9 @@ static long getElementValue(_GLFWjoystick* js, _GLFWjoyelementNS* element)
|
||||
|
||||
// Comparison function for matching the SDL element order
|
||||
//
|
||||
static CFComparisonResult compareElements(const void* fp, const void* sp, void* user)
|
||||
static CFComparisonResult compareElements(const void* fp,
|
||||
const void* sp,
|
||||
void* user)
|
||||
{
|
||||
const _GLFWjoyelementNS* fe = fp;
|
||||
const _GLFWjoyelementNS* se = sp;
|
||||
@@ -183,7 +185,8 @@ static void matchCallback(void* context,
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(elements); i++)
|
||||
{
|
||||
IOHIDElementRef native = (IOHIDElementRef) CFArrayGetValueAtIndex(elements, i);
|
||||
IOHIDElementRef native = (IOHIDElementRef)
|
||||
CFArrayGetValueAtIndex(elements, i);
|
||||
if (CFGetTypeID(native) != IOHIDElementGetTypeID())
|
||||
continue;
|
||||
|
||||
|
||||
+14
-3
@@ -54,7 +54,8 @@ static char* getDisplayName(CGDirectDisplayID displayID)
|
||||
|
||||
while ((service = IOIteratorNext(it)) != 0)
|
||||
{
|
||||
info = IODisplayCreateInfoDictionary(service, kIODisplayOnlyPreferredName);
|
||||
info = IODisplayCreateInfoDictionary(service,
|
||||
kIODisplayOnlyPreferredName);
|
||||
|
||||
CFNumberRef vendorIDRef =
|
||||
CFDictionaryGetValue(info, CFSTR(kDisplayVendorID));
|
||||
@@ -185,7 +186,13 @@ static CGDisplayFadeReservationToken beginFadeReservation(void)
|
||||
CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken;
|
||||
|
||||
if (CGAcquireDisplayFadeReservation(5, &token) == kCGErrorSuccess)
|
||||
CGDisplayFade(token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
|
||||
{
|
||||
CGDisplayFade(token, 0.3,
|
||||
kCGDisplayBlendNormal,
|
||||
kCGDisplayBlendSolidColor,
|
||||
0.0, 0.0, 0.0,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
@@ -196,7 +203,11 @@ static void endFadeReservation(CGDisplayFadeReservationToken token)
|
||||
{
|
||||
if (token != kCGDisplayFadeReservationInvalidToken)
|
||||
{
|
||||
CGDisplayFade(token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
|
||||
CGDisplayFade(token, 0.5,
|
||||
kCGDisplayBlendSolidColor,
|
||||
kCGDisplayBlendNormal,
|
||||
0.0, 0.0, 0.0,
|
||||
FALSE);
|
||||
CGReleaseDisplayFadeReservation(token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ typedef struct _GLFWlibraryNS
|
||||
CGEventSourceRef eventSource;
|
||||
id delegate;
|
||||
id autoreleasePool;
|
||||
id cursor;
|
||||
GLFWbool cursorHidden;
|
||||
TISInputSourceRef inputSource;
|
||||
IOHIDManagerRef hidManager;
|
||||
id unicodeData;
|
||||
|
||||
+41
-17
@@ -88,19 +88,43 @@ static GLFWbool cursorInClientArea(_GLFWwindow* window)
|
||||
return [window->ns.view mouse:pos inRect:[window->ns.view frame]];
|
||||
}
|
||||
|
||||
// Hides the cursor if not already hidden
|
||||
//
|
||||
static void hideCursor(_GLFWwindow* window)
|
||||
{
|
||||
if (!_glfw.ns.cursorHidden)
|
||||
{
|
||||
[NSCursor hide];
|
||||
_glfw.ns.cursorHidden = GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Shows the cursor if not already shown
|
||||
//
|
||||
static void showCursor(_GLFWwindow* window)
|
||||
{
|
||||
if (_glfw.ns.cursorHidden)
|
||||
{
|
||||
[NSCursor unhide];
|
||||
_glfw.ns.cursorHidden = GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Updates the cursor image according to its cursor mode
|
||||
//
|
||||
static void updateCursorImage(_GLFWwindow* window)
|
||||
{
|
||||
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
||||
{
|
||||
showCursor(window);
|
||||
|
||||
if (window->cursor)
|
||||
[(NSCursor*) window->cursor->ns.object set];
|
||||
else
|
||||
[[NSCursor arrowCursor] set];
|
||||
}
|
||||
else
|
||||
[(NSCursor*) _glfw.ns.cursor set];
|
||||
hideCursor(window);
|
||||
}
|
||||
|
||||
// Transforms the specified y-coordinate between the CG display and NS screen
|
||||
@@ -363,20 +387,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
|
||||
@implementation GLFWContentView
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
if (self == [GLFWContentView class])
|
||||
{
|
||||
if (_glfw.ns.cursor == nil)
|
||||
{
|
||||
NSImage* data = [[NSImage alloc] initWithSize:NSMakeSize(16, 16)];
|
||||
_glfw.ns.cursor = [[NSCursor alloc] initWithImage:data
|
||||
hotSpot:NSZeroPoint];
|
||||
[data release];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (id)initWithGlfwWindow:(_GLFWwindow *)initWindow
|
||||
{
|
||||
self = [super init];
|
||||
@@ -522,11 +532,17 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
|
||||
- (void)mouseExited:(NSEvent *)event
|
||||
{
|
||||
if (window->cursorMode == GLFW_CURSOR_HIDDEN)
|
||||
showCursor(window);
|
||||
|
||||
_glfwInputCursorEnter(window, GLFW_FALSE);
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(NSEvent *)event
|
||||
{
|
||||
if (window->cursorMode == GLFW_CURSOR_HIDDEN)
|
||||
hideCursor(window);
|
||||
|
||||
_glfwInputCursorEnter(window, GLFW_TRUE);
|
||||
}
|
||||
|
||||
@@ -698,10 +714,11 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
selectedRange:(NSRange)selectedRange
|
||||
replacementRange:(NSRange)replacementRange
|
||||
{
|
||||
[markedText release];
|
||||
if ([string isKindOfClass:[NSAttributedString class]])
|
||||
[markedText initWithAttributedString:string];
|
||||
markedText = [[NSMutableAttributedString alloc] initWithAttributedString:string];
|
||||
else
|
||||
[markedText initWithString:string];
|
||||
markedText = [[NSMutableAttributedString alloc] initWithString:string];
|
||||
}
|
||||
|
||||
- (void)unmarkText
|
||||
@@ -982,6 +999,13 @@ static GLFWbool initializeAppKit(void)
|
||||
[NSApp setDelegate:_glfw.ns.delegate];
|
||||
[NSApp run];
|
||||
|
||||
// Press and Hold prevents some keys from emitting repeated characters
|
||||
NSDictionary* defaults =
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],
|
||||
@"ApplePressAndHoldEnabled",
|
||||
nil];
|
||||
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
|
||||
+28
-4
@@ -116,10 +116,18 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
||||
if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
|
||||
continue;
|
||||
|
||||
#if defined(_GLFW_EGLDEVICE)
|
||||
// Only consider stream EGLConfigs
|
||||
if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_STREAM_BIT_KHR))
|
||||
continue;
|
||||
|
||||
#else
|
||||
// Only consider window EGLConfigs
|
||||
if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
|
||||
continue;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(_GLFW_X11)
|
||||
// Only consider EGLConfigs with associated Visuals
|
||||
if (!getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID))
|
||||
@@ -286,7 +294,9 @@ GLFWbool _glfwInitEGL(void)
|
||||
int i;
|
||||
const char* sonames[] =
|
||||
{
|
||||
#if defined(_GLFW_WIN32)
|
||||
#if defined(_GLFW_EGL_LIBRARY)
|
||||
_GLFW_EGL_LIBRARY,
|
||||
#elif defined(_GLFW_WIN32)
|
||||
"libEGL.dll",
|
||||
"EGL.dll",
|
||||
#elif defined(_GLFW_COCOA)
|
||||
@@ -374,6 +384,9 @@ GLFWbool _glfwInitEGL(void)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
// For EGLDevice backend the display gets initialized
|
||||
// in _glfwPlatformInit()
|
||||
#if !defined(_GLFW_EGLDEVICE)
|
||||
_glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY);
|
||||
if (_glfw.egl.display == EGL_NO_DISPLAY)
|
||||
{
|
||||
@@ -394,6 +407,7 @@ GLFWbool _glfwInitEGL(void)
|
||||
_glfwTerminateEGL();
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
_glfw.egl.KHR_create_context =
|
||||
extensionSupportedEGL("EGL_KHR_create_context");
|
||||
@@ -579,6 +593,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
setAttrib(EGL_NONE, EGL_NONE);
|
||||
}
|
||||
|
||||
// The surface for EGLDevice backened is created in _glfwPlatformCreateWindow
|
||||
//
|
||||
#if !defined (_GLFW_EGLDEVICE)
|
||||
window->context.egl.surface =
|
||||
eglCreateWindowSurface(_glfw.egl.display,
|
||||
config,
|
||||
@@ -591,6 +608,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
getEGLErrorString(eglGetError()));
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
window->context.egl.config = config;
|
||||
|
||||
@@ -601,7 +619,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
const char** sonames;
|
||||
const char* es1sonames[] =
|
||||
{
|
||||
#if defined(_GLFW_WIN32)
|
||||
#if defined(_GLFW_GLESV1_LIBRARY)
|
||||
_GLFW_GLESV1_LIBRARY,
|
||||
#elif defined(_GLFW_WIN32)
|
||||
"GLESv1_CM.dll",
|
||||
"libGLES_CM.dll",
|
||||
#elif defined(_GLFW_COCOA)
|
||||
@@ -614,7 +634,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
};
|
||||
const char* es2sonames[] =
|
||||
{
|
||||
#if defined(_GLFW_WIN32)
|
||||
#if defined(_GLFW_GLESV2_LIBRARY)
|
||||
_GLFW_GLESV2_LIBRARY,
|
||||
#elif defined(_GLFW_WIN32)
|
||||
"GLESv2.dll",
|
||||
"libGLESv2.dll",
|
||||
#elif defined(_GLFW_COCOA)
|
||||
@@ -628,7 +650,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
};
|
||||
const char* glsonames[] =
|
||||
{
|
||||
#if defined(_GLFW_WIN32)
|
||||
#if defined(_GLFW_OPENGL_LIBRARY)
|
||||
_GLFW_OPENGL_LIBRARY,
|
||||
#elif defined(_GLFW_WIN32)
|
||||
#elif defined(_GLFW_COCOA)
|
||||
#else
|
||||
"libGL.so.1",
|
||||
|
||||
@@ -47,6 +47,10 @@ typedef struct wl_egl_window* EGLNativeWindowType;
|
||||
#define EGLAPIENTRY
|
||||
typedef MirEGLNativeDisplayType EGLNativeDisplayType;
|
||||
typedef MirEGLNativeWindowType EGLNativeWindowType;
|
||||
#elif defined(_GLFW_EGLDEVICE)
|
||||
#define EGLAPIENTRY
|
||||
typedef void* EGLNativeDisplayType;
|
||||
typedef int EGLNativeWindowType;
|
||||
#else
|
||||
#error "No supported EGL platform selected"
|
||||
#endif
|
||||
@@ -84,6 +88,8 @@ typedef MirEGLNativeWindowType EGLNativeWindowType;
|
||||
#define EGL_OPENGL_ES_API 0x30a0
|
||||
#define EGL_OPENGL_API 0x30a2
|
||||
#define EGL_NONE 0x3038
|
||||
#define EGL_WIDTH 0x3057
|
||||
#define EGL_HEIGHT 0x3056
|
||||
#define EGL_EXTENSIONS 0x3055
|
||||
#define EGL_CONTEXT_CLIENT_VERSION 0x3098
|
||||
#define EGL_NATIVE_VISUAL_ID 0x302e
|
||||
@@ -118,6 +124,7 @@ typedef void* EGLConfig;
|
||||
typedef void* EGLContext;
|
||||
typedef void* EGLDisplay;
|
||||
typedef void* EGLSurface;
|
||||
typedef intptr_t EGLAttrib;
|
||||
|
||||
// EGL function pointer typedefs
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*);
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 EGLDevice - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <linux/limits.h>
|
||||
|
||||
static GLFWbool initializeExtensions(void)
|
||||
{
|
||||
_glfw.egldevice.QueryDevicesEXT =
|
||||
(PFNEGLQUERYDEVICESEXTPROC)
|
||||
eglGetProcAddress("eglQueryDevicesEXT");
|
||||
_glfw.egldevice.QueryDeviceStringEXT =
|
||||
(PFNEGLQUERYDEVICESTRINGEXTPROC)
|
||||
eglGetProcAddress("eglQueryDeviceStringEXT");
|
||||
_glfw.egldevice.GetPlatformDisplayEXT =
|
||||
(PFNEGLGETPLATFORMDISPLAYEXTPROC)
|
||||
eglGetProcAddress("eglGetPlatformDisplayEXT");
|
||||
_glfw.egldevice.GetOutputLayersEXT =
|
||||
(PFNEGLGETOUTPUTLAYERSEXTPROC)
|
||||
eglGetProcAddress("eglGetOutputLayersEXT");
|
||||
_glfw.egldevice.CreateStreamKHR =
|
||||
(PFNEGLCREATESTREAMKHRPROC)
|
||||
eglGetProcAddress("eglCreateStreamKHR");
|
||||
_glfw.egldevice.DestroyStreamKHR =
|
||||
(PFNEGLDESTROYSTREAMKHRPROC)
|
||||
eglGetProcAddress("eglDestroyStreamKHR");
|
||||
_glfw.egldevice.StreamConsumerOutputEXT =
|
||||
(PFNEGLSTREAMCONSUMEROUTPUTEXTPROC)
|
||||
eglGetProcAddress("eglStreamConsumerOutputEXT");
|
||||
_glfw.egldevice.CreateStreamProducerSurfaceKHR =
|
||||
(PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC)
|
||||
eglGetProcAddress("eglCreateStreamProducerSurfaceKHR");
|
||||
|
||||
if(!_glfw.egldevice.QueryDevicesEXT ||
|
||||
!_glfw.egldevice.QueryDeviceStringEXT ||
|
||||
!_glfw.egldevice.GetPlatformDisplayEXT ||
|
||||
!_glfw.egldevice.GetOutputLayersEXT ||
|
||||
!_glfw.egldevice.CreateStreamKHR ||
|
||||
!_glfw.egldevice.DestroyStreamKHR ||
|
||||
!_glfw.egldevice.StreamConsumerOutputEXT ||
|
||||
!_glfw.egldevice.CreateStreamProducerSurfaceKHR)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Failed to find required EGL extension functions");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
static EGLDeviceEXT getEGLDevice(void)
|
||||
{
|
||||
int i, num_devs;
|
||||
EGLDeviceEXT* egl_devs, eglDevice;
|
||||
const char *clientExtensionString;
|
||||
|
||||
eglDevice = EGL_NO_DEVICE_EXT;
|
||||
clientExtensionString = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
|
||||
if (!_glfwStringInExtensionString("EGL_EXT_device_base",
|
||||
clientExtensionString) &&
|
||||
(!_glfwStringInExtensionString("EGL_EXT_device_enumeration",
|
||||
clientExtensionString) ||
|
||||
!_glfwStringInExtensionString("EGL_EXT_device_query",
|
||||
clientExtensionString)))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: EGL_EXT_device base extensions not found");
|
||||
}
|
||||
|
||||
if (!eglQueryDevicesEXT(0, NULL, &num_devs))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Falied to query EGLDevice");
|
||||
}
|
||||
if (num_devs < 1)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: No devices found");
|
||||
}
|
||||
|
||||
egl_devs = calloc(sizeof(EGLDeviceEXT), num_devs);
|
||||
if (egl_devs == NULL)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Unable to allocate memory for device storage");
|
||||
}
|
||||
|
||||
// Select suitable device
|
||||
if (!eglQueryDevicesEXT(num_devs, egl_devs, &num_devs))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Failed to query EGL devices");
|
||||
}
|
||||
|
||||
for (i = 0; i <= num_devs; i++)
|
||||
{
|
||||
const char* deviceExtensionString;
|
||||
|
||||
deviceExtensionString = eglQueryDeviceStringEXT(egl_devs[i], EGL_EXTENSIONS);
|
||||
if (_glfwStringInExtensionString("EGL_EXT_device_drm",
|
||||
deviceExtensionString))
|
||||
{
|
||||
eglDevice = egl_devs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(egl_devs);
|
||||
|
||||
if (eglDevice == EGL_NO_DEVICE_EXT)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Missing required extension EGL_EXT_device_drm");
|
||||
}
|
||||
return eglDevice;
|
||||
}
|
||||
|
||||
static int getDRMFd(EGLDeviceEXT eglDevice)
|
||||
{
|
||||
int drm_fd;
|
||||
const char* drmName;
|
||||
|
||||
drmName = eglQueryDeviceStringEXT(eglDevice, EGL_DRM_DEVICE_FILE_EXT);
|
||||
if (!drmName || (strnlen(drmName, PATH_MAX) == 0))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Couldn't obtain device file from 0x%p",
|
||||
(void*)(uintptr_t)eglDevice);
|
||||
}
|
||||
|
||||
drm_fd = drmOpen(drmName, NULL);
|
||||
if (drm_fd < 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Couldn't open device file '%s'", drmName);
|
||||
}
|
||||
|
||||
return drm_fd;
|
||||
}
|
||||
|
||||
static GLFWbool initEGLDisplay(EGLDeviceEXT egl_dev, int drm_fd)
|
||||
{
|
||||
const char* displayExtensionString;
|
||||
EGLint displayAttribs[] = {
|
||||
EGL_DRM_MASTER_FD_EXT,
|
||||
drm_fd,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
_glfw.egl.display = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT,
|
||||
(void*)egl_dev,
|
||||
displayAttribs);
|
||||
if (_glfw.egl.display == EGL_NO_DISPLAY)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Couldn't obtain EGLDisplay for device");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor))
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to initialize EGL");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
// Check for stream_consumer_egloutput + output_drm support
|
||||
displayExtensionString = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
|
||||
if (!_glfwStringInExtensionString("EGL_EXT_output_base",
|
||||
displayExtensionString))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Missing required extension EGL_EXT_output_base");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!_glfwStringInExtensionString("EGL_EXT_output_drm",
|
||||
displayExtensionString))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Missing required extension EGL_EXT_output_drm");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!_glfwStringInExtensionString("EGL_KHR_stream",
|
||||
displayExtensionString))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Missing required extension EGL_KHR_stream");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!_glfwStringInExtensionString("EGL_KHR_stream_producer_eglsurface",
|
||||
displayExtensionString))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Missing required extension EGL_KHR_stream_producer_eglsurface");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
if (!_glfwStringInExtensionString("EGL_EXT_stream_consumer_egloutput",
|
||||
displayExtensionString))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Missing required extension EGL_EXT_stream_consumer_egloutput");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformInit(void)
|
||||
{
|
||||
EGLDeviceEXT egl_dev;
|
||||
int drm_fd;
|
||||
|
||||
// Initialize EGL
|
||||
if (!_glfwInitEGL())
|
||||
return GLFW_FALSE;
|
||||
|
||||
// Initialize global data and extension function pointers
|
||||
if (!initializeExtensions())
|
||||
return GLFW_FALSE;
|
||||
|
||||
// Query and Obtain EGLDevice
|
||||
egl_dev = getEGLDevice();
|
||||
|
||||
// Obtain and open DRM device file
|
||||
drm_fd = getDRMFd(egl_dev);
|
||||
|
||||
// Store for use later
|
||||
_glfw.egldevice.drmFd = drm_fd;
|
||||
|
||||
// Obtain EGLDisplay
|
||||
if (!initEGLDisplay(egl_dev, drm_fd))
|
||||
return GLFW_FALSE;
|
||||
|
||||
_glfwInitTimerPOSIX();
|
||||
|
||||
_glfwPollMonitorsEGLDevice();
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformTerminate(void)
|
||||
{
|
||||
_glfwTerminateEGL();
|
||||
_glfwTerminateJoysticksLinux();
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetVersionString(void)
|
||||
{
|
||||
return _GLFW_VERSION_NUMBER "EGLDevice EGL"
|
||||
#if defined(_GLFW_BUILD_DLL)
|
||||
" shared"
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 EGLDevice - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// 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"
|
||||
|
||||
static GLFWbool pickConnector(_GLFWmonitor* monitor, int drm_fd, drmModeRes* res_info)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
// Getting suitable connector, encoder and crtc
|
||||
for (i = 0; i < res_info->count_connectors; i++)
|
||||
{
|
||||
monitor->egldevice.connId = res_info->connectors[i];
|
||||
|
||||
drmModeConnector* conn_info;
|
||||
|
||||
conn_info =
|
||||
drmModeGetConnector(drm_fd, monitor->egldevice.connId);
|
||||
if (!conn_info)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Unable to obtain info for connector (%d)",
|
||||
monitor->egldevice.connId);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
if (conn_info->connection == DRM_MODE_CONNECTED &&
|
||||
conn_info->count_modes > 0 &&
|
||||
conn_info->count_encoders > 0)
|
||||
{
|
||||
monitor->egldevice.encId = conn_info->encoders[0];
|
||||
|
||||
drmModeEncoder* enc_info;
|
||||
|
||||
enc_info =
|
||||
drmModeGetEncoder(drm_fd, monitor->egldevice.encId);
|
||||
if (!enc_info) {
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Unable to query DRM-KMS information for connector index %d", i);
|
||||
}
|
||||
|
||||
// Select the modesize
|
||||
monitor->currentMode.width = (int)conn_info->modes[0].hdisplay;
|
||||
monitor->currentMode.height = (int)conn_info->modes[0].vdisplay;
|
||||
monitor->currentMode.refreshRate = (int)conn_info->modes[0].vrefresh;
|
||||
monitor->modeCount = (int)conn_info->count_modes;
|
||||
monitor->name = conn_info->modes[0].name;
|
||||
|
||||
for (j = 0; j < res_info->count_crtcs; j++)
|
||||
{
|
||||
if ((enc_info->possible_crtcs & (1 << j)) == 0)
|
||||
continue;
|
||||
|
||||
monitor->egldevice.crtcId = res_info->crtcs[j];
|
||||
monitor->egldevice.crtcIndex = j;
|
||||
|
||||
if (res_info->crtcs[i] == enc_info->crtc_id)
|
||||
break;
|
||||
}
|
||||
if (monitor->egldevice.crtcId == 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Unable to select suitable CRTC");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
drmModeFreeEncoder(enc_info);
|
||||
}
|
||||
drmModeFreeConnector(conn_info);
|
||||
}
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
static GLFWbool initDRMResources(_GLFWmonitor* monitor, int drm_fd)
|
||||
{
|
||||
drmModeRes* res_info;
|
||||
|
||||
res_info = drmModeGetResources(drm_fd);
|
||||
if (!res_info)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Couldn't obtain DRM-KMS resources");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if(!pickConnector(monitor, drm_fd, res_info))
|
||||
return GLFW_FALSE;
|
||||
|
||||
drmModeFreeResources(res_info);
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/////////// GLFW platform API //////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwPollMonitorsEGLDevice(void)
|
||||
{
|
||||
_GLFWmonitor* monitor = _glfwAllocMonitor("Monitor", 0, 0);
|
||||
|
||||
// Obtain DRM resource info
|
||||
if (!initDRMResources(monitor, _glfw.egldevice.drmFd))
|
||||
{
|
||||
_glfwFreeMonitor(monitor);
|
||||
return;
|
||||
}
|
||||
|
||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_FIRST);
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformGetMonitorPos not implemented");
|
||||
}
|
||||
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformGetVideoModes not implemented");
|
||||
*found = 0;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformGetVideoMode not implemented");
|
||||
}
|
||||
|
||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformGetGammaRamp not implemented");
|
||||
}
|
||||
|
||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformSetGammaRamp not implemented");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 EGLDevice - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
#include "posix_time.h"
|
||||
#include "linux_joystick.h"
|
||||
#include "posix_thread.h"
|
||||
#include "egl_context.h"
|
||||
#include "osmesa_context.h"
|
||||
|
||||
#define EGL_NO_DEVICE_EXT ((EGLDeviceEXT) 0)
|
||||
#define EGL_DRM_DEVICE_FILE_EXT 0x3233
|
||||
#define EGL_PLATFORM_DEVICE_EXT 0x313f
|
||||
#define EGL_DRM_MASTER_FD_EXT 0x333c
|
||||
#define EGL_STREAM_FIFO_LENGTH_KHR 0x31fc
|
||||
#define EGL_DRM_CRTC_EXT 0x3234
|
||||
#define EGL_NO_STREAM_KHR ((EGLStreamKHR) 0)
|
||||
#define EGL_STREAM_BIT_KHR 0x0800
|
||||
|
||||
typedef void* EGLOutputLayerEXT;
|
||||
typedef void* EGLStreamKHR;
|
||||
typedef void* EGLDeviceEXT;
|
||||
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFNEGLQUERYDEVICESEXTPROC)(EGLint,EGLDeviceEXT*,EGLint*);
|
||||
typedef const char *(EGLAPIENTRY * PFNEGLQUERYDEVICESTRINGEXTPROC)(EGLDeviceEXT,EGLint);
|
||||
typedef EGLDisplay (EGLAPIENTRY * PFNEGLGETPLATFORMDISPLAYEXTPROC)(EGLenum,void*,const EGLint*);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETOUTPUTLAYERSEXTPROC)(EGLDisplay,const EGLAttrib*,EGLOutputLayerEXT*,EGLint,EGLint*);
|
||||
typedef EGLStreamKHR (EGLAPIENTRY * PFNEGLCREATESTREAMKHRPROC)(EGLDisplay,const EGLint*);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYSTREAMKHRPROC)(EGLDisplay,EGLStreamKHR);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSTREAMCONSUMEROUTPUTEXTPROC)(EGLDisplay,EGLStreamKHR,EGLOutputLayerEXT);
|
||||
typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC)(EGLDisplay,EGLConfig,EGLStreamKHR,const EGLint*);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSTREAMATTRIBKHRPROC)(EGLDisplay,EGLStreamKHR,EGLenum,EGLint);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSTREAMCONSUMERACQUIREATTRIBKHRPROC)(EGLDisplay,EGLStreamKHR,const EGLAttrib*);
|
||||
#define eglQueryDevicesEXT _glfw.egldevice.QueryDevicesEXT
|
||||
#define eglQueryDeviceStringEXT _glfw.egldevice.QueryDeviceStringEXT
|
||||
#define eglGetPlatformDisplayEXT _glfw.egldevice.GetPlatformDisplayEXT
|
||||
#define eglGetOutputLayersEXT _glfw.egldevice.GetOutputLayersEXT
|
||||
#define eglCreateStreamKHR _glfw.egldevice.CreateStreamKHR
|
||||
#define eglDestroyStreamKHR _glfw.egldevice.DestroyStreamKHR
|
||||
#define eglStreamConsumerOutputEXT _glfw.egldevice.StreamConsumerOutputEXT
|
||||
#define eglCreateStreamProducerSurfaceKHR _glfw.egldevice.CreateStreamProducerSurfaceKHR
|
||||
#define eglStreamAttribKHR _glfw.egldevice.StreamAttribKHR
|
||||
#define eglStreamConsumerAcquireAttribKHR _glfw.egldevice.StreamConsumerAcquireAttribKHR
|
||||
|
||||
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||
#define _glfw_dlclose(handle) dlclose(handle)
|
||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||
|
||||
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
|
||||
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType)window->egldevice.handle)
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowEGLDevice egldevice
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryEGLDevice egldevice
|
||||
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorEGLDevice egldevice
|
||||
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorEGLDevice egldevice
|
||||
|
||||
#define _GLFW_PLATFORM_CONTEXT_STATE
|
||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
|
||||
|
||||
// EGLDevice-specific per-window data
|
||||
//
|
||||
typedef struct _GLFWwindowEGLDevice
|
||||
{
|
||||
int xsurfsize, ysurfsize;
|
||||
int xoffset, yoffset;
|
||||
int fifo;
|
||||
|
||||
uint32_t planeId;
|
||||
|
||||
EGLDisplay handle;
|
||||
EGLOutputLayerEXT eglLayer;
|
||||
EGLStreamKHR eglStream;
|
||||
} _GLFWwindowEGLDevice;
|
||||
|
||||
// EGLDevice-specific global data
|
||||
//
|
||||
typedef struct _GLFWlibraryEGLDevice
|
||||
{
|
||||
int drmFd;
|
||||
|
||||
PFNEGLQUERYDEVICESEXTPROC QueryDevicesEXT;
|
||||
PFNEGLQUERYDEVICESTRINGEXTPROC QueryDeviceStringEXT;
|
||||
PFNEGLGETPLATFORMDISPLAYEXTPROC GetPlatformDisplayEXT;
|
||||
PFNEGLGETOUTPUTLAYERSEXTPROC GetOutputLayersEXT;
|
||||
PFNEGLCREATESTREAMKHRPROC CreateStreamKHR;
|
||||
PFNEGLDESTROYSTREAMKHRPROC DestroyStreamKHR;
|
||||
PFNEGLSTREAMCONSUMEROUTPUTEXTPROC StreamConsumerOutputEXT;
|
||||
PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC CreateStreamProducerSurfaceKHR;
|
||||
PFNEGLSTREAMATTRIBKHRPROC StreamAttribKHR;
|
||||
PFNEGLSTREAMCONSUMERACQUIREATTRIBKHRPROC StreamConsumerAcquireAttribKHR;
|
||||
} _GLFWlibraryEGLDevice;
|
||||
|
||||
// EGLDevice-specific per-monitor data
|
||||
//
|
||||
typedef struct _GLFWmonitorEGLDevice
|
||||
{
|
||||
int crtcIndex;
|
||||
uint32_t connId, encId, crtcId;
|
||||
} _GLFWmonitorEGLDevice;
|
||||
|
||||
// EGLDevice-specific per-cursor data
|
||||
//
|
||||
typedef struct _GLFWcursorEGLDevice
|
||||
{
|
||||
} _GLFWcursorEGLDevice;
|
||||
|
||||
void _glfwPollMonitorsEGLDevice(void);
|
||||
|
||||
@@ -0,0 +1,430 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 EGLDevice - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//////// GLFW platform API /////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
int n;
|
||||
_GLFWmonitor* monitor;
|
||||
EGLAttrib layerAttribs[] = { EGL_NONE, EGL_NONE, EGL_NONE };
|
||||
EGLint streamAttribs[] = { EGL_STREAM_FIFO_LENGTH_KHR,
|
||||
window->egldevice.fifo, EGL_NONE };
|
||||
EGLint surfaceAttribs[] = { EGL_WIDTH, 0, EGL_HEIGHT, 0, EGL_NONE };
|
||||
|
||||
if (window->monitor)
|
||||
monitor = window->monitor;
|
||||
else
|
||||
monitor = _glfw.monitors[0];
|
||||
|
||||
window->egldevice.xsurfsize = wndconfig->width;
|
||||
window->egldevice.ysurfsize = wndconfig->height;
|
||||
|
||||
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
|
||||
// Get the layer for this crtc/plane
|
||||
layerAttribs[0] = EGL_DRM_CRTC_EXT;
|
||||
layerAttribs[1] = (EGLAttrib)monitor->egldevice.crtcId;
|
||||
|
||||
if (!eglGetOutputLayersEXT(_glfw.egl.display, layerAttribs,
|
||||
&window->egldevice.eglLayer,
|
||||
1, &n) || !n)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Unable to obtain EGLOutputLayer");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
// Create a stream and connect to the output
|
||||
window->egldevice.eglStream =
|
||||
eglCreateStreamKHR(_glfw.egl.display, streamAttribs);
|
||||
if (window->egldevice.eglStream == EGL_NO_STREAM_KHR)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Unable to create stream (error 0x%x)",
|
||||
eglGetError());
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
if (!eglStreamConsumerOutputEXT(_glfw.egl.display,
|
||||
window->egldevice.eglStream,
|
||||
window->egldevice.eglLayer))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Unable to connect stream (error 0x%x)",
|
||||
eglGetError());
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
// Create a surface to feed the stream
|
||||
surfaceAttribs[1] = window->egldevice.xsurfsize;
|
||||
surfaceAttribs[3] = window->egldevice.ysurfsize;
|
||||
window->context.egl.surface =
|
||||
eglCreateStreamProducerSurfaceKHR(_glfw.egl.display,
|
||||
window->context.egl.config,
|
||||
window->egldevice.eglStream,
|
||||
surfaceAttribs);
|
||||
if (window->context.egl.surface == EGL_NO_SURFACE)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Unable to create rendering surface (error 0x%x)", eglGetError());
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (window->context.client != GLFW_NO_API)
|
||||
window->context.destroy(window);
|
||||
|
||||
if (window->egldevice.eglStream != EGL_NO_STREAM_KHR)
|
||||
eglDestroyStreamKHR(_glfw.egl.display, window->egldevice.eglStream);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformSetWindowTitle is not supported");
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
||||
int count, const GLFWimage* images)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformSetWindowIcon is not supported");
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
||||
{
|
||||
if (xpos)
|
||||
*xpos = window->egldevice.xoffset;
|
||||
if (ypos)
|
||||
*ypos = window->egldevice.yoffset;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
|
||||
{
|
||||
window->egldevice.xoffset = xpos;
|
||||
window->egldevice.yoffset = ypos;
|
||||
|
||||
drmModeRes* res_info;
|
||||
_GLFWmonitor* monitor;
|
||||
|
||||
if (window->monitor)
|
||||
monitor = window->monitor;
|
||||
else
|
||||
monitor = _glfw.monitors[0];
|
||||
|
||||
res_info = drmModeGetResources(_glfw.egldevice.drmFd);
|
||||
if (drmModeSetCrtc(_glfw.egldevice.drmFd,
|
||||
res_info->crtcs[monitor->egldevice.crtcIndex],
|
||||
-1, window->egldevice.xoffset, window->egldevice.yoffset,
|
||||
&res_info->connectors[monitor->egldevice.crtcIndex], 1, NULL))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: Setting window pos failed");
|
||||
}
|
||||
drmModeFreeResources(res_info);
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
||||
{
|
||||
if (width)
|
||||
*width = window->egldevice.xsurfsize;
|
||||
if (height)
|
||||
*height = window->egldevice.ysurfsize;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformSetWindowSize not implemented");
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||
int minwidth, int minheight,
|
||||
int maxwidth, int maxheight)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformSetWindowSizeLimits not implemented");
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformSetWindowAspectRatio not implemented");
|
||||
}
|
||||
|
||||
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
|
||||
{
|
||||
_glfwPlatformGetWindowSize(window, width, height);
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||
int* left, int* top,
|
||||
int* right, int* bottom)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformGetWindowFrameSize not implemented");
|
||||
}
|
||||
|
||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformIconifyWindow not implemented");
|
||||
}
|
||||
|
||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformRestoreWindow not implemented");
|
||||
}
|
||||
|
||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformMaximizeWindow not implemented");
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformSetWindowResizable not implemented");
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformSetWindowDecorated not implemented");
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformSetWindowFloating not implemented");
|
||||
}
|
||||
|
||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformRequestWindowAttention not implemented");
|
||||
}
|
||||
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformUnhideWindow not implemented");
|
||||
}
|
||||
|
||||
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformHideWindow not implemented");
|
||||
}
|
||||
|
||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
_GLFWmonitor* monitor,
|
||||
int xpos, int ypos,
|
||||
int width, int height,
|
||||
int refreshRate)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformSetWindowMonitor not implemented");
|
||||
}
|
||||
int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformWindowFocused not implemented");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformWindowIconified not implemented");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowVisible(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformWindowVisible not implemented");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformWindowMaximized not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _glfwPlatformPollEvents(void)
|
||||
{
|
||||
_glfwDetectJoystickConnectionLinux();
|
||||
}
|
||||
|
||||
void _glfwPlatformWaitEvents(void)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformWaitEvents not supported");
|
||||
}
|
||||
|
||||
void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformWaitEventsTimeout not supported");
|
||||
}
|
||||
|
||||
void _glfwPlatformPostEmptyEvent(void)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformPostEmptyEvent not supported");
|
||||
}
|
||||
|
||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformGetCursorPos not supported");
|
||||
}
|
||||
|
||||
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformSetCursorPos not supported");
|
||||
}
|
||||
|
||||
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformSetCursorMode not supported");
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetKeyName(int key, int scancode)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformGetKeyName not supported");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformCreateCursor not supported");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformCreateStandardCursor not supported");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformSetCursor not supported");
|
||||
}
|
||||
|
||||
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformSetClipboardString not supported");
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformGetClipboardString not supported");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetScancodeName(int scancode)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformGetScancodeName not supported");
|
||||
return "";
|
||||
}
|
||||
|
||||
int _glfwPlatformGetKeyScancode(int key)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformGetKeyScancode not supported");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformGetRequiredInstanceExtensions not supported");
|
||||
}
|
||||
|
||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformGetPhysicalDevicePresentationSupport not supported");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
_GLFWwindow* window,
|
||||
const VkAllocationCallbacks* allocator,
|
||||
VkSurfaceKHR* surface)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGLDevice: _glfwPlatformCreateWindowSurface not supported");
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
#cmakedefine _GLFW_MIR
|
||||
// Define this to 1 if building GLFW for OSMesa
|
||||
#cmakedefine _GLFW_OSMESA
|
||||
// Define this to 1 if building GLFW for EGLDevice
|
||||
#cmakedefine _GLFW_EGLDEVICE
|
||||
|
||||
// Define this to 1 if building as a shared library / dynamic library / DLL
|
||||
#cmakedefine _GLFW_BUILD_DLL
|
||||
|
||||
+3
-1
@@ -244,7 +244,9 @@ GLFWbool _glfwInitGLX(void)
|
||||
int i;
|
||||
const char* sonames[] =
|
||||
{
|
||||
#if defined(__CYGWIN__)
|
||||
#if defined(_GLFW_GLX_LIBRARY)
|
||||
_GLFW_GLX_LIBRARY,
|
||||
#elif defined(__CYGWIN__)
|
||||
"libGL-1.so",
|
||||
#else
|
||||
"libGL.so.1",
|
||||
|
||||
+1
-1
@@ -148,7 +148,7 @@ static void terminate(void)
|
||||
void _glfwInputError(int code, const char* format, ...)
|
||||
{
|
||||
_GLFWerror* error;
|
||||
char description[1024];
|
||||
char description[_GLFW_MESSAGE_SIZE];
|
||||
|
||||
if (format)
|
||||
{
|
||||
|
||||
+58
-65
@@ -354,10 +354,10 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
|
||||
return window->stickyKeys;
|
||||
case GLFW_STICKY_MOUSE_BUTTONS:
|
||||
return window->stickyMouseButtons;
|
||||
default:
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
||||
@@ -367,79 +367,72 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
switch (mode)
|
||||
if (mode == GLFW_CURSOR)
|
||||
{
|
||||
case GLFW_CURSOR:
|
||||
if (value != GLFW_CURSOR_NORMAL &&
|
||||
value != GLFW_CURSOR_HIDDEN &&
|
||||
value != GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
if (value != GLFW_CURSOR_NORMAL &&
|
||||
value != GLFW_CURSOR_HIDDEN &&
|
||||
value != GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid cursor mode 0x%08X",
|
||||
value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (window->cursorMode == value)
|
||||
return;
|
||||
|
||||
window->cursorMode = value;
|
||||
|
||||
_glfwPlatformGetCursorPos(window,
|
||||
&window->virtualCursorPosX,
|
||||
&window->virtualCursorPosY);
|
||||
|
||||
if (_glfwPlatformWindowFocused(window))
|
||||
_glfwPlatformSetCursorMode(window, value);
|
||||
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid cursor mode 0x%08X",
|
||||
value);
|
||||
return;
|
||||
}
|
||||
|
||||
case GLFW_STICKY_KEYS:
|
||||
{
|
||||
if (window->stickyKeys == value)
|
||||
return;
|
||||
|
||||
if (!value)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Release all sticky keys
|
||||
for (i = 0; i <= GLFW_KEY_LAST; i++)
|
||||
{
|
||||
if (window->keys[i] == _GLFW_STICK)
|
||||
window->keys[i] = GLFW_RELEASE;
|
||||
}
|
||||
}
|
||||
|
||||
window->stickyKeys = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
if (window->cursorMode == value)
|
||||
return;
|
||||
}
|
||||
|
||||
case GLFW_STICKY_MOUSE_BUTTONS:
|
||||
{
|
||||
if (window->stickyMouseButtons == value)
|
||||
return;
|
||||
window->cursorMode = value;
|
||||
|
||||
if (!value)
|
||||
{
|
||||
int i;
|
||||
_glfwPlatformGetCursorPos(window,
|
||||
&window->virtualCursorPosX,
|
||||
&window->virtualCursorPosY);
|
||||
|
||||
// Release all sticky mouse buttons
|
||||
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
|
||||
{
|
||||
if (window->mouseButtons[i] == _GLFW_STICK)
|
||||
window->mouseButtons[i] = GLFW_RELEASE;
|
||||
}
|
||||
}
|
||||
|
||||
window->stickyMouseButtons = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
return;
|
||||
}
|
||||
if (_glfwPlatformWindowFocused(window))
|
||||
_glfwPlatformSetCursorMode(window, value);
|
||||
}
|
||||
else if (mode == GLFW_STICKY_KEYS)
|
||||
{
|
||||
value = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
if (window->stickyKeys == value)
|
||||
return;
|
||||
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
|
||||
if (!value)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Release all sticky keys
|
||||
for (i = 0; i <= GLFW_KEY_LAST; i++)
|
||||
{
|
||||
if (window->keys[i] == _GLFW_STICK)
|
||||
window->keys[i] = GLFW_RELEASE;
|
||||
}
|
||||
}
|
||||
|
||||
window->stickyKeys = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
}
|
||||
else if (mode == GLFW_STICKY_MOUSE_BUTTONS)
|
||||
{
|
||||
value = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
if (window->stickyMouseButtons == value)
|
||||
return;
|
||||
|
||||
if (!value)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Release all sticky mouse buttons
|
||||
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
|
||||
{
|
||||
if (window->mouseButtons[i] == _GLFW_STICK)
|
||||
window->mouseButtons[i] = GLFW_RELEASE;
|
||||
}
|
||||
}
|
||||
|
||||
window->stickyMouseButtons = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
}
|
||||
else
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
|
||||
}
|
||||
|
||||
GLFWAPI const char* glfwGetKeyName(int key, int scancode)
|
||||
|
||||
+5
-1
@@ -54,6 +54,8 @@
|
||||
#define _GLFW_POLL_BUTTONS 2
|
||||
#define _GLFW_POLL_ALL (_GLFW_POLL_AXES | _GLFW_POLL_BUTTONS)
|
||||
|
||||
#define _GLFW_MESSAGE_SIZE 1024
|
||||
|
||||
typedef int GLFWbool;
|
||||
|
||||
typedef struct _GLFWerror _GLFWerror;
|
||||
@@ -188,6 +190,8 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
|
||||
#include "mir_platform.h"
|
||||
#elif defined(_GLFW_OSMESA)
|
||||
#include "null_platform.h"
|
||||
#elif defined(_GLFW_EGLDEVICE)
|
||||
#include "egldevice_platform.h"
|
||||
#else
|
||||
#error "No supported window creation API selected"
|
||||
#endif
|
||||
@@ -263,7 +267,7 @@ struct _GLFWerror
|
||||
{
|
||||
_GLFWerror* next;
|
||||
int code;
|
||||
char description[1024];
|
||||
char description[_GLFW_MESSAGE_SIZE];
|
||||
};
|
||||
|
||||
/*! @brief Initialization configuration.
|
||||
|
||||
+13
-26
@@ -266,28 +266,17 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
||||
const char* dirname = "/dev/input";
|
||||
|
||||
_glfw.linjs.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||
if (_glfw.linjs.inotify == -1)
|
||||
if (_glfw.linjs.inotify > 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Linux: Failed to initialize inotify: %s",
|
||||
strerror(errno));
|
||||
return GLFW_FALSE;
|
||||
// HACK: Register for IN_ATTRIB to get notified when udev is done
|
||||
// This works well in practice but the true way is libudev
|
||||
|
||||
_glfw.linjs.watch = inotify_add_watch(_glfw.linjs.inotify,
|
||||
dirname,
|
||||
IN_CREATE | IN_ATTRIB | IN_DELETE);
|
||||
}
|
||||
|
||||
// HACK: Register for IN_ATTRIB as well to get notified when udev is done
|
||||
// This works well in practice but the true way is libudev
|
||||
|
||||
_glfw.linjs.watch = inotify_add_watch(_glfw.linjs.inotify,
|
||||
dirname,
|
||||
IN_CREATE | IN_ATTRIB | IN_DELETE);
|
||||
if (_glfw.linjs.watch == -1)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Linux: Failed to watch for joystick connections in %s: %s",
|
||||
dirname,
|
||||
strerror(errno));
|
||||
// Continue without device connection notifications
|
||||
}
|
||||
// Continue without device connection notifications if inotify fails
|
||||
|
||||
if (regcomp(&_glfw.linjs.regex, "^event[0-9]\\+$", 0) != 0)
|
||||
{
|
||||
@@ -318,13 +307,8 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
||||
closedir(dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Linux: Failed to open joystick device directory %s: %s",
|
||||
dirname,
|
||||
strerror(errno));
|
||||
// Continue with no joysticks detected
|
||||
}
|
||||
|
||||
// Continue with no joysticks if enumeration fails
|
||||
|
||||
qsort(_glfw.joysticks, count, sizeof(_GLFWjoystick), compareJoysticks);
|
||||
return GLFW_TRUE;
|
||||
@@ -359,6 +343,9 @@ void _glfwDetectJoystickConnectionLinux(void)
|
||||
ssize_t offset = 0;
|
||||
char buffer[16384];
|
||||
|
||||
if (_glfw.linjs.inotify <= 0)
|
||||
return;
|
||||
|
||||
const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer));
|
||||
|
||||
while (size > offset)
|
||||
|
||||
@@ -23,6 +23,16 @@
|
||||
// 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:
|
||||
@@ -220,6 +230,7 @@ const char* _glfwDefaultMappings =
|
||||
"03000000100800000300000010010000,USB Gamepad,platform:Linux,a:b2,b:b1,x:b3,y:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,\n"
|
||||
"05000000ac0500003232000001000000,VR-BOX,platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,\n"
|
||||
"03000000780000000600000010010000,Microntek USB Joystick,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftx:a0,lefty:a1,\n"
|
||||
|
||||
"78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
|
||||
"78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
|
||||
"78696e70757403000000000000000000,XInput Arcade Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
//========================================================================
|
||||
// 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,\n"
|
||||
"78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
|
||||
"78696e70757403000000000000000000,XInput Arcade Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
|
||||
"78696e70757404000000000000000000,XInput Flight Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
|
||||
"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
|
||||
"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
|
||||
"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n";
|
||||
|
||||
+1
-1
@@ -231,7 +231,7 @@ const char* _glfwPlatformGetVersionString(void)
|
||||
#else
|
||||
" gettimeofday"
|
||||
#endif
|
||||
" /dev/js"
|
||||
" evdev"
|
||||
#if defined(_GLFW_BUILD_DLL)
|
||||
" shared"
|
||||
#endif
|
||||
|
||||
+2
-1
@@ -869,7 +869,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceMirPresentationSupportKHR vkGetPhysicalDeviceMirPresentationSupportKHR =
|
||||
PFN_vkGetPhysicalDeviceMirPresentationSupportKHR
|
||||
vkGetPhysicalDeviceMirPresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceMirPresentationSupportKHR)
|
||||
|
||||
@@ -113,7 +113,9 @@ GLFWbool _glfwInitOSMesa(void)
|
||||
int i;
|
||||
const char* sonames[] =
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
#if defined(_GLFW_OSMESA_LIBRARY)
|
||||
_GLFW_OSMESA_LIBRARY,
|
||||
#elif defined(_WIN32)
|
||||
"libOSMesa.dll",
|
||||
"OSMesa.dll",
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
+3
-1
@@ -49,7 +49,9 @@ GLFWbool _glfwInitVulkan(int mode)
|
||||
return GLFW_TRUE;
|
||||
|
||||
#if !defined(_GLFW_VULKAN_STATIC)
|
||||
#if defined(_GLFW_WIN32)
|
||||
#if defined(_GLFW_VULKAN_LIBRARY)
|
||||
_glfw.vk.handle = _glfw_dlopen(_GLFW_VULKAN_LIBRARY);
|
||||
#elif defined(_GLFW_WIN32)
|
||||
_glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
|
||||
#elif defined(_GLFW_COCOA)
|
||||
_glfw.vk.handle = _glfw_dlopen("libMoltenVK.dylib");
|
||||
|
||||
+8
-8
@@ -233,15 +233,15 @@ static int choosePixelFormat(_GLFWwindow* window,
|
||||
//
|
||||
static GLFWbool isCompositionEnabled(void)
|
||||
{
|
||||
BOOL enabled;
|
||||
if (_glfw.win32.dwmapi.instance)
|
||||
{
|
||||
BOOL enabled;
|
||||
|
||||
if (!_glfw_DwmIsCompositionEnabled)
|
||||
return FALSE;
|
||||
if (DwmIsCompositionEnabled(&enabled) == S_OK)
|
||||
return enabled;
|
||||
}
|
||||
|
||||
if (_glfw_DwmIsCompositionEnabled(&enabled) != S_OK)
|
||||
return FALSE;
|
||||
|
||||
return enabled;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void makeContextCurrentWGL(_GLFWwindow* window)
|
||||
@@ -276,7 +276,7 @@ static void swapBuffersWGL(_GLFWwindow* window)
|
||||
{
|
||||
int count = abs(window->context.wgl.interval);
|
||||
while (count--)
|
||||
_glfw_DwmFlush();
|
||||
DwmFlush();
|
||||
}
|
||||
|
||||
SwapBuffers(window->context.wgl.dc);
|
||||
|
||||
+75
-17
@@ -30,7 +30,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
|
||||
static const GUID _glfw_GUID_DEVINTERFACE_HID = {0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}};
|
||||
static const GUID _glfw_GUID_DEVINTERFACE_HID =
|
||||
{0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}};
|
||||
|
||||
#define GUID_DEVINTERFACE_HID _glfw_GUID_DEVINTERFACE_HID
|
||||
|
||||
@@ -68,7 +69,8 @@ static GLFWbool loadLibraries(void)
|
||||
_glfw.win32.winmm.instance = LoadLibraryA("winmm.dll");
|
||||
if (!_glfw.win32.winmm.instance)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to load winmm.dll");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to load winmm.dll");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
@@ -78,7 +80,8 @@ static GLFWbool loadLibraries(void)
|
||||
_glfw.win32.user32.instance = LoadLibraryA("user32.dll");
|
||||
if (!_glfw.win32.user32.instance)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to load user32.dll");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to load user32.dll");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
@@ -124,9 +127,9 @@ static GLFWbool loadLibraries(void)
|
||||
_glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
|
||||
if (_glfw.win32.dwmapi.instance)
|
||||
{
|
||||
_glfw.win32.dwmapi.DwmIsCompositionEnabled = (PFN_DwmIsCompositionEnabled)
|
||||
_glfw.win32.dwmapi.IsCompositionEnabled = (PFN_DwmIsCompositionEnabled)
|
||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
|
||||
_glfw.win32.dwmapi.DwmFlush = (PFN_DwmFlush)
|
||||
_glfw.win32.dwmapi.Flush = (PFN_DwmFlush)
|
||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
|
||||
}
|
||||
|
||||
@@ -357,19 +360,19 @@ static HWND createHelperWindow(void)
|
||||
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
|
||||
{
|
||||
WCHAR* target;
|
||||
int length;
|
||||
int count;
|
||||
|
||||
length = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
|
||||
if (!length)
|
||||
count = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
|
||||
if (!count)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert string from UTF-8");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
target = calloc(length, sizeof(WCHAR));
|
||||
target = calloc(count, sizeof(WCHAR));
|
||||
|
||||
if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, length))
|
||||
if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, count))
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert string from UTF-8");
|
||||
@@ -385,19 +388,19 @@ WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
|
||||
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
|
||||
{
|
||||
char* target;
|
||||
int length;
|
||||
int size;
|
||||
|
||||
length = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
|
||||
if (!length)
|
||||
size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
|
||||
if (!size)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert string to UTF-8");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
target = calloc(length, 1);
|
||||
target = calloc(size, 1);
|
||||
|
||||
if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, length, NULL, NULL))
|
||||
if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL))
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert string to UTF-8");
|
||||
@@ -412,8 +415,8 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
|
||||
//
|
||||
void _glfwInputErrorWin32(int error, const char* description)
|
||||
{
|
||||
WCHAR buffer[1024] = L"";
|
||||
char message[2048] = "";
|
||||
WCHAR buffer[_GLFW_MESSAGE_SIZE] = L"";
|
||||
char message[_GLFW_MESSAGE_SIZE] = "";
|
||||
|
||||
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||
@@ -429,6 +432,60 @@ void _glfwInputErrorWin32(int error, const char* description)
|
||||
_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 //////
|
||||
@@ -448,6 +505,7 @@ int _glfwPlatformInit(void)
|
||||
return GLFW_FALSE;
|
||||
|
||||
createKeyTables();
|
||||
_glfwUpdateKeyNamesWin32();
|
||||
|
||||
if (_glfw_SetProcessDpiAwareness)
|
||||
_glfw_SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||
|
||||
+32
-41
@@ -50,16 +50,26 @@ typedef struct _GLFWobjenumWin32
|
||||
|
||||
// Define local copies of the necessary GUIDs
|
||||
//
|
||||
static const GUID _glfw_IID_IDirectInput8W = {0xbf798031,0x483a,0x4da2,{0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00}};
|
||||
static const GUID _glfw_GUID_XAxis = {0xa36d02e0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_YAxis = {0xa36d02e1,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_ZAxis = {0xa36d02e2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_RxAxis = {0xa36d02f4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_RyAxis = {0xa36d02f5,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_RzAxis = {0xa36d02e3,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_Slider = {0xa36d02e4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_Button = {0xa36d02f0,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}};
|
||||
static const GUID _glfw_IID_IDirectInput8W =
|
||||
{0xbf798031,0x483a,0x4da2,{0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00}};
|
||||
static const GUID _glfw_GUID_XAxis =
|
||||
{0xa36d02e0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_YAxis =
|
||||
{0xa36d02e1,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_ZAxis =
|
||||
{0xa36d02e2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_RxAxis =
|
||||
{0xa36d02f4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_RyAxis =
|
||||
{0xa36d02f5,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_RzAxis =
|
||||
{0xa36d02e3,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_Slider =
|
||||
{0xa36d02e4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_Button =
|
||||
{0xa36d02f0,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
|
||||
@@ -345,10 +355,12 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (!_glfw.joysticks[jid].present)
|
||||
continue;
|
||||
if (memcmp(&_glfw.joysticks[jid].win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||
return DIENUM_CONTINUE;
|
||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||
if (js->present)
|
||||
{
|
||||
if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (supportsXInput(&di->guidProduct))
|
||||
@@ -675,7 +687,6 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
int i, dpad = 0;
|
||||
DWORD result;
|
||||
XINPUT_STATE xis;
|
||||
float axes[6] = { 0.f, 0.f, 0.f, 0.f, -1.f, -1.f };
|
||||
const WORD buttons[10] =
|
||||
{
|
||||
XINPUT_GAMEPAD_A,
|
||||
@@ -702,32 +713,12 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
if (mode == _GLFW_POLL_PRESENCE)
|
||||
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)
|
||||
{
|
||||
axes[0] = (xis.Gamepad.sThumbLX + 0.5f) / 32767.f;
|
||||
axes[1] = (xis.Gamepad.sThumbLY + 0.5f) / 32767.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)
|
||||
{
|
||||
axes[2] = (xis.Gamepad.sThumbRX + 0.5f) / 32767.f;
|
||||
axes[3] = (xis.Gamepad.sThumbRY + 0.5f) / 32767.f;
|
||||
}
|
||||
|
||||
if (xis.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||
axes[4] = xis.Gamepad.bLeftTrigger / 127.5f - 1.f;
|
||||
|
||||
if (xis.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||
axes[5] = xis.Gamepad.bRightTrigger / 127.5f - 1.f;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
_glfwInputJoystickAxis(js, i, axes[i]);
|
||||
_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++)
|
||||
{
|
||||
|
||||
+48
-16
@@ -33,6 +33,27 @@
|
||||
#include <malloc.h>
|
||||
|
||||
|
||||
// Callback for EnumDisplayMonitors in createMonitor
|
||||
//
|
||||
static BOOL CALLBACK monitorCallback(HMONITOR handle,
|
||||
HDC dc,
|
||||
RECT* rect,
|
||||
LPARAM data)
|
||||
{
|
||||
MONITORINFOEXW mi;
|
||||
ZeroMemory(&mi, sizeof(mi));
|
||||
mi.cbSize = sizeof(mi);
|
||||
|
||||
if (GetMonitorInfoW(handle, (MONITORINFO*) &mi))
|
||||
{
|
||||
_GLFWmonitor* monitor = (_GLFWmonitor*) data;
|
||||
if (wcscmp(mi.szDevice, monitor->win32.adapterName) == 0)
|
||||
monitor->win32.handle = handle;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Create monitor from an adapter and (optionally) a display
|
||||
//
|
||||
static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
||||
@@ -41,6 +62,8 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
||||
_GLFWmonitor* monitor;
|
||||
char* name;
|
||||
HDC dc;
|
||||
DEVMODEW dm;
|
||||
RECT rect;
|
||||
|
||||
if (display)
|
||||
name = _glfwCreateUTF8FromWideStringWin32(display->DeviceString);
|
||||
@@ -78,6 +101,16 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
ZeroMemory(&dm, sizeof(dm));
|
||||
dm.dmSize = sizeof(dm);
|
||||
EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -109,8 +142,8 @@ void _glfwPollMonitorsWin32(void)
|
||||
{
|
||||
int type = _GLFW_INSERT_LAST;
|
||||
|
||||
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
|
||||
adapter.cb = sizeof(DISPLAY_DEVICEW);
|
||||
ZeroMemory(&adapter, sizeof(adapter));
|
||||
adapter.cb = sizeof(adapter);
|
||||
|
||||
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
|
||||
break;
|
||||
@@ -123,8 +156,8 @@ void _glfwPollMonitorsWin32(void)
|
||||
|
||||
for (displayIndex = 0; ; displayIndex++)
|
||||
{
|
||||
ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
|
||||
display.cb = sizeof(DISPLAY_DEVICEW);
|
||||
ZeroMemory(&display, sizeof(display));
|
||||
display.cb = sizeof(display);
|
||||
|
||||
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
|
||||
break;
|
||||
@@ -211,7 +244,7 @@ GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desire
|
||||
return GLFW_TRUE;
|
||||
|
||||
ZeroMemory(&dm, sizeof(dm));
|
||||
dm.dmSize = sizeof(DEVMODEW);
|
||||
dm.dmSize = sizeof(dm);
|
||||
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL |
|
||||
DM_DISPLAYFREQUENCY;
|
||||
dm.dmPelsWidth = best->width;
|
||||
@@ -276,19 +309,19 @@ void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor)
|
||||
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
{
|
||||
DEVMODEW settings;
|
||||
ZeroMemory(&settings, sizeof(DEVMODEW));
|
||||
settings.dmSize = sizeof(DEVMODEW);
|
||||
DEVMODEW dm;
|
||||
ZeroMemory(&dm, sizeof(dm));
|
||||
dm.dmSize = sizeof(dm);
|
||||
|
||||
EnumDisplaySettingsExW(monitor->win32.adapterName,
|
||||
ENUM_CURRENT_SETTINGS,
|
||||
&settings,
|
||||
&dm,
|
||||
EDS_ROTATEDMODE);
|
||||
|
||||
if (xpos)
|
||||
*xpos = settings.dmPosition.x;
|
||||
*xpos = dm.dmPosition.x;
|
||||
if (ypos)
|
||||
*ypos = settings.dmPosition.y;
|
||||
*ypos = dm.dmPosition.y;
|
||||
}
|
||||
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||
@@ -304,8 +337,8 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||
GLFWvidmode mode;
|
||||
DEVMODEW dm;
|
||||
|
||||
ZeroMemory(&dm, sizeof(DEVMODEW));
|
||||
dm.dmSize = sizeof(DEVMODEW);
|
||||
ZeroMemory(&dm, sizeof(dm));
|
||||
dm.dmSize = sizeof(dm);
|
||||
|
||||
if (!EnumDisplaySettingsW(monitor->win32.adapterName, modeIndex, &dm))
|
||||
break;
|
||||
@@ -371,9 +404,8 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||
{
|
||||
DEVMODEW dm;
|
||||
|
||||
ZeroMemory(&dm, sizeof(DEVMODEW));
|
||||
dm.dmSize = sizeof(DEVMODEW);
|
||||
ZeroMemory(&dm, sizeof(dm));
|
||||
dm.dmSize = sizeof(dm);
|
||||
|
||||
EnumDisplaySettingsW(monitor->win32.adapterName, ENUM_CURRENT_SETTINGS, &dm);
|
||||
|
||||
|
||||
@@ -63,7 +63,6 @@
|
||||
|
||||
#include <wctype.h>
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#include <dinput.h>
|
||||
#include <xinput.h>
|
||||
#include <dbt.h>
|
||||
@@ -180,8 +179,8 @@ typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,PCHANGEF
|
||||
// dwmapi.dll function pointer typedefs
|
||||
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
||||
typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
|
||||
#define _glfw_DwmIsCompositionEnabled _glfw.win32.dwmapi.DwmIsCompositionEnabled
|
||||
#define _glfw_DwmFlush _glfw.win32.dwmapi.DwmFlush
|
||||
#define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled
|
||||
#define DwmFlush _glfw.win32.dwmapi.Flush
|
||||
|
||||
// shcore.dll function pointer typedefs
|
||||
typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
|
||||
@@ -233,6 +232,7 @@ typedef struct _GLFWwindowWin32
|
||||
HICON smallIcon;
|
||||
|
||||
GLFWbool cursorTracked;
|
||||
GLFWbool frameAction;
|
||||
GLFWbool iconified;
|
||||
GLFWbool maximized;
|
||||
|
||||
@@ -249,9 +249,9 @@ typedef struct _GLFWlibraryWin32
|
||||
DWORD foregroundLockTimeout;
|
||||
int acquiredMonitorCount;
|
||||
char* clipboardString;
|
||||
char keyName[64];
|
||||
short int keycodes[512];
|
||||
short int scancodes[GLFW_KEY_LAST + 1];
|
||||
char keynames[GLFW_KEY_LAST + 1][5];
|
||||
// Where to place the cursor when re-enabled
|
||||
double restoreCursorPosX, restoreCursorPosY;
|
||||
// The window whose disabled cursor mode is active
|
||||
@@ -284,8 +284,8 @@ typedef struct _GLFWlibraryWin32
|
||||
|
||||
struct {
|
||||
HINSTANCE instance;
|
||||
PFN_DwmIsCompositionEnabled DwmIsCompositionEnabled;
|
||||
PFN_DwmFlush DwmFlush;
|
||||
PFN_DwmIsCompositionEnabled IsCompositionEnabled;
|
||||
PFN_DwmFlush Flush;
|
||||
} dwmapi;
|
||||
|
||||
struct {
|
||||
@@ -299,6 +299,7 @@ typedef struct _GLFWlibraryWin32
|
||||
//
|
||||
typedef struct _GLFWmonitorWin32
|
||||
{
|
||||
HMONITOR handle;
|
||||
// This size matches the static size of DISPLAY_DEVICE.DeviceName
|
||||
WCHAR adapterName[32];
|
||||
WCHAR displayName[32];
|
||||
@@ -351,6 +352,7 @@ void _glfwUnregisterWindowClassWin32(void);
|
||||
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
|
||||
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
|
||||
void _glfwInputErrorWin32(int error, const char* description);
|
||||
void _glfwUpdateKeyNamesWin32(void);
|
||||
|
||||
void _glfwInitTimerWin32(void);
|
||||
|
||||
|
||||
+51
-16
@@ -111,7 +111,7 @@ static HICON createIcon(const GLFWimage* image,
|
||||
unsigned char* source = image->pixels;
|
||||
|
||||
ZeroMemory(&bi, sizeof(bi));
|
||||
bi.bV5Size = sizeof(BITMAPV5HEADER);
|
||||
bi.bV5Size = sizeof(bi);
|
||||
bi.bV5Width = image->width;
|
||||
bi.bV5Height = -image->height;
|
||||
bi.bV5Planes = 1;
|
||||
@@ -495,10 +495,47 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_MOUSEACTIVATE:
|
||||
{
|
||||
// HACK: Postpone cursor disabling when the window was activated by
|
||||
// clicking a caption button
|
||||
if (HIWORD(lParam) == WM_LBUTTONDOWN)
|
||||
{
|
||||
if (LOWORD(lParam) == HTCLOSE ||
|
||||
LOWORD(lParam) == HTMINBUTTON ||
|
||||
LOWORD(lParam) == HTMAXBUTTON)
|
||||
{
|
||||
window->win32.frameAction = GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_CAPTURECHANGED:
|
||||
{
|
||||
// HACK: Disable the cursor once the caption button action has been
|
||||
// completed or cancelled
|
||||
if (lParam == 0 && window->win32.frameAction)
|
||||
{
|
||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED);
|
||||
|
||||
window->win32.frameAction = GLFW_FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_SETFOCUS:
|
||||
{
|
||||
_glfwInputWindowFocus(window, GLFW_TRUE);
|
||||
|
||||
// HACK: Do not disable cursor while the user is interacting with
|
||||
// a caption button
|
||||
if (window->win32.frameAction)
|
||||
break;
|
||||
|
||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED);
|
||||
|
||||
@@ -547,6 +584,12 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_INPUTLANGCHANGE:
|
||||
{
|
||||
_glfwUpdateKeyNamesWin32();
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_CHAR:
|
||||
case WM_SYSCHAR:
|
||||
case WM_UNICHAR:
|
||||
@@ -758,6 +801,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
case WM_ENTERSIZEMOVE:
|
||||
case WM_ENTERMENULOOP:
|
||||
{
|
||||
// HACK: Postpone cursor disabling while the user is moving or
|
||||
// resizing the window or using the menu
|
||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL);
|
||||
|
||||
@@ -767,6 +812,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
case WM_EXITSIZEMOVE:
|
||||
case WM_EXITMENULOOP:
|
||||
{
|
||||
// HACK: Disable the cursor once the user is done moving or
|
||||
// resizing the window or using the menu
|
||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED);
|
||||
|
||||
@@ -1611,20 +1658,7 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
||||
|
||||
const char* _glfwPlatformGetScancodeName(int scancode)
|
||||
{
|
||||
WCHAR name[16];
|
||||
|
||||
if (!GetKeyNameTextW(scancode << 16, name, sizeof(name) / sizeof(WCHAR)))
|
||||
return NULL;
|
||||
|
||||
if (!WideCharToMultiByte(CP_UTF8, 0, name, -1,
|
||||
_glfw.win32.keyName,
|
||||
sizeof(_glfw.win32.keyName),
|
||||
NULL, NULL))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _glfw.win32.keyName;
|
||||
return _glfw.win32.keynames[_glfw.win32.keycodes[scancode]];
|
||||
}
|
||||
|
||||
int _glfwPlatformGetKeyScancode(int key)
|
||||
@@ -1764,7 +1798,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR =
|
||||
PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR
|
||||
vkGetPhysicalDeviceWin32PresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceWin32PresentationSupportKHR)
|
||||
|
||||
+65
-70
@@ -278,119 +278,118 @@ GLFWAPI void glfwWindowHint(int hint, int value)
|
||||
{
|
||||
case GLFW_RED_BITS:
|
||||
_glfw.hints.framebuffer.redBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_GREEN_BITS:
|
||||
_glfw.hints.framebuffer.greenBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_BLUE_BITS:
|
||||
_glfw.hints.framebuffer.blueBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_ALPHA_BITS:
|
||||
_glfw.hints.framebuffer.alphaBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_DEPTH_BITS:
|
||||
_glfw.hints.framebuffer.depthBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_STENCIL_BITS:
|
||||
_glfw.hints.framebuffer.stencilBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_ACCUM_RED_BITS:
|
||||
_glfw.hints.framebuffer.accumRedBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_ACCUM_GREEN_BITS:
|
||||
_glfw.hints.framebuffer.accumGreenBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_ACCUM_BLUE_BITS:
|
||||
_glfw.hints.framebuffer.accumBlueBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_ACCUM_ALPHA_BITS:
|
||||
_glfw.hints.framebuffer.accumAlphaBits = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_AUX_BUFFERS:
|
||||
_glfw.hints.framebuffer.auxBuffers = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_STEREO:
|
||||
_glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_DOUBLEBUFFER:
|
||||
_glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_SAMPLES:
|
||||
_glfw.hints.framebuffer.samples = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_SRGB_CAPABLE:
|
||||
_glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_RESIZABLE:
|
||||
_glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_DECORATED:
|
||||
_glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_FOCUSED:
|
||||
_glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_AUTO_ICONIFY:
|
||||
_glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_FLOATING:
|
||||
_glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_MAXIMIZED:
|
||||
_glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_VISIBLE:
|
||||
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_COCOA_RETINA_FRAMEBUFFER:
|
||||
_glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_COCOA_FRAME_AUTOSAVE:
|
||||
_glfw.hints.window.ns.frame = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_COCOA_GRAPHICS_SWITCHING:
|
||||
_glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_CENTER_CURSOR:
|
||||
_glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_CLIENT_API:
|
||||
_glfw.hints.context.client = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_CONTEXT_CREATION_API:
|
||||
_glfw.hints.context.source = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_CONTEXT_VERSION_MAJOR:
|
||||
_glfw.hints.context.major = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_CONTEXT_VERSION_MINOR:
|
||||
_glfw.hints.context.minor = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_CONTEXT_ROBUSTNESS:
|
||||
_glfw.hints.context.robustness = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_OPENGL_FORWARD_COMPAT:
|
||||
_glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_OPENGL_DEBUG_CONTEXT:
|
||||
_glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_CONTEXT_NO_ERROR:
|
||||
_glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
return;
|
||||
case GLFW_OPENGL_PROFILE:
|
||||
_glfw.hints.context.profile = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_CONTEXT_RELEASE_BEHAVIOR:
|
||||
_glfw.hints.context.release = value;
|
||||
break;
|
||||
return;
|
||||
case GLFW_REFRESH_RATE:
|
||||
_glfw.hints.refreshRate = value;
|
||||
break;
|
||||
default:
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
|
||||
@@ -770,41 +769,37 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
|
||||
|
||||
value = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
|
||||
switch (attrib)
|
||||
if (attrib == GLFW_AUTO_ICONIFY)
|
||||
window->autoIconify = value;
|
||||
else if (attrib == GLFW_RESIZABLE)
|
||||
{
|
||||
case GLFW_RESIZABLE:
|
||||
if (window->resizable != value)
|
||||
{
|
||||
window->resizable = value;
|
||||
if (!window->monitor)
|
||||
_glfwPlatformSetWindowResizable(window, value);
|
||||
}
|
||||
if (window->resizable == value)
|
||||
return;
|
||||
|
||||
case GLFW_DECORATED:
|
||||
if (window->decorated != value)
|
||||
{
|
||||
window->decorated = value;
|
||||
if (!window->monitor)
|
||||
_glfwPlatformSetWindowDecorated(window, value);
|
||||
}
|
||||
return;
|
||||
|
||||
case GLFW_FLOATING:
|
||||
if (window->floating != value)
|
||||
{
|
||||
window->floating = value;
|
||||
if (!window->monitor)
|
||||
_glfwPlatformSetWindowFloating(window, value);
|
||||
}
|
||||
return;
|
||||
|
||||
case GLFW_AUTO_ICONIFY:
|
||||
window->autoIconify = value;
|
||||
return;
|
||||
window->resizable = value;
|
||||
if (!window->monitor)
|
||||
_glfwPlatformSetWindowResizable(window, value);
|
||||
}
|
||||
else if (attrib == GLFW_DECORATED)
|
||||
{
|
||||
if (window->decorated == value)
|
||||
return;
|
||||
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
|
||||
window->decorated = value;
|
||||
if (!window->monitor)
|
||||
_glfwPlatformSetWindowDecorated(window, value);
|
||||
}
|
||||
else if (attrib == GLFW_FLOATING)
|
||||
{
|
||||
if (window->floating == value)
|
||||
return;
|
||||
|
||||
window->floating = value;
|
||||
if (!window->monitor)
|
||||
_glfwPlatformSetWindowFloating(window, value);
|
||||
}
|
||||
else
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
|
||||
}
|
||||
|
||||
GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle)
|
||||
|
||||
+2
-2
@@ -294,7 +294,7 @@ static int toGLFWKeyCode(uint32_t key)
|
||||
|
||||
static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
|
||||
{
|
||||
if (sym == XKB_KEY_NoSymbol)
|
||||
if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
|
||||
return sym;
|
||||
if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym)
|
||||
!= XKB_COMPOSE_FEED_ACCEPTED)
|
||||
@@ -737,7 +737,7 @@ const char* _glfwPlatformGetVersionString(void)
|
||||
#else
|
||||
" gettimeofday"
|
||||
#endif
|
||||
" /dev/js"
|
||||
" evdev"
|
||||
#if defined(_GLFW_BUILD_DLL)
|
||||
" shared"
|
||||
#endif
|
||||
|
||||
+2
-1
@@ -1019,7 +1019,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR =
|
||||
PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
|
||||
vkGetPhysicalDeviceWaylandPresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceWaylandPresentationSupportKHR)
|
||||
|
||||
+121
-36
@@ -237,8 +237,8 @@ static void createKeyTables(void)
|
||||
|
||||
if (_glfw.x11.xkb.available)
|
||||
{
|
||||
// Use XKB to determine physical key locations independently of the current
|
||||
// keyboard layout
|
||||
// Use XKB to determine physical key locations independently of the
|
||||
// current keyboard layout
|
||||
|
||||
char name[XkbKeyNameLength + 1];
|
||||
XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd);
|
||||
@@ -505,22 +505,63 @@ static GLFWbool initExtensions(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (XRRQueryExtension(_glfw.x11.display,
|
||||
&_glfw.x11.randr.eventBase,
|
||||
&_glfw.x11.randr.errorBase))
|
||||
_glfw.x11.randr.handle = dlopen("libXrandr.so.2", RTLD_LAZY | RTLD_GLOBAL);
|
||||
if (_glfw.x11.randr.handle)
|
||||
{
|
||||
if (XRRQueryVersion(_glfw.x11.display,
|
||||
&_glfw.x11.randr.major,
|
||||
&_glfw.x11.randr.minor))
|
||||
_glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRAllocGamma");
|
||||
_glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
|
||||
_glfw.x11.randr.FreeCrtcInfo = (PFN_XRRFreeCrtcInfo)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRFreeCrtcInfo");
|
||||
_glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
|
||||
_glfw.x11.randr.FreeOutputInfo = (PFN_XRRFreeOutputInfo)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRFreeOutputInfo");
|
||||
_glfw.x11.randr.FreeScreenResources = (PFN_XRRFreeScreenResources)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRFreeScreenResources");
|
||||
_glfw.x11.randr.GetCrtcGamma = (PFN_XRRGetCrtcGamma)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGamma");
|
||||
_glfw.x11.randr.GetCrtcGammaSize = (PFN_XRRGetCrtcGammaSize)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize");
|
||||
_glfw.x11.randr.GetCrtcInfo = (PFN_XRRGetCrtcInfo)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRGetCrtcInfo");
|
||||
_glfw.x11.randr.GetOutputInfo = (PFN_XRRGetOutputInfo)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRGetOutputInfo");
|
||||
_glfw.x11.randr.GetOutputPrimary = (PFN_XRRGetOutputPrimary)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRGetOutputPrimary");
|
||||
_glfw.x11.randr.GetScreenResourcesCurrent = (PFN_XRRGetScreenResourcesCurrent)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent");
|
||||
_glfw.x11.randr.QueryExtension = (PFN_XRRQueryExtension)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRQueryExtension");
|
||||
_glfw.x11.randr.QueryVersion = (PFN_XRRQueryVersion)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRQueryVersion");
|
||||
_glfw.x11.randr.SelectInput = (PFN_XRRSelectInput)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRSelectInput");
|
||||
_glfw.x11.randr.SetCrtcConfig = (PFN_XRRSetCrtcConfig)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRSetCrtcConfig");
|
||||
_glfw.x11.randr.SetCrtcGamma = (PFN_XRRSetCrtcGamma)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRSetCrtcGamma");
|
||||
_glfw.x11.randr.UpdateConfiguration = (PFN_XRRUpdateConfiguration)
|
||||
dlsym(_glfw.x11.randr.handle, "XRRUpdateConfiguration");
|
||||
|
||||
if (XRRQueryExtension(_glfw.x11.display,
|
||||
&_glfw.x11.randr.eventBase,
|
||||
&_glfw.x11.randr.errorBase))
|
||||
{
|
||||
// The GLFW RandR path requires at least version 1.3
|
||||
if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3)
|
||||
_glfw.x11.randr.available = GLFW_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to query RandR version");
|
||||
if (XRRQueryVersion(_glfw.x11.display,
|
||||
&_glfw.x11.randr.major,
|
||||
&_glfw.x11.randr.minor))
|
||||
{
|
||||
// The GLFW RandR path requires at least version 1.3
|
||||
if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3)
|
||||
_glfw.x11.randr.available = GLFW_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to query RandR version");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,12 +593,34 @@ static GLFWbool initExtensions(void)
|
||||
RROutputChangeNotifyMask);
|
||||
}
|
||||
|
||||
if (XineramaQueryExtension(_glfw.x11.display,
|
||||
&_glfw.x11.xinerama.major,
|
||||
&_glfw.x11.xinerama.minor))
|
||||
_glfw.x11.xcursor.handle = dlopen("libXcursor.so.1", RTLD_LAZY | RTLD_GLOBAL);
|
||||
if (_glfw.x11.xcursor.handle)
|
||||
{
|
||||
if (XineramaIsActive(_glfw.x11.display))
|
||||
_glfw.x11.xinerama.available = GLFW_TRUE;
|
||||
_glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate)
|
||||
dlsym(_glfw.x11.xcursor.handle, "XcursorImageCreate");
|
||||
_glfw.x11.xcursor.ImageDestroy = (PFN_XcursorImageDestroy)
|
||||
dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy");
|
||||
_glfw.x11.xcursor.ImageLoadCursor = (PFN_XcursorImageLoadCursor)
|
||||
dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor");
|
||||
}
|
||||
|
||||
_glfw.x11.xinerama.handle = dlopen("libXinerama.so.1", RTLD_LAZY | RTLD_GLOBAL);
|
||||
if (_glfw.x11.xinerama.handle)
|
||||
{
|
||||
_glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive)
|
||||
dlsym(_glfw.x11.xinerama.handle, "XineramaIsActive");
|
||||
_glfw.x11.xinerama.QueryExtension = (PFN_XineramaQueryExtension)
|
||||
dlsym(_glfw.x11.xinerama.handle, "XineramaQueryExtension");
|
||||
_glfw.x11.xinerama.QueryScreens = (PFN_XineramaQueryScreens)
|
||||
dlsym(_glfw.x11.xinerama.handle, "XineramaQueryScreens");
|
||||
|
||||
if (XineramaQueryExtension(_glfw.x11.display,
|
||||
&_glfw.x11.xinerama.major,
|
||||
&_glfw.x11.xinerama.minor))
|
||||
{
|
||||
if (XineramaIsActive(_glfw.x11.display))
|
||||
_glfw.x11.xinerama.available = GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
_glfw.x11.xkb.major = 1;
|
||||
@@ -584,7 +647,7 @@ static GLFWbool initExtensions(void)
|
||||
_glfw.x11.x11xcb.handle = dlopen("libX11-xcb.so.1", RTLD_LAZY | RTLD_GLOBAL);
|
||||
if (_glfw.x11.x11xcb.handle)
|
||||
{
|
||||
_glfw.x11.x11xcb.XGetXCBConnection = (PFN_XGetXCBConnection)
|
||||
_glfw.x11.x11xcb.GetXCBConnection = (PFN_XGetXCBConnection)
|
||||
dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection");
|
||||
}
|
||||
|
||||
@@ -598,10 +661,7 @@ static GLFWbool initExtensions(void)
|
||||
|
||||
// String format atoms
|
||||
_glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False);
|
||||
_glfw.x11.UTF8_STRING =
|
||||
XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
|
||||
_glfw.x11.COMPOUND_STRING =
|
||||
XInternAtom(_glfw.x11.display, "COMPOUND_STRING", False);
|
||||
_glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
|
||||
_glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False);
|
||||
|
||||
// Custom selection property atom
|
||||
@@ -611,6 +671,8 @@ static GLFWbool initExtensions(void)
|
||||
// ICCCM standard clipboard atoms
|
||||
_glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False);
|
||||
_glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False);
|
||||
_glfw.x11.PRIMARY = XInternAtom(_glfw.x11.display, "PRIMARY", False);
|
||||
_glfw.x11.INCR = XInternAtom(_glfw.x11.display, "INCR", False);
|
||||
_glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False);
|
||||
|
||||
// Clipboard manager atoms
|
||||
@@ -715,7 +777,7 @@ void _glfwReleaseErrorHandlerX11(void)
|
||||
//
|
||||
void _glfwInputErrorX11(int error, const char* message)
|
||||
{
|
||||
char buffer[8192];
|
||||
char buffer[_GLFW_MESSAGE_SIZE];
|
||||
XGetErrorText(_glfw.x11.display, _glfw.x11.errorCode,
|
||||
buffer, sizeof(buffer));
|
||||
|
||||
@@ -729,6 +791,9 @@ Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot)
|
||||
int i;
|
||||
Cursor cursor;
|
||||
|
||||
if (!_glfw.x11.xcursor.handle)
|
||||
return None;
|
||||
|
||||
XcursorImage* native = XcursorImageCreate(image->width, image->height);
|
||||
if (native == NULL)
|
||||
return None;
|
||||
@@ -795,12 +860,13 @@ int _glfwPlatformInit(void)
|
||||
_glfw.x11.screen = DefaultScreen(_glfw.x11.display);
|
||||
_glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen);
|
||||
_glfw.x11.context = XUniqueContext();
|
||||
_glfw.x11.helperWindowHandle = createHelperWindow();
|
||||
_glfw.x11.hiddenCursorHandle = createHiddenCursor();
|
||||
|
||||
if (!initExtensions())
|
||||
return GLFW_FALSE;
|
||||
|
||||
_glfw.x11.helperWindowHandle = createHelperWindow();
|
||||
_glfw.x11.hiddenCursorHandle = createHiddenCursor();
|
||||
|
||||
if (XSupportsLocale())
|
||||
{
|
||||
XSetLocaleModifiers("");
|
||||
@@ -829,12 +895,6 @@ int _glfwPlatformInit(void)
|
||||
|
||||
void _glfwPlatformTerminate(void)
|
||||
{
|
||||
if (_glfw.x11.x11xcb.handle)
|
||||
{
|
||||
dlclose(_glfw.x11.x11xcb.handle);
|
||||
_glfw.x11.x11xcb.handle = NULL;
|
||||
}
|
||||
|
||||
if (_glfw.x11.helperWindowHandle)
|
||||
{
|
||||
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) ==
|
||||
@@ -853,6 +913,7 @@ void _glfwPlatformTerminate(void)
|
||||
_glfw.x11.hiddenCursorHandle = (Cursor) 0;
|
||||
}
|
||||
|
||||
free(_glfw.x11.primarySelectionString);
|
||||
free(_glfw.x11.clipboardString);
|
||||
|
||||
if (_glfw.x11.im)
|
||||
@@ -869,6 +930,30 @@ void _glfwPlatformTerminate(void)
|
||||
_glfw.x11.display = NULL;
|
||||
}
|
||||
|
||||
if (_glfw.x11.x11xcb.handle)
|
||||
{
|
||||
dlclose(_glfw.x11.x11xcb.handle);
|
||||
_glfw.x11.x11xcb.handle = NULL;
|
||||
}
|
||||
|
||||
if (_glfw.x11.xcursor.handle)
|
||||
{
|
||||
dlclose(_glfw.x11.xcursor.handle);
|
||||
_glfw.x11.xcursor.handle = NULL;
|
||||
}
|
||||
|
||||
if (_glfw.x11.randr.handle)
|
||||
{
|
||||
dlclose(_glfw.x11.randr.handle);
|
||||
_glfw.x11.randr.handle = NULL;
|
||||
}
|
||||
|
||||
if (_glfw.x11.xinerama.handle)
|
||||
{
|
||||
dlclose(_glfw.x11.xinerama.handle);
|
||||
_glfw.x11.xinerama.handle = NULL;
|
||||
}
|
||||
|
||||
// NOTE: This needs to be done after XCloseDisplay, as libGL registers
|
||||
// cleanup callbacks that get called by it
|
||||
_glfwTerminateGLX();
|
||||
@@ -887,7 +972,7 @@ const char* _glfwPlatformGetVersionString(void)
|
||||
" gettimeofday"
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
" /dev/js"
|
||||
" evdev"
|
||||
#endif
|
||||
#if defined(_GLFW_BUILD_DLL)
|
||||
" shared"
|
||||
|
||||
+84
-1
@@ -47,10 +47,60 @@
|
||||
// The XInput extension provides raw mouse motion input
|
||||
#include <X11/extensions/XInput2.h>
|
||||
|
||||
typedef XRRCrtcGamma* (* PFN_XRRAllocGamma)(int);
|
||||
typedef void (* PFN_XRRFreeCrtcInfo)(XRRCrtcInfo*);
|
||||
typedef void (* PFN_XRRFreeGamma)(XRRCrtcGamma*);
|
||||
typedef void (* PFN_XRRFreeOutputInfo)(XRROutputInfo*);
|
||||
typedef void (* PFN_XRRFreeScreenResources)(XRRScreenResources*);
|
||||
typedef XRRCrtcGamma* (* PFN_XRRGetCrtcGamma)(Display*,RRCrtc);
|
||||
typedef int (* PFN_XRRGetCrtcGammaSize)(Display*,RRCrtc);
|
||||
typedef XRRCrtcInfo* (* PFN_XRRGetCrtcInfo) (Display*,XRRScreenResources*,RRCrtc);
|
||||
typedef XRROutputInfo* (* PFN_XRRGetOutputInfo)(Display*,XRRScreenResources*,RROutput);
|
||||
typedef RROutput (* PFN_XRRGetOutputPrimary)(Display*,Window);
|
||||
typedef XRRScreenResources* (* PFN_XRRGetScreenResourcesCurrent)(Display*,Window);
|
||||
typedef Bool (* PFN_XRRQueryExtension)(Display*,int*,int*);
|
||||
typedef Status (* PFN_XRRQueryVersion)(Display*,int*,int*);
|
||||
typedef void (* PFN_XRRSelectInput)(Display*,Window,int);
|
||||
typedef Status (* PFN_XRRSetCrtcConfig)(Display*,XRRScreenResources*,RRCrtc,Time,int,int,RRMode,Rotation,RROutput*,int);
|
||||
typedef void (* PFN_XRRSetCrtcGamma)(Display*,RRCrtc,XRRCrtcGamma*);
|
||||
typedef int (* PFN_XRRUpdateConfiguration)(XEvent*);
|
||||
#define XRRAllocGamma _glfw.x11.randr.AllocGamma
|
||||
#define XRRFreeCrtcInfo _glfw.x11.randr.FreeCrtcInfo
|
||||
#define XRRFreeGamma _glfw.x11.randr.FreeGamma
|
||||
#define XRRFreeOutputInfo _glfw.x11.randr.FreeOutputInfo
|
||||
#define XRRFreeScreenResources _glfw.x11.randr.FreeScreenResources
|
||||
#define XRRGetCrtcGamma _glfw.x11.randr.GetCrtcGamma
|
||||
#define XRRGetCrtcGammaSize _glfw.x11.randr.GetCrtcGammaSize
|
||||
#define XRRGetCrtcInfo _glfw.x11.randr.GetCrtcInfo
|
||||
#define XRRGetOutputInfo _glfw.x11.randr.GetOutputInfo
|
||||
#define XRRGetOutputPrimary _glfw.x11.randr.GetOutputPrimary
|
||||
#define XRRGetScreenResourcesCurrent _glfw.x11.randr.GetScreenResourcesCurrent
|
||||
#define XRRQueryExtension _glfw.x11.randr.QueryExtension
|
||||
#define XRRQueryVersion _glfw.x11.randr.QueryVersion
|
||||
#define XRRSelectInput _glfw.x11.randr.SelectInput
|
||||
#define XRRSetCrtcConfig _glfw.x11.randr.SetCrtcConfig
|
||||
#define XRRSetCrtcGamma _glfw.x11.randr.SetCrtcGamma
|
||||
#define XRRUpdateConfiguration _glfw.x11.randr.UpdateConfiguration
|
||||
|
||||
typedef XcursorImage* (* PFN_XcursorImageCreate)(int,int);
|
||||
typedef void (* PFN_XcursorImageDestroy)(XcursorImage*);
|
||||
typedef Cursor (* PFN_XcursorImageLoadCursor)(Display*,const XcursorImage*);
|
||||
#define XcursorImageCreate _glfw.x11.xcursor.ImageCreate
|
||||
#define XcursorImageDestroy _glfw.x11.xcursor.ImageDestroy
|
||||
#define XcursorImageLoadCursor _glfw.x11.xcursor.ImageLoadCursor
|
||||
|
||||
typedef Bool (* PFN_XineramaIsActive)(Display*);
|
||||
typedef Bool (* PFN_XineramaQueryExtension)(Display*,int*,int*);
|
||||
typedef XineramaScreenInfo* (* PFN_XineramaQueryScreens)(Display*,int*);
|
||||
#define XineramaIsActive _glfw.x11.xinerama.IsActive
|
||||
#define XineramaQueryExtension _glfw.x11.xinerama.QueryExtension
|
||||
#define XineramaQueryScreens _glfw.x11.xinerama.QueryScreens
|
||||
|
||||
typedef XID xcb_window_t;
|
||||
typedef XID xcb_visualid_t;
|
||||
typedef struct xcb_connection_t xcb_connection_t;
|
||||
typedef xcb_connection_t* (* PFN_XGetXCBConnection)(Display*);
|
||||
#define XGetXCBConnection _glfw.x11.x11xcb.GetXCBConnection
|
||||
|
||||
typedef Bool (* PFN_XF86VidModeQueryExtension)(Display*,int*,int*);
|
||||
typedef Bool (* PFN_XF86VidModeGetGammaRamp)(Display*,int,int,unsigned short*,unsigned short*,unsigned short*);
|
||||
@@ -161,6 +211,8 @@ typedef struct _GLFWlibraryX11
|
||||
XIM im;
|
||||
// Most recent error code received by X error handler
|
||||
int errorCode;
|
||||
// Primary selection string (while the primary selection is owned)
|
||||
char* primarySelectionString;
|
||||
// Clipboard string (while the selection is owned)
|
||||
char* clipboardString;
|
||||
// Key name string
|
||||
@@ -213,7 +265,9 @@ typedef struct _GLFWlibraryX11
|
||||
// Selection (clipboard) atoms
|
||||
Atom TARGETS;
|
||||
Atom MULTIPLE;
|
||||
Atom INCR;
|
||||
Atom CLIPBOARD;
|
||||
Atom PRIMARY;
|
||||
Atom CLIPBOARD_MANAGER;
|
||||
Atom SAVE_TARGETS;
|
||||
Atom NULL_;
|
||||
@@ -224,12 +278,30 @@ typedef struct _GLFWlibraryX11
|
||||
|
||||
struct {
|
||||
GLFWbool available;
|
||||
void* handle;
|
||||
int eventBase;
|
||||
int errorBase;
|
||||
int major;
|
||||
int minor;
|
||||
GLFWbool gammaBroken;
|
||||
GLFWbool monitorBroken;
|
||||
PFN_XRRAllocGamma AllocGamma;
|
||||
PFN_XRRFreeCrtcInfo FreeCrtcInfo;
|
||||
PFN_XRRFreeGamma FreeGamma;
|
||||
PFN_XRRFreeOutputInfo FreeOutputInfo;
|
||||
PFN_XRRFreeScreenResources FreeScreenResources;
|
||||
PFN_XRRGetCrtcGamma GetCrtcGamma;
|
||||
PFN_XRRGetCrtcGammaSize GetCrtcGammaSize;
|
||||
PFN_XRRGetCrtcInfo GetCrtcInfo;
|
||||
PFN_XRRGetOutputInfo GetOutputInfo;
|
||||
PFN_XRRGetOutputPrimary GetOutputPrimary;
|
||||
PFN_XRRGetScreenResourcesCurrent GetScreenResourcesCurrent;
|
||||
PFN_XRRQueryExtension QueryExtension;
|
||||
PFN_XRRQueryVersion QueryVersion;
|
||||
PFN_XRRSelectInput SelectInput;
|
||||
PFN_XRRSetCrtcConfig SetCrtcConfig;
|
||||
PFN_XRRSetCrtcGamma SetCrtcGamma;
|
||||
PFN_XRRUpdateConfiguration UpdateConfiguration;
|
||||
} randr;
|
||||
|
||||
struct {
|
||||
@@ -256,15 +328,26 @@ typedef struct _GLFWlibraryX11
|
||||
Atom format;
|
||||
} xdnd;
|
||||
|
||||
struct {
|
||||
void* handle;
|
||||
PFN_XcursorImageCreate ImageCreate;
|
||||
PFN_XcursorImageDestroy ImageDestroy;
|
||||
PFN_XcursorImageLoadCursor ImageLoadCursor;
|
||||
} xcursor;
|
||||
|
||||
struct {
|
||||
GLFWbool available;
|
||||
void* handle;
|
||||
int major;
|
||||
int minor;
|
||||
PFN_XineramaIsActive IsActive;
|
||||
PFN_XineramaQueryExtension QueryExtension;
|
||||
PFN_XineramaQueryScreens QueryScreens;
|
||||
} xinerama;
|
||||
|
||||
struct {
|
||||
void* handle;
|
||||
PFN_XGetXCBConnection XGetXCBConnection;
|
||||
PFN_XGetXCBConnection GetXCBConnection;
|
||||
} x11xcb;
|
||||
|
||||
struct {
|
||||
|
||||
+296
-148
@@ -164,6 +164,17 @@ static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointe
|
||||
event->xproperty.atom == _glfw.x11.NET_FRAME_EXTENTS;
|
||||
}
|
||||
|
||||
// Returns whether it is a property event for the specified selection transfer
|
||||
//
|
||||
static Bool isSelPropNewValueNotify(Display* display, XEvent* event, XPointer pointer)
|
||||
{
|
||||
XEvent* notification = (XEvent*) pointer;
|
||||
return event->type == PropertyNotify &&
|
||||
event->xproperty.state == PropertyNewValue &&
|
||||
event->xproperty.window == notification->xselection.requestor &&
|
||||
event->xproperty.atom == notification->xselection.property;
|
||||
}
|
||||
|
||||
// Translates a GLFW standard cursor to a font cursor shape
|
||||
//
|
||||
static int translateCursorShape(int shape)
|
||||
@@ -449,6 +460,81 @@ static char** parseUriList(char* text, int* count)
|
||||
return paths;
|
||||
}
|
||||
|
||||
// Encode a Unicode code point to a UTF-8 stream
|
||||
// Based on cutef8 by Jeff Bezanson (Public Domain)
|
||||
//
|
||||
static size_t encodeUTF8(char* s, unsigned int ch)
|
||||
{
|
||||
size_t count = 0;
|
||||
|
||||
if (ch < 0x80)
|
||||
s[count++] = (char) ch;
|
||||
else if (ch < 0x800)
|
||||
{
|
||||
s[count++] = (ch >> 6) | 0xc0;
|
||||
s[count++] = (ch & 0x3f) | 0x80;
|
||||
}
|
||||
else if (ch < 0x10000)
|
||||
{
|
||||
s[count++] = (ch >> 12) | 0xe0;
|
||||
s[count++] = ((ch >> 6) & 0x3f) | 0x80;
|
||||
s[count++] = (ch & 0x3f) | 0x80;
|
||||
}
|
||||
else if (ch < 0x110000)
|
||||
{
|
||||
s[count++] = (ch >> 18) | 0xf0;
|
||||
s[count++] = ((ch >> 12) & 0x3f) | 0x80;
|
||||
s[count++] = ((ch >> 6) & 0x3f) | 0x80;
|
||||
s[count++] = (ch & 0x3f) | 0x80;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// Decode a Unicode code point from a UTF-8 stream
|
||||
// Based on cutef8 by Jeff Bezanson (Public Domain)
|
||||
//
|
||||
#if defined(X_HAVE_UTF8_STRING)
|
||||
static unsigned int decodeUTF8(const char** s)
|
||||
{
|
||||
unsigned int ch = 0, count = 0;
|
||||
static const unsigned int offsets[] =
|
||||
{
|
||||
0x00000000u, 0x00003080u, 0x000e2080u,
|
||||
0x03c82080u, 0xfa082080u, 0x82082080u
|
||||
};
|
||||
|
||||
do
|
||||
{
|
||||
ch = (ch << 6) + (unsigned char) **s;
|
||||
(*s)++;
|
||||
count++;
|
||||
} while ((**s & 0xc0) == 0x80);
|
||||
|
||||
assert(count <= 6);
|
||||
return ch - offsets[count - 1];
|
||||
}
|
||||
#endif /*X_HAVE_UTF8_STRING*/
|
||||
|
||||
// Convert the specified Latin-1 string to UTF-8
|
||||
//
|
||||
static char* convertLatin1toUTF8(const char* source)
|
||||
{
|
||||
size_t size = 1;
|
||||
const char* sp;
|
||||
|
||||
for (sp = source; *sp; sp++)
|
||||
size += (*sp & 0x80) ? 2 : 1;
|
||||
|
||||
char* target = calloc(size, 1);
|
||||
char* tp = target;
|
||||
|
||||
for (sp = source; *sp; sp++)
|
||||
tp += encodeUTF8(tp, *sp);
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
// Centers the cursor over the window client area
|
||||
//
|
||||
static void centerCursor(_GLFWwindow* window)
|
||||
@@ -671,11 +757,15 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
||||
static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
|
||||
{
|
||||
int i;
|
||||
const Atom formats[] = { _glfw.x11.UTF8_STRING,
|
||||
_glfw.x11.COMPOUND_STRING,
|
||||
XA_STRING };
|
||||
char* selectionString = NULL;
|
||||
const Atom formats[] = { _glfw.x11.UTF8_STRING, XA_STRING };
|
||||
const int formatCount = sizeof(formats) / sizeof(formats[0]);
|
||||
|
||||
if (request->selection == _glfw.x11.PRIMARY)
|
||||
selectionString = _glfw.x11.primarySelectionString;
|
||||
else
|
||||
selectionString = _glfw.x11.clipboardString;
|
||||
|
||||
if (request->property == None)
|
||||
{
|
||||
// The requester is a legacy client (ICCCM section 2.2)
|
||||
@@ -690,7 +780,6 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
|
||||
const Atom targets[] = { _glfw.x11.TARGETS,
|
||||
_glfw.x11.MULTIPLE,
|
||||
_glfw.x11.UTF8_STRING,
|
||||
_glfw.x11.COMPOUND_STRING,
|
||||
XA_STRING };
|
||||
|
||||
XChangeProperty(_glfw.x11.display,
|
||||
@@ -735,8 +824,8 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
|
||||
targets[i],
|
||||
8,
|
||||
PropModeReplace,
|
||||
(unsigned char*) _glfw.x11.clipboardString,
|
||||
strlen(_glfw.x11.clipboardString));
|
||||
(unsigned char *) selectionString,
|
||||
strlen(selectionString));
|
||||
}
|
||||
else
|
||||
targets[i + 1] = None;
|
||||
@@ -787,8 +876,8 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
|
||||
request->target,
|
||||
8,
|
||||
PropModeReplace,
|
||||
(unsigned char*) _glfw.x11.clipboardString,
|
||||
strlen(_glfw.x11.clipboardString));
|
||||
(unsigned char *) selectionString,
|
||||
strlen(selectionString));
|
||||
|
||||
return request->property;
|
||||
}
|
||||
@@ -801,8 +890,16 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
|
||||
|
||||
static void handleSelectionClear(XEvent* event)
|
||||
{
|
||||
free(_glfw.x11.clipboardString);
|
||||
_glfw.x11.clipboardString = NULL;
|
||||
if (event->xselectionclear.selection == _glfw.x11.PRIMARY)
|
||||
{
|
||||
free(_glfw.x11.primarySelectionString);
|
||||
_glfw.x11.primarySelectionString = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(_glfw.x11.clipboardString);
|
||||
_glfw.x11.clipboardString = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void handleSelectionRequest(XEvent* event)
|
||||
@@ -823,6 +920,147 @@ static void handleSelectionRequest(XEvent* event)
|
||||
XSendEvent(_glfw.x11.display, request->requestor, False, 0, &reply);
|
||||
}
|
||||
|
||||
static const char* getSelectionString(Atom selection)
|
||||
{
|
||||
size_t i;
|
||||
char** selectionString = NULL;
|
||||
const Atom targets[] = { _glfw.x11.UTF8_STRING, XA_STRING };
|
||||
const size_t targetCount = sizeof(targets) / sizeof(targets[0]);
|
||||
|
||||
if (selection == _glfw.x11.PRIMARY)
|
||||
selectionString = &_glfw.x11.primarySelectionString;
|
||||
else
|
||||
selectionString = &_glfw.x11.clipboardString;
|
||||
|
||||
if (XGetSelectionOwner(_glfw.x11.display, selection) ==
|
||||
_glfw.x11.helperWindowHandle)
|
||||
{
|
||||
// Instead of doing a large number of X round-trips just to put this
|
||||
// string into a window property and then read it back, just return it
|
||||
return *selectionString;
|
||||
}
|
||||
|
||||
free(*selectionString);
|
||||
*selectionString = NULL;
|
||||
|
||||
for (i = 0; i < targetCount; i++)
|
||||
{
|
||||
char* data;
|
||||
Atom actualType;
|
||||
int actualFormat;
|
||||
unsigned long itemCount, bytesAfter;
|
||||
XEvent notification, dummy;
|
||||
|
||||
XConvertSelection(_glfw.x11.display,
|
||||
selection,
|
||||
targets[i],
|
||||
_glfw.x11.GLFW_SELECTION,
|
||||
_glfw.x11.helperWindowHandle,
|
||||
CurrentTime);
|
||||
|
||||
while (!XCheckTypedWindowEvent(_glfw.x11.display,
|
||||
_glfw.x11.helperWindowHandle,
|
||||
SelectionNotify,
|
||||
¬ification))
|
||||
{
|
||||
waitForEvent(NULL);
|
||||
}
|
||||
|
||||
if (notification.xselection.property == None)
|
||||
continue;
|
||||
|
||||
XCheckIfEvent(_glfw.x11.display,
|
||||
&dummy,
|
||||
isSelPropNewValueNotify,
|
||||
(XPointer) ¬ification);
|
||||
|
||||
XGetWindowProperty(_glfw.x11.display,
|
||||
notification.xselection.requestor,
|
||||
notification.xselection.property,
|
||||
0,
|
||||
LONG_MAX,
|
||||
True,
|
||||
AnyPropertyType,
|
||||
&actualType,
|
||||
&actualFormat,
|
||||
&itemCount,
|
||||
&bytesAfter,
|
||||
(unsigned char**) &data);
|
||||
|
||||
if (actualType == _glfw.x11.INCR)
|
||||
{
|
||||
size_t size = 1;
|
||||
char* string = NULL;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
while (!XCheckIfEvent(_glfw.x11.display,
|
||||
&dummy,
|
||||
isSelPropNewValueNotify,
|
||||
(XPointer) ¬ification))
|
||||
{
|
||||
waitForEvent(NULL);
|
||||
}
|
||||
|
||||
XFree(data);
|
||||
XGetWindowProperty(_glfw.x11.display,
|
||||
notification.xselection.requestor,
|
||||
notification.xselection.property,
|
||||
0,
|
||||
LONG_MAX,
|
||||
True,
|
||||
AnyPropertyType,
|
||||
&actualType,
|
||||
&actualFormat,
|
||||
&itemCount,
|
||||
&bytesAfter,
|
||||
(unsigned char**) &data);
|
||||
|
||||
if (itemCount)
|
||||
{
|
||||
size += itemCount;
|
||||
string = realloc(string, size);
|
||||
string[size - itemCount - 1] = '\0';
|
||||
strcat(string, data);
|
||||
}
|
||||
|
||||
if (!itemCount)
|
||||
{
|
||||
if (targets[i] == XA_STRING)
|
||||
{
|
||||
*selectionString = convertLatin1toUTF8(string);
|
||||
free(string);
|
||||
}
|
||||
else
|
||||
*selectionString = string;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (actualType == targets[i])
|
||||
{
|
||||
if (targets[i] == XA_STRING)
|
||||
*selectionString = convertLatin1toUTF8(data);
|
||||
else
|
||||
*selectionString = strdup(data);
|
||||
}
|
||||
|
||||
XFree(data);
|
||||
|
||||
if (*selectionString)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!*selectionString)
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"X11: Failed to convert selection to string");
|
||||
}
|
||||
|
||||
return *selectionString;
|
||||
}
|
||||
|
||||
// Make the specified window and its video mode active on its monitor
|
||||
//
|
||||
static GLFWbool acquireMonitor(_GLFWwindow* window)
|
||||
@@ -888,62 +1126,6 @@ static void releaseMonitor(_GLFWwindow* window)
|
||||
}
|
||||
}
|
||||
|
||||
// Encode a Unicode code point to a UTF-8 stream
|
||||
// Based on cutef8 by Jeff Bezanson (Public Domain)
|
||||
//
|
||||
static size_t encodeUTF8(char* s, unsigned int ch)
|
||||
{
|
||||
size_t count = 0;
|
||||
|
||||
if (ch < 0x80)
|
||||
s[count++] = (char) ch;
|
||||
else if (ch < 0x800)
|
||||
{
|
||||
s[count++] = (ch >> 6) | 0xc0;
|
||||
s[count++] = (ch & 0x3f) | 0x80;
|
||||
}
|
||||
else if (ch < 0x10000)
|
||||
{
|
||||
s[count++] = (ch >> 12) | 0xe0;
|
||||
s[count++] = ((ch >> 6) & 0x3f) | 0x80;
|
||||
s[count++] = (ch & 0x3f) | 0x80;
|
||||
}
|
||||
else if (ch < 0x110000)
|
||||
{
|
||||
s[count++] = (ch >> 18) | 0xf0;
|
||||
s[count++] = ((ch >> 12) & 0x3f) | 0x80;
|
||||
s[count++] = ((ch >> 6) & 0x3f) | 0x80;
|
||||
s[count++] = (ch & 0x3f) | 0x80;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// Decode a Unicode code point from a UTF-8 stream
|
||||
// Based on cutef8 by Jeff Bezanson (Public Domain)
|
||||
//
|
||||
#if defined(X_HAVE_UTF8_STRING)
|
||||
static unsigned int decodeUTF8(const char** s)
|
||||
{
|
||||
unsigned int ch = 0, count = 0;
|
||||
static const unsigned int offsets[] =
|
||||
{
|
||||
0x00000000u, 0x00003080u, 0x000e2080u,
|
||||
0x03c82080u, 0xfa082080u, 0x82082080u
|
||||
};
|
||||
|
||||
do
|
||||
{
|
||||
ch = (ch << 6) + (unsigned char) **s;
|
||||
(*s)++;
|
||||
count++;
|
||||
} while ((**s & 0xc0) == 0x80);
|
||||
|
||||
assert(count <= 6);
|
||||
return ch - offsets[count - 1];
|
||||
}
|
||||
#endif /*X_HAVE_UTF8_STRING*/
|
||||
|
||||
// Process the specified X event
|
||||
//
|
||||
static void processEvent(XEvent *event)
|
||||
@@ -1081,8 +1263,10 @@ static void processEvent(XEvent *event)
|
||||
|
||||
count = XwcLookupString(window->x11.ic,
|
||||
&event->xkey,
|
||||
buffer, sizeof(buffer) / sizeof(wchar_t),
|
||||
NULL, &status);
|
||||
buffer,
|
||||
sizeof(buffer) / sizeof(wchar_t),
|
||||
NULL,
|
||||
&status);
|
||||
|
||||
if (status == XBufferOverflow)
|
||||
{
|
||||
@@ -1255,7 +1439,8 @@ static void processEvent(XEvent *event)
|
||||
const int x = event->xmotion.x;
|
||||
const int y = event->xmotion.y;
|
||||
|
||||
if (x != window->x11.warpCursorPosX || y != window->x11.warpCursorPosY)
|
||||
if (x != window->x11.warpCursorPosX ||
|
||||
y != window->x11.warpCursorPosY)
|
||||
{
|
||||
// The cursor was moved by something other than GLFW
|
||||
|
||||
@@ -1334,14 +1519,15 @@ static void processEvent(XEvent *event)
|
||||
|
||||
if (protocol == _glfw.x11.WM_DELETE_WINDOW)
|
||||
{
|
||||
// The window manager was asked to close the window, for example by
|
||||
// the user pressing a 'close' window decoration button
|
||||
// The window manager was asked to close the window, for
|
||||
// example by the user pressing a 'close' window decoration
|
||||
// button
|
||||
_glfwInputWindowCloseRequest(window);
|
||||
}
|
||||
else if (protocol == _glfw.x11.NET_WM_PING)
|
||||
{
|
||||
// The window manager is pinging the application to ensure it's
|
||||
// still responding to events
|
||||
// The window manager is pinging the application to ensure
|
||||
// it's still responding to events
|
||||
|
||||
XEvent reply = *event;
|
||||
reply.xclient.window = _glfw.x11.root;
|
||||
@@ -1683,9 +1869,10 @@ void _glfwPushSelectionToManagerX11(void)
|
||||
{
|
||||
if (event.xselection.target == _glfw.x11.SAVE_TARGETS)
|
||||
{
|
||||
// This means one of two things; either the selection was
|
||||
// not owned, which means there is no clipboard manager, or
|
||||
// the transfer to the clipboard manager has completed
|
||||
// This means one of two things; either the selection
|
||||
// was not owned, which means there is no clipboard
|
||||
// manager, or the transfer to the clipboard manager has
|
||||
// completed
|
||||
// In either case, it means we are done here
|
||||
return;
|
||||
}
|
||||
@@ -2572,72 +2759,7 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
|
||||
|
||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
{
|
||||
size_t i;
|
||||
const Atom formats[] = { _glfw.x11.UTF8_STRING,
|
||||
_glfw.x11.COMPOUND_STRING,
|
||||
XA_STRING };
|
||||
const size_t formatCount = sizeof(formats) / sizeof(formats[0]);
|
||||
|
||||
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) ==
|
||||
_glfw.x11.helperWindowHandle)
|
||||
{
|
||||
// Instead of doing a large number of X round-trips just to put this
|
||||
// string into a window property and then read it back, just return it
|
||||
return _glfw.x11.clipboardString;
|
||||
}
|
||||
|
||||
free(_glfw.x11.clipboardString);
|
||||
_glfw.x11.clipboardString = NULL;
|
||||
|
||||
for (i = 0; i < formatCount; i++)
|
||||
{
|
||||
char* data;
|
||||
XEvent event;
|
||||
|
||||
XConvertSelection(_glfw.x11.display,
|
||||
_glfw.x11.CLIPBOARD,
|
||||
formats[i],
|
||||
_glfw.x11.GLFW_SELECTION,
|
||||
_glfw.x11.helperWindowHandle,
|
||||
CurrentTime);
|
||||
|
||||
while (!XCheckTypedWindowEvent(_glfw.x11.display,
|
||||
_glfw.x11.helperWindowHandle,
|
||||
SelectionNotify,
|
||||
&event))
|
||||
{
|
||||
waitForEvent(NULL);
|
||||
}
|
||||
|
||||
if (event.xselection.property == None)
|
||||
continue;
|
||||
|
||||
if (_glfwGetWindowPropertyX11(event.xselection.requestor,
|
||||
event.xselection.property,
|
||||
event.xselection.target,
|
||||
(unsigned char**) &data))
|
||||
{
|
||||
_glfw.x11.clipboardString = strdup(data);
|
||||
}
|
||||
|
||||
if (data)
|
||||
XFree(data);
|
||||
|
||||
XDeleteProperty(_glfw.x11.display,
|
||||
event.xselection.requestor,
|
||||
event.xselection.property);
|
||||
|
||||
if (_glfw.x11.clipboardString)
|
||||
break;
|
||||
}
|
||||
|
||||
if (_glfw.x11.clipboardString == NULL)
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"X11: Failed to convert clipboard to string");
|
||||
}
|
||||
|
||||
return _glfw.x11.clipboardString;
|
||||
return getSelectionString(_glfw.x11.CLIPBOARD);
|
||||
}
|
||||
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||
@@ -2670,7 +2792,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
|
||||
if (_glfw.vk.KHR_xcb_surface && _glfw.x11.x11xcb.handle)
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR =
|
||||
PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR
|
||||
vkGetPhysicalDeviceXcbPresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceXcbPresentationSupportKHR)
|
||||
@@ -2680,8 +2803,7 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
xcb_connection_t* connection =
|
||||
_glfw.x11.x11xcb.XGetXCBConnection(_glfw.x11.display);
|
||||
xcb_connection_t* connection = XGetXCBConnection(_glfw.x11.display);
|
||||
if (!connection)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
@@ -2696,7 +2818,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
}
|
||||
else
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR =
|
||||
PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR
|
||||
vkGetPhysicalDeviceXlibPresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceXlibPresentationSupportKHR)
|
||||
@@ -2724,8 +2847,7 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
VkXcbSurfaceCreateInfoKHR sci;
|
||||
PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR;
|
||||
|
||||
xcb_connection_t* connection =
|
||||
_glfw.x11.x11xcb.XGetXCBConnection(_glfw.x11.display);
|
||||
xcb_connection_t* connection = XGetXCBConnection(_glfw.x11.display);
|
||||
if (!connection)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
@@ -2807,3 +2929,29 @@ GLFWAPI Window glfwGetX11Window(GLFWwindow* handle)
|
||||
return window->x11.handle;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSetX11SelectionString(const char* string)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
free(_glfw.x11.primarySelectionString);
|
||||
_glfw.x11.primarySelectionString = strdup(string);
|
||||
|
||||
XSetSelectionOwner(_glfw.x11.display,
|
||||
_glfw.x11.PRIMARY,
|
||||
_glfw.x11.helperWindowHandle,
|
||||
CurrentTime);
|
||||
|
||||
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.PRIMARY) !=
|
||||
_glfw.x11.helperWindowHandle)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to become owner of primary selection");
|
||||
}
|
||||
}
|
||||
|
||||
GLFWAPI const char* glfwGetX11SelectionString(void)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
return getSelectionString(_glfw.x11.PRIMARY);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ add_executable(cursor cursor.c ${GLAD})
|
||||
add_executable(empty WIN32 MACOSX_BUNDLE empty.c ${TINYCTHREAD} ${GLAD})
|
||||
add_executable(gamma WIN32 MACOSX_BUNDLE gamma.c ${GLAD})
|
||||
add_executable(icon WIN32 MACOSX_BUNDLE icon.c ${GLAD})
|
||||
add_executable(inputlag WIN32 MACOSX_BUNDLE inputlag.c ${GETOPT} ${GLAD})
|
||||
add_executable(joysticks WIN32 MACOSX_BUNDLE joysticks.c ${GLAD})
|
||||
add_executable(sharing WIN32 MACOSX_BUNDLE sharing.c ${GETOPT} ${GLAD})
|
||||
add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c ${GETOPT} ${GLAD})
|
||||
@@ -45,8 +46,8 @@ if (RT_LIBRARY)
|
||||
target_link_libraries(threads "${RT_LIBRARY}")
|
||||
endif()
|
||||
|
||||
set(WINDOWS_BINARIES empty gamma icon joysticks sharing tearing threads timeout
|
||||
title windows)
|
||||
set(WINDOWS_BINARIES empty gamma icon inputlag joysticks sharing tearing threads
|
||||
timeout title windows)
|
||||
set(CONSOLE_BINARIES clipboard events msaa glfwinfo iconify monitors reopen
|
||||
cursor)
|
||||
|
||||
@@ -73,6 +74,7 @@ endif()
|
||||
if (APPLE)
|
||||
set_target_properties(empty PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Empty Event")
|
||||
set_target_properties(gamma PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gamma")
|
||||
set_target_properties(inputlag PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Input Lag")
|
||||
set_target_properties(joysticks PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Joysticks")
|
||||
set_target_properties(sharing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Sharing")
|
||||
set_target_properties(tearing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Tearing")
|
||||
|
||||
+1
-1
@@ -806,7 +806,7 @@ int main(int argc, char** argv)
|
||||
if (list_extensions)
|
||||
list_context_extensions(client, major, minor);
|
||||
|
||||
printf("Vulkan support: %s\n",
|
||||
printf("Vulkan loader: %s\n",
|
||||
glfwVulkanSupported() ? "available" : "missing");
|
||||
|
||||
if (glfwVulkanSupported())
|
||||
|
||||
@@ -0,0 +1,305 @@
|
||||
//========================================================================
|
||||
// Input lag test
|
||||
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
//
|
||||
// This test renders a marker at the cursor position reported by GLFW to
|
||||
// check how much it lags behind the hardware mouse cursor
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#define NK_IMPLEMENTATION
|
||||
#define NK_INCLUDE_FIXED_TYPES
|
||||
#define NK_INCLUDE_FONT_BAKING
|
||||
#define NK_INCLUDE_DEFAULT_FONT
|
||||
#define NK_INCLUDE_DEFAULT_ALLOCATOR
|
||||
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
|
||||
#define NK_INCLUDE_STANDARD_VARARGS
|
||||
#include <nuklear.h>
|
||||
|
||||
#define NK_GLFW_GL2_IMPLEMENTATION
|
||||
#include <nuklear_glfw_gl2.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "getopt.h"
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
printf("Usage: inputlag [-h] [-f]\n");
|
||||
printf("Options:\n");
|
||||
printf(" -f create full screen window\n");
|
||||
printf(" -h show this help\n");
|
||||
}
|
||||
|
||||
struct nk_vec2 cursor_new, cursor_pos, cursor_vel;
|
||||
enum { cursor_sync_query, cursor_input_message } cursor_method = cursor_sync_query;
|
||||
|
||||
void sample_input(GLFWwindow* window)
|
||||
{
|
||||
float a = .25; // exponential smoothing factor
|
||||
|
||||
if (cursor_method == cursor_sync_query) {
|
||||
double x, y;
|
||||
glfwGetCursorPos(window, &x, &y);
|
||||
cursor_new.x = (float) x;
|
||||
cursor_new.y = (float) y;
|
||||
}
|
||||
|
||||
cursor_vel.x = (cursor_new.x - cursor_pos.x) * a + cursor_vel.x * (1 - a);
|
||||
cursor_vel.y = (cursor_new.y - cursor_pos.y) * a + cursor_vel.y * (1 - a);
|
||||
cursor_pos = cursor_new;
|
||||
}
|
||||
|
||||
void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
cursor_new.x = (float) xpos;
|
||||
cursor_new.y = (float) ypos;
|
||||
}
|
||||
|
||||
int enable_vsync = nk_true;
|
||||
|
||||
void update_vsync()
|
||||
{
|
||||
glfwSwapInterval(enable_vsync == nk_true ? 1 : 0);
|
||||
}
|
||||
|
||||
int swap_clear = nk_false;
|
||||
int swap_finish = nk_true;
|
||||
int swap_occlusion_query = nk_false;
|
||||
int swap_read_pixels = nk_false;
|
||||
GLuint occlusion_query;
|
||||
|
||||
void swap_buffers(GLFWwindow* window)
|
||||
{
|
||||
glfwSwapBuffers(window);
|
||||
|
||||
if (swap_clear)
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
if (swap_finish)
|
||||
glFinish();
|
||||
|
||||
if (swap_occlusion_query) {
|
||||
GLint occlusion_result;
|
||||
if (!occlusion_query)
|
||||
glGenQueries(1, &occlusion_query);
|
||||
glBeginQuery(GL_SAMPLES_PASSED, occlusion_query);
|
||||
glBegin(GL_POINTS);
|
||||
glVertex2f(0, 0);
|
||||
glEnd();
|
||||
glEndQuery(GL_SAMPLES_PASSED);
|
||||
glGetQueryObjectiv(occlusion_query, GL_QUERY_RESULT, &occlusion_result);
|
||||
}
|
||||
|
||||
if (swap_read_pixels) {
|
||||
unsigned char rgba[4];
|
||||
glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba);
|
||||
}
|
||||
}
|
||||
|
||||
void error_callback(int error, const char* description)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", description);
|
||||
}
|
||||
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
{
|
||||
if (action != GLFW_PRESS)
|
||||
return;
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case GLFW_KEY_ESCAPE:
|
||||
glfwSetWindowShouldClose(window, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void draw_marker(struct nk_command_buffer* canvas, int lead, struct nk_vec2 pos)
|
||||
{
|
||||
struct nk_color colors[4] = { nk_rgb(255,0,0), nk_rgb(255,255,0), nk_rgb(0,255,0), nk_rgb(0,96,255) };
|
||||
struct nk_rect rect = { -5 + pos.x, -5 + pos.y, 10, 10 };
|
||||
nk_fill_circle(canvas, rect, colors[lead]);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int ch, width, height;
|
||||
unsigned long frame_count = 0;
|
||||
double last_time, current_time;
|
||||
double frame_rate = 0;
|
||||
int fullscreen = GLFW_FALSE;
|
||||
GLFWmonitor* monitor = NULL;
|
||||
GLFWwindow* window;
|
||||
struct nk_context* nk;
|
||||
struct nk_font_atlas* atlas;
|
||||
|
||||
int show_forecasts = nk_true;
|
||||
|
||||
while ((ch = getopt(argc, argv, "fh")) != -1)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 'h':
|
||||
usage();
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
case 'f':
|
||||
fullscreen = GLFW_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
glfwSetErrorCallback(error_callback);
|
||||
|
||||
if (!glfwInit())
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
if (fullscreen)
|
||||
{
|
||||
const GLFWvidmode* mode;
|
||||
|
||||
monitor = glfwGetPrimaryMonitor();
|
||||
mode = glfwGetVideoMode(monitor);
|
||||
|
||||
width = mode->width;
|
||||
height = mode->height;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = 640;
|
||||
height = 480;
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
|
||||
window = glfwCreateWindow(width, height, "Input lag test", monitor, NULL);
|
||||
if (!window)
|
||||
{
|
||||
glfwTerminate();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
|
||||
update_vsync();
|
||||
|
||||
last_time = glfwGetTime();
|
||||
|
||||
nk = nk_glfw3_init(window, NK_GLFW3_INSTALL_CALLBACKS);
|
||||
nk_glfw3_font_stash_begin(&atlas);
|
||||
nk_glfw3_font_stash_end();
|
||||
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, cursor_pos_callback);
|
||||
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
int width, height;
|
||||
struct nk_rect area;
|
||||
|
||||
glfwPollEvents();
|
||||
sample_input(window);
|
||||
|
||||
glfwGetWindowSize(window, &width, &height);
|
||||
area = nk_rect(0.f, 0.f, (float) width, (float) height);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
nk_glfw3_new_frame();
|
||||
if (nk_begin(nk, "", area, 0))
|
||||
{
|
||||
nk_flags align_left = NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE;
|
||||
struct nk_command_buffer *canvas = nk_window_get_canvas(nk);
|
||||
int lead;
|
||||
|
||||
for (lead = show_forecasts ? 3 : 0; lead >= 0; lead--)
|
||||
draw_marker(canvas, lead, nk_vec2(cursor_pos.x + cursor_vel.x * lead,
|
||||
cursor_pos.y + cursor_vel.y * lead));
|
||||
|
||||
// print instructions
|
||||
nk_layout_row_dynamic(nk, 20, 1);
|
||||
nk_label(nk, "Move mouse uniformly and check marker under cursor:", align_left);
|
||||
for (lead = 0; lead <= 3; lead++) {
|
||||
nk_layout_row_begin(nk, NK_STATIC, 12, 2);
|
||||
nk_layout_row_push(nk, 25);
|
||||
draw_marker(canvas, lead, nk_layout_space_to_screen(nk, nk_vec2(20, 5)));
|
||||
nk_label(nk, "", 0);
|
||||
nk_layout_row_push(nk, 500);
|
||||
if (lead == 0)
|
||||
nk_label(nk, "- current cursor position (no input lag)", align_left);
|
||||
else
|
||||
nk_labelf(nk, align_left, "- %d-frame forecast (input lag is %d frame)", lead, lead);
|
||||
nk_layout_row_end(nk);
|
||||
}
|
||||
|
||||
nk_layout_row_dynamic(nk, 20, 1);
|
||||
|
||||
nk_checkbox_label(nk, "Show forecasts", &show_forecasts);
|
||||
nk_label(nk, "Input method:", align_left);
|
||||
if (nk_option_label(nk, "glfwGetCursorPos (sync query)", cursor_method == cursor_sync_query))
|
||||
cursor_method = cursor_sync_query;
|
||||
if (nk_option_label(nk, "glfwSetCursorPosCallback (latest input message)", cursor_method == cursor_input_message))
|
||||
cursor_method = cursor_input_message;
|
||||
|
||||
nk_label(nk, "", 0); // separator
|
||||
|
||||
nk_value_float(nk, "FPS", (float) frame_rate);
|
||||
if (nk_checkbox_label(nk, "Enable vsync", &enable_vsync))
|
||||
update_vsync();
|
||||
|
||||
nk_label(nk, "", 0); // separator
|
||||
|
||||
nk_label(nk, "After swap:", align_left);
|
||||
nk_checkbox_label(nk, "glClear", &swap_clear);
|
||||
nk_checkbox_label(nk, "glFinish", &swap_finish);
|
||||
nk_checkbox_label(nk, "draw with occlusion query", &swap_occlusion_query);
|
||||
nk_checkbox_label(nk, "glReadPixels", &swap_read_pixels);
|
||||
}
|
||||
|
||||
nk_end(nk);
|
||||
nk_glfw3_render(NK_ANTI_ALIASING_ON);
|
||||
|
||||
swap_buffers(window);
|
||||
|
||||
frame_count++;
|
||||
|
||||
current_time = glfwGetTime();
|
||||
if (current_time - last_time > 1.0)
|
||||
{
|
||||
frame_rate = frame_count / (current_time - last_time);
|
||||
frame_count = 0;
|
||||
last_time = current_time;
|
||||
}
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user