Merge branch '3.3-stable' into new-cursors-on-3.3-stable

This commit is contained in:
Camilla Löwy 2022-03-04 15:10:14 +01:00
commit 2a6dac679c
42 changed files with 701 additions and 615 deletions

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.0...3.20 FATAL_ERROR) cmake_minimum_required(VERSION 3.0...3.20 FATAL_ERROR)
project(GLFW VERSION 3.3.5 LANGUAGES C) project(GLFW VERSION 3.3.7 LANGUAGES C)
set(CMAKE_LEGACY_CYGWIN_WIN32 OFF) set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
@ -266,7 +266,6 @@ if (_GLFW_WAYLAND)
include(CheckIncludeFiles) include(CheckIncludeFiles)
include(CheckFunctionExists) include(CheckFunctionExists)
check_include_files(xkbcommon/xkbcommon-compose.h HAVE_XKBCOMMON_COMPOSE_H)
check_function_exists(memfd_create HAVE_MEMFD_CREATE) check_function_exists(memfd_create HAVE_MEMFD_CREATE)
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")

228
CONTRIBUTORS.md Normal file
View File

@ -0,0 +1,228 @@
# Acknowledgements
GLFW exists because people around the world donated their time and lent their
skills. This list only includes contributions to the main repository and
excludes other invaluable contributions like language bindings and text and
video tutorials.
- Bobyshev Alexander
- Laurent Aphecetche
- Matt Arsenault
- ashishgamedev
- David Avedissian
- Keith Bauer
- John Bartholomew
- Coşku Baş
- Niklas Behrens
- Andrew Belt
- Nevyn Bengtsson
- Niklas Bergström
- Denis Bernard
- Doug Binks
- blanco
- Waris Boonyasiriwat
- Kyle Brenneman
- Rok Breulj
- Kai Burjack
- Martin Capitanio
- Nicolas Caramelli
- David Carlier
- Arturo Castro
- Chi-kwan Chan
- Joseph Chua
- Ian Clarkson
- Michał Cichoń
- Lambert Clara
- Anna Clarke
- Josh Codd
- Yaron Cohen-Tal
- Omar Cornut
- Andrew Corrigan
- Bailey Cosier
- Noel Cower
- CuriouserThing
- Jason Daly
- Jarrod Davis
- Olivier Delannoy
- Paul R. Deppe
- Michael Dickens
- Роман Донченко
- Mario Dorn
- Wolfgang Draxinger
- Jonathan Dummer
- Ralph Eastwood
- Fredrik Ehnbom
- Robin Eklind
- Jan Ekström
- Siavash Eliasi
- TheExileFox
- Felipe Ferreira
- Michael Fogleman
- Jason Francis
- Gerald Franz
- Mário Freitas
- GeO4d
- Marcus Geelnard
- ghuser404
- Charles Giessen
- Ryan C. Gordon
- Stephen Gowen
- Kovid Goyal
- Eloi Marín Gratacós
- Stefan Gustavson
- Andrew Gutekanst
- Stephen Gutekanst
- Jonathan Hale
- hdf89shfdfs
- Sylvain Hellegouarch
- Matthew Henry
- heromyth
- Lucas Hinderberger
- Paul Holden
- Warren Hu
- Charles Huber
- InKryption
- IntellectualKitty
- Aaron Jacobs
- Erik S. V. Jansson
- Toni Jovanoski
- Arseny Kapoulkine
- Cem Karan
- Osman Keskin
- Koray Kilinc
- Josh Kilmer
- Byunghoon Kim
- Cameron King
- Peter Knut
- Christoph Kubisch
- Yuri Kunde Schlesner
- Rokas Kupstys
- Konstantin Käfer
- Eric Larson
- Francis Lecavalier
- Jong Won Lee
- Robin Leffmann
- Glenn Lewis
- Shane Liesegang
- Anders Lindqvist
- Leon Linhart
- Marco Lizza
- Eyal Lotem
- Aaron Loucks
- Luflosi
- lukect
- Tristam MacDonald
- Hans Mackowiak
- Дмитри Малышев
- Zbigniew Mandziejewicz
- Adam Marcus
- Célestin Marot
- Kyle McDonald
- David V. McKay
- David Medlock
- Bryce Mehring
- Jonathan Mercier
- Marcel Metz
- Liam Middlebrook
- Ave Milia
- Jonathan Miller
- Kenneth Miller
- Bruce Mitchener
- Jack Moffitt
- Jeff Molofee
- Alexander Monakov
- Pierre Morel
- Jon Morton
- Pierre Moulon
- Martins Mozeiko
- Julian Møller
- ndogxj
- Kristian Nielsen
- Kamil Nowakowski
- onox
- Denis Ovod
- Ozzy
- Andri Pálsson
- Peoro
- Braden Pellett
- Christopher Pelloux
- Arturo J. Pérez
- Vladimir Perminov
- Anthony Pesch
- Orson Peters
- Emmanuel Gil Peyrot
- Cyril Pichard
- Keith Pitt
- Stanislav Podgorskiy
- Konstantin Podsvirov
- Nathan Poirier
- Alexandre Pretyman
- Pablo Prietz
- przemekmirek
- pthom
- Guillaume Racicot
- Philip Rideout
- Eddie Ringle
- Max Risuhin
- Jorge Rodriguez
- Luca Rood
- Ed Ropple
- Aleksey Rybalkin
- Mikko Rytkönen
- Riku Salminen
- Brandon Schaefer
- Sebastian Schuberth
- Christian Sdunek
- Matt Sealey
- Steve Sexton
- Arkady Shapkin
- Ali Sherief
- Yoshiki Shibukawa
- Dmitri Shuralyov
- Daniel Sieger
- Daniel Skorupski
- Bradley Smith
- Cliff Smolinsky
- 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
- Arthur Tombs
- Ioannis Tsakpinis
- Samuli Tuomola
- Matthew Turner
- urraka
- Elias Vanderstuyft
- Stef Velzel
- Jari Vetoniemi
- Ricardo Vieira
- Nicholas Vitovitch
- Simon Voordouw
- Corentin Wallez
- Torsten Walluhn
- Patrick Walton
- Xo Wang
- Jay Weisskopf
- Frank Wille
- Richard A. Wilkes
- Tatsuya Yatagawa
- Ryogo Yoshimura
- Rácz Zalán
- Lukas Zanner
- Andrey Zholos
- Aihui Zhu
- Santi Zupancic
- Jonas Ådahl
- Lasse Öörni
- Leonard König
- All the unmentioned and anonymous contributors in the GLFW community, for bug
reports, patches, feedback, testing and encouragement

250
README.md
View File

@ -39,6 +39,11 @@ you have used GLFW 2 in the past, there is a [transition
guide](https://www.glfw.org/docs/latest/moving.html) for moving to the GLFW guide](https://www.glfw.org/docs/latest/moving.html) for moving to the GLFW
3 API. 3 API.
GLFW exists because of the contributions of [many people](CONTRIBUTORS.md)
around the world, whether by reporting bugs, providing community support, adding
features, reviewing or testing code, debugging, proofreading docs, suggesting
features or fixing bugs.
## Compiling GLFW ## Compiling GLFW
@ -118,22 +123,18 @@ information on what to include when reporting a bug.
## Changelog ## Changelog
- Bugfix: Buffers were swapped at creation on single-buffered windows (#1873) - [Cocoa] Bugfix: `kUTTypeURL` was deprecated in macOS 12.0 (#2003)
- Bugfix: Gamepad mapping updates could spam `GLFW_INVALID_VALUE` due to - [X11] Bugfix: Dynamic loading on OpenBSD failed due to soname differences
incompatible controllers sharing hardware ID (#1763) - [Wayland] Added support for key names via xkbcommon
- [Win32] Bugfix: `USE_MSVC_RUNTIME_LIBRARY_DLL` had no effect on CMake 3.15 or - [Wayland] Bugfix: Key repeat could lead to a race condition (#1710)
later (#1783,#1796) - [Wayland] Bugfix: Activating a window would emit two input focus events
- [Win32] Bugfix: Compilation with LLVM for Windows failed (#1807,#1824,#1874) - [Wayland] Bugfix: Disable key repeat mechanism when window loses input focus
- [Cocoa] Bugfix: The MoltenVK layer contents scale was updated only after - [Wayland] Bugfix: Window hiding and showing did not work (#1492,#1731)
related events were emitted - [Wayland] Bugfix: A key being repeated was not released when window lost focus
- [Cocoa] Bugfix: Moving the cursor programmatically would freeze it for - [Wayland] Bugfix: Showing a hidden window did not emit a window refresh event
a fraction of a second (#1962) - [Wayland] Bugfix: Full screen window creation did not ignore `GLFW_VISIBLE`
- [X11] Bugfix: Changing `GLFW_FLOATING` could leak memory - [Wayland] Bugfix: Some keys were reported as wrong key or `GLFW_KEY_UNKNOWN`
- [Wayland] Bugfix: Some keys were not repeating in Wayland (#1908) - [Wayland] Bugfix: Text input did not repeat along with key repeat
- [Wayland] Bugfix: Non-arrow cursors are offset from the hotspot (#1706,#1899)
- [NSGL] Bugfix: Defining `GL_SILENCE_DEPRECATION` externally caused
a duplicate definition warning (#1840)
- [EGL] Bugfix: The `GLFW_DOUBLEBUFFER` context attribute was ignored (#1843)
## Contact ## Contact
@ -152,220 +153,3 @@ request, please file it in the
Finally, if you're interested in helping out with the development of GLFW or Finally, if you're interested in helping out with the development of GLFW or
porting it to your favorite platform, join us on the forum, GitHub or IRC. porting it to your favorite platform, join us on the forum, GitHub or IRC.
## Acknowledgements
GLFW exists because people around the world donated their time and lent their
skills.
- Bobyshev Alexander
- Laurent Aphecetche
- Matt Arsenault
- ashishgamedev
- David Avedissian
- Keith Bauer
- John Bartholomew
- Coşku Baş
- Niklas Behrens
- Andrew Belt
- Nevyn Bengtsson
- Niklas Bergström
- Denis Bernard
- Doug Binks
- blanco
- Waris Boonyasiriwat
- Kyle Brenneman
- Rok Breulj
- Kai Burjack
- Martin Capitanio
- Nicolas Caramelli
- David Carlier
- Arturo Castro
- Chi-kwan Chan
- Joseph Chua
- Ian Clarkson
- Michał Cichoń
- Lambert Clara
- Anna Clarke
- Yaron Cohen-Tal
- Omar Cornut
- Andrew Corrigan
- Bailey Cosier
- Noel Cower
- CuriouserThing
- Jason Daly
- Jarrod Davis
- Olivier Delannoy
- Paul R. Deppe
- Michael Dickens
- Роман Донченко
- Mario Dorn
- Wolfgang Draxinger
- Jonathan Dummer
- Ralph Eastwood
- Fredrik Ehnbom
- Robin Eklind
- Siavash Eliasi
- Felipe Ferreira
- Michael Fogleman
- Gerald Franz
- Mário Freitas
- GeO4d
- Marcus Geelnard
- Charles Giessen
- Ryan C. Gordon
- Stephen Gowen
- Kovid Goyal
- Eloi Marín Gratacós
- Stefan Gustavson
- Jonathan Hale
- hdf89shfdfs
- Sylvain Hellegouarch
- Matthew Henry
- heromyth
- Lucas Hinderberger
- Paul Holden
- Warren Hu
- Charles Huber
- IntellectualKitty
- Aaron Jacobs
- Erik S. V. Jansson
- Toni Jovanoski
- Arseny Kapoulkine
- Cem Karan
- Osman Keskin
- Koray Kilinc
- Josh Kilmer
- Byunghoon Kim
- Cameron King
- Peter Knut
- Christoph Kubisch
- Yuri Kunde Schlesner
- Rokas Kupstys
- Konstantin Käfer
- Eric Larson
- Francis Lecavalier
- Jong Won Lee
- Robin Leffmann
- Glenn Lewis
- Shane Liesegang
- Anders Lindqvist
- Leon Linhart
- Marco Lizza
- Eyal Lotem
- Aaron Loucks
- Luflosi
- lukect
- Tristam MacDonald
- Hans Mackowiak
- Дмитри Малышев
- Zbigniew Mandziejewicz
- Adam Marcus
- Célestin Marot
- Kyle McDonald
- David V. McKay
- David Medlock
- Bryce Mehring
- Jonathan Mercier
- Marcel Metz
- Liam Middlebrook
- Ave Milia
- Jonathan Miller
- Kenneth Miller
- Bruce Mitchener
- Jack Moffitt
- Jeff Molofee
- Alexander Monakov
- Pierre Morel
- Jon Morton
- Pierre Moulon
- Martins Mozeiko
- Julian Møller
- ndogxj
- Kristian Nielsen
- Kamil Nowakowski
- onox
- Denis Ovod
- Ozzy
- Andri Pálsson
- Peoro
- Braden Pellett
- Christopher Pelloux
- Arturo J. Pérez
- Vladimir Perminov
- Anthony Pesch
- Orson Peters
- Emmanuel Gil Peyrot
- Cyril Pichard
- Keith Pitt
- Stanislav Podgorskiy
- Konstantin Podsvirov
- Nathan Poirier
- Alexandre Pretyman
- Pablo Prietz
- przemekmirek
- pthom
- Guillaume Racicot
- Philip Rideout
- Eddie Ringle
- Max Risuhin
- Jorge Rodriguez
- Luca Rood
- Ed Ropple
- Aleksey Rybalkin
- Mikko Rytkönen
- Riku Salminen
- Brandon Schaefer
- Sebastian Schuberth
- Christian Sdunek
- Matt Sealey
- Steve Sexton
- Arkady Shapkin
- Ali Sherief
- Yoshiki Shibukawa
- Dmitri Shuralyov
- Daniel Skorupski
- Bradley Smith
- Cliff Smolinsky
- 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
- Arthur Tombs
- Ioannis Tsakpinis
- Samuli Tuomola
- Matthew Turner
- urraka
- Elias Vanderstuyft
- Stef Velzel
- Jari Vetoniemi
- Ricardo Vieira
- Nicholas Vitovitch
- Simon Voordouw
- Corentin Wallez
- Torsten Walluhn
- Patrick Walton
- Xo Wang
- Jay Weisskopf
- Frank Wille
- Richard A. Wilkes
- Tatsuya Yatagawa
- Ryogo Yoshimura
- Lukas Zanner
- Andrey Zholos
- Aihui Zhu
- Santi Zupancic
- Jonas Ådahl
- Lasse Öörni
- Leonard König
- All the unmentioned and anonymous contributors in the GLFW community, for bug
reports, patches, feedback, testing and encouragement

View File

@ -208,13 +208,6 @@ ALIASES = "thread_safety=@par Thread safety^^" \
"macos=__macOS:__" \ "macos=__macOS:__" \
"linux=__Linux:__" "linux=__Linux:__"
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding
# "class=itcl::class" will allow you to use the command class in the
# itcl::class meaning.
TCL_SUBST =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
# sources only. Doxygen will then generate output that is more tailored for C. # sources only. Doxygen will then generate output that is more tailored for C.
# For instance, some of the names that are used will be different. The list # For instance, some of the names that are used will be different. The list
@ -854,12 +847,6 @@ VERBATIM_HEADERS = YES
ALPHABETICAL_INDEX = YES ALPHABETICAL_INDEX = YES
# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
# in which this list will be split (can be a number in the range [1..20])
COLS_IN_ALPHA_INDEX = 5
# In case all classes in a project start with a common prefix, all # In case all classes in a project start with a common prefix, all
# classes will be put under the same header in the alphabetical index. # classes will be put under the same header in the alphabetical index.
# The IGNORE_PREFIX tag can be used to specify one or more prefixes that # The IGNORE_PREFIX tag can be used to specify one or more prefixes that
@ -1367,13 +1354,6 @@ LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO LATEX_HIDE_INDICES = NO
# If LATEX_SOURCE_CODE is set to YES then doxygen will include
# source code with syntax highlighting in the LaTeX output.
# Note that which sources are shown also depends on other settings
# such as SOURCE_BROWSER.
LATEX_SOURCE_CODE = NO
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the # The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
# http://en.wikipedia.org/wiki/BibTeX for more info. # http://en.wikipedia.org/wiki/BibTeX for more info.

View File

@ -2,7 +2,7 @@
// This is an example program for the GLFW library // This is an example program for the GLFW library
// //
// The program uses a "split window" view, rendering four views of the // The program uses a "split window" view, rendering four views of the
// same scene in one window (e.g. uesful for 3D modelling software). This // same scene in one window (e.g. useful for 3D modelling software). This
// demo uses scissors to separate the four different rendering areas from // demo uses scissors to separate the four different rendering areas from
// each other. // each other.
// //

View File

@ -190,6 +190,9 @@ extern "C" {
#else /*__APPLE__*/ #else /*__APPLE__*/
#include <GL/glcorearb.h> #include <GL/glcorearb.h>
#if defined(GLFW_INCLUDE_GLEXT)
#include <GL/glext.h>
#endif
#endif /*__APPLE__*/ #endif /*__APPLE__*/
@ -296,7 +299,7 @@ extern "C" {
* release is made that does not contain any API changes. * release is made that does not contain any API changes.
* @ingroup init * @ingroup init
*/ */
#define GLFW_VERSION_REVISION 5 #define GLFW_VERSION_REVISION 7
/*! @} */ /*! @} */
/*! @brief One. /*! @brief One.
@ -968,7 +971,7 @@ extern "C" {
* and [attribute](@ref GLFW_CONTEXT_VERSION_MINOR_attrib). * and [attribute](@ref GLFW_CONTEXT_VERSION_MINOR_attrib).
*/ */
#define GLFW_CONTEXT_VERSION_MINOR 0x00022003 #define GLFW_CONTEXT_VERSION_MINOR 0x00022003
/*! @brief Context client API revision number hint and attribute. /*! @brief Context client API revision number attribute.
* *
* Context client API revision number * Context client API revision number
* [attribute](@ref GLFW_CONTEXT_REVISION_attrib). * [attribute](@ref GLFW_CONTEXT_REVISION_attrib).
@ -3386,6 +3389,11 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* window);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @wayland Because Wayland wants every frame of the desktop to be
* complete, this function does not immediately make the window visible.
* Instead it will become visible the next time the window framebuffer is
* updated after this call.
*
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
* @sa @ref window_hide * @sa @ref window_hide
@ -5326,6 +5334,8 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string);
* joystick is not present, does not have a mapping or an * joystick is not present, does not have a mapping or an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref GLFW_INVALID_ENUM.
*
* @pointer_lifetime The returned string is allocated and freed by GLFW. You * @pointer_lifetime The returned string is allocated and freed by GLFW. You
* should not free it yourself. It is valid until the specified joystick is * should not free it yourself. It is valid until the specified joystick is
* disconnected, the gamepad mappings are updated or the library is terminated. * disconnected, the gamepad mappings are updated or the library is terminated.
@ -5415,8 +5425,8 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
* @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL`
* if an [error](@ref error_handling) occurred. * if an [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR. * GLFW_FORMAT_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
* *
* @pointer_lifetime The returned string is allocated and freed by GLFW. You * @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 * should not free it yourself. It is valid until the next call to @ref
@ -5810,9 +5820,6 @@ GLFWAPI int glfwVulkanSupported(void);
* returned array, as it is an error to specify an extension more than once in * returned array, as it is an error to specify an extension more than once in
* the `VkInstanceCreateInfo` struct. * the `VkInstanceCreateInfo` struct.
* *
* @remark @macos GLFW currently supports both the `VK_MVK_macos_surface` and
* the newer `VK_EXT_metal_surface` extensions.
*
* @pointer_lifetime The returned array is allocated and freed by GLFW. You * @pointer_lifetime The returned array is allocated and freed by GLFW. You
* should not free it yourself. It is guaranteed to be valid only until the * should not free it yourself. It is guaranteed to be valid only until the
* library is terminated. * library is terminated.
@ -5951,8 +5958,10 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhys
* @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should
* eliminate almost all occurrences of these errors. * eliminate almost all occurrences of these errors.
* *
* @remark @macos This function currently only supports the * @remark @macos GLFW prefers the `VK_EXT_metal_surface` extension, with the
* `VK_MVK_macos_surface` extension from MoltenVK. * `VK_MVK_macos_surface` extension as a fallback. The name of the selected
* extension, if any, is included in the array returned by @ref
* glfwGetRequiredInstanceExtensions.
* *
* @remark @macos This function creates and sets a `CAMetalLayer` instance for * @remark @macos This function creates and sets a `CAMetalLayer` instance for
* the window content view, which is required for MoltenVK to function. * the window content view, which is required for MoltenVK to function.

View File

@ -132,6 +132,8 @@ extern "C" {
* of the specified monitor, or `NULL` if an [error](@ref error_handling) * of the specified monitor, or `NULL` if an [error](@ref error_handling)
* occurred. * occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -147,6 +149,8 @@ GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor);
* `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -161,6 +165,8 @@ GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor);
* @return The `HWND` of the specified window, or `NULL` if an * @return The `HWND` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @remark The `HDC` associated with the window can be queried with the * @remark The `HDC` associated with the window can be queried with the
* [GetDC](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc) * [GetDC](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc)
* function. * function.
@ -185,6 +191,9 @@ GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window);
* @return The `HGLRC` of the specified window, or `NULL` if an * @return The `HGLRC` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
* GLFW_NOT_INITIALIZED.
*
* @remark The `HDC` associated with the window can be queried with the * @remark The `HDC` associated with the window can be queried with the
* [GetDC](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc) * [GetDC](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc)
* function. * function.
@ -209,6 +218,8 @@ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window);
* @return The `CGDirectDisplayID` of the specified monitor, or * @return The `CGDirectDisplayID` of the specified monitor, or
* `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -223,6 +234,8 @@ GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor);
* @return The `NSWindow` of the specified window, or `nil` if an * @return The `NSWindow` of the specified window, or `nil` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -239,6 +252,9 @@ GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window);
* @return The `NSOpenGLContext` of the specified window, or `nil` if an * @return The `NSOpenGLContext` of the specified window, or `nil` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
* GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -255,6 +271,8 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* window);
* @return The `Display` used by GLFW, or `NULL` if an * @return The `Display` used by GLFW, or `NULL` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -269,6 +287,8 @@ GLFWAPI Display* glfwGetX11Display(void);
* @return The `RRCrtc` of the specified monitor, or `None` if an * @return The `RRCrtc` of the specified monitor, or `None` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -283,6 +303,8 @@ GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
* @return The `RROutput` of the specified monitor, or `None` if an * @return The `RROutput` of the specified monitor, or `None` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -297,6 +319,8 @@ GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
* @return The `Window` of the specified window, or `None` if an * @return The `Window` of the specified window, or `None` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -363,6 +387,9 @@ GLFWAPI const char* glfwGetX11SelectionString(void);
* @return The `GLXContext` of the specified window, or `NULL` if an * @return The `GLXContext` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
* GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -377,6 +404,9 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);
* @return The `GLXWindow` of the specified window, or `None` if an * @return The `GLXWindow` of the specified window, or `None` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
* GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -393,6 +423,8 @@ GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window);
* @return The `struct wl_display*` used by GLFW, or `NULL` if an * @return The `struct wl_display*` used by GLFW, or `NULL` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -407,6 +439,8 @@ GLFWAPI struct wl_display* glfwGetWaylandDisplay(void);
* @return The `struct wl_output*` of the specified monitor, or `NULL` if an * @return The `struct wl_output*` of the specified monitor, or `NULL` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -421,6 +455,8 @@ GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
* @return The main `struct wl_surface*` of the specified window, or `NULL` if * @return The main `struct wl_surface*` of the specified window, or `NULL` if
* an [error](@ref error_handling) occurred. * an [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -437,6 +473,8 @@ GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
* @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -451,6 +489,9 @@ GLFWAPI EGLDisplay glfwGetEGLDisplay(void);
* @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
* GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -465,6 +506,9 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
* @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
* GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -488,6 +532,9 @@ GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
* GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -509,6 +556,9 @@ GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width, int* height
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
* GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *
@ -523,6 +573,9 @@ GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width, int* height
* @return The `OSMesaContext` of the specified window, or `NULL` if an * @return The `OSMesaContext` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
* GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Access is not
* synchronized. * synchronized.
* *

View File

@ -58,7 +58,7 @@ static char* getMonitorName(CGDirectDisplayID displayID, NSScreen* screen)
io_service_t service; io_service_t service;
CFDictionaryRef info; CFDictionaryRef info;
if (IOServiceGetMatchingServices(kIOMasterPortDefault, if (IOServiceGetMatchingServices(MACH_PORT_NULL,
IOServiceMatching("IODisplayConnect"), IOServiceMatching("IODisplayConnect"),
&it) != 0) &it) != 0)
{ {
@ -231,7 +231,7 @@ static double getFallbackRefreshRate(CGDirectDisplayID displayID)
io_iterator_t it; io_iterator_t it;
io_service_t service; io_service_t service;
if (IOServiceGetMatchingServices(kIOMasterPortDefault, if (IOServiceGetMatchingServices(MACH_PORT_NULL,
IOServiceMatching("IOFramebuffer"), IOServiceMatching("IOFramebuffer"),
&it) != 0) &it) != 0)
{ {

View File

@ -42,8 +42,10 @@ typedef void* id;
#endif #endif
// NOTE: Many Cocoa enum values have been renamed and we need to build across // NOTE: Many Cocoa enum values have been renamed and we need to build across
// SDK versions where one is unavailable or the other deprecated // SDK versions where one is unavailable or deprecated.
// We use the newer names in code and these macros to handle compatibility // We use the newer names in code and replace them with the older names if
// the base SDK does not provide the newer names.
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200 #if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat #define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
#define NSEventMaskAny NSAnyEventMask #define NSEventMaskAny NSAnyEventMask
@ -62,6 +64,15 @@ typedef void* id;
#define NSWindowStyleMaskTitled NSTitledWindowMask #define NSWindowStyleMaskTitled NSTitledWindowMask
#endif #endif
// NOTE: Many Cocoa dynamically linked constants have been renamed and we need
// to build across SDK versions where one is unavailable or deprecated.
// We use the newer names in code and replace them with the older names if
// the deployment target is older than the newer names.
#if MAC_OS_X_VERSION_MIN_REQUIRED < 101300
#define NSPasteboardTypeURL NSURLPboardType
#endif
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK; typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
typedef VkFlags VkMetalSurfaceCreateFlagsEXT; typedef VkFlags VkMetalSurfaceCreateFlagsEXT;
@ -135,7 +146,6 @@ typedef struct _GLFWwindowNS
// since the last cursor motion event was processed // since the last cursor motion event was processed
// This is kept to counteract Cocoa doing the same internally // This is kept to counteract Cocoa doing the same internally
double cursorWarpDeltaX, cursorWarpDeltaY; double cursorWarpDeltaX, cursorWarpDeltaY;
} _GLFWwindowNS; } _GLFWwindowNS;
// Cocoa-specific global data // Cocoa-specific global data
@ -170,7 +180,6 @@ typedef struct _GLFWlibraryNS
PFN_LMGetKbdType GetKbdType; PFN_LMGetKbdType GetKbdType;
CFStringRef kPropertyUnicodeKeyLayoutData; CFStringRef kPropertyUnicodeKeyLayoutData;
} tis; } tis;
} _GLFWlibraryNS; } _GLFWlibraryNS;
// Cocoa-specific per-monitor data // Cocoa-specific per-monitor data
@ -182,7 +191,6 @@ typedef struct _GLFWmonitorNS
uint32_t unitNumber; uint32_t unitNumber;
id screen; id screen;
double fallbackRefreshRate; double fallbackRefreshRate;
} _GLFWmonitorNS; } _GLFWmonitorNS;
// Cocoa-specific per-cursor data // Cocoa-specific per-cursor data
@ -190,7 +198,6 @@ typedef struct _GLFWmonitorNS
typedef struct _GLFWcursorNS typedef struct _GLFWcursorNS
{ {
id object; id object;
} _GLFWcursorNS; } _GLFWcursorNS;
// Cocoa-specific global timer data // Cocoa-specific global timer data
@ -198,7 +205,6 @@ typedef struct _GLFWcursorNS
typedef struct _GLFWtimerNS typedef struct _GLFWtimerNS
{ {
uint64_t frequency; uint64_t frequency;
} _GLFWtimerNS; } _GLFWtimerNS;

View File

@ -361,9 +361,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
markedText = [[NSMutableAttributedString alloc] init]; markedText = [[NSMutableAttributedString alloc] init];
[self updateTrackingAreas]; [self updateTrackingAreas];
// NOTE: kUTTypeURL corresponds to NSPasteboardTypeURL but is available [self registerForDraggedTypes:@[NSPasteboardTypeURL]];
// on 10.7 without having been deprecated yet
[self registerForDraggedTypes:@[(__bridge NSString*) kUTTypeURL]];
} }
return self; return self;

View File

@ -230,6 +230,12 @@ static void swapBuffersEGL(_GLFWwindow* window)
return; return;
} }
#if defined(_GLFW_WAYLAND)
// NOTE: Swapping buffers on a hidden window on Wayland makes it visible
if (!window->wl.visible)
return;
#endif
eglSwapBuffers(_glfw.egl.display, window->context.egl.surface); eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
} }
@ -314,6 +320,8 @@ GLFWbool _glfwInitEGL(void)
"libEGL.dylib", "libEGL.dylib",
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
"libEGL-1.so", "libEGL-1.so",
#elif defined(__OpenBSD__)
"libEGL.so",
#else #else
"libEGL.so.1", "libEGL.so.1",
#endif #endif
@ -426,6 +434,8 @@ GLFWbool _glfwInitEGL(void)
extensionSupportedEGL("EGL_KHR_get_all_proc_addresses"); extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
_glfw.egl.KHR_context_flush_control = _glfw.egl.KHR_context_flush_control =
extensionSupportedEGL("EGL_KHR_context_flush_control"); extensionSupportedEGL("EGL_KHR_context_flush_control");
_glfw.egl.EXT_present_opaque =
extensionSupportedEGL("EGL_EXT_present_opaque");
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -599,6 +609,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
if (!fbconfig->doublebuffer) if (!fbconfig->doublebuffer)
setAttrib(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER); setAttrib(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
if (_glfw.egl.EXT_present_opaque)
setAttrib(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent);
setAttrib(EGL_NONE, EGL_NONE); setAttrib(EGL_NONE, EGL_NONE);
window->context.egl.surface = window->context.egl.surface =
@ -630,6 +643,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
"libGLES_CM.dll", "libGLES_CM.dll",
#elif defined(_GLFW_COCOA) #elif defined(_GLFW_COCOA)
"libGLESv1_CM.dylib", "libGLESv1_CM.dylib",
#elif defined(__OpenBSD__)
"libGLESv1_CM.so",
#else #else
"libGLESv1_CM.so.1", "libGLESv1_CM.so.1",
"libGLES_CM.so.1", "libGLES_CM.so.1",
@ -647,6 +662,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
"libGLESv2.dylib", "libGLESv2.dylib",
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
"libGLESv2-2.so", "libGLESv2-2.so",
#elif defined(__OpenBSD__)
"libGLESv2.so",
#else #else
"libGLESv2.so.2", "libGLESv2.so.2",
#endif #endif
@ -658,6 +675,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
_GLFW_OPENGL_LIBRARY, _GLFW_OPENGL_LIBRARY,
#elif defined(_GLFW_WIN32) #elif defined(_GLFW_WIN32)
#elif defined(_GLFW_COCOA) #elif defined(_GLFW_COCOA)
#elif defined(__OpenBSD__)
"libGL.so",
#else #else
"libGL.so.1", "libGL.so.1",
#endif #endif
@ -765,7 +784,7 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT); _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT);
if (window->context.client == GLFW_NO_API) if (window->context.source != GLFW_EGL_CONTEXT_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return EGL_NO_CONTEXT; return EGL_NO_CONTEXT;
@ -779,7 +798,7 @@ GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE); _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE);
if (window->context.client == GLFW_NO_API) if (window->context.source != GLFW_EGL_CONTEXT_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return EGL_NO_SURFACE; return EGL_NO_SURFACE;

View File

@ -108,6 +108,7 @@ typedef struct wl_egl_window* EGLNativeWindowType;
#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097 #define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0 #define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098 #define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
#define EGL_PRESENT_OPAQUE_EXT 0x31df
typedef int EGLint; typedef int EGLint;
typedef unsigned int EGLBoolean; typedef unsigned int EGLBoolean;
@ -164,7 +165,6 @@ typedef struct _GLFWcontextEGL
EGLSurface surface; EGLSurface surface;
void* client; void* client;
} _GLFWcontextEGL; } _GLFWcontextEGL;
// EGL-specific global data // EGL-specific global data
@ -180,6 +180,7 @@ typedef struct _GLFWlibraryEGL
GLFWbool KHR_gl_colorspace; GLFWbool KHR_gl_colorspace;
GLFWbool KHR_get_all_proc_addresses; GLFWbool KHR_get_all_proc_addresses;
GLFWbool KHR_context_flush_control; GLFWbool KHR_context_flush_control;
GLFWbool EXT_present_opaque;
void* handle; void* handle;
@ -199,7 +200,6 @@ typedef struct _GLFWlibraryEGL
PFN_eglSwapInterval SwapInterval; PFN_eglSwapInterval SwapInterval;
PFN_eglQueryString QueryString; PFN_eglQueryString QueryString;
PFN_eglGetProcAddress GetProcAddress; PFN_eglGetProcAddress GetProcAddress;
} _GLFWlibraryEGL; } _GLFWlibraryEGL;

View File

@ -53,8 +53,6 @@
// Define this to 1 to force use of high-performance GPU on hybrid systems // Define this to 1 to force use of high-performance GPU on hybrid systems
#cmakedefine _GLFW_USE_HYBRID_HPG #cmakedefine _GLFW_USE_HYBRID_HPG
// Define this to 1 if xkbcommon supports the compose key
#cmakedefine HAVE_XKBCOMMON_COMPOSE_H
// Define this to 1 if the libc supports memfd_create() // Define this to 1 if the libc supports memfd_create()
#cmakedefine HAVE_MEMFD_CREATE #cmakedefine HAVE_MEMFD_CREATE

View File

@ -260,6 +260,8 @@ GLFWbool _glfwInitGLX(void)
_GLFW_GLX_LIBRARY, _GLFW_GLX_LIBRARY,
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
"libGL-1.so", "libGL-1.so",
#elif defined(__OpenBSD__)
"libGL.so",
#else #else
"libGL.so.1", "libGL.so.1",
"libGL.so", "libGL.so",
@ -674,7 +676,7 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (window->context.client == GLFW_NO_API) if (window->context.source != GLFW_NATIVE_CONTEXT_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL; return NULL;
@ -688,7 +690,7 @@ GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(None); _GLFW_REQUIRE_INIT_OR_RETURN(None);
if (window->context.client == GLFW_NO_API) if (window->context.source != GLFW_NATIVE_CONTEXT_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return None; return None;

View File

@ -117,7 +117,6 @@ typedef struct _GLFWcontextGLX
{ {
GLXContext handle; GLXContext handle;
GLXWindow window; GLXWindow window;
} _GLFWcontextGLX; } _GLFWcontextGLX;
// GLX-specific global data // GLX-specific global data
@ -165,7 +164,6 @@ typedef struct _GLFWlibraryGLX
GLFWbool EXT_create_context_es2_profile; GLFWbool EXT_create_context_es2_profile;
GLFWbool ARB_create_context_no_error; GLFWbool ARB_create_context_no_error;
GLFWbool ARB_context_flush_control; GLFWbool ARB_context_flush_control;
} _GLFWlibraryGLX; } _GLFWlibraryGLX;
GLFWbool _glfwInitGLX(void); GLFWbool _glfwInitGLX(void);

View File

@ -36,16 +36,15 @@
#include <assert.h> #include <assert.h>
// The global variables below comprise all mutable global data in GLFW // NOTE: The global variables below comprise all mutable global data in GLFW
// // Any other mutable global variable is a bug
// Any other global variable is a bug
// Global state shared between compilation units of GLFW // This contains all mutable state shared between compilation units of GLFW
// //
_GLFWlibrary _glfw = { GLFW_FALSE }; _GLFWlibrary _glfw = { GLFW_FALSE };
// These are outside of _glfw so they can be used before initialization and // These are outside of _glfw so they can be used before initialization and
// after termination // after termination without special handling when _glfw is cleared to zero
// //
static _GLFWerror _glfwMainThreadError; static _GLFWerror _glfwMainThreadError;
static GLFWerrorfun _glfwErrorCallback; static GLFWerrorfun _glfwErrorCallback;
@ -112,6 +111,37 @@ static void terminate(void)
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Encode a Unicode code point to a UTF-8 stream
// Based on cutef8 by Jeff Bezanson (Public Domain)
//
size_t _glfwEncodeUTF8(char* s, uint32_t codepoint)
{
size_t count = 0;
if (codepoint < 0x80)
s[count++] = (char) codepoint;
else if (codepoint < 0x800)
{
s[count++] = (codepoint >> 6) | 0xc0;
s[count++] = (codepoint & 0x3f) | 0x80;
}
else if (codepoint < 0x10000)
{
s[count++] = (codepoint >> 12) | 0xe0;
s[count++] = ((codepoint >> 6) & 0x3f) | 0x80;
s[count++] = (codepoint & 0x3f) | 0x80;
}
else if (codepoint < 0x110000)
{
s[count++] = (codepoint >> 18) | 0xf0;
s[count++] = ((codepoint >> 12) & 0x3f) | 0x80;
s[count++] = ((codepoint >> 6) & 0x3f) | 0x80;
s[count++] = (codepoint & 0x3f) | 0x80;
}
return count;
}
char* _glfw_strdup(const char* source) char* _glfw_strdup(const char* source)
{ {
const size_t length = strlen(source); const size_t length = strlen(source);

View File

@ -278,7 +278,7 @@ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int m
// Notifies shared code of a Unicode codepoint input event // Notifies shared code of a Unicode codepoint input event
// The 'plain' parameter determines whether to emit a regular character event // The 'plain' parameter determines whether to emit a regular character event
// //
void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain) void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool plain)
{ {
if (codepoint < 32 || (codepoint > 126 && codepoint < 160)) if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
return; return;
@ -401,6 +401,7 @@ void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
// //
void _glfwInitGamepadMappings(void) void _glfwInitGamepadMappings(void)
{ {
int jid;
size_t i; size_t i;
const size_t count = sizeof(_glfwDefaultMappings) / sizeof(char*); const size_t count = sizeof(_glfwDefaultMappings) / sizeof(char*);
_glfw.mappings = calloc(count, sizeof(_GLFWmapping)); _glfw.mappings = calloc(count, sizeof(_GLFWmapping));
@ -410,6 +411,13 @@ void _glfwInitGamepadMappings(void)
if (parseMapping(&_glfw.mappings[_glfw.mappingCount], _glfwDefaultMappings[i])) if (parseMapping(&_glfw.mappings[_glfw.mappingCount], _glfwDefaultMappings[i]))
_glfw.mappingCount++; _glfw.mappingCount++;
} }
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
_GLFWjoystick* js = _glfw.joysticks + jid;
if (js->present)
js->mapping = findValidMapping(js);
}
} }
// Returns an available joystick object with arrays and name allocated // Returns an available joystick object with arrays and name allocated

View File

@ -718,7 +718,7 @@ void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
void _glfwInputKey(_GLFWwindow* window, void _glfwInputKey(_GLFWwindow* window,
int key, int scancode, int action, int mods); int key, int scancode, int action, int mods);
void _glfwInputChar(_GLFWwindow* window, void _glfwInputChar(_GLFWwindow* window,
unsigned int codepoint, int mods, GLFWbool plain); uint32_t codepoint, int mods, GLFWbool plain);
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset); void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset);
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods); void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos); void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
@ -774,6 +774,8 @@ GLFWbool _glfwInitVulkan(int mode);
void _glfwTerminateVulkan(void); void _glfwTerminateVulkan(void);
const char* _glfwGetVulkanResultString(VkResult result); const char* _glfwGetVulkanResultString(VkResult result);
size_t _glfwEncodeUTF8(char* s, uint32_t codepoint);
char* _glfw_strdup(const char* source); char* _glfw_strdup(const char* source);
float _glfw_fminf(float a, float b); float _glfw_fminf(float a, float b);
float _glfw_fmaxf(float a, float b); float _glfw_fmaxf(float a, float b);

View File

@ -25,8 +25,10 @@
//======================================================================== //========================================================================
// NOTE: Many Cocoa enum values have been renamed and we need to build across // NOTE: Many Cocoa enum values have been renamed and we need to build across
// SDK versions where one is unavailable or the other deprecated // SDK versions where one is unavailable or deprecated.
// We use the newer names in code and these macros to handle compatibility // We use the newer names in code and replace them with the older names if
// the base SDK does not provide the newer names.
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101400 #if MAC_OS_X_VERSION_MAX_ALLOWED < 101400
#define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval #define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval
#define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity #define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
@ -44,7 +46,6 @@ typedef struct _GLFWcontextNSGL
{ {
id pixelFormat; id pixelFormat;
id object; id object;
} _GLFWcontextNSGL; } _GLFWcontextNSGL;
// NSGL-specific global data // NSGL-specific global data
@ -53,7 +54,6 @@ typedef struct _GLFWlibraryNSGL
{ {
// dlopen handle for OpenGL.framework (for glfwGetProcAddress) // dlopen handle for OpenGL.framework (for glfwGetProcAddress)
CFBundleRef framework; CFBundleRef framework;
} _GLFWlibraryNSGL; } _GLFWlibraryNSGL;

View File

@ -365,7 +365,7 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(nil); _GLFW_REQUIRE_INIT_OR_RETURN(nil);
if (window->context.client == GLFW_NO_API) if (window->context.source != GLFW_NATIVE_CONTEXT_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return nil; return nil;

View File

@ -124,6 +124,8 @@ GLFWbool _glfwInitOSMesa(void)
"libOSMesa.8.dylib", "libOSMesa.8.dylib",
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
"libOSMesa-8.so", "libOSMesa-8.so",
#elif defined(__OpenBSD__)
"libOSMesa.so",
#else #else
"libOSMesa.so.8", "libOSMesa.so.8",
"libOSMesa.so.6", "libOSMesa.so.6",
@ -302,6 +304,12 @@ GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
if (window->context.source != GLFW_OSMESA_CONTEXT_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return GLFW_FALSE;
}
if (!OSMesaGetColorBuffer(window->context.osmesa.handle, if (!OSMesaGetColorBuffer(window->context.osmesa.handle,
&mesaWidth, &mesaHeight, &mesaWidth, &mesaHeight,
&mesaFormat, &mesaBuffer)) &mesaFormat, &mesaBuffer))
@ -335,6 +343,12 @@ GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
if (window->context.source != GLFW_OSMESA_CONTEXT_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return GLFW_FALSE;
}
if (!OSMesaGetDepthBuffer(window->context.osmesa.handle, if (!OSMesaGetDepthBuffer(window->context.osmesa.handle,
&mesaWidth, &mesaHeight, &mesaWidth, &mesaHeight,
&mesaBytes, &mesaBuffer)) &mesaBytes, &mesaBuffer))
@ -361,7 +375,7 @@ GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (window->context.client == GLFW_NO_API) if (window->context.source != GLFW_OSMESA_CONTEXT_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL; return NULL;

View File

@ -66,7 +66,6 @@ typedef struct _GLFWcontextOSMesa
int width; int width;
int height; int height;
void* buffer; void* buffer;
} _GLFWcontextOSMesa; } _GLFWcontextOSMesa;
// OSMesa-specific global data // OSMesa-specific global data
@ -82,7 +81,6 @@ typedef struct _GLFWlibraryOSMesa
PFN_OSMesaGetColorBuffer GetColorBuffer; PFN_OSMesaGetColorBuffer GetColorBuffer;
PFN_OSMesaGetDepthBuffer GetDepthBuffer; PFN_OSMesaGetDepthBuffer GetDepthBuffer;
PFN_OSMesaGetProcAddress GetProcAddress; PFN_OSMesaGetProcAddress GetProcAddress;
} _GLFWlibraryOSMesa; } _GLFWlibraryOSMesa;

View File

@ -37,7 +37,6 @@ typedef struct _GLFWtlsPOSIX
{ {
GLFWbool allocated; GLFWbool allocated;
pthread_key_t key; pthread_key_t key;
} _GLFWtlsPOSIX; } _GLFWtlsPOSIX;
// POSIX-specific mutex data // POSIX-specific mutex data
@ -46,6 +45,5 @@ typedef struct _GLFWmutexPOSIX
{ {
GLFWbool allocated; GLFWbool allocated;
pthread_mutex_t handle; pthread_mutex_t handle;
} _GLFWmutexPOSIX; } _GLFWmutexPOSIX;

View File

@ -36,7 +36,6 @@ typedef struct _GLFWtimerPOSIX
{ {
GLFWbool monotonic; GLFWbool monotonic;
uint64_t frequency; uint64_t frequency;
} _GLFWtimerPOSIX; } _GLFWtimerPOSIX;

View File

@ -59,6 +59,8 @@ GLFWbool _glfwInitVulkan(int mode)
_glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib"); _glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
if (!_glfw.vk.handle) if (!_glfw.vk.handle)
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS(); _glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS();
#elif defined(__OpenBSD__)
_glfw.vk.handle = _glfw_dlopen("libvulkan.so");
#else #else
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1"); _glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
#endif #endif

View File

@ -787,7 +787,7 @@ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (window->context.client == GLFW_NO_API) if (window->context.source != GLFW_NATIVE_CONTEXT_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL; return NULL;

View File

@ -115,7 +115,6 @@ typedef struct _GLFWcontextWGL
HDC dc; HDC dc;
HGLRC handle; HGLRC handle;
int interval; int interval;
} _GLFWcontextWGL; } _GLFWcontextWGL;
// WGL-specific global data // WGL-specific global data
@ -148,7 +147,6 @@ typedef struct _GLFWlibraryWGL
GLFWbool ARB_create_context_robustness; GLFWbool ARB_create_context_robustness;
GLFWbool ARB_create_context_no_error; GLFWbool ARB_create_context_no_error;
GLFWbool ARB_context_flush_control; GLFWbool ARB_context_flush_control;
} _GLFWlibraryWGL; } _GLFWlibraryWGL;

View File

@ -72,17 +72,6 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
// //
static GLFWbool loadLibraries(void) 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");
return GLFW_FALSE;
}
_glfw.win32.winmm.GetTime = (PFN_timeGetTime)
GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");
_glfw.win32.user32.instance = LoadLibraryA("user32.dll"); _glfw.win32.user32.instance = LoadLibraryA("user32.dll");
if (!_glfw.win32.user32.instance) if (!_glfw.win32.user32.instance)
{ {
@ -180,9 +169,6 @@ static void freeLibraries(void)
if (_glfw.win32.dinput8.instance) if (_glfw.win32.dinput8.instance)
FreeLibrary(_glfw.win32.dinput8.instance); FreeLibrary(_glfw.win32.dinput8.instance);
if (_glfw.win32.winmm.instance)
FreeLibrary(_glfw.win32.winmm.instance);
if (_glfw.win32.user32.instance) if (_glfw.win32.user32.instance)
FreeLibrary(_glfw.win32.user32.instance); FreeLibrary(_glfw.win32.user32.instance);

View File

@ -318,8 +318,19 @@ void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* ysc
{ {
UINT xdpi, ydpi; UINT xdpi, ydpi;
if (xscale)
*xscale = 0.f;
if (yscale)
*yscale = 0.f;
if (IsWindows8Point1OrGreater()) if (IsWindows8Point1OrGreater())
GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi); {
if (GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi) != S_OK)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to query monitor DPI");
return;
}
}
else else
{ {
const HDC dc = GetDC(NULL); const HDC dc = GetDC(NULL);

View File

@ -218,10 +218,6 @@ typedef enum
#define DIDFT_OPTIONAL 0x80000000 #define DIDFT_OPTIONAL 0x80000000
#endif #endif
// winmm.dll function pointer typedefs
typedef DWORD (WINAPI * PFN_timeGetTime)(void);
#define timeGetTime _glfw.win32.winmm.GetTime
// xinput.dll function pointer typedefs // xinput.dll function pointer typedefs
typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*); typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*);
typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*); typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
@ -328,7 +324,6 @@ typedef struct _GLFWwindowWin32
int lastCursorPosX, lastCursorPosY; int lastCursorPosX, lastCursorPosY;
// The last recevied high surrogate when decoding pairs of UTF-16 messages // The last recevied high surrogate when decoding pairs of UTF-16 messages
WCHAR highSurrogate; WCHAR highSurrogate;
} _GLFWwindowWin32; } _GLFWwindowWin32;
// Win32-specific global data // Win32-specific global data
@ -351,11 +346,6 @@ typedef struct _GLFWlibraryWin32
int rawInputSize; int rawInputSize;
UINT mouseTrailSize; UINT mouseTrailSize;
struct {
HINSTANCE instance;
PFN_timeGetTime GetTime;
} winmm;
struct { struct {
HINSTANCE instance; HINSTANCE instance;
PFN_DirectInput8Create Create; PFN_DirectInput8Create Create;
@ -396,7 +386,6 @@ typedef struct _GLFWlibraryWin32
HINSTANCE instance; HINSTANCE instance;
PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_; PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_;
} ntdll; } ntdll;
} _GLFWlibraryWin32; } _GLFWlibraryWin32;
// Win32-specific per-monitor data // Win32-specific per-monitor data
@ -411,7 +400,6 @@ typedef struct _GLFWmonitorWin32
char publicDisplayName[32]; char publicDisplayName[32];
GLFWbool modesPruned; GLFWbool modesPruned;
GLFWbool modeChanged; GLFWbool modeChanged;
} _GLFWmonitorWin32; } _GLFWmonitorWin32;
// Win32-specific per-cursor data // Win32-specific per-cursor data
@ -419,16 +407,13 @@ typedef struct _GLFWmonitorWin32
typedef struct _GLFWcursorWin32 typedef struct _GLFWcursorWin32
{ {
HCURSOR handle; HCURSOR handle;
} _GLFWcursorWin32; } _GLFWcursorWin32;
// Win32-specific global timer data // Win32-specific global timer data
// //
typedef struct _GLFWtimerWin32 typedef struct _GLFWtimerWin32
{ {
GLFWbool hasPC;
uint64_t frequency; uint64_t frequency;
} _GLFWtimerWin32; } _GLFWtimerWin32;
// Win32-specific thread local storage data // Win32-specific thread local storage data
@ -437,7 +422,6 @@ typedef struct _GLFWtlsWin32
{ {
GLFWbool allocated; GLFWbool allocated;
DWORD index; DWORD index;
} _GLFWtlsWin32; } _GLFWtlsWin32;
// Win32-specific mutex data // Win32-specific mutex data
@ -446,7 +430,6 @@ typedef struct _GLFWmutexWin32
{ {
GLFWbool allocated; GLFWbool allocated;
CRITICAL_SECTION section; CRITICAL_SECTION section;
} _GLFWmutexWin32; } _GLFWmutexWin32;

View File

@ -38,18 +38,7 @@
// //
void _glfwInitTimerWin32(void) void _glfwInitTimerWin32(void)
{ {
uint64_t frequency; QueryPerformanceFrequency((LARGE_INTEGER*) &_glfw.timer.win32.frequency);
if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
{
_glfw.timer.win32.hasPC = GLFW_TRUE;
_glfw.timer.win32.frequency = frequency;
}
else
{
_glfw.timer.win32.hasPC = GLFW_FALSE;
_glfw.timer.win32.frequency = 1000;
}
} }
@ -59,14 +48,9 @@ void _glfwInitTimerWin32(void)
uint64_t _glfwPlatformGetTimerValue(void) uint64_t _glfwPlatformGetTimerValue(void)
{ {
if (_glfw.timer.win32.hasPC) uint64_t value;
{ QueryPerformanceCounter((LARGE_INTEGER*) &value);
uint64_t value; return value;
QueryPerformanceCounter((LARGE_INTEGER*) &value);
return value;
}
else
return (uint64_t) timeGetTime();
} }
uint64_t _glfwPlatformGetTimerFrequency(void) uint64_t _glfwPlatformGetTimerFrequency(void)

View File

@ -646,7 +646,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
window->win32.highSurrogate = (WCHAR) wParam; window->win32.highSurrogate = (WCHAR) wParam;
else else
{ {
unsigned int codepoint = 0; uint32_t codepoint = 0;
if (wParam >= 0xdc00 && wParam <= 0xdfff) if (wParam >= 0xdc00 && wParam <= 0xdfff)
{ {
@ -677,7 +677,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
return TRUE; return TRUE;
} }
_glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GLFW_TRUE); _glfwInputChar(window, (uint32_t) wParam, getKeyMods(), GLFW_TRUE);
return 0; return 0;
} }
@ -1297,8 +1297,12 @@ static int createNativeWindow(_GLFWwindow* window,
{ {
float xscale, yscale; float xscale, yscale;
_glfwPlatformGetWindowContentScale(window, &xscale, &yscale); _glfwPlatformGetWindowContentScale(window, &xscale, &yscale);
rect.right = (int) (rect.right * xscale);
rect.bottom = (int) (rect.bottom * yscale); if (xscale > 0.f && yscale > 0.f)
{
rect.right = (int) (rect.right * xscale);
rect.bottom = (int) (rect.bottom * yscale);
}
} }
ClientToScreen(window->win32.handle, (POINT*) &rect.left); ClientToScreen(window->win32.handle, (POINT*) &rect.left);

View File

@ -193,12 +193,12 @@ static void pointerHandleMotion(void* data,
return; return;
x = wl_fixed_to_double(sx); x = wl_fixed_to_double(sx);
y = wl_fixed_to_double(sy); y = wl_fixed_to_double(sy);
window->wl.cursorPosX = x;
window->wl.cursorPosY = y;
switch (window->wl.decorations.focus) switch (window->wl.decorations.focus)
{ {
case mainWindow: case mainWindow:
window->wl.cursorPosX = x;
window->wl.cursorPosY = y;
_glfwInputCursorPos(window, x, y); _glfwInputCursorPos(window, x, y);
_glfw.wl.cursorPreviousName = NULL; _glfw.wl.cursorPreviousName = NULL;
return; return;
@ -298,6 +298,7 @@ static void pointerHandleButton(void* data,
else else
wl_shell_surface_resize(window->wl.shellSurface, _glfw.wl.seat, wl_shell_surface_resize(window->wl.shellSurface, _glfw.wl.seat,
serial, edges); serial, edges);
return;
} }
} }
else if (button == BTN_RIGHT) else if (button == BTN_RIGHT)
@ -373,12 +374,8 @@ static void keyboardHandleKeymap(void* data,
{ {
struct xkb_keymap* keymap; struct xkb_keymap* keymap;
struct xkb_state* state; struct xkb_state* state;
#ifdef HAVE_XKBCOMMON_COMPOSE_H
struct xkb_compose_table* composeTable; struct xkb_compose_table* composeTable;
struct xkb_compose_state* composeState; struct xkb_compose_state* composeState;
#endif
char* mapStr; char* mapStr;
const char* locale; const char* locale;
@ -426,7 +423,6 @@ static void keyboardHandleKeymap(void* data,
if (!locale) if (!locale)
locale = "C"; locale = "C";
#ifdef HAVE_XKBCOMMON_COMPOSE_H
composeTable = composeTable =
xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale, xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
XKB_COMPOSE_COMPILE_NO_FLAGS); XKB_COMPOSE_COMPILE_NO_FLAGS);
@ -446,7 +442,6 @@ static void keyboardHandleKeymap(void* data,
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to create XKB compose table"); "Wayland: Failed to create XKB compose table");
} }
#endif
xkb_keymap_unref(_glfw.wl.xkb.keymap); xkb_keymap_unref(_glfw.wl.xkb.keymap);
xkb_state_unref(_glfw.wl.xkb.state); xkb_state_unref(_glfw.wl.xkb.state);
@ -500,20 +495,22 @@ static void keyboardHandleLeave(void* data,
if (!window) if (!window)
return; return;
struct itimerspec timer = {};
timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
_glfw.wl.serial = serial; _glfw.wl.serial = serial;
_glfw.wl.keyboardFocus = NULL; _glfw.wl.keyboardFocus = NULL;
_glfwInputWindowFocus(window, GLFW_FALSE); _glfwInputWindowFocus(window, GLFW_FALSE);
} }
static int toGLFWKeyCode(uint32_t key) static int translateKey(uint32_t scancode)
{ {
if (key < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0])) if (scancode < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
return _glfw.wl.keycodes[key]; return _glfw.wl.keycodes[scancode];
return GLFW_KEY_UNKNOWN; return GLFW_KEY_UNKNOWN;
} }
#ifdef HAVE_XKBCOMMON_COMPOSE_H
static xkb_keysym_t composeSymbol(xkb_keysym_t sym) static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
{ {
if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState) if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
@ -533,77 +530,65 @@ static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
return sym; return sym;
} }
} }
#endif
static GLFWbool inputChar(_GLFWwindow* window, uint32_t key) GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode)
{ {
uint32_t code, numSyms; const xkb_keysym_t* keysyms;
long cp; const xkb_keycode_t keycode = scancode + 8;
const xkb_keysym_t *syms;
xkb_keysym_t sym;
code = key + 8; if (xkb_state_key_get_syms(_glfw.wl.xkb.state, keycode, &keysyms) == 1)
numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms);
if (numSyms == 1)
{ {
#ifdef HAVE_XKBCOMMON_COMPOSE_H const xkb_keysym_t keysym = composeSymbol(keysyms[0]);
sym = composeSymbol(syms[0]); const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
#else if (codepoint != GLFW_INVALID_CODEPOINT)
sym = syms[0];
#endif
cp = _glfwKeySym2Unicode(sym);
if (cp != -1)
{ {
const int mods = _glfw.wl.xkb.modifiers; const int mods = _glfw.wl.xkb.modifiers;
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
_glfwInputChar(window, cp, mods, plain); _glfwInputChar(window, codepoint, mods, plain);
} }
} }
return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, code); return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, keycode);
} }
static void keyboardHandleKey(void* data, static void keyboardHandleKey(void* data,
struct wl_keyboard* keyboard, struct wl_keyboard* keyboard,
uint32_t serial, uint32_t serial,
uint32_t time, uint32_t time,
uint32_t key, uint32_t scancode,
uint32_t state) uint32_t state)
{ {
int keyCode;
int action;
_GLFWwindow* window = _glfw.wl.keyboardFocus; _GLFWwindow* window = _glfw.wl.keyboardFocus;
GLFWbool shouldRepeat;
struct itimerspec timer = {};
if (!window) if (!window)
return; return;
keyCode = toGLFWKeyCode(key); const int key = translateKey(scancode);
action = state == WL_KEYBOARD_KEY_STATE_PRESSED const int action =
? GLFW_PRESS : GLFW_RELEASE; state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
_glfw.wl.serial = serial; _glfw.wl.serial = serial;
_glfwInputKey(window, keyCode, key, action, _glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers);
_glfw.wl.xkb.modifiers);
struct itimerspec timer = {};
if (action == GLFW_PRESS) if (action == GLFW_PRESS)
{ {
shouldRepeat = inputChar(window, key); const GLFWbool shouldRepeat = _glfwInputTextWayland(window, scancode);
if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0) if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0)
{ {
_glfw.wl.keyboardLastKey = keyCode; _glfw.wl.keyboardLastKey = key;
_glfw.wl.keyboardLastScancode = key; _glfw.wl.keyboardLastScancode = scancode;
if (_glfw.wl.keyboardRepeatRate > 1) if (_glfw.wl.keyboardRepeatRate > 1)
timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyboardRepeatRate; timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyboardRepeatRate;
else else
timer.it_interval.tv_sec = 1; timer.it_interval.tv_sec = 1;
timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000; timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000;
timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000; timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000;
} }
} }
timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL); timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
} }
@ -615,9 +600,6 @@ static void keyboardHandleModifiers(void* data,
uint32_t modsLocked, uint32_t modsLocked,
uint32_t group) uint32_t group)
{ {
xkb_mod_mask_t mask;
unsigned int modifiers = 0;
_glfw.wl.serial = serial; _glfw.wl.serial = serial;
if (!_glfw.wl.xkb.keymap) if (!_glfw.wl.xkb.keymap)
@ -631,24 +613,29 @@ static void keyboardHandleModifiers(void* data,
0, 0,
group); group);
mask = xkb_state_serialize_mods(_glfw.wl.xkb.state, const xkb_mod_mask_t mask =
XKB_STATE_MODS_DEPRESSED | xkb_state_serialize_mods(_glfw.wl.xkb.state,
XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_MODS_DEPRESSED |
XKB_STATE_MODS_LATCHED | XKB_STATE_LAYOUT_DEPRESSED |
XKB_STATE_LAYOUT_LATCHED); XKB_STATE_MODS_LATCHED |
XKB_STATE_LAYOUT_LATCHED);
unsigned int mods = 0;
if (mask & _glfw.wl.xkb.controlMask) if (mask & _glfw.wl.xkb.controlMask)
modifiers |= GLFW_MOD_CONTROL; mods |= GLFW_MOD_CONTROL;
if (mask & _glfw.wl.xkb.altMask) if (mask & _glfw.wl.xkb.altMask)
modifiers |= GLFW_MOD_ALT; mods |= GLFW_MOD_ALT;
if (mask & _glfw.wl.xkb.shiftMask) if (mask & _glfw.wl.xkb.shiftMask)
modifiers |= GLFW_MOD_SHIFT; mods |= GLFW_MOD_SHIFT;
if (mask & _glfw.wl.xkb.superMask) if (mask & _glfw.wl.xkb.superMask)
modifiers |= GLFW_MOD_SUPER; mods |= GLFW_MOD_SUPER;
if (mask & _glfw.wl.xkb.capsLockMask) if (mask & _glfw.wl.xkb.capsLockMask)
modifiers |= GLFW_MOD_CAPS_LOCK; mods |= GLFW_MOD_CAPS_LOCK;
if (mask & _glfw.wl.xkb.numLockMask) if (mask & _glfw.wl.xkb.numLockMask)
modifiers |= GLFW_MOD_NUM_LOCK; mods |= GLFW_MOD_NUM_LOCK;
_glfw.wl.xkb.modifiers = modifiers;
_glfw.wl.xkb.modifiers = mods;
} }
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION #ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
@ -973,7 +960,7 @@ static void createKeyTables(void)
_glfw.wl.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT; _glfw.wl.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
_glfw.wl.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER; _glfw.wl.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
_glfw.wl.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER; _glfw.wl.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
_glfw.wl.keycodes[KEY_MENU] = GLFW_KEY_MENU; _glfw.wl.keycodes[KEY_COMPOSE] = GLFW_KEY_MENU;
_glfw.wl.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK; _glfw.wl.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
_glfw.wl.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK; _glfw.wl.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
_glfw.wl.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN; _glfw.wl.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
@ -1016,7 +1003,7 @@ static void createKeyTables(void)
_glfw.wl.keycodes[KEY_F23] = GLFW_KEY_F23; _glfw.wl.keycodes[KEY_F23] = GLFW_KEY_F23;
_glfw.wl.keycodes[KEY_F24] = GLFW_KEY_F24; _glfw.wl.keycodes[KEY_F24] = GLFW_KEY_F24;
_glfw.wl.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE; _glfw.wl.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
_glfw.wl.keycodes[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY; _glfw.wl.keycodes[KEY_KPASTERISK] = GLFW_KEY_KP_MULTIPLY;
_glfw.wl.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT; _glfw.wl.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
_glfw.wl.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD; _glfw.wl.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
_glfw.wl.keycodes[KEY_KP0] = GLFW_KEY_KP_0; _glfw.wl.keycodes[KEY_KP0] = GLFW_KEY_KP_0;
@ -1029,9 +1016,10 @@ static void createKeyTables(void)
_glfw.wl.keycodes[KEY_KP7] = GLFW_KEY_KP_7; _glfw.wl.keycodes[KEY_KP7] = GLFW_KEY_KP_7;
_glfw.wl.keycodes[KEY_KP8] = GLFW_KEY_KP_8; _glfw.wl.keycodes[KEY_KP8] = GLFW_KEY_KP_8;
_glfw.wl.keycodes[KEY_KP9] = GLFW_KEY_KP_9; _glfw.wl.keycodes[KEY_KP9] = GLFW_KEY_KP_9;
_glfw.wl.keycodes[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL; _glfw.wl.keycodes[KEY_KPDOT] = GLFW_KEY_KP_DECIMAL;
_glfw.wl.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL; _glfw.wl.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
_glfw.wl.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER; _glfw.wl.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
_glfw.wl.keycodes[KEY_102ND] = GLFW_KEY_WORLD_2;
for (scancode = 0; scancode < 256; scancode++) for (scancode = 0; scancode < 256; scancode++)
{ {
@ -1105,6 +1093,8 @@ int _glfwPlatformInit(void)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index"); _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
_glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats) _glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats"); _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats");
_glfw.wl.xkb.keymap_key_get_syms_by_level = (PFN_xkb_keymap_key_get_syms_by_level)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_get_syms_by_level");
_glfw.wl.xkb.state_new = (PFN_xkb_state_new) _glfw.wl.xkb.state_new = (PFN_xkb_state_new)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new"); _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new");
_glfw.wl.xkb.state_unref = (PFN_xkb_state_unref) _glfw.wl.xkb.state_unref = (PFN_xkb_state_unref)
@ -1115,8 +1105,9 @@ int _glfwPlatformInit(void)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask"); _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask");
_glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods) _glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods"); _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods");
_glfw.wl.xkb.state_key_get_layout = (PFN_xkb_state_key_get_layout)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_layout");
#ifdef HAVE_XKBCOMMON_COMPOSE_H
_glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale) _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale"); _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");
_glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref) _glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref)
@ -1131,7 +1122,6 @@ int _glfwPlatformInit(void)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status"); _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status");
_glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym) _glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym"); _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");
#endif
_glfw.wl.display = wl_display_connect(NULL); _glfw.wl.display = wl_display_connect(NULL);
if (!_glfw.wl.display) if (!_glfw.wl.display)
@ -1169,7 +1159,7 @@ int _glfwPlatformInit(void)
_glfw.wl.timerfd = -1; _glfw.wl.timerfd = -1;
if (_glfw.wl.seatVersion >= 4) if (_glfw.wl.seatVersion >= 4)
_glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
if (_glfw.wl.pointer && _glfw.wl.shm) if (_glfw.wl.pointer && _glfw.wl.shm)
{ {
@ -1196,7 +1186,7 @@ int _glfwPlatformInit(void)
wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm); wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm);
_glfw.wl.cursorSurface = _glfw.wl.cursorSurface =
wl_compositor_create_surface(_glfw.wl.compositor); wl_compositor_create_surface(_glfw.wl.compositor);
_glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
} }
if (_glfw.wl.seat && _glfw.wl.dataDeviceManager) if (_glfw.wl.seat && _glfw.wl.dataDeviceManager)
@ -1230,10 +1220,8 @@ void _glfwPlatformTerminate(void)
_glfw.wl.egl.handle = NULL; _glfw.wl.egl.handle = NULL;
} }
#ifdef HAVE_XKBCOMMON_COMPOSE_H
if (_glfw.wl.xkb.composeState) if (_glfw.wl.xkb.composeState)
xkb_compose_state_unref(_glfw.wl.xkb.composeState); xkb_compose_state_unref(_glfw.wl.xkb.composeState);
#endif
if (_glfw.wl.xkb.keymap) if (_glfw.wl.xkb.keymap)
xkb_keymap_unref(_glfw.wl.xkb.keymap); xkb_keymap_unref(_glfw.wl.xkb.keymap);
if (_glfw.wl.xkb.state) if (_glfw.wl.xkb.state)

View File

@ -26,9 +26,7 @@
#include <wayland-client.h> #include <wayland-client.h>
#include <xkbcommon/xkbcommon.h> #include <xkbcommon/xkbcommon.h>
#ifdef HAVE_XKBCOMMON_COMPOSE_H
#include <xkbcommon/xkbcommon-compose.h> #include <xkbcommon/xkbcommon-compose.h>
#endif
#include <dlfcn.h> #include <dlfcn.h>
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR; typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
@ -112,24 +110,27 @@ typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context
typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*); typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*);
typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*); typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*);
typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t); typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t);
typedef int (* PFN_xkb_keymap_key_get_syms_by_level)(struct xkb_keymap*,xkb_keycode_t,xkb_layout_index_t,xkb_level_index_t,const xkb_keysym_t**);
typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*); typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
typedef void (* PFN_xkb_state_unref)(struct xkb_state*); typedef void (* PFN_xkb_state_unref)(struct xkb_state*);
typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**); typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t); typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component); typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component);
typedef xkb_layout_index_t (* PFN_xkb_state_key_get_layout)(struct xkb_state*,xkb_keycode_t);
#define xkb_context_new _glfw.wl.xkb.context_new #define xkb_context_new _glfw.wl.xkb.context_new
#define xkb_context_unref _glfw.wl.xkb.context_unref #define xkb_context_unref _glfw.wl.xkb.context_unref
#define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string #define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string
#define xkb_keymap_unref _glfw.wl.xkb.keymap_unref #define xkb_keymap_unref _glfw.wl.xkb.keymap_unref
#define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index #define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index
#define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats #define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats
#define xkb_keymap_key_get_syms_by_level _glfw.wl.xkb.keymap_key_get_syms_by_level
#define xkb_state_new _glfw.wl.xkb.state_new #define xkb_state_new _glfw.wl.xkb.state_new
#define xkb_state_unref _glfw.wl.xkb.state_unref #define xkb_state_unref _glfw.wl.xkb.state_unref
#define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms #define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms
#define xkb_state_update_mask _glfw.wl.xkb.state_update_mask #define xkb_state_update_mask _glfw.wl.xkb.state_update_mask
#define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods #define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods
#define xkb_state_key_get_layout _glfw.wl.xkb.state_key_get_layout
#ifdef HAVE_XKBCOMMON_COMPOSE_H
typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags); typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*); typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags); typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags);
@ -144,7 +145,6 @@ typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_st
#define xkb_compose_state_feed _glfw.wl.xkb.compose_state_feed #define xkb_compose_state_feed _glfw.wl.xkb.compose_state_feed
#define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status #define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status
#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym #define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
#endif
#define _GLFW_DECORATION_WIDTH 4 #define _GLFW_DECORATION_WIDTH 4
#define _GLFW_DECORATION_TOP 24 #define _GLFW_DECORATION_TOP 24
@ -158,7 +158,6 @@ typedef enum _GLFWdecorationSideWayland
leftDecoration, leftDecoration,
rightDecoration, rightDecoration,
bottomDecoration, bottomDecoration,
} _GLFWdecorationSideWayland; } _GLFWdecorationSideWayland;
typedef struct _GLFWdecorationWayland typedef struct _GLFWdecorationWayland
@ -166,7 +165,6 @@ typedef struct _GLFWdecorationWayland
struct wl_surface* surface; struct wl_surface* surface;
struct wl_subsurface* subsurface; struct wl_subsurface* subsurface;
struct wp_viewport* viewport; struct wp_viewport* viewport;
} _GLFWdecorationWayland; } _GLFWdecorationWayland;
// Wayland-specific per-window data // Wayland-specific per-window data
@ -216,7 +214,6 @@ typedef struct _GLFWwindowWayland
_GLFWdecorationWayland top, left, right, bottom; _GLFWdecorationWayland top, left, right, bottom;
int focus; int focus;
} decorations; } decorations;
} _GLFWwindowWayland; } _GLFWwindowWayland;
// Wayland-specific global data // Wayland-specific global data
@ -265,16 +262,14 @@ typedef struct _GLFWlibraryWayland
int timerfd; int timerfd;
short int keycodes[256]; short int keycodes[256];
short int scancodes[GLFW_KEY_LAST + 1]; short int scancodes[GLFW_KEY_LAST + 1];
char keynames[GLFW_KEY_LAST + 1][5];
struct { struct {
void* handle; void* handle;
struct xkb_context* context; struct xkb_context* context;
struct xkb_keymap* keymap; struct xkb_keymap* keymap;
struct xkb_state* state; struct xkb_state* state;
#ifdef HAVE_XKBCOMMON_COMPOSE_H
struct xkb_compose_state* composeState; struct xkb_compose_state* composeState;
#endif
xkb_mod_mask_t controlMask; xkb_mod_mask_t controlMask;
xkb_mod_mask_t altMask; xkb_mod_mask_t altMask;
@ -290,13 +285,14 @@ typedef struct _GLFWlibraryWayland
PFN_xkb_keymap_unref keymap_unref; PFN_xkb_keymap_unref keymap_unref;
PFN_xkb_keymap_mod_get_index keymap_mod_get_index; PFN_xkb_keymap_mod_get_index keymap_mod_get_index;
PFN_xkb_keymap_key_repeats keymap_key_repeats; PFN_xkb_keymap_key_repeats keymap_key_repeats;
PFN_xkb_keymap_key_get_syms_by_level keymap_key_get_syms_by_level;
PFN_xkb_state_new state_new; PFN_xkb_state_new state_new;
PFN_xkb_state_unref state_unref; PFN_xkb_state_unref state_unref;
PFN_xkb_state_key_get_syms state_key_get_syms; PFN_xkb_state_key_get_syms state_key_get_syms;
PFN_xkb_state_update_mask state_update_mask; PFN_xkb_state_update_mask state_update_mask;
PFN_xkb_state_serialize_mods state_serialize_mods; PFN_xkb_state_serialize_mods state_serialize_mods;
PFN_xkb_state_key_get_layout state_key_get_layout;
#ifdef HAVE_XKBCOMMON_COMPOSE_H
PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale; PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;
PFN_xkb_compose_table_unref compose_table_unref; PFN_xkb_compose_table_unref compose_table_unref;
PFN_xkb_compose_state_new compose_state_new; PFN_xkb_compose_state_new compose_state_new;
@ -304,7 +300,6 @@ typedef struct _GLFWlibraryWayland
PFN_xkb_compose_state_feed compose_state_feed; PFN_xkb_compose_state_feed compose_state_feed;
PFN_xkb_compose_state_get_status compose_state_get_status; PFN_xkb_compose_state_get_status compose_state_get_status;
PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym; PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;
#endif
} xkb; } xkb;
_GLFWwindow* pointerFocus; _GLFWwindow* pointerFocus;
@ -326,7 +321,6 @@ typedef struct _GLFWlibraryWayland
PFN_wl_egl_window_destroy window_destroy; PFN_wl_egl_window_destroy window_destroy;
PFN_wl_egl_window_resize window_resize; PFN_wl_egl_window_resize window_resize;
} egl; } egl;
} _GLFWlibraryWayland; } _GLFWlibraryWayland;
// Wayland-specific per-monitor data // Wayland-specific per-monitor data
@ -340,7 +334,6 @@ typedef struct _GLFWmonitorWayland
int x; int x;
int y; int y;
int scale; int scale;
} _GLFWmonitorWayland; } _GLFWmonitorWayland;
// Wayland-specific per-cursor data // Wayland-specific per-cursor data
@ -357,4 +350,5 @@ typedef struct _GLFWcursorWayland
void _glfwAddOutputWayland(uint32_t name, uint32_t version); void _glfwAddOutputWayland(uint32_t name, uint32_t version);
GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode);

View File

@ -493,35 +493,6 @@ static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)
} }
} }
static GLFWbool createSurface(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig)
{
window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor);
if (!window->wl.surface)
return GLFW_FALSE;
wl_surface_add_listener(window->wl.surface,
&surfaceListener,
window);
wl_surface_set_user_data(window->wl.surface, window);
window->wl.native = wl_egl_window_create(window->wl.surface,
wndconfig->width,
wndconfig->height);
if (!window->wl.native)
return GLFW_FALSE;
window->wl.width = wndconfig->width;
window->wl.height = wndconfig->height;
window->wl.scale = 1;
if (!window->wl.transparent)
setOpaqueRegion(window);
return GLFW_TRUE;
}
static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor, static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor,
int refreshRate) int refreshRate)
{ {
@ -653,7 +624,6 @@ static void xdgToplevelHandleConfigure(void* data,
} }
if (fullscreen && activated) if (fullscreen && activated)
window->wl.wasFullscreen = GLFW_TRUE; window->wl.wasFullscreen = GLFW_TRUE;
_glfwInputWindowFocus(window, activated);
} }
static void xdgToplevelHandleClose(void* data, static void xdgToplevelHandleClose(void* data,
@ -761,6 +731,46 @@ static GLFWbool createXdgSurface(_GLFWwindow* window)
return GLFW_TRUE; return GLFW_TRUE;
} }
static GLFWbool createSurface(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
const _GLFWfbconfig* fbconfig)
{
window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor);
if (!window->wl.surface)
return GLFW_FALSE;
wl_surface_add_listener(window->wl.surface,
&surfaceListener,
window);
wl_surface_set_user_data(window->wl.surface, window);
window->wl.native = wl_egl_window_create(window->wl.surface,
wndconfig->width,
wndconfig->height);
if (!window->wl.native)
return GLFW_FALSE;
window->wl.width = wndconfig->width;
window->wl.height = wndconfig->height;
window->wl.scale = 1;
window->wl.title = _glfw_strdup(wndconfig->title);
window->wl.transparent = fbconfig->transparent;
if (!window->wl.transparent)
setOpaqueRegion(window);
if (window->monitor || wndconfig->visible)
{
if (!createXdgSurface(window))
return GLFW_FALSE;
window->wl.visible = GLFW_TRUE;
}
return GLFW_TRUE;
}
static void setCursorImage(_GLFWwindow* window, static void setCursorImage(_GLFWwindow* window,
_GLFWcursorWayland* cursorWayland) _GLFWcursorWayland* cursorWayland)
{ {
@ -825,22 +835,19 @@ static void incrementCursorImage(_GLFWwindow* window)
static void handleEvents(int timeout) static void handleEvents(int timeout)
{ {
struct wl_display* display = _glfw.wl.display; struct pollfd fds[] =
struct pollfd fds[] = { {
{ wl_display_get_fd(display), POLLIN }, { wl_display_get_fd(_glfw.wl.display), POLLIN },
{ _glfw.wl.timerfd, POLLIN }, { _glfw.wl.timerfd, POLLIN },
{ _glfw.wl.cursorTimerfd, POLLIN }, { _glfw.wl.cursorTimerfd, POLLIN },
}; };
ssize_t read_ret;
uint64_t repeats, i;
while (wl_display_prepare_read(display) != 0) while (wl_display_prepare_read(_glfw.wl.display) != 0)
wl_display_dispatch_pending(display); wl_display_dispatch_pending(_glfw.wl.display);
// If an error different from EAGAIN happens, we have likely been // If an error other than EAGAIN happens, we have likely been disconnected
// disconnected from the Wayland session, try to handle that the best we // from the Wayland session; try to handle that the best we can.
// can. if (wl_display_flush(_glfw.wl.display) < 0 && errno != EAGAIN)
if (wl_display_flush(display) < 0 && errno != EAGAIN)
{ {
_GLFWwindow* window = _glfw.windowListHead; _GLFWwindow* window = _glfw.windowListHead;
while (window) while (window)
@ -848,7 +855,8 @@ static void handleEvents(int timeout)
_glfwInputWindowCloseRequest(window); _glfwInputWindowCloseRequest(window);
window = window->next; window = window->next;
} }
wl_display_cancel_read(display);
wl_display_cancel_read(_glfw.wl.display);
return; return;
} }
@ -856,46 +864,41 @@ static void handleEvents(int timeout)
{ {
if (fds[0].revents & POLLIN) if (fds[0].revents & POLLIN)
{ {
wl_display_read_events(display); wl_display_read_events(_glfw.wl.display);
wl_display_dispatch_pending(display); wl_display_dispatch_pending(_glfw.wl.display);
} }
else else
{ wl_display_cancel_read(_glfw.wl.display);
wl_display_cancel_read(display);
}
if (fds[1].revents & POLLIN) if (fds[1].revents & POLLIN)
{ {
read_ret = read(_glfw.wl.timerfd, &repeats, sizeof(repeats)); uint64_t repeats;
if (read_ret != 8)
return;
if (_glfw.wl.keyboardFocus) if (read(_glfw.wl.timerfd, &repeats, sizeof(repeats)) == 8)
{ {
for (i = 0; i < repeats; ++i) for (uint64_t i = 0; i < repeats; i++)
{ {
_glfwInputKey(_glfw.wl.keyboardFocus, _glfwInputKey(_glfw.wl.keyboardFocus,
_glfw.wl.keyboardLastKey, _glfw.wl.keyboardLastKey,
_glfw.wl.keyboardLastScancode, _glfw.wl.keyboardLastScancode,
GLFW_REPEAT, GLFW_PRESS,
_glfw.wl.xkb.modifiers); _glfw.wl.xkb.modifiers);
_glfwInputTextWayland(_glfw.wl.keyboardFocus,
_glfw.wl.keyboardLastScancode);
} }
} }
} }
if (fds[2].revents & POLLIN) if (fds[2].revents & POLLIN)
{ {
read_ret = read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)); uint64_t repeats;
if (read_ret != 8)
return;
incrementCursorImage(_glfw.wl.pointerFocus); if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8)
incrementCursorImage(_glfw.wl.pointerFocus);
} }
} }
else else
{ wl_display_cancel_read(_glfw.wl.display);
wl_display_cancel_read(display);
}
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -907,9 +910,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) const _GLFWfbconfig* fbconfig)
{ {
window->wl.transparent = fbconfig->transparent; if (!createSurface(window, wndconfig, fbconfig))
if (!createSurface(window, wndconfig))
return GLFW_FALSE; return GLFW_FALSE;
if (ctxconfig->client != GLFW_NO_API) if (ctxconfig->client != GLFW_NO_API)
@ -931,38 +932,6 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
} }
} }
if (wndconfig->title)
window->wl.title = _glfw_strdup(wndconfig->title);
if (wndconfig->visible)
{
if (_glfw.wl.wmBase)
{
if (!createXdgSurface(window))
return GLFW_FALSE;
}
else
{
if (!createShellSurface(window))
return GLFW_FALSE;
}
window->wl.visible = GLFW_TRUE;
}
else
{
window->wl.xdg.surface = NULL;
window->wl.xdg.toplevel = NULL;
window->wl.shellSurface = NULL;
window->wl.visible = GLFW_FALSE;
}
window->wl.currentCursor = NULL;
window->wl.monitors = calloc(1, sizeof(_GLFWmonitor*));
window->wl.monitorsCount = 0;
window->wl.monitorsSize = 1;
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -1180,29 +1149,29 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
{ {
if (!window->wl.visible) if (!window->wl.visible)
{ {
// NOTE: The XDG/shell surface is created here so command-line applications
// with off-screen windows do not appear in for example the Unity dock
if (_glfw.wl.wmBase) if (_glfw.wl.wmBase)
createXdgSurface(window); {
if (!window->wl.xdg.toplevel)
createXdgSurface(window);
}
else if (!window->wl.shellSurface) else if (!window->wl.shellSurface)
createShellSurface(window); createShellSurface(window);
window->wl.visible = GLFW_TRUE; window->wl.visible = GLFW_TRUE;
_glfwInputWindowDamage(window);
} }
} }
void _glfwPlatformHideWindow(_GLFWwindow* window) void _glfwPlatformHideWindow(_GLFWwindow* window)
{ {
if (window->wl.xdg.toplevel) if (window->wl.visible)
{ {
xdg_toplevel_destroy(window->wl.xdg.toplevel); window->wl.visible = GLFW_FALSE;
xdg_surface_destroy(window->wl.xdg.surface); wl_surface_attach(window->wl.surface, NULL, 0, 0);
window->wl.xdg.toplevel = NULL; wl_surface_commit(window->wl.surface);
window->wl.xdg.surface = NULL;
} }
else if (window->wl.shellSurface)
{
wl_shell_surface_destroy(window->wl.shellSurface);
window->wl.shellSurface = NULL;
}
window->wl.visible = GLFW_FALSE;
} }
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
@ -1365,8 +1334,57 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
const char* _glfwPlatformGetScancodeName(int scancode) const char* _glfwPlatformGetScancodeName(int scancode)
{ {
// TODO if (scancode < 0 || scancode > 255 ||
return NULL; _glfw.wl.keycodes[scancode] == GLFW_KEY_UNKNOWN)
{
_glfwInputError(GLFW_INVALID_VALUE,
"Wayland: Invalid scancode %i",
scancode);
return NULL;
}
const int key = _glfw.wl.keycodes[scancode];
const xkb_keycode_t keycode = scancode + 8;
const xkb_layout_index_t layout =
xkb_state_key_get_layout(_glfw.wl.xkb.state, keycode);
if (layout == XKB_LAYOUT_INVALID)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to retrieve layout for key name");
return NULL;
}
const xkb_keysym_t* keysyms = NULL;
xkb_keymap_key_get_syms_by_level(_glfw.wl.xkb.keymap,
keycode,
layout,
0,
&keysyms);
if (keysyms == NULL)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to retrieve keysym for key name");
return NULL;
}
const uint32_t codepoint = _glfwKeySym2Unicode(keysyms[0]);
if (codepoint == GLFW_INVALID_CODEPOINT)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to retrieve codepoint for key name");
return NULL;
}
const size_t count = _glfwEncodeUTF8(_glfw.wl.keynames[key], codepoint);
if (count == 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to encode codepoint for key name");
return NULL;
}
_glfw.wl.keynames[key][count] = '\0';
return _glfw.wl.keynames[key];
} }
int _glfwPlatformGetKeyScancode(int key) int _glfwPlatformGetKeyScancode(int key)

View File

@ -568,7 +568,11 @@ static void detectEWMH(void)
// //
static GLFWbool initExtensions(void) static GLFWbool initExtensions(void)
{ {
#if defined(__OpenBSD__)
_glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so");
#else
_glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1"); _glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1");
#endif
if (_glfw.x11.vidmode.handle) if (_glfw.x11.vidmode.handle)
{ {
_glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension) _glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension)
@ -588,6 +592,8 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__) #if defined(__CYGWIN__)
_glfw.x11.xi.handle = _glfw_dlopen("libXi-6.so"); _glfw.x11.xi.handle = _glfw_dlopen("libXi-6.so");
#elif defined(__OpenBSD__)
_glfw.x11.xi.handle = _glfw_dlopen("libXi.so");
#else #else
_glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6"); _glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6");
#endif #endif
@ -618,6 +624,8 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__) #if defined(__CYGWIN__)
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr-2.so"); _glfw.x11.randr.handle = _glfw_dlopen("libXrandr-2.so");
#elif defined(__OpenBSD__)
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so");
#else #else
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2"); _glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2");
#endif #endif
@ -710,6 +718,8 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__) #if defined(__CYGWIN__)
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor-1.so"); _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor-1.so");
#elif defined(__OpenBSD__)
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so");
#else #else
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1"); _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1");
#endif #endif
@ -731,6 +741,8 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__) #if defined(__CYGWIN__)
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama-1.so"); _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama-1.so");
#elif defined(__OpenBSD__)
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so");
#else #else
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1"); _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1");
#endif #endif
@ -782,6 +794,8 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__) #if defined(__CYGWIN__)
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb-1.so"); _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb-1.so");
#elif defined(__OpenBSD__)
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so");
#else #else
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1"); _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1");
#endif #endif
@ -793,6 +807,8 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__) #if defined(__CYGWIN__)
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender-1.so"); _glfw.x11.xrender.handle = _glfw_dlopen("libXrender-1.so");
#elif defined(__OpenBSD__)
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so");
#else #else
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1"); _glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1");
#endif #endif

View File

@ -208,7 +208,6 @@ typedef struct _GLFWwindowX11
// The time of the last KeyPress event per keycode, for discarding // The time of the last KeyPress event per keycode, for discarding
// duplicate key events generated for some keys by ibus // duplicate key events generated for some keys by ibus
Time keyPressTimes[256]; Time keyPressTimes[256];
} _GLFWwindowX11; } _GLFWwindowX11;
// X11-specific global data // X11-specific global data
@ -414,7 +413,6 @@ typedef struct _GLFWlibraryX11
PFN_XRenderQueryVersion QueryVersion; PFN_XRenderQueryVersion QueryVersion;
PFN_XRenderFindVisualFormat FindVisualFormat; PFN_XRenderFindVisualFormat FindVisualFormat;
} xrender; } xrender;
} _GLFWlibraryX11; } _GLFWlibraryX11;
// X11-specific per-monitor data // X11-specific per-monitor data
@ -428,7 +426,6 @@ typedef struct _GLFWmonitorX11
// Index of corresponding Xinerama screen, // Index of corresponding Xinerama screen,
// for EWMH full screen window placement // for EWMH full screen window placement
int index; int index;
} _GLFWmonitorX11; } _GLFWmonitorX11;
// X11-specific per-cursor data // X11-specific per-cursor data
@ -436,7 +433,6 @@ typedef struct _GLFWmonitorX11
typedef struct _GLFWcursorX11 typedef struct _GLFWcursorX11
{ {
Cursor handle; Cursor handle;
} _GLFWcursorX11; } _GLFWcursorX11;

View File

@ -429,45 +429,14 @@ static char** parseUriList(char* text, int* count)
return paths; 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 // Decode a Unicode code point from a UTF-8 stream
// Based on cutef8 by Jeff Bezanson (Public Domain) // Based on cutef8 by Jeff Bezanson (Public Domain)
// //
#if defined(X_HAVE_UTF8_STRING) #if defined(X_HAVE_UTF8_STRING)
static unsigned int decodeUTF8(const char** s) static uint32_t decodeUTF8(const char** s)
{ {
unsigned int ch = 0, count = 0; uint32_t codepoint = 0, count = 0;
static const unsigned int offsets[] = static const uint32_t offsets[] =
{ {
0x00000000u, 0x00003080u, 0x000e2080u, 0x00000000u, 0x00003080u, 0x000e2080u,
0x03c82080u, 0xfa082080u, 0x82082080u 0x03c82080u, 0xfa082080u, 0x82082080u
@ -475,13 +444,13 @@ static unsigned int decodeUTF8(const char** s)
do do
{ {
ch = (ch << 6) + (unsigned char) **s; codepoint = (codepoint << 6) + (unsigned char) **s;
(*s)++; (*s)++;
count++; count++;
} while ((**s & 0xc0) == 0x80); } while ((**s & 0xc0) == 0x80);
assert(count <= 6); assert(count <= 6);
return ch - offsets[count - 1]; return codepoint - offsets[count - 1];
} }
#endif /*X_HAVE_UTF8_STRING*/ #endif /*X_HAVE_UTF8_STRING*/
@ -499,7 +468,7 @@ static char* convertLatin1toUTF8(const char* source)
char* tp = target; char* tp = target;
for (sp = source; *sp; sp++) for (sp = source; *sp; sp++)
tp += encodeUTF8(tp, *sp); tp += _glfwEncodeUTF8(tp, *sp);
return target; return target;
} }
@ -1359,9 +1328,9 @@ static void processEvent(XEvent *event)
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods); _glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
const long character = _glfwKeySym2Unicode(keysym); const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
if (character != -1) if (codepoint != GLFW_INVALID_CODEPOINT)
_glfwInputChar(window, character, mods, plain); _glfwInputChar(window, codepoint, mods, plain);
} }
return; return;
@ -2123,8 +2092,8 @@ void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
longCount += 2 + images[i].width * images[i].height; longCount += 2 + images[i].width * images[i].height;
long* icon = calloc(longCount, sizeof(long)); unsigned long* icon = calloc(longCount, sizeof(unsigned long));
long* target = icon; unsigned long* target = icon;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
@ -2133,13 +2102,19 @@ void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
for (j = 0; j < images[i].width * images[i].height; j++) for (j = 0; j < images[i].width * images[i].height; j++)
{ {
*target++ = (images[i].pixels[j * 4 + 0] << 16) | *target++ = (((unsigned long) images[i].pixels[j * 4 + 0]) << 16) |
(images[i].pixels[j * 4 + 1] << 8) | (((unsigned long) images[i].pixels[j * 4 + 1]) << 8) |
(images[i].pixels[j * 4 + 2] << 0) | (((unsigned long) images[i].pixels[j * 4 + 2]) << 0) |
(images[i].pixels[j * 4 + 3] << 24); (((unsigned long) images[i].pixels[j * 4 + 3]) << 24);
} }
} }
// NOTE: XChangeProperty expects 32-bit values like the image data above to be
// placed in the 32 least significant bits of individual longs. This is
// true even if long is 64-bit and a WM protocol calls for "packed" data.
// This is because of a historical mistake that then became part of the Xlib
// ABI. Xlib will pack these values into a regular array of 32-bit values
// before sending it over the wire.
XChangeProperty(_glfw.x11.display, window->x11.handle, XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_ICON, _glfw.x11.NET_WM_ICON,
XA_CARDINAL, 32, XA_CARDINAL, 32,
@ -2896,11 +2871,11 @@ const char* _glfwPlatformGetScancodeName(int scancode)
if (keysym == NoSymbol) if (keysym == NoSymbol)
return NULL; return NULL;
const long ch = _glfwKeySym2Unicode(keysym); const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
if (ch == -1) if (codepoint == GLFW_INVALID_CODEPOINT)
return NULL; return NULL;
const size_t count = encodeUTF8(_glfw.x11.keynames[key], (unsigned int) ch); const size_t count = _glfwEncodeUTF8(_glfw.x11.keynames[key], codepoint);
if (count == 0) if (count == 0)
return NULL; return NULL;

View File

@ -907,7 +907,7 @@ static const struct codepair {
// Convert XKB KeySym to Unicode // Convert XKB KeySym to Unicode
// //
long _glfwKeySym2Unicode(unsigned int keysym) uint32_t _glfwKeySym2Unicode(unsigned int keysym)
{ {
int min = 0; int min = 0;
int max = sizeof(keysymtab) / sizeof(struct codepair) - 1; int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
@ -937,6 +937,6 @@ long _glfwKeySym2Unicode(unsigned int keysym)
} }
// No matching Unicode value found // No matching Unicode value found
return -1; return GLFW_INVALID_CODEPOINT;
} }

View File

@ -24,5 +24,7 @@
// //
//======================================================================== //========================================================================
long _glfwKeySym2Unicode(unsigned int keysym); #define GLFW_INVALID_CODEPOINT 0xffffffffu
uint32_t _glfwKeySym2Unicode(unsigned int keysym);

View File

@ -111,6 +111,12 @@ int main(int argc, char** argv)
{ {
const GLFWgammaramp* ramp = glfwGetGammaRamp(monitor); const GLFWgammaramp* ramp = glfwGetGammaRamp(monitor);
if (!ramp)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
const size_t array_size = ramp->size * sizeof(short); const size_t array_size = ramp->size * sizeof(short);
orig_ramp.size = ramp->size; orig_ramp.size = ramp->size;
orig_ramp.red = malloc(array_size); orig_ramp.red = malloc(array_size);

View File

@ -37,7 +37,7 @@
#include "getopt.h" #include "getopt.h"
static int windowed_xpos, windowed_ypos, windowed_width, windowed_height; static int windowed_xpos, windowed_ypos, windowed_width = 640, windowed_height = 480;
static void usage(void) static void usage(void)
{ {
@ -180,8 +180,8 @@ static GLFWwindow* create_window(GLFWmonitor* monitor)
} }
else else
{ {
width = 640; width = windowed_width;
height = 480; height = windowed_height;
} }
window = glfwCreateWindow(width, height, "Iconify", monitor, NULL); window = glfwCreateWindow(width, height, "Iconify", monitor, NULL);