Compare commits

...

60 Commits

Author SHA1 Message Date
Camilla Löwy 92dcf4ce74 Start 3.6 2026-08-03 19:04:50 +02:00
Camilla Löwy d9d6f0f1f9 Start 3.5.1
Due to a misconfigured tool, an incorrect 3.5.0 tag was briefly made
available in the main Git repository.  Thanks to the manual intervention
of many packaging volunteers this has been almost entirely rolled back.
To make sure this release supersedes the incorrect tag everywhere, the
first release of GLFW 3.5 is named 3.5.1.

There are no code changes other than the version patch number.

Fixes #2758
2026-07-31 14:46:04 +02:00
Camilla Löwy deeadd3c30 Tag remaining Git and CI plumbing export-ignore 2026-07-28 17:39:40 +02:00
Camilla Löwy 0984b4354a Update changelog and add credit
Related to #2713
Related to #2810
2026-07-28 17:39:33 +02:00
road2react b7ef2919b0 Wayland: Fix rounding of fractional scale sizes
The framebuffer size for fractional scale surfaces should be rounded to
the closest integer, not truncated as is currently done.

This implements the rounding formula that the discussions over at
wayland-protocols item 132 and MR 309 appear to be converging on.

Fixes #2713
Closes #2810
2026-07-28 17:18:05 +02:00
Camilla Löwy 463cf73610 Win32: Fix scancode for media keys
Media key events were incorrectly reported with a scancode of 0x100.

This is based on a snippet by dougbinks in #2625.

Fixes #1768
Closes #2417
Fixes #2625
2026-07-09 21:51:02 +02:00
Jonas Ådahl ed6452b13c Wayland: Set the correct min/max size when non-resizable
Libdecor is a thin wrapper around xdg_toplevel, and expects the same
kind of information passed to it as if it was a xdg_toplevel. This
includes the min/max size when non-resizable, which was set when using
xdg_toplevel directly, but not when using libdecor. This fixes issues
with min/max size missing when mapping a non-resizable window.

Related to #2842
2026-06-26 16:30:12 +02:00
Camilla Löwy e94108d9db Wayland: Fix undecorated libdecor frame creation
In order to safely call libdecor_frame_set_visibility during window
creation, a libdecor frame state was synthesized and committed.

This commit instead postpones the call to libdecor_frame_set_visibility
until after the frame state received by the frame configure event has
been committed.  This appears to be a more polite approach.

Related to #2842
2026-06-26 16:30:12 +02:00
Camilla Löwy dc86d02ff1 Wayland: Fix some event types not being processed
If there was already an event available in the Wayland queue, that event
would be processed but other kinds of events (libdecor, key repeat,
joystick connection, etc.) would not be.

This commit restores the processing of all available events on every
call to glfw*Events.  It is partially based on #2842 by jadahl.

Because some libdecor plugins also process non-Wayland events, without
providing an fd for them, libdecor_dispatch is now called
unconditionally.

Fixes #2793
Closes #2795
Related to #2842
2026-06-26 16:26:43 +02:00
Camilla Löwy 06406a00a0 Wayland: Remove unused struct member 2026-06-10 01:07:02 +02:00
Tomáš Mráz de0c378aa2 Wayland: Conditionally define _GNU_SOURCE
This fixes a re-definition warning for the _GNU_SOURCE macro.

Edited by elmindreda: code formatting, author credit

Related to go-gl/glfw#359
Fixes #2833
2026-06-10 01:07:02 +02:00
Camilla Löwy 567b1ec244 Cocoa: Fix some key events not being emitted
The key combinations Cmd+Period, Ctrl+Tab and Ctrl+Esc are not passed to
the first responder as key events.

This commit catches and claims these specific key events via the key
equivalents mechanism and emits them from there instead.

Closes #1362
Fixes #2278
2026-06-09 21:56:04 +02:00
Camilla Löwy 0136febb1e Add credit
Related to #2863
2026-06-09 21:56:04 +02:00
halx99 6c397996b8 Fix Windows CI
Closes #2863
2026-06-09 21:55:55 +02:00
Camilla Löwy b00e6a8a88 Update to actions/checkout@v5 from v4
This is necessary due to the deprecation of Node.js 20 on Github Action
runners.
2026-03-30 20:11:56 +02:00
Camilla Löwy 51683a6f1c Use C99 booleans for Khronos API extensions 2026-03-27 14:36:35 +01:00
Camilla Löwy 55fd451d5f Wayland: Remove unused struct member
The libdecor initialization sync callback was saved in the library
struct but never meaningfully used.
2026-03-27 14:35:28 +01:00
Camilla Löwy 1929088dd9 Make the empty events test somewhat plausible
The empty events test now makes slightly more plausible use of
glfwPostEmptyEvent.  As a side-effect, the test now also works as
intended on Wayland.
2026-03-20 16:06:29 +01:00
Camilla Löwy 3130c004e1 Wayland: Fix missing flush in glfwHideWindow 2026-03-20 16:06:29 +01:00
Camilla Löwy bb8048122a Wayland: Fix glfwPostEmptyEvent leaking a proxy
The client-side proxy of the callback from each call to wl_display_sync
was never destroyed.

Fixes #2836
2026-03-20 16:04:12 +01:00
Camilla Löwy 50b0a135a5 Wayland: Fix deadlock causing timeout
If the frame was processed by wl_display_dispatch_queue_pending, this
would be treated as no frame having been received.

Oops.

This bug was introduced by fdd14e65b1.
2026-03-13 17:20:44 +01:00
Camilla Löwy fdd14e65b1 Wayland: Fix EGL buffer swap blocking indefinitely
When the swap interval was nonzero, EGL on Wayland would wait
indefinitely for a frame callback on a suspended window, causing
applications that call eglSwapBuffers to halt.

This re-implements the wait for a surface frame so that we can add
a reasonable timeout, while setting the EGL swap interval to zero.  That
allows applications to make progress despite the window being suspended.

Some insights for how to structure this workaround were gleaned from
dri2_wl_swap_buffers_with_damage in Mesa.

This initial implementation still has a race between glfwHideWindow and
glfwSwapBuffers when rendering on a separate thread.  This could lead to
a window becoming visible again after being hidden on the main thread.

Related to #1350
Fixes #2582
Fixes #2640
Fixes #2719
Fixes #2723
Fixes #2800
Fixes #2827
2026-03-06 14:31:27 +01:00
Camilla Löwy 54b18d5547 Fix cleanup on success in threaded rendering test 2026-03-06 14:31:26 +01:00
Camilla Löwy 05f57c0bee Wayland: Improve support for discrete scrolling
This adds support for high-resolution scroll input scaled to match
legacy discrete scroll input.  It is available on compositors that
support wl_seat version 8 or later.

High-resolution "discrete" values now replace non-scaled scroll
values when available.
2026-03-06 14:31:26 +01:00
Camilla Löwy 0d15b54c7a Use C99 booleans in config structs 2026-03-06 14:31:26 +01:00
Camilla Löwy f472380d7e Use C99 isfinite instead of various ad-hoc tests 2026-03-06 14:31:26 +01:00
Camilla Löwy 1839271de4 Wayland: Remove last traces of legacy Unicode path
The legacy keysym-to-Unicode path is only used on X11 since
21fea01161, but the file was still
included in Wayland-only builds.
2026-03-06 14:31:26 +01:00
Camilla Löwy aa5047709d POSIX: Include helper header via platform glue 2026-03-06 14:31:25 +01:00
Camilla Löwy bae8aa6e7d macOS: Fix Vulkan loader loading for Null platform 2026-03-06 14:31:25 +01:00
Camilla Löwy c5c0b69149 Fix pkgconfig dependency lists treated as strings
All other parts of the file correctly treated these variables as lists.
2026-03-06 14:31:25 +01:00
Camilla Löwy 29cd880ab5 macOS: Clarify separation between Cocoa and macOS
The timer code uses no part of Cocoa and is in turn used by other
backends than Cocoa on macOS.

The macOS timer code is now labeled macOS.  Cocoa-specific files are now
consistently labeled Cocoa, not macOS.
2026-03-06 14:31:25 +01:00
Yan Pujante 3d89365fdb Added Emscripten external platform (comment) 2026-02-28 15:40:56 +00:00
Camilla Löwy 7c9ea95233 Null: Disable Vulkan on macOS for the moment
This only affects builds on macOS where only the Null platform is
enabled.
2026-02-13 15:36:08 +01:00
Camilla Löwy abfbf07830 Null: Fix dynamic library name selection
The name selection for the Vulkan loader and the EGL and client
libraries used the GLFW platform macros instead of the platform's own
macros.  This caused the selection to be incorrect when building only
the Null platform on any platform but Linux (where it only accidentally
worked due to being the default case).

OSMesa was already using the correct method.
2026-02-13 15:25:06 +01:00
Camilla Löwy 99cdcfb0a4 Wayland: Unify pointer input paths
This reduces pointer frame support to a small amount of plumbing.
2026-02-13 14:44:10 +01:00
Camilla Löwy 001f94eaa7 Wayland: Add support for pointer event frames
This adds support for wl_seat version 5, which adds pointer frames.
This allows two-dimensional scroll input to be emitted as single events
instead of one event per axis per motion.

It's also the the foundation for future enhancements like properly
scaled discrete scroll events and server-side key repeat.

Fixes #2494
2026-02-13 14:44:09 +01:00
Camilla Löwy 3f14b6feed EGL: Try eglGetProcAddress before fallback method
This order matches what is done for every other context creation API
that has a similar fallback method.
2026-02-13 14:44:09 +01:00
Camilla Löwy f0b2992b3a Allow NULL argument to _glfwPlatformFreeModule
This matches the behavior of _glfw_free and the public API, simplifying
cleanup code.
2026-02-13 14:43:07 +01:00
Camilla Löwy b579ea6792 Wayland: Fix libwayland-client not unloaded 2026-02-13 13:25:36 +01:00
Camilla Löwy a3095e1aa5 X11: Fix libXext not unloaded at termination 2026-02-13 13:25:36 +01:00
Camilla Löwy a98badf088 Wayland: Fix key repeat on very old compositors
The client-side key repeat timer fd was only created for wl_seat version
4 or later, but was then used unconditionally during event processing.

Rather than have this mechanism do nothing in a more correct way on
wl_seat version 3 or earlier (which is very old by now), this commit
creates the key repeat timer fd and then sets (hopefully gentle)
hardcoded repeat delay and rate.
2026-02-13 13:25:35 +01:00
Camilla Löwy c4684b288d Remove some pointless comments 2026-02-13 13:25:35 +01:00
Camilla Löwy 232164f62b Wayland: Remove duplicate cursor state
The shared window struct already tracks the current cursor.
2026-02-05 17:28:32 +01:00
Camilla Löwy abb9db0d75 Wayland: Fix fallback decoration button input
Fallback decoration mouse button actions were performed for both press
and release events.  The requests made using a mouse button release
serials were presumably (and correctly) discarded by the compositor.

This commit removes the generation of these nuisance requests.
2026-02-05 17:25:11 +01:00
Camilla Löwy 0aa77a9a3a Wayland: Release input devices where possible
On systems with wl_seat verison 3 or later, use release instead of
destroy on input devices when they are disconnected.
2026-02-04 18:08:37 +01:00
Camilla Löwy 7b370d8df0 Wayland: Simplify pointer surface state
Track which surface contains the pointer with one piece of state instead
of three partially overlapping ones.
2026-02-04 18:08:37 +01:00
Camilla Löwy f871f14d5e Add update flag to timeout test
Redrawing the window contents for every possible event is not
a reasonable thing for an application to do.  The test should be whether
redrawing on demand plus periodic updates works with near-idle CPU use
and no extra input latency.

This change incidentally makes the test well-behaved on Wayland, where
it was previously broken due to every EGL buffer swap causing an event
to be received.
2026-02-04 18:07:19 +01:00
Camilla Löwy bafb134769 Documentation work
Elaborate on what 'work' means in the context of joystick input.
2026-01-27 20:51:00 +01:00
Camilla Löwy 2d7ae8f2d0 Wayland: Cleanup
This is only a semantic change.  The values are the same.
2026-01-15 21:09:01 +01:00
Camilla Löwy 96e0f49395 X11: Place argument assertion after platform check
This lets automated testing check that GLFW_NOT_INITIALIZED is emitted
for every public function.
2026-01-14 21:03:13 +01:00
Camilla Löwy 9352d8fe93 X11: Cleanup 2026-01-14 18:26:50 +01:00
Camilla Löwy a228a8b447 X11: Fix window made non-floating by being hidden
The previous implementation was based on the incorrect assumption that
the _NET_WM_STATE_ABOVE state is always retained on unmapped windows.
According to EWMH the WM should remove the _NET_WM_STATE property when
a window is unmapped.

This commit moves the adding of _NET_WM_STATE_ABOVE to before mapping
the window during glfwShowWindow.  The logic for removing
_NET_WM_STATE_ABOVE from hidden windows is retained, as EWMH still
allows WMs to leave the window property on unmapped window.

Fixes #2276
2026-01-12 21:26:42 +01:00
Camilla Löwy dbadda2683 Formatting 2025-12-05 13:33:10 +01:00
Camilla Löwy 08449b7183 Linux: Add missing header for ioctl
Fixes #2778
2025-12-04 20:30:12 +01:00
Camilla Löwy 1ce855b0b1 Wayland: Fix missing checks for optional protocol 2025-12-04 20:30:12 +01:00
Camilla Löwy ebff6606ee Simplify test for shared library build 2025-11-17 22:57:23 +01:00
Doug Binks 162896e5b9 Wayland: free modules at end of terminate function
- Fixes #2744
2025-11-14 16:35:47 +00:00
Doug Binks 936307558e X11: Clamp w,h in glfwSetWindowSize to >= 1
-  prevents BadValue error and program exit
2025-11-08 10:37:52 +00:00
Drew Weymouth 4df5129529 X11: check crtcInfo for NULL when polling monitors 2025-11-07 17:39:26 +00:00
Ivor Wanders 6de70d8252 X11: Prevent BadWindow when creating small windows
The glfwCreateWindow function ensures that the width and height are
at least greater or equal than zero, but on X11 it is invalid to
create a window with dimensions that equal zero, see [1].

This change ensures that the dimensions passed to XCreateWindow are
at least 1 by 1.

This issue was detected in [2], where a call to glfwCreateWindow
was done to request a 1x1 window, with a _glfw.x11.contentScaleX of
less than 1.0 (0.958333) this results in a request for a 0x0 window
which then causes an BadWindow error from X11.

[1]: https://gitlab.freedesktop.org/xorg/lib/libx11/-/blob/e003f52661679e95b51ff24e317af6178fe2a73c/specs/libX11/CH03.xml#L1333-1337
[2]: https://github.com/WerWolv/ImHex/pull/2390
2025-11-07 17:24:35 +00:00
75 changed files with 1145 additions and 830 deletions
+2
View File
@@ -3,3 +3,5 @@
.gitattributes export-ignore
.travis.yml export-ignore
.appveyor.yml export-ignore
.mailmap export-ignore
.github export-ignore
+8 -8
View File
@@ -17,7 +17,7 @@ jobs:
CC: clang
CFLAGS: -Werror
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Install dependencies
run: |
sudo apt update
@@ -57,7 +57,7 @@ jobs:
MACOSX_DEPLOYMENT_TARGET: 10.11
CMAKE_OSX_ARCHITECTURES: x86_64;arm64
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Configure Null shared library
run: cmake -B build-null-shared -D GLFW_BUILD_COCOA=OFF -D BUILD_SHARED_LIBS=ON
@@ -74,27 +74,27 @@ jobs:
- name: Build Cocoa shared library
run: cmake --build build-cocoa-shared --parallel
build-windows-vs2022:
name: Windows (VS2022)
build-windows-msvc:
name: Windows (MSVC)
runs-on: windows-latest
timeout-minutes: 4
env:
CFLAGS: /WX
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Configure Win32 shared x86 library
run: cmake -B build-win32-shared-x86 -G "Visual Studio 17 2022" -A Win32 -D BUILD_SHARED_LIBS=ON
run: cmake -B build-win32-shared-x86 -A Win32 -D BUILD_SHARED_LIBS=ON
- name: Build Win32 shared x86 library
run: cmake --build build-win32-shared-x86 --parallel
- name: Configure Win32 static x64 library
run: cmake -B build-win32-static-x64 -G "Visual Studio 17 2022" -A x64
run: cmake -B build-win32-static-x64 -A x64
- name: Build Win32 static x64 library
run: cmake --build build-win32-static-x64 --parallel
- name: Configure Win32 shared x64 library
run: cmake -B build-win32-shared-x64 -G "Visual Studio 17 2022" -A x64 -D BUILD_SHARED_LIBS=ON
run: cmake -B build-win32-shared-x64 -A x64 -D BUILD_SHARED_LIBS=ON
- name: Build Win32 shared x64 library
run: cmake --build build-win32-shared-x64 --parallel
+2 -2
View File
@@ -57,11 +57,11 @@ src/glfw3ConfigVersion.cmake
# Compiled binaries
src/libglfw.so
src/libglfw.so.3
src/libglfw.so.3.5
src/libglfw.so.3.6
src/libglfw.dylib
src/libglfw.dylib
src/libglfw.3.dylib
src/libglfw.3.5.dylib
src/libglfw.3.6.dylib
src/libglfw3.a
src/glfw3.lib
src/glfw3.dll
+2 -6
View File
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16...3.28 FATAL_ERROR)
project(GLFW VERSION 3.5.0 LANGUAGES C HOMEPAGE_URL "https://www.glfw.org/")
project(GLFW VERSION 3.6.0 LANGUAGES C HOMEPAGE_URL "https://www.glfw.org/")
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
@@ -38,11 +38,7 @@ set(GLFW_LIBRARY_TYPE "${GLFW_LIBRARY_TYPE}" CACHE STRING
"Library type override for GLFW (SHARED, STATIC, OBJECT, or empty to follow BUILD_SHARED_LIBS)")
if (GLFW_LIBRARY_TYPE)
if (GLFW_LIBRARY_TYPE STREQUAL "SHARED")
set(GLFW_BUILD_SHARED_LIBRARY TRUE)
else()
set(GLFW_BUILD_SHARED_LIBRARY FALSE)
endif()
string(COMPARE EQUAL "${GLFW_LIBRARY_TYPE}" "SHARED" GLFW_BUILD_SHARED_LIBRARY)
else()
set(GLFW_BUILD_SHARED_LIBRARY ${BUILD_SHARED_LIBS})
endif()
+14
View File
@@ -6,10 +6,12 @@ excludes other invaluable contributions like language bindings and text and
video tutorials.
- Bobyshev Alexander
- Alzathar
- Laurent Aphecetche
- Matt Arsenault
- Takuro Ashie
- ashishgamedev
- avagordon01
- David Avedissian
- Luca Bacci
- Keith Bauer
@@ -55,7 +57,9 @@ video tutorials.
- Bill Currie
- Jason Daly
- danhambleton
- danijel1023
- Jarrod Davis
- Aaron Day
- decce
- Olivier Delannoy
- Paul R. Deppe
@@ -75,10 +79,12 @@ video tutorials.
- Nikita Fediuchin
- Felipe Ferreira
- Michael Fogleman
- Folling
- forworldm
- Jason Francis
- Gerald Franz
- Mário Freitas
- Friz64
- GeO4d
- Marcus Geelnard
- Gegy
@@ -94,6 +100,7 @@ video tutorials.
- Andrew Gutekanst
- Stephen Gutekanst
- Jonathan Hale
- halx99
- Daniel Hauser
- hdf89shfdfs
- Moritz Heinemann
@@ -160,8 +167,10 @@ video tutorials.
- Bryce Mehring
- Jonathan Mercier
- Marcel Metz
- Lucas Michaudel
- Liam Middlebrook
- mightgoyardstill
- Mihail
- Ave Milia
- Icyllis Milica
- Jonathan Miller
@@ -175,6 +184,7 @@ video tutorials.
- Jon Morton
- Pierre Moulon
- Martins Mozeiko
- Tomáš Mráz
- Pascal Muetschard
- James Murphy
- Julian Møller
@@ -221,6 +231,7 @@ video tutorials.
- Philip Rideout
- Eddie Ringle
- Max Risuhin
- road2react
- Joe Roback
- Jorge Rodriguez
- Jari Ronkainen
@@ -228,6 +239,7 @@ video tutorials.
- Ed Ropple
- Aleksey Rybalkin
- Mikko Rytkönen
- saikyun
- Riku Salminen
- Yoshinori Sano
- Brandon Schaefer
@@ -282,10 +294,12 @@ video tutorials.
- Corentin Wallez
- Torsten Walluhn
- Patrick Walton
- Ivor Wanders
- Jim Wang
- Xo Wang
- Andre Weissflog
- Jay Weisskopf
- Drew Weymouth
- Frank Wille
- Andy Williams
- Joel Winarske
+2 -30
View File
@@ -118,37 +118,9 @@ guide](https://github.com/glfw/glfw/blob/master/docs/CONTRIBUTING.md) for
information on what to include when reporting a bug.
## Changelog since 3.4
## Changelog since 3.5
- Added `GLFW_UNLIMITED_MOUSE_BUTTONS` input mode that allows mouse buttons beyond
the limit of the mouse button tokens to be reported (#2423)
- Added `glfwGetEGLConfig` function to query the `EGLConfig` of a window (#2045)
- Added `glfwGetGLXFBConfig` function to query the `GLXFBConfig` of a window (#1925)
- Updated minimum CMake version to 3.16 (#2541)
- Removed support for building with original MinGW (#2540)
- [Win32] Removed support for Windows XP and Vista (#2505)
- [Cocoa] Added `QuartzCore` framework as link-time dependency
- [Cocoa] Removed support for OS X 10.10 Yosemite and earlier (#2506)
- [Wayland] Bugfix: The fractional scaling related objects were not destroyed
- [Wayland] Bugfix: `glfwInit` would segfault on compositor with no seat (#2517)
- [Wayland] Bugfix: A drag entering a non-GLFW surface could cause a segfault
- [Wayland] Bugfix: Ignore key repeat events when no window has keyboard focus (#2727)
- [Wayland] Bugfix: Reset key repeat timer when window destroyed (#2741,#2727)
- [Wayland] Bugfix: Memory would leak if reading a data offer failed midway
- [Wayland] Bugfix: Retrieved cursor position would be incorrect when hovering over
fallback decorations
- [Wayland] Bugfix: Fallback decorations would report scroll events
- [Wayland] Bugfix: Keyboard repeat events halted when any key is released (#2568)
- [Wayland] Bugfix: Fallback decorations would show menu at wrong position
- [Wayland] Bugfix: The cursor was not updated when clicking through from
a modal to a fallback decoration
- [Wayland] Bugfix: The cursor position was not updated when clicking through
from a modal to the content area
- [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631)
- [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface`
- [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless`
- [EGL] Allowed native access on Wayland with `GLFW_CONTEXT_CREATION_API` set to
`GLFW_NATIVE_CONTEXT_API` (#2518)
None.
## Contact
+1 -1
View File
@@ -310,7 +310,7 @@ With a few changes to your `CMakeLists.txt` you can locate the package and
target files generated when GLFW is installed.
```cmake
find_package(glfw3 3.5 REQUIRED)
find_package(glfw3 3.6 REQUIRED)
```
Once GLFW has been added to the project, link against it with the `glfw` target.
+3 -3
View File
@@ -621,17 +621,17 @@ The format of the string is as follows:
- The names of the always supported context creation APIs EGL and OSMesa
- Any additional compile-time options, APIs and (on Windows) what compiler was used
For example, compiling GLFW 3.5 with MinGW-64 as a DLL for Windows, may result
For example, compiling GLFW 3.6 with MinGW-64 as a DLL for Windows, may result
in a version string like this:
```c
3.5.0 Win32 WGL Null EGL OSMesa MinGW-w64 DLL
3.6.0 Win32 WGL Null EGL OSMesa MinGW-w64 DLL
```
Compiling GLFW as a static library for Linux, with both Wayland and X11 enabled, may
result in a version string like this:
```c
3.5.0 Wayland X11 GLX Null EGL OSMesa monotonic
3.6.0 Wayland X11 GLX Null EGL OSMesa monotonic
```
+2 -44
View File
@@ -1,69 +1,27 @@
# Release notes for version 3.5 {#news}
# Release notes for version 3.6 {#news}
[TOC]
## New features {#features}
### Unlimited mouse buttons {#unlimited_mouse_buttons}
GLFW now has an input mode which allows an unlimited number of mouse buttons to
be reported by the mouse buttton callback, rather than just the associated
[mouse button tokens](@ref buttons). This allows using mouse buttons with
values over 8. For compatibility with older versions, the
@ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode needs to be set to make use of
this.
### EGLConfig native access function {#eglconfig}
GLFW now provides the @ref glfwGetEGLConfig native access function for querying
the `EGLConfig` of a window that has a `EGLSurface`.
### GLXFBConfig native access function {#glxfbconfig}
GLFW now provides the @ref glfwGetGLXFBConfig native access function for
querying the `GLXFBConfig` of a window that has a `GLXWindow`.
## Caveats {#caveats}
## Deprecations {#deprecations}
## Removals {#removals}
### Windows XP and Vista support has been removed {#winxp_vista}
Support for Windows XP and Vista has been removed. Windows XP has been out of extended
support since 2014.
### Original MinGW support has been removed {#original_mingw}
Support for the now unmaintained original MinGW distribution has been removed.
This does not apply to the much more capable [MinGW-w64](https://www.mingw-w64.org/),
which remains fully supported. MinGW-w64 can build both 32- and 64-bit binaries, is
actively maintained and available on many platforms.
## New symbols {#new_symbols}
### New functions {#new_functions}
- @ref glfwGetEGLConfig
- @ref glfwGetGLXFBConfig
### New types {#new_types}
### New constants {#new_constants}
- @ref GLFW_UNLIMITED_MOUSE_BUTTONS
## Release notes for earlier versions {#news_archive}
- [Release notes for 3.5](https://www.glfw.org/docs/3.5/news.html)
- [Release notes for 3.4](https://www.glfw.org/docs/3.4/news.html)
- [Release notes for 3.3](https://www.glfw.org/docs/3.3/news.html)
- [Release notes for 3.2](https://www.glfw.org/docs/3.2/news.html)
+16 -5
View File
@@ -1,5 +1,5 @@
/*************************************************************************
* GLFW 3.5 - www.glfw.org
* GLFW 3.6 - www.glfw.org
* A library for OpenGL, window and input
*------------------------------------------------------------------------
* Copyright (c) 2002-2006 Marcus Geelnard
@@ -291,7 +291,7 @@ extern "C" {
* features are added to the API but it remains backward-compatible.
* @ingroup init
*/
#define GLFW_VERSION_MINOR 5
#define GLFW_VERSION_MINOR 6
/*! @brief The revision number of the GLFW header.
*
* The revision number of the GLFW header. This is incremented when a bug fix
@@ -1344,6 +1344,10 @@ extern "C" {
#define GLFW_PLATFORM_NULL 0x00060005
/*! @} */
/* Reserved platform define for external Emscripten ports: 0x00060006
* See https://github.com/pongasoft/emscripten-glfw
*/
#define GLFW_DONT_CARE -1
@@ -4520,7 +4524,8 @@ GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow*
* GLFW will pass those events on to the application callbacks before
* returning.
*
* Event processing is not required for joystick input to work.
* Event processing is not required to receive joystick input. Joystick state
* is polled when a joystick input or gamepad input function is called.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
@@ -4565,7 +4570,8 @@ GLFWAPI void glfwPollEvents(void);
* GLFW will pass those events on to the application callbacks before
* returning.
*
* Event processing is not required for joystick input to work.
* Event processing is not required to receive joystick input. Joystick state
* is polled when a joystick input or gamepad input function is called.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
@@ -4612,7 +4618,8 @@ GLFWAPI void glfwWaitEvents(void);
* GLFW will pass those events on to the application callbacks before
* returning.
*
* Event processing is not required for joystick input to work.
* Event processing is not required to receive joystick input. Joystick state
* is polled when a joystick input or gamepad input function is called.
*
* @param[in] timeout The maximum amount of time, in seconds, to wait.
*
@@ -6167,6 +6174,10 @@ GLFWAPI GLFWwindow* glfwGetCurrentContext(void);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.
*
* @remark __Wayland:__ When the swap interval is greater than zero and the
* window is not in view, this function may take a few extra milliseconds to
* return.
*
* @remark __EGL:__ The context of the specified window must be current on the
* calling thread.
*
+1 -1
View File
@@ -1,5 +1,5 @@
/*************************************************************************
* GLFW 3.5 - www.glfw.org
* GLFW 3.6 - www.glfw.org
* A library for OpenGL, window and input
*------------------------------------------------------------------------
* Copyright (c) 2002-2006 Marcus Geelnard
+10 -5
View File
@@ -10,7 +10,7 @@ add_library(glfw ${GLFW_LIBRARY_TYPE}
# The time, thread and module code is shared between all backends on a given OS,
# including the null backend, which still needs those bits to be functional
if (APPLE)
target_sources(glfw PRIVATE cocoa_time.h cocoa_time.c posix_thread.h
target_sources(glfw PRIVATE macos_time.h macos_time.c posix_thread.h
posix_module.c posix_thread.c)
elseif (WIN32)
target_sources(glfw PRIVATE win32_time.h win32_thread.h win32_module.c
@@ -46,7 +46,7 @@ endif()
if (GLFW_BUILD_X11)
target_compile_definitions(glfw PRIVATE _GLFW_X11)
target_sources(glfw PRIVATE x11_platform.h xkb_unicode.h x11_init.c
target_sources(glfw PRIVATE x11_platform.h x11_init.c
x11_monitor.c x11_window.c xkb_unicode.c
glx_context.c)
endif()
@@ -145,11 +145,11 @@ endif()
if (GLFW_BUILD_COCOA)
target_link_libraries(glfw PRIVATE "-framework Cocoa"
"-framework IOKit"
"-framework CoreFoundation"
"-framework QuartzCore")
set(glfw_PKG_DEPS "")
set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation -framework QuartzCore")
list(APPEND glfw_PKG_LIBS "-framework Cocoa"
"-framework IOKit"
"-framework QuartzCore")
endif()
if (GLFW_BUILD_WAYLAND)
@@ -234,6 +234,11 @@ if (UNIX AND NOT APPLE)
endif()
endif()
if (APPLE)
target_link_libraries(glfw PRIVATE "-framework CoreFoundation")
list(APPEND glfw_PKG_LIBS "-framework CoreFoundation")
endif()
if (WIN32)
if (GLFW_USE_HYBRID_HPG)
target_compile_definitions(glfw PRIVATE _GLFW_USE_HYBRID_HPG)
+3 -36
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 macOS - www.glfw.org
// GLFW 3.6 Cocoa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
//
@@ -450,41 +450,6 @@ static GLFWbool initializeTIS(void)
@end // GLFWApplicationDelegate
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
void* _glfwLoadLocalVulkanLoaderCocoa(void)
{
CFBundleRef bundle = CFBundleGetMainBundle();
if (!bundle)
return NULL;
CFURLRef frameworksUrl = CFBundleCopyPrivateFrameworksURL(bundle);
if (!frameworksUrl)
return NULL;
CFURLRef loaderUrl = CFURLCreateCopyAppendingPathComponent(
kCFAllocatorDefault, frameworksUrl, CFSTR("libvulkan.1.dylib"), false);
if (!loaderUrl)
{
CFRelease(frameworksUrl);
return NULL;
}
char path[PATH_MAX];
void* handle = NULL;
if (CFURLGetFileSystemRepresentation(loaderUrl, true, (UInt8*) path, sizeof(path) - 1))
handle = _glfwPlatformLoadModule(path);
CFRelease(loaderUrl);
CFRelease(frameworksUrl);
return handle;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
@@ -688,6 +653,8 @@ void _glfwTerminateCocoa(void)
_glfwTerminateEGL();
_glfwTerminateOSMesa();
memset(&_glfw.ns, 0, sizeof(_glfw.ns));
} // autoreleasepool
}
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Cocoa - www.glfw.org
// GLFW 3.6 Cocoa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
//
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Cocoa - www.glfw.org
// GLFW 3.6 Cocoa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 macOS - www.glfw.org
// GLFW 3.6 Cocoa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
+1 -3
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 macOS - www.glfw.org
// GLFW 3.6 Cocoa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
//
@@ -291,8 +291,6 @@ void _glfwRestoreVideoModeCocoa(_GLFWmonitor* monitor);
float _glfwTransformYCocoa(float y);
void* _glfwLoadLocalVulkanLoaderCocoa(void);
GLFWbool _glfwInitNSGL(void);
void _glfwTerminateNSGL(void);
GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
+29 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 macOS - www.glfw.org
// GLFW 3.6 Cocoa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
//
@@ -599,6 +599,34 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
_glfwInputKey(window, key, [event keyCode], GLFW_RELEASE, mods);
}
- (BOOL)performKeyEquivalent:(NSEvent *)event
{
// HACK: Some key combinations are consumed before reaching keyDown:
// so we claim those events and emit them here
const int key = translateKey([event keyCode]);
const int mods = translateFlags([event modifierFlags]);
if (mods & GLFW_MOD_CONTROL)
{
if (key == GLFW_KEY_TAB || key == GLFW_KEY_ESCAPE)
{
_glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
return YES;
}
}
if (mods & GLFW_MOD_SUPER)
{
if (key == GLFW_KEY_PERIOD)
{
_glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
return YES;
}
}
return [super performKeyEquivalent:event];
}
- (void)scrollWheel:(NSEvent *)event
{
double deltaX = [event scrollingDeltaX];
+8 -3
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 - www.glfw.org
// GLFW 3.6 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
@@ -195,7 +195,7 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
{
current = alternatives + i;
if (desired->stereo > 0 && current->stereo == 0)
if (desired->stereo && !current->stereo)
{
// Stereo is a hard constraint
continue;
@@ -368,7 +368,12 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
window->context.getProcAddress("glGetIntegerv");
window->context.GetString = (PFNGLGETSTRINGPROC)
window->context.getProcAddress("glGetString");
if (!window->context.GetIntegerv || !window->context.GetString)
window->context.Flush = (PFNGLFLUSHPROC)
window->context.getProcAddress("glFlush");
if (!window->context.GetIntegerv ||
!window->context.GetString ||
!window->context.Flush)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
glfwMakeContextCurrent((GLFWwindow*) previous);
+48 -30
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 EGL - www.glfw.org
// GLFW 3.6 EGL - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -254,6 +254,12 @@ static void makeContextCurrentEGL(_GLFWwindow* window)
getEGLErrorString(eglGetError()));
return;
}
#if defined(_GLFW_WAYLAND)
// NOTE: Disable EGL vsync so we can substitute our own that includes a timeout
if (_glfw.platform.platformID == GLFW_PLATFORM_WAYLAND)
eglSwapInterval(_glfw.egl.display, 0);
#endif // _GLFW_WAYLAND
}
else
{
@@ -287,6 +293,15 @@ static void swapBuffersEGL(_GLFWwindow* window)
// NOTE: Swapping buffers on a hidden window on Wayland makes it visible
if (!window->wl.visible)
return;
// NOTE: We wait for a frame manually so we can add a timeout,
// as the EGL implementation will wait indefinitely
if (window->wl.egl.interval > 0)
{
window->context.Flush();
if (!_glfwWaitForEGLFrameWayland(window))
return;
}
}
#endif
@@ -295,6 +310,16 @@ static void swapBuffersEGL(_GLFWwindow* window)
static void swapIntervalEGL(int interval)
{
#if defined(_GLFW_WAYLAND)
if (_glfw.platform.platformID == GLFW_PLATFORM_WAYLAND)
{
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
assert(window != NULL);
window->wl.egl.interval = interval;
return;
}
#endif
eglSwapInterval(_glfw.egl.display, interval);
}
@@ -312,18 +337,19 @@ static int extensionSupportedEGL(const char* extension)
static GLFWglproc getProcAddressEGL(const char* procname)
{
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
assert(window != NULL);
const GLFWglproc proc = (GLFWglproc) eglGetProcAddress(procname);
if (proc)
return proc;
if (window->context.egl.client)
if (!_glfw.egl.KHR_get_all_proc_addresses)
{
GLFWglproc proc = (GLFWglproc)
_glfwPlatformGetModuleSymbol(window->context.egl.client, procname);
if (proc)
return proc;
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
assert(window != NULL);
return _glfwPlatformGetModuleSymbol(window->context.egl.client, procname);
}
return eglGetProcAddress(procname);
return NULL;
}
static void destroyContextEGL(_GLFWwindow* window)
@@ -333,11 +359,8 @@ static void destroyContextEGL(_GLFWwindow* window)
if (_glfw.platform.platformID != GLFW_PLATFORM_X11 ||
window->context.client != GLFW_OPENGL_API)
{
if (window->context.egl.client)
{
_glfwPlatformFreeModule(window->context.egl.client);
window->context.egl.client = NULL;
}
_glfwPlatformFreeModule(window->context.egl.client);
window->context.egl.client = NULL;
}
if (window->context.egl.surface)
@@ -358,8 +381,6 @@ static void destroyContextEGL(_GLFWwindow* window)
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Initialize EGL
//
GLFWbool _glfwInitEGL(void)
{
int i;
@@ -369,10 +390,10 @@ GLFWbool _glfwInitEGL(void)
{
#if defined(_GLFW_EGL_LIBRARY)
_GLFW_EGL_LIBRARY,
#elif defined(_GLFW_WIN32)
#elif defined(_WIN32)
"libEGL.dll",
"EGL.dll",
#elif defined(_GLFW_COCOA)
#elif defined(__APPLE__)
"libEGL.dylib",
#elif defined(__CYGWIN__)
"libEGL-1.so",
@@ -545,8 +566,6 @@ GLFWbool _glfwInitEGL(void)
return GLFW_TRUE;
}
// Terminate EGL
//
void _glfwTerminateEGL(void)
{
if (_glfw.egl.display)
@@ -555,7 +574,8 @@ void _glfwTerminateEGL(void)
_glfw.egl.display = EGL_NO_DISPLAY;
}
if (_glfw.egl.handle)
// Free modules only after all wayland termination functions are called
if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND)
{
_glfwPlatformFreeModule(_glfw.egl.handle);
_glfw.egl.handle = NULL;
@@ -569,8 +589,6 @@ void _glfwTerminateEGL(void)
attribs[index++] = v; \
}
// Create the OpenGL or OpenGL ES context
//
GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
@@ -657,7 +675,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
if (ctxconfig->noerror)
{
if (_glfw.egl.KHR_create_context_no_error)
SET_ATTRIB(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
SET_ATTRIB(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, true);
}
if (mask)
@@ -768,10 +786,10 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{
#if defined(_GLFW_GLESV1_LIBRARY)
_GLFW_GLESV1_LIBRARY,
#elif defined(_GLFW_WIN32)
#elif defined(_WIN32)
"GLESv1_CM.dll",
"libGLES_CM.dll",
#elif defined(_GLFW_COCOA)
#elif defined(__APPLE__)
"libGLESv1_CM.dylib",
#elif defined(__OpenBSD__) || defined(__NetBSD__)
"libGLESv1_CM.so",
@@ -785,10 +803,10 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{
#if defined(_GLFW_GLESV2_LIBRARY)
_GLFW_GLESV2_LIBRARY,
#elif defined(_GLFW_WIN32)
#elif defined(_WIN32)
"GLESv2.dll",
"libGLESv2.dll",
#elif defined(_GLFW_COCOA)
#elif defined(__APPLE__)
"libGLESv2.dylib",
#elif defined(__CYGWIN__)
"libGLESv2-2.so",
@@ -803,8 +821,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{
#if defined(_GLFW_OPENGL_LIBRARY)
_GLFW_OPENGL_LIBRARY,
#elif defined(_GLFW_WIN32)
#elif defined(_GLFW_COCOA)
#elif defined(_WIN32)
#elif defined(__APPLE__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
"libGL.so",
#else
+16 -27
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 GLX - www.glfw.org
// GLFW 3.6 GLX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -119,9 +119,7 @@ static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
u->accumAlphaBits = getGLXFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE);
u->auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS);
if (getGLXFBConfigAttrib(n, GLX_STEREO))
u->stereo = GLFW_TRUE;
u->stereo = getGLXFBConfigAttrib(n, GLX_STEREO);
if (_glfw.glx.ARB_multisample)
u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES);
@@ -253,8 +251,6 @@ static void destroyContextGLX(_GLFWwindow* window)
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Initialize GLX
//
GLFWbool _glfwInitGLX(void)
{
const char* sonames[] =
@@ -369,7 +365,7 @@ GLFWbool _glfwInitGLX(void)
getProcAddressGLX("glXSwapIntervalEXT");
if (_glfw.glx.SwapIntervalEXT)
_glfw.glx.EXT_swap_control = GLFW_TRUE;
_glfw.glx.EXT_swap_control = true;
}
if (extensionSupportedGLX("GLX_SGI_swap_control"))
@@ -378,7 +374,7 @@ GLFWbool _glfwInitGLX(void)
getProcAddressGLX("glXSwapIntervalSGI");
if (_glfw.glx.SwapIntervalSGI)
_glfw.glx.SGI_swap_control = GLFW_TRUE;
_glfw.glx.SGI_swap_control = true;
}
if (extensionSupportedGLX("GLX_MESA_swap_control"))
@@ -387,17 +383,17 @@ GLFWbool _glfwInitGLX(void)
getProcAddressGLX("glXSwapIntervalMESA");
if (_glfw.glx.SwapIntervalMESA)
_glfw.glx.MESA_swap_control = GLFW_TRUE;
_glfw.glx.MESA_swap_control = true;
}
if (extensionSupportedGLX("GLX_ARB_multisample"))
_glfw.glx.ARB_multisample = GLFW_TRUE;
_glfw.glx.ARB_multisample = true;
if (extensionSupportedGLX("GLX_ARB_framebuffer_sRGB"))
_glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE;
_glfw.glx.ARB_framebuffer_sRGB = true;
if (extensionSupportedGLX("GLX_EXT_framebuffer_sRGB"))
_glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE;
_glfw.glx.EXT_framebuffer_sRGB = true;
if (extensionSupportedGLX("GLX_ARB_create_context"))
{
@@ -405,39 +401,34 @@ GLFWbool _glfwInitGLX(void)
getProcAddressGLX("glXCreateContextAttribsARB");
if (_glfw.glx.CreateContextAttribsARB)
_glfw.glx.ARB_create_context = GLFW_TRUE;
_glfw.glx.ARB_create_context = true;
}
if (extensionSupportedGLX("GLX_ARB_create_context_robustness"))
_glfw.glx.ARB_create_context_robustness = GLFW_TRUE;
_glfw.glx.ARB_create_context_robustness = true;
if (extensionSupportedGLX("GLX_ARB_create_context_profile"))
_glfw.glx.ARB_create_context_profile = GLFW_TRUE;
_glfw.glx.ARB_create_context_profile = true;
if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))
_glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE;
_glfw.glx.EXT_create_context_es2_profile = true;
if (extensionSupportedGLX("GLX_ARB_create_context_no_error"))
_glfw.glx.ARB_create_context_no_error = GLFW_TRUE;
_glfw.glx.ARB_create_context_no_error = true;
if (extensionSupportedGLX("GLX_ARB_context_flush_control"))
_glfw.glx.ARB_context_flush_control = GLFW_TRUE;
_glfw.glx.ARB_context_flush_control = true;
return GLFW_TRUE;
}
// Terminate GLX
//
void _glfwTerminateGLX(void)
{
// NOTE: This function must not call any X11 functions, as it is called
// after XCloseDisplay (see _glfwTerminateX11 for details)
if (_glfw.glx.handle)
{
_glfwPlatformFreeModule(_glfw.glx.handle);
_glfw.glx.handle = NULL;
}
_glfwPlatformFreeModule(_glfw.glx.handle);
_glfw.glx.handle = NULL;
}
#define SET_ATTRIB(a, v) \
@@ -447,8 +438,6 @@ void _glfwTerminateGLX(void)
attribs[index++] = v; \
}
// Create the OpenGL or OpenGL ES context
//
GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
+5 -5
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 - www.glfw.org
// GLFW 3.6 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
@@ -49,18 +49,18 @@ static GLFWerrorfun _glfwErrorCallback;
static GLFWallocator _glfwInitAllocator;
static _GLFWinitconfig _glfwInitHints =
{
.hatButtons = GLFW_TRUE,
.hatButtons = true,
.angleType = GLFW_ANGLE_PLATFORM_TYPE_NONE,
.platformID = GLFW_ANY_PLATFORM,
.vulkanLoader = NULL,
.ns =
{
.menubar = GLFW_TRUE,
.chdir = GLFW_TRUE
.menubar = true,
.chdir = true
},
.x11 =
{
.xcbVulkanSurface = GLFW_TRUE,
.xcbVulkanSurface = true,
},
.wl =
{
+8 -12
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 - www.glfw.org
// GLFW 3.6 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -333,10 +333,8 @@ void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
{
assert(window != NULL);
assert(xoffset > -FLT_MAX);
assert(xoffset < FLT_MAX);
assert(yoffset > -FLT_MAX);
assert(yoffset < FLT_MAX);
assert(isfinite(xoffset));
assert(isfinite(yoffset));
if (window->callbacks.scroll)
window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
@@ -375,10 +373,8 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
{
assert(window != NULL);
assert(xpos > -FLT_MAX);
assert(xpos < FLT_MAX);
assert(ypos > -FLT_MAX);
assert(ypos < FLT_MAX);
assert(isfinite(xpos));
assert(isfinite(ypos));
if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)
return;
@@ -436,6 +432,7 @@ void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value)
assert(js != NULL);
assert(axis >= 0);
assert(axis < js->axisCount);
assert(isfinite(value));
js->axes[axis] = value;
}
@@ -818,8 +815,7 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (xpos != xpos || xpos < -DBL_MAX || xpos > DBL_MAX ||
ypos != ypos || ypos < -DBL_MAX || ypos > DBL_MAX)
if (!isfinite(xpos) || !isfinite(ypos))
{
_glfwInputError(GLFW_INVALID_VALUE,
"Invalid cursor position %f %f",
@@ -1499,7 +1495,7 @@ GLFWAPI void glfwSetTime(double time)
{
_GLFW_REQUIRE_INIT();
if (time != time || time < 0.0 || time > 18446744073.0)
if (!isfinite(time) || time < 0.0 || time > 18446744073.0)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", time);
return;
+53 -51
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 - www.glfw.org
// GLFW 3.6 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -109,6 +109,7 @@ typedef void (APIENTRY * PFNGLCLEARPROC)(GLbitfield);
typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGPROC)(GLenum);
typedef void (APIENTRY * PFNGLGETINTEGERVPROC)(GLenum,GLint*);
typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint);
typedef void (APIENTRY * PFNGLFLUSHPROC)(void);
#define EGL_SUCCESS 0x3000
#define EGL_NOT_INITIALIZED 0x3001
@@ -374,16 +375,16 @@ struct _GLFWerror
//
struct _GLFWinitconfig
{
GLFWbool hatButtons;
bool hatButtons;
int angleType;
int platformID;
PFN_vkGetInstanceProcAddr vulkanLoader;
struct {
GLFWbool menubar;
GLFWbool chdir;
bool menubar;
bool chdir;
} ns;
struct {
GLFWbool xcbVulkanSurface;
bool xcbVulkanSurface;
} x11;
struct {
int libdecorMode;
@@ -402,18 +403,18 @@ struct _GLFWwndconfig
int ypos;
int width;
int height;
GLFWbool resizable;
GLFWbool visible;
GLFWbool decorated;
GLFWbool focused;
GLFWbool autoIconify;
GLFWbool floating;
GLFWbool maximized;
GLFWbool centerCursor;
GLFWbool focusOnShow;
GLFWbool mousePassthrough;
GLFWbool scaleToMonitor;
GLFWbool scaleFramebuffer;
bool resizable;
bool visible;
bool decorated;
bool focused;
bool autoIconify;
bool floating;
bool maximized;
bool centerCursor;
bool focusOnShow;
bool mousePassthrough;
bool scaleToMonitor;
bool scaleFramebuffer;
struct {
char frameName[256];
} ns;
@@ -422,8 +423,8 @@ struct _GLFWwndconfig
char instanceName[256];
} x11;
struct {
GLFWbool keymenu;
GLFWbool showDefault;
bool keymenu;
bool showDefault;
} win32;
struct {
char appId[256];
@@ -442,15 +443,15 @@ struct _GLFWctxconfig
int source;
int major;
int minor;
GLFWbool forward;
GLFWbool debug;
GLFWbool noerror;
bool forward;
bool debug;
bool noerror;
int profile;
int robustness;
int release;
_GLFWwindow* share;
struct {
GLFWbool offline;
bool offline;
} nsgl;
};
@@ -475,11 +476,11 @@ struct _GLFWfbconfig
int accumBlueBits;
int accumAlphaBits;
int auxBuffers;
GLFWbool stereo;
bool stereo;
int samples;
GLFWbool sRGB;
GLFWbool doublebuffer;
GLFWbool transparent;
bool sRGB;
bool doublebuffer;
bool transparent;
uintptr_t handle;
};
@@ -498,6 +499,7 @@ struct _GLFWcontext
PFNGLGETSTRINGIPROC GetStringi;
PFNGLGETINTEGERVPROC GetIntegerv;
PFNGLGETSTRINGPROC GetString;
PFNGLFLUSHPROC Flush;
void (*makeCurrent)(_GLFWwindow*);
void (*swapBuffers)(_GLFWwindow*);
@@ -805,22 +807,22 @@ struct _GLFWlibrary
EGLint major, minor;
GLFWbool prefix;
GLFWbool KHR_create_context;
GLFWbool KHR_create_context_no_error;
GLFWbool KHR_gl_colorspace;
GLFWbool KHR_get_all_proc_addresses;
GLFWbool KHR_context_flush_control;
GLFWbool EXT_client_extensions;
GLFWbool EXT_platform_base;
GLFWbool EXT_platform_x11;
GLFWbool EXT_platform_wayland;
GLFWbool EXT_present_opaque;
GLFWbool ANGLE_platform_angle;
GLFWbool ANGLE_platform_angle_opengl;
GLFWbool ANGLE_platform_angle_d3d;
GLFWbool ANGLE_platform_angle_vulkan;
GLFWbool ANGLE_platform_angle_metal;
GLFWbool MESA_platform_surfaceless;
bool KHR_create_context;
bool KHR_create_context_no_error;
bool KHR_gl_colorspace;
bool KHR_get_all_proc_addresses;
bool KHR_context_flush_control;
bool EXT_client_extensions;
bool EXT_platform_base;
bool EXT_platform_x11;
bool EXT_platform_wayland;
bool EXT_present_opaque;
bool ANGLE_platform_angle;
bool ANGLE_platform_angle_opengl;
bool ANGLE_platform_angle_d3d;
bool ANGLE_platform_angle_vulkan;
bool ANGLE_platform_angle_metal;
bool MESA_platform_surfaceless;
void* handle;
@@ -864,14 +866,14 @@ struct _GLFWlibrary
void* handle;
char* extensions[2];
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
GLFWbool KHR_surface;
GLFWbool KHR_win32_surface;
GLFWbool MVK_macos_surface;
GLFWbool EXT_metal_surface;
GLFWbool KHR_xlib_surface;
GLFWbool KHR_xcb_surface;
GLFWbool KHR_wayland_surface;
GLFWbool EXT_headless_surface;
bool KHR_surface;
bool KHR_win32_surface;
bool MVK_macos_surface;
bool EXT_metal_surface;
bool KHR_xlib_surface;
bool KHR_xcb_surface;
bool KHR_wayland_surface;
bool EXT_headless_surface;
} vk;
struct {
+2 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Linux - www.glfw.org
// GLFW 3.6 Linux - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
@@ -32,6 +32,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Linux - www.glfw.org
// GLFW 3.6 Linux - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
//
+5 -5
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 macOS - www.glfw.org
// GLFW 3.6 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
//
@@ -26,7 +26,7 @@
#include "internal.h"
#if defined(GLFW_BUILD_COCOA_TIMER)
#if defined(GLFW_BUILD_MACOS_TIMER)
#include <mach/mach_time.h>
@@ -40,7 +40,7 @@ void _glfwPlatformInitTimer(void)
mach_timebase_info_data_t info;
mach_timebase_info(&info);
_glfw.timer.ns.frequency = (info.denom * 1e9) / info.numer;
_glfw.timer.macos.frequency = (info.denom * 1e9) / info.numer;
}
uint64_t _glfwPlatformGetTimerValue(void)
@@ -50,8 +50,8 @@ uint64_t _glfwPlatformGetTimerValue(void)
uint64_t _glfwPlatformGetTimerFrequency(void)
{
return _glfw.timer.ns.frequency;
return _glfw.timer.macos.frequency;
}
#endif // GLFW_BUILD_COCOA_TIMER
#endif // GLFW_BUILD_MACOS_TIMER
+5 -5
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 macOS - www.glfw.org
// GLFW 3.6 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2021 Camilla Löwy <elmindreda@glfw.org>
//
@@ -24,12 +24,12 @@
//
//========================================================================
#define GLFW_COCOA_LIBRARY_TIMER_STATE _GLFWtimerNS ns;
#define GLFW_MACOS_LIBRARY_TIMER_STATE _GLFWtimerMacOS macos;
// Cocoa-specific global timer data
// macOS-specific global timer data
//
typedef struct _GLFWtimerNS
typedef struct _GLFWtimerMacOS
{
uint64_t frequency;
} _GLFWtimerNS;
} _GLFWtimerMacOS;
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 - www.glfw.org
// GLFW 3.6 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
//
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 - www.glfw.org
// GLFW 3.6 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
//
+4 -3
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 - www.glfw.org
// GLFW 3.6 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -467,14 +467,15 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
unsigned short* values;
GLFWgammaramp ramp;
const GLFWgammaramp* original;
assert(gamma > 0.f);
assert(gamma <= FLT_MAX);
assert(isfinite(gamma));
_GLFW_REQUIRE_INIT();
assert(handle != NULL);
if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX)
if (!isfinite(gamma) || gamma <= 0.f)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
return;
+1 -7
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 macOS - www.glfw.org
// GLFW 3.6 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
//
@@ -128,8 +128,6 @@ static void destroyContextNSGL(_GLFWwindow* window)
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Initialize OpenGL support
//
GLFWbool _glfwInitNSGL(void)
{
if (_glfw.nsgl.framework)
@@ -147,14 +145,10 @@ GLFWbool _glfwInitNSGL(void)
return GLFW_TRUE;
}
// Terminate OpenGL support
//
void _glfwTerminateNSGL(void)
{
}
// Create the OpenGL context
//
GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
+2 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 - www.glfw.org
// GLFW 3.6 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
@@ -260,5 +260,6 @@ void _glfwTerminateNull(void)
free(_glfw.null.clipboardString);
_glfwTerminateOSMesa();
_glfwTerminateEGL();
memset(&_glfw.null, 0, sizeof(_glfw.null));
}
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 - www.glfw.org
// GLFW 3.6 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
//
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 - www.glfw.org
// GLFW 3.6 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
//
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 - www.glfw.org
// GLFW 3.6 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2019 Camilla Löwy <elmindreda@glfw.org>
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 - www.glfw.org
// GLFW 3.6 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 - www.glfw.org
// GLFW 3.6 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2019 Camilla Löwy <elmindreda@glfw.org>
+3 -6
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 OSMesa - www.glfw.org
// GLFW 3.6 OSMesa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
@@ -180,11 +180,8 @@ GLFWbool _glfwInitOSMesa(void)
void _glfwTerminateOSMesa(void)
{
if (_glfw.osmesa.handle)
{
_glfwPlatformFreeModule(_glfw.osmesa.handle);
_glfw.osmesa.handle = NULL;
}
_glfwPlatformFreeModule(_glfw.osmesa.handle);
_glfw.osmesa.handle = NULL;
}
#define SET_ATTRIB(a, v) \
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 - www.glfw.org
// GLFW 3.6 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
+7 -6
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 - www.glfw.org
// GLFW 3.6 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
@@ -28,7 +28,7 @@
#if defined(GLFW_BUILD_WIN32_TIMER) || \
defined(GLFW_BUILD_WIN32_MODULE) || \
defined(GLFW_BUILD_WIN32_THREAD) || \
defined(GLFW_BUILD_COCOA_TIMER) || \
defined(GLFW_BUILD_MACOS_TIMER) || \
defined(GLFW_BUILD_POSIX_TIMER) || \
defined(GLFW_BUILD_POSIX_MODULE) || \
defined(GLFW_BUILD_POSIX_THREAD) || \
@@ -184,7 +184,7 @@
#if defined(_WIN32)
#define GLFW_BUILD_WIN32_TIMER
#elif defined(__APPLE__)
#define GLFW_BUILD_COCOA_TIMER
#define GLFW_BUILD_MACOS_TIMER
#else
#define GLFW_BUILD_POSIX_TIMER
#endif
@@ -192,9 +192,9 @@
#if defined(GLFW_BUILD_WIN32_TIMER)
#include "win32_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_WIN32_LIBRARY_TIMER_STATE
#elif defined(GLFW_BUILD_COCOA_TIMER)
#include "cocoa_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_COCOA_LIBRARY_TIMER_STATE
#elif defined(GLFW_BUILD_MACOS_TIMER)
#include "macos_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_MACOS_LIBRARY_TIMER_STATE
#elif defined(GLFW_BUILD_POSIX_TIMER)
#include "posix_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_POSIX_LIBRARY_TIMER_STATE
@@ -207,6 +207,7 @@
#endif
#if defined(_GLFW_WAYLAND) || defined(_GLFW_X11)
#include "posix_poll.h"
#define GLFW_BUILD_POSIX_POLL
#endif
+3 -2
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 POSIX - www.glfw.org
// GLFW 3.6 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2021 Camilla Löwy <elmindreda@glfw.org>
//
@@ -41,7 +41,8 @@ void* _glfwPlatformLoadModule(const char* path)
void _glfwPlatformFreeModule(void* module)
{
dlclose(module);
if (module)
dlclose(module);
}
GLFWproc _glfwPlatformGetModuleSymbol(void* module, const char* name)
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 POSIX - www.glfw.org
// GLFW 3.6 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2022 Camilla Löwy <elmindreda@glfw.org>
//
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 POSIX - www.glfw.org
// GLFW 3.6 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2022 Camilla Löwy <elmindreda@glfw.org>
//
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 POSIX - www.glfw.org
// GLFW 3.6 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 POSIX - www.glfw.org
// GLFW 3.6 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 POSIX - www.glfw.org
// GLFW 3.6 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 POSIX - www.glfw.org
// GLFW 3.6 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
+48 -14
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 - www.glfw.org
// GLFW 3.6 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
@@ -34,6 +34,40 @@
#define _GLFW_FIND_LOADER 1
#define _GLFW_REQUIRE_LOADER 2
#if defined(__APPLE__)
#include <CoreFoundation/CoreFoundation.h>
static void* loadLocalVulkanLoaderMacOS(void)
{
CFBundleRef bundle = CFBundleGetMainBundle();
if (!bundle)
return NULL;
CFURLRef frameworksUrl = CFBundleCopyPrivateFrameworksURL(bundle);
if (!frameworksUrl)
return NULL;
CFURLRef loaderUrl = CFURLCreateCopyAppendingPathComponent(
kCFAllocatorDefault, frameworksUrl, CFSTR("libvulkan.1.dylib"), false);
if (!loaderUrl)
{
CFRelease(frameworksUrl);
return NULL;
}
char path[PATH_MAX];
void* handle = NULL;
if (CFURLGetFileSystemRepresentation(loaderUrl, true, (UInt8*) path, sizeof(path) - 1))
handle = _glfwPlatformLoadModule(path);
CFRelease(loaderUrl);
CFRelease(frameworksUrl);
return handle;
}
#endif // __APPLE__
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
@@ -55,12 +89,12 @@ GLFWbool _glfwInitVulkan(int mode)
{
#if defined(_GLFW_VULKAN_LIBRARY)
_glfw.vk.handle = _glfwPlatformLoadModule(_GLFW_VULKAN_LIBRARY);
#elif defined(_GLFW_WIN32)
#elif defined(_WIN32)
_glfw.vk.handle = _glfwPlatformLoadModule("vulkan-1.dll");
#elif defined(_GLFW_COCOA)
#elif defined(__APPLE__)
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib");
if (!_glfw.vk.handle)
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa();
_glfw.vk.handle = loadLocalVulkanLoaderMacOS();
#elif defined(__OpenBSD__) || defined(__NetBSD__)
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so");
#else
@@ -129,21 +163,21 @@ GLFWbool _glfwInitVulkan(int mode)
for (i = 0; i < count; i++)
{
if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
_glfw.vk.KHR_surface = GLFW_TRUE;
_glfw.vk.KHR_surface = true;
else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
_glfw.vk.KHR_win32_surface = GLFW_TRUE;
_glfw.vk.KHR_win32_surface = true;
else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
_glfw.vk.MVK_macos_surface = GLFW_TRUE;
_glfw.vk.MVK_macos_surface = true;
else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0)
_glfw.vk.EXT_metal_surface = GLFW_TRUE;
_glfw.vk.EXT_metal_surface = true;
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
_glfw.vk.KHR_xlib_surface = GLFW_TRUE;
_glfw.vk.KHR_xlib_surface = true;
else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
_glfw.vk.KHR_xcb_surface = GLFW_TRUE;
_glfw.vk.KHR_xcb_surface = true;
else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
_glfw.vk.KHR_wayland_surface = GLFW_TRUE;
_glfw.vk.KHR_wayland_surface = true;
else if (strcmp(ep[i].extensionName, "VK_EXT_headless_surface") == 0)
_glfw.vk.EXT_headless_surface = GLFW_TRUE;
_glfw.vk.EXT_headless_surface = true;
}
_glfw_free(ep);
@@ -157,8 +191,8 @@ GLFWbool _glfwInitVulkan(int mode)
void _glfwTerminateVulkan(void)
{
if (_glfw.vk.handle)
_glfwPlatformFreeModule(_glfw.vk.handle);
_glfwPlatformFreeModule(_glfw.vk.handle);
_glfw.vk.handle = NULL;
}
const char* _glfwGetVulkanResultString(VkResult result)
+9 -23
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 WGL - www.glfw.org
// GLFW 3.6 WGL - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -186,28 +186,22 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
u->accumAlphaBits = FIND_ATTRIB_VALUE(WGL_ACCUM_ALPHA_BITS_ARB);
u->auxBuffers = FIND_ATTRIB_VALUE(WGL_AUX_BUFFERS_ARB);
if (FIND_ATTRIB_VALUE(WGL_STEREO_ARB))
u->stereo = GLFW_TRUE;
u->stereo = FIND_ATTRIB_VALUE(WGL_STEREO_ARB);
if (_glfw.wgl.ARB_multisample)
u->samples = FIND_ATTRIB_VALUE(WGL_SAMPLES_ARB);
if (ctxconfig->client == GLFW_OPENGL_API)
{
if (_glfw.wgl.ARB_framebuffer_sRGB ||
_glfw.wgl.EXT_framebuffer_sRGB)
{
if (FIND_ATTRIB_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
u->sRGB = GLFW_TRUE;
}
if (_glfw.wgl.ARB_framebuffer_sRGB || _glfw.wgl.EXT_framebuffer_sRGB)
u->sRGB = FIND_ATTRIB_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
}
else
{
if (_glfw.wgl.EXT_colorspace)
{
if (FIND_ATTRIB_VALUE(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT)
u->sRGB = GLFW_TRUE;
u->sRGB = true;
}
}
}
@@ -261,9 +255,7 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
u->accumAlphaBits = pfd.cAccumAlphaBits;
u->auxBuffers = pfd.cAuxBuffers;
if (pfd.dwFlags & PFD_STEREO)
u->stereo = GLFW_TRUE;
u->stereo = (pfd.dwFlags & PFD_STEREO);
}
u->handle = pixelFormat;
@@ -401,8 +393,6 @@ static void destroyContextWGL(_GLFWwindow* window)
}
}
// Initialize WGL
//
GLFWbool _glfwInitWGL(void)
{
PIXELFORMATDESCRIPTOR pfd;
@@ -521,12 +511,10 @@ GLFWbool _glfwInitWGL(void)
return GLFW_TRUE;
}
// Terminate WGL
//
void _glfwTerminateWGL(void)
{
if (_glfw.wgl.instance)
_glfwPlatformFreeModule(_glfw.wgl.instance);
_glfwPlatformFreeModule(_glfw.wgl.instance);
_glfw.wgl.instance = NULL;
}
#define SET_ATTRIB(a, v) \
@@ -536,8 +524,6 @@ void _glfwTerminateWGL(void)
attribs[index++] = v; \
}
// Create the OpenGL or OpenGL ES context
//
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
@@ -670,7 +656,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
if (ctxconfig->noerror)
{
if (_glfw.wgl.ARB_create_context_no_error)
SET_ATTRIB(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
SET_ATTRIB(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, true);
}
// NOTE: Only request an explicitly versioned context when necessary, as
+11 -26
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Win32 - www.glfw.org
// GLFW 3.6 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -166,29 +166,6 @@ static GLFWbool loadLibraries(void)
return GLFW_TRUE;
}
// Unload used libraries (DLLs)
//
static void freeLibraries(void)
{
if (_glfw.win32.xinput.instance)
_glfwPlatformFreeModule(_glfw.win32.xinput.instance);
if (_glfw.win32.dinput8.instance)
_glfwPlatformFreeModule(_glfw.win32.dinput8.instance);
if (_glfw.win32.user32.instance)
_glfwPlatformFreeModule(_glfw.win32.user32.instance);
if (_glfw.win32.dwmapi.instance)
_glfwPlatformFreeModule(_glfw.win32.dwmapi.instance);
if (_glfw.win32.shcore.instance)
_glfwPlatformFreeModule(_glfw.win32.shcore.instance);
if (_glfw.win32.ntdll.instance)
_glfwPlatformFreeModule(_glfw.win32.ntdll.instance);
}
// Create key code translation tables
//
static void createKeyTables(void)
@@ -528,7 +505,8 @@ void _glfwUpdateKeyNamesWin32(void)
if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD)
{
const UINT vks[] = {
const UINT vks[] =
{
VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,
VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, VK_DIVIDE,
@@ -720,7 +698,14 @@ void _glfwTerminateWin32(void)
_glfwTerminateEGL();
_glfwTerminateOSMesa();
freeLibraries();
_glfwPlatformFreeModule(_glfw.win32.xinput.instance);
_glfwPlatformFreeModule(_glfw.win32.dinput8.instance);
_glfwPlatformFreeModule(_glfw.win32.user32.instance);
_glfwPlatformFreeModule(_glfw.win32.dwmapi.instance);
_glfwPlatformFreeModule(_glfw.win32.shcore.instance);
_glfwPlatformFreeModule(_glfw.win32.ntdll.instance);
memset(&_glfw.win32, 0, sizeof(_glfw.win32));
}
#endif // _GLFW_WIN32
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Win32 - www.glfw.org
// GLFW 3.6 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Win32 - www.glfw.org
// GLFW 3.6 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
//
+3 -2
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Win32 - www.glfw.org
// GLFW 3.6 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2021 Camilla Löwy <elmindreda@glfw.org>
//
@@ -39,7 +39,8 @@ void* _glfwPlatformLoadModule(const char* path)
void _glfwPlatformFreeModule(void* module)
{
FreeLibrary((HMODULE) module);
if (module)
FreeLibrary((HMODULE) module);
}
GLFWproc _glfwPlatformGetModuleSymbol(void* module, const char* name)
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Win32 - www.glfw.org
// GLFW 3.6 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
+13 -13
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Win32 - www.glfw.org
// GLFW 3.6 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -336,18 +336,18 @@ typedef struct _GLFWlibraryWGL
PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
GLFWbool EXT_swap_control;
GLFWbool EXT_colorspace;
GLFWbool ARB_multisample;
GLFWbool ARB_framebuffer_sRGB;
GLFWbool EXT_framebuffer_sRGB;
GLFWbool ARB_pixel_format;
GLFWbool ARB_create_context;
GLFWbool ARB_create_context_profile;
GLFWbool EXT_create_context_es2_profile;
GLFWbool ARB_create_context_robustness;
GLFWbool ARB_create_context_no_error;
GLFWbool ARB_context_flush_control;
bool EXT_swap_control;
bool EXT_colorspace;
bool ARB_multisample;
bool ARB_framebuffer_sRGB;
bool EXT_framebuffer_sRGB;
bool ARB_pixel_format;
bool ARB_create_context;
bool ARB_create_context_profile;
bool EXT_create_context_es2_profile;
bool ARB_create_context_robustness;
bool ARB_create_context_no_error;
bool ARB_context_flush_control;
} _GLFWlibraryWGL;
// Win32-specific per-window data
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Win32 - www.glfw.org
// GLFW 3.6 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Win32 - www.glfw.org
// GLFW 3.6 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Win32 - www.glfw.org
// GLFW 3.6 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Win32 - www.glfw.org
// GLFW 3.6 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
+6 -5
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Win32 - www.glfw.org
// GLFW 3.6 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -711,11 +711,12 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
const int mods = getKeyMods();
scancode = (HIWORD(lParam) & (KF_EXTENDED | 0xff));
if (!scancode)
if (!(scancode & 0xff))
{
// NOTE: Some synthetic key messages have a scancode of zero
// HACK: Map the virtual key back to a usable scancode
scancode = MapVirtualKeyW((UINT) wParam, MAPVK_VK_TO_VSC);
// NOTE: Both media keys and the synthetic key messages from Windows
// Clipboard History are reported with a scancode of zero
// HACK: Map the virtual key to a scancode but preserve extended bit
scancode |= MapVirtualKeyW((UINT) wParam, MAPVK_VK_TO_VSC);
}
// HACK: Alt+PrtSc has a different scancode than just PrtSc
+39 -40
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 - www.glfw.org
// GLFW 3.6 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -32,7 +32,7 @@
#include <string.h>
#include <stdlib.h>
#include <float.h>
#include <math.h>
//////////////////////////////////////////////////////////////////////////
////// GLFW event API //////
@@ -135,9 +135,9 @@ void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscal
{
assert(window != NULL);
assert(xscale > 0.f);
assert(xscale < FLT_MAX);
assert(isfinite(xscale));
assert(yscale > 0.f);
assert(yscale < FLT_MAX);
assert(isfinite(yscale));
if (window->callbacks.scale)
window->callbacks.scale((GLFWwindow*) window, xscale, yscale);
@@ -265,16 +265,16 @@ void glfwDefaultWindowHints(void)
// The default is a focused, visible, resizable window with decorations
memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
_glfw.hints.window.resizable = GLFW_TRUE;
_glfw.hints.window.visible = GLFW_TRUE;
_glfw.hints.window.decorated = GLFW_TRUE;
_glfw.hints.window.focused = GLFW_TRUE;
_glfw.hints.window.autoIconify = GLFW_TRUE;
_glfw.hints.window.centerCursor = GLFW_TRUE;
_glfw.hints.window.focusOnShow = GLFW_TRUE;
_glfw.hints.window.resizable = true;
_glfw.hints.window.visible = true;
_glfw.hints.window.decorated = true;
_glfw.hints.window.focused = true;
_glfw.hints.window.autoIconify = true;
_glfw.hints.window.centerCursor = true;
_glfw.hints.window.focusOnShow = true;
_glfw.hints.window.xpos = GLFW_ANY_POSITION;
_glfw.hints.window.ypos = GLFW_ANY_POSITION;
_glfw.hints.window.scaleFramebuffer = GLFW_TRUE;
_glfw.hints.window.scaleFramebuffer = true;
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
// double buffered
@@ -285,7 +285,7 @@ void glfwDefaultWindowHints(void)
_glfw.hints.framebuffer.alphaBits = 8;
_glfw.hints.framebuffer.depthBits = 24;
_glfw.hints.framebuffer.stencilBits = 8;
_glfw.hints.framebuffer.doublebuffer = GLFW_TRUE;
_glfw.hints.framebuffer.doublebuffer = true;
// The default is to select the highest available refresh rate
_glfw.hints.refreshRate = GLFW_DONT_CARE;
@@ -331,40 +331,40 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_glfw.hints.framebuffer.auxBuffers = value;
return;
case GLFW_STEREO:
_glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.framebuffer.stereo = value;
return;
case GLFW_DOUBLEBUFFER:
_glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.framebuffer.doublebuffer = value;
return;
case GLFW_TRANSPARENT_FRAMEBUFFER:
_glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.framebuffer.transparent = value;
return;
case GLFW_SAMPLES:
_glfw.hints.framebuffer.samples = value;
return;
case GLFW_SRGB_CAPABLE:
_glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.framebuffer.sRGB = value;
return;
case GLFW_RESIZABLE:
_glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.window.resizable = value;
return;
case GLFW_DECORATED:
_glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.window.decorated = value;
return;
case GLFW_FOCUSED:
_glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.window.focused = value;
return;
case GLFW_AUTO_ICONIFY:
_glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.window.autoIconify = value;
return;
case GLFW_FLOATING:
_glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.window.floating = value;
return;
case GLFW_MAXIMIZED:
_glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.window.maximized = value;
return;
case GLFW_VISIBLE:
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.window.visible = value;
return;
case GLFW_POSITION_X:
_glfw.hints.window.xpos = value;
@@ -373,29 +373,29 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_glfw.hints.window.ypos = value;
return;
case GLFW_WIN32_KEYBOARD_MENU:
_glfw.hints.window.win32.keymenu = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.window.win32.keymenu = value;
return;
case GLFW_WIN32_SHOWDEFAULT:
_glfw.hints.window.win32.showDefault = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.window.win32.showDefault = value;
return;
case GLFW_COCOA_GRAPHICS_SWITCHING:
_glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.context.nsgl.offline = value;
return;
case GLFW_SCALE_TO_MONITOR:
_glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.window.scaleToMonitor = value;
return;
case GLFW_SCALE_FRAMEBUFFER:
case GLFW_COCOA_RETINA_FRAMEBUFFER:
_glfw.hints.window.scaleFramebuffer = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.window.scaleFramebuffer = value;
return;
case GLFW_CENTER_CURSOR:
_glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.window.centerCursor = value;
return;
case GLFW_FOCUS_ON_SHOW:
_glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.window.focusOnShow = value;
return;
case GLFW_MOUSE_PASSTHROUGH:
_glfw.hints.window.mousePassthrough = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.window.mousePassthrough = value;
return;
case GLFW_CLIENT_API:
_glfw.hints.context.client = value;
@@ -413,13 +413,13 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_glfw.hints.context.robustness = value;
return;
case GLFW_OPENGL_FORWARD_COMPAT:
_glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.context.forward = value;
return;
case GLFW_CONTEXT_DEBUG:
_glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.context.debug = value;
return;
case GLFW_CONTEXT_NO_ERROR:
_glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
_glfw.hints.context.noerror = value;
return;
case GLFW_OPENGL_PROFILE:
_glfw.hints.context.profile = value;
@@ -776,7 +776,7 @@ GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle)
GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity)
{
assert(opacity == opacity);
assert(isfinite(opacity));
assert(opacity >= 0.f);
assert(opacity <= 1.f);
@@ -785,7 +785,7 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity)
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (opacity != opacity || opacity < 0.f || opacity > 1.f)
if (!isfinite(opacity) || opacity < 0.f || opacity > 1.f)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid window opacity %f", opacity);
return;
@@ -1178,11 +1178,10 @@ GLFWAPI void glfwWaitEvents(void)
GLFWAPI void glfwWaitEventsTimeout(double timeout)
{
_GLFW_REQUIRE_INIT();
assert(timeout == timeout);
assert(isfinite(timeout));
assert(timeout >= 0.0);
assert(timeout <= DBL_MAX);
if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)
if (!isfinite(timeout) || timeout < 0.0)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", timeout);
return;
+52 -41
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Wayland - www.glfw.org
// GLFW 3.6 Wayland - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
//
@@ -135,15 +135,8 @@ static void registryHandleGlobal(void* userData,
{
_glfw.wl.seat =
wl_registry_bind(registry, name, &wl_seat_interface,
_glfw_min(4, version));
_glfw_min(8, version));
_glfwAddSeatListenerWayland(_glfw.wl.seat);
if (wl_seat_get_version(_glfw.wl.seat) >=
WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
{
_glfw.wl.keyRepeatTimerfd =
timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
}
}
}
else if (strcmp(interface, "wl_data_device_manager") == 0)
@@ -251,10 +244,7 @@ static void libdecorReadyCallback(void* userData,
uint32_t time)
{
_glfw.wl.libdecor.ready = GLFW_TRUE;
assert(_glfw.wl.libdecor.callback == callback);
wl_callback_destroy(_glfw.wl.libdecor.callback);
_glfw.wl.libdecor.callback = NULL;
wl_callback_destroy(callback);
}
static const struct wl_callback_listener libdecorReadyListener =
@@ -585,6 +575,14 @@ int _glfwInitWayland(void)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_get_fd");
_glfw.wl.client.display_prepare_read = (PFN_wl_display_prepare_read)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_prepare_read");
_glfw.wl.client.display_create_queue = (PFN_wl_display_create_queue)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_create_queue");
_glfw.wl.client.display_prepare_read_queue = (PFN_wl_display_prepare_read_queue)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_prepare_read_queue");
_glfw.wl.client.display_dispatch_queue_pending = (PFN_wl_display_dispatch_queue_pending)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_dispatch_queue_pending");
_glfw.wl.client.event_queue_destroy = (PFN_wl_event_queue_destroy)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_event_queue_destroy");
_glfw.wl.client.proxy_marshal = (PFN_wl_proxy_marshal)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_marshal");
_glfw.wl.client.proxy_add_listener = (PFN_wl_proxy_add_listener)
@@ -607,6 +605,12 @@ int _glfwInitWayland(void)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_version");
_glfw.wl.client.proxy_marshal_flags = (PFN_wl_proxy_marshal_flags)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_marshal_flags");
_glfw.wl.client.proxy_create_wrapper = (PFN_wl_proxy_create_wrapper)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_create_wrapper");
_glfw.wl.client.proxy_wrapper_destroy = (PFN_wl_proxy_wrapper_destroy)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_wrapper_destroy");
_glfw.wl.client.proxy_set_queue = (PFN_wl_proxy_set_queue)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_set_queue");
if (!_glfw.wl.client.display_flush ||
!_glfw.wl.client.display_cancel_read ||
@@ -616,6 +620,10 @@ int _glfwInitWayland(void)
!_glfw.wl.client.display_roundtrip ||
!_glfw.wl.client.display_get_fd ||
!_glfw.wl.client.display_prepare_read ||
!_glfw.wl.client.display_create_queue ||
!_glfw.wl.client.display_prepare_read_queue ||
!_glfw.wl.client.display_dispatch_queue_pending ||
!_glfw.wl.client.event_queue_destroy ||
!_glfw.wl.client.proxy_marshal ||
!_glfw.wl.client.proxy_add_listener ||
!_glfw.wl.client.proxy_destroy ||
@@ -624,7 +632,10 @@ int _glfwInitWayland(void)
!_glfw.wl.client.proxy_get_user_data ||
!_glfw.wl.client.proxy_set_user_data ||
!_glfw.wl.client.proxy_get_tag ||
!_glfw.wl.client.proxy_set_tag)
!_glfw.wl.client.proxy_set_tag ||
!_glfw.wl.client.proxy_create_wrapper ||
!_glfw.wl.client.proxy_wrapper_destroy ||
!_glfw.wl.client.proxy_set_queue)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to load libwayland-client entry point");
@@ -787,6 +798,8 @@ int _glfwInitWayland(void)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_unset_capabilities");
_glfw.wl.libdecor.libdecor_frame_set_visibility_ = (PFN_libdecor_frame_set_visibility)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_visibility");
_glfw.wl.libdecor.libdecor_frame_is_visible_ = (PFN_libdecor_frame_is_visible)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_is_visible");
_glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ = (PFN_libdecor_frame_get_xdg_toplevel)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_get_xdg_toplevel");
_glfw.wl.libdecor.libdecor_configuration_get_content_size_ = (PFN_libdecor_configuration_get_content_size)
@@ -818,6 +831,7 @@ int _glfwInitWayland(void)
!_glfw.wl.libdecor.libdecor_frame_set_capabilities_ ||
!_glfw.wl.libdecor.libdecor_frame_unset_capabilities_ ||
!_glfw.wl.libdecor.libdecor_frame_set_visibility_ ||
!_glfw.wl.libdecor.libdecor_frame_is_visible_ ||
!_glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ ||
!_glfw.wl.libdecor.libdecor_configuration_get_content_size_ ||
!_glfw.wl.libdecor.libdecor_configuration_get_window_state_ ||
@@ -834,7 +848,17 @@ int _glfwInitWayland(void)
createKeyTables();
_glfw.wl.xkb.context = xkb_context_new(0);
_glfw.wl.keyRepeatTimerfd =
timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
if (_glfw.wl.keyRepeatTimerfd == -1)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to create timerfd: %s",
strerror(errno));
return GLFW_FALSE;
}
_glfw.wl.xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!_glfw.wl.xkb.context)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
@@ -857,10 +881,8 @@ int _glfwInitWayland(void)
libdecor_dispatch(_glfw.wl.libdecor.context, 0);
// Create sync point to "know" when libdecor is ready for use
_glfw.wl.libdecor.callback = wl_display_sync(_glfw.wl.display);
wl_callback_add_listener(_glfw.wl.libdecor.callback,
&libdecorReadyListener,
NULL);
struct wl_callback* callback = wl_display_sync(_glfw.wl.display);
wl_callback_add_listener(callback, &libdecorReadyListener, NULL);
}
}
@@ -907,18 +929,6 @@ void _glfwTerminateWayland(void)
libdecor_unref(_glfw.wl.libdecor.context);
}
if (_glfw.wl.libdecor.handle)
{
_glfwPlatformFreeModule(_glfw.wl.libdecor.handle);
_glfw.wl.libdecor.handle = NULL;
}
if (_glfw.wl.egl.handle)
{
_glfwPlatformFreeModule(_glfw.wl.egl.handle);
_glfw.wl.egl.handle = NULL;
}
if (_glfw.wl.xkb.composeState)
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
if (_glfw.wl.xkb.keymap)
@@ -927,21 +937,11 @@ void _glfwTerminateWayland(void)
xkb_state_unref(_glfw.wl.xkb.state);
if (_glfw.wl.xkb.context)
xkb_context_unref(_glfw.wl.xkb.context);
if (_glfw.wl.xkb.handle)
{
_glfwPlatformFreeModule(_glfw.wl.xkb.handle);
_glfw.wl.xkb.handle = NULL;
}
if (_glfw.wl.cursorTheme)
wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
if (_glfw.wl.cursorThemeHiDPI)
wl_cursor_theme_destroy(_glfw.wl.cursorThemeHiDPI);
if (_glfw.wl.cursor.handle)
{
_glfwPlatformFreeModule(_glfw.wl.cursor.handle);
_glfw.wl.cursor.handle = NULL;
}
for (unsigned int i = 0; i < _glfw.wl.offerCount; i++)
wl_data_offer_destroy(_glfw.wl.offers[i].offer);
@@ -1001,7 +1001,18 @@ void _glfwTerminateWayland(void)
if (_glfw.wl.cursorTimerfd >= 0)
close(_glfw.wl.cursorTimerfd);
// Free modules only after all Wayland termination functions are called
_glfwPlatformFreeModule(_glfw.egl.handle);
_glfwPlatformFreeModule(_glfw.wl.libdecor.handle);
_glfwPlatformFreeModule(_glfw.wl.egl.handle);
_glfwPlatformFreeModule(_glfw.wl.xkb.handle);
_glfwPlatformFreeModule(_glfw.wl.cursor.handle);
_glfwPlatformFreeModule(_glfw.wl.client.handle);
_glfw_free(_glfw.wl.clipboardString);
memset(&_glfw.wl, 0, sizeof(_glfw.wl));
}
#endif // _GLFW_WAYLAND
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Wayland - www.glfw.org
// GLFW 3.6 Wayland - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
//
+53 -12
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Wayland - www.glfw.org
// GLFW 3.6 Wayland - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
//
@@ -42,8 +42,6 @@ typedef struct VkWaylandSurfaceCreateInfoKHR
typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWaylandSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);
#include "posix_poll.h"
typedef int (* PFN_wl_display_flush)(struct wl_display* display);
typedef void (* PFN_wl_display_cancel_read)(struct wl_display* display);
typedef int (* PFN_wl_display_dispatch_pending)(struct wl_display* display);
@@ -53,6 +51,10 @@ typedef void (* PFN_wl_display_disconnect)(struct wl_display*);
typedef int (* PFN_wl_display_roundtrip)(struct wl_display*);
typedef int (* PFN_wl_display_get_fd)(struct wl_display*);
typedef int (* PFN_wl_display_prepare_read)(struct wl_display*);
typedef struct wl_event_queue* (* PFN_wl_display_create_queue)(struct wl_display*);
typedef void (* PFN_wl_event_queue_destroy)(struct wl_event_queue*);
typedef int (* PFN_wl_display_prepare_read_queue)(struct wl_display*,struct wl_event_queue*);
typedef int (* PFN_wl_display_dispatch_queue_pending)(struct wl_display*,struct wl_event_queue*);
typedef void (* PFN_wl_proxy_marshal)(struct wl_proxy*,uint32_t,...);
typedef int (* PFN_wl_proxy_add_listener)(struct wl_proxy*,void(**)(void),void*);
typedef void (* PFN_wl_proxy_destroy)(struct wl_proxy*);
@@ -64,6 +66,9 @@ typedef void (* PFN_wl_proxy_set_tag)(struct wl_proxy*,const char*const*);
typedef const char* const* (* PFN_wl_proxy_get_tag)(struct wl_proxy*);
typedef uint32_t (* PFN_wl_proxy_get_version)(struct wl_proxy*);
typedef struct wl_proxy* (* PFN_wl_proxy_marshal_flags)(struct wl_proxy*,uint32_t,const struct wl_interface*,uint32_t,uint32_t,...);
typedef void* (* PFN_wl_proxy_create_wrapper)(void*);
typedef void (* PFN_wl_proxy_wrapper_destroy)(void*);
typedef void (* PFN_wl_proxy_set_queue)(struct wl_proxy*,struct wl_event_queue*);
#define wl_display_flush _glfw.wl.client.display_flush
#define wl_display_cancel_read _glfw.wl.client.display_cancel_read
#define wl_display_dispatch_pending _glfw.wl.client.display_dispatch_pending
@@ -72,6 +77,10 @@ typedef struct wl_proxy* (* PFN_wl_proxy_marshal_flags)(struct wl_proxy*,uint32_
#define wl_display_roundtrip _glfw.wl.client.display_roundtrip
#define wl_display_get_fd _glfw.wl.client.display_get_fd
#define wl_display_prepare_read _glfw.wl.client.display_prepare_read
#define wl_display_create_queue _glfw.wl.client.display_create_queue
#define wl_display_prepare_read_queue _glfw.wl.client.display_prepare_read_queue
#define wl_display_dispatch_queue_pending _glfw.wl.client.display_dispatch_queue_pending
#define wl_event_queue_destroy _glfw.wl.client.event_queue_destroy
#define wl_proxy_marshal _glfw.wl.client.proxy_marshal
#define wl_proxy_add_listener _glfw.wl.client.proxy_add_listener
#define wl_proxy_destroy _glfw.wl.client.proxy_destroy
@@ -83,6 +92,9 @@ typedef struct wl_proxy* (* PFN_wl_proxy_marshal_flags)(struct wl_proxy*,uint32_
#define wl_proxy_set_tag _glfw.wl.client.proxy_set_tag
#define wl_proxy_get_version _glfw.wl.client.proxy_get_version
#define wl_proxy_marshal_flags _glfw.wl.client.proxy_marshal_flags
#define wl_proxy_create_wrapper _glfw.wl.client.proxy_create_wrapper
#define wl_proxy_wrapper_destroy _glfw.wl.client.proxy_wrapper_destroy
#define wl_proxy_set_queue _glfw.wl.client.proxy_set_queue
struct wl_shm;
struct wl_output;
@@ -136,18 +148,22 @@ struct wl_output;
#define GLFW_WAYLAND_MONITOR_STATE _GLFWmonitorWayland wl;
#define GLFW_WAYLAND_CURSOR_STATE _GLFWcursorWayland wl;
struct wl_cursor_image {
struct wl_cursor_image
{
uint32_t width;
uint32_t height;
uint32_t hotspot_x;
uint32_t hotspot_y;
uint32_t delay;
};
struct wl_cursor {
struct wl_cursor
{
unsigned int image_count;
struct wl_cursor_image** images;
char* name;
};
typedef struct wl_cursor_theme* (* PFN_wl_cursor_theme_load)(const char*, int, struct wl_shm*);
typedef void (* PFN_wl_cursor_theme_destroy)(struct wl_cursor_theme*);
typedef struct wl_cursor* (* PFN_wl_cursor_theme_get_cursor)(struct wl_cursor_theme*, const char*);
@@ -295,6 +311,7 @@ typedef void (* PFN_libdecor_frame_unset_maximized)(struct libdecor_frame*);
typedef void (* PFN_libdecor_frame_set_capabilities)(struct libdecor_frame*,enum libdecor_capabilities);
typedef void (* PFN_libdecor_frame_unset_capabilities)(struct libdecor_frame*,enum libdecor_capabilities);
typedef void (* PFN_libdecor_frame_set_visibility)(struct libdecor_frame*,bool visible);
typedef bool (* PFN_libdecor_frame_is_visible)(struct libdecor_frame*);
typedef struct xdg_toplevel* (* PFN_libdecor_frame_get_xdg_toplevel)(struct libdecor_frame*);
typedef bool (* PFN_libdecor_configuration_get_content_size)(struct libdecor_configuration*,struct libdecor_frame*,int*,int*);
typedef bool (* PFN_libdecor_configuration_get_window_state)(struct libdecor_configuration*,enum libdecor_window_state*);
@@ -320,6 +337,7 @@ typedef void (* PFN_libdecor_state_free)(struct libdecor_state*);
#define libdecor_frame_set_capabilities _glfw.wl.libdecor.libdecor_frame_set_capabilities_
#define libdecor_frame_unset_capabilities _glfw.wl.libdecor.libdecor_frame_unset_capabilities_
#define libdecor_frame_set_visibility _glfw.wl.libdecor.libdecor_frame_set_visibility_
#define libdecor_frame_is_visible _glfw.wl.libdecor.libdecor_frame_is_visible_
#define libdecor_frame_get_xdg_toplevel _glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_
#define libdecor_configuration_get_content_size _glfw.wl.libdecor.libdecor_configuration_get_content_size_
#define libdecor_configuration_get_window_state _glfw.wl.libdecor.libdecor_configuration_get_window_state_
@@ -356,14 +374,16 @@ typedef struct _GLFWwindowWayland
GLFWbool maximized;
GLFWbool activated;
GLFWbool fullscreen;
GLFWbool hovered;
GLFWbool transparent;
GLFWbool scaleFramebuffer;
struct wl_surface* surface;
struct wl_callback* callback;
struct {
struct wl_event_queue* queue;
struct wl_egl_window* window;
struct wl_callback* callback;
struct wl_surface* wrapper;
int interval;
} egl;
struct {
@@ -385,7 +405,6 @@ typedef struct _GLFWwindowWayland
struct libdecor_frame* frame;
} libdecor;
_GLFWcursor* currentCursor;
double cursorPosX, cursorPosY;
char* appId;
@@ -412,8 +431,8 @@ typedef struct _GLFWwindowWayland
GLFWbool decorations;
struct wl_buffer* buffer;
_GLFWfallbackEdgeWayland top, left, right, bottom;
struct wl_surface* focus;
wl_fixed_t pointerX, pointerY;
double pointerX, pointerY;
uint32_t buttonPressSerial;
const char* cursorName;
} fallback;
} _GLFWwindowWayland;
@@ -453,6 +472,7 @@ typedef struct _GLFWlibraryWayland
const char* tag;
struct wl_surface* pointerSurface;
struct wl_cursor_theme* cursorTheme;
struct wl_cursor_theme* cursorThemeHiDPI;
struct wl_surface* cursorSurface;
@@ -470,6 +490,19 @@ typedef struct _GLFWlibraryWayland
short int scancodes[GLFW_KEY_LAST + 1];
char keynames[GLFW_KEY_LAST + 1][5];
struct {
struct wl_surface* pointerSurface;
unsigned int events;
double pointerX;
double pointerY;
double scrollX;
double scrollY;
double discreteX;
double discreteY;
int button;
int action;
} pending;
struct {
void* handle;
struct xkb_context* context;
@@ -511,7 +544,6 @@ typedef struct _GLFWlibraryWayland
PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;
} xkb;
_GLFWwindow* pointerFocus;
_GLFWwindow* keyboardFocus;
struct {
@@ -524,6 +556,10 @@ typedef struct _GLFWlibraryWayland
PFN_wl_display_roundtrip display_roundtrip;
PFN_wl_display_get_fd display_get_fd;
PFN_wl_display_prepare_read display_prepare_read;
PFN_wl_display_create_queue display_create_queue;
PFN_wl_display_prepare_read_queue display_prepare_read_queue;
PFN_wl_display_dispatch_queue_pending display_dispatch_queue_pending;
PFN_wl_event_queue_destroy event_queue_destroy;
PFN_wl_proxy_marshal proxy_marshal;
PFN_wl_proxy_add_listener proxy_add_listener;
PFN_wl_proxy_destroy proxy_destroy;
@@ -535,6 +571,9 @@ typedef struct _GLFWlibraryWayland
PFN_wl_proxy_set_tag proxy_set_tag;
PFN_wl_proxy_get_version proxy_get_version;
PFN_wl_proxy_marshal_flags proxy_marshal_flags;
PFN_wl_proxy_create_wrapper proxy_create_wrapper;
PFN_wl_proxy_wrapper_destroy proxy_wrapper_destroy;
PFN_wl_proxy_set_queue proxy_set_queue;
} client;
struct {
@@ -557,7 +596,6 @@ typedef struct _GLFWlibraryWayland
struct {
void* handle;
struct libdecor* context;
struct wl_callback* callback;
GLFWbool ready;
PFN_libdecor_new libdecor_new_;
PFN_libdecor_unref libdecor_unref_;
@@ -579,6 +617,7 @@ typedef struct _GLFWlibraryWayland
PFN_libdecor_frame_set_capabilities libdecor_frame_set_capabilities_;
PFN_libdecor_frame_unset_capabilities libdecor_frame_unset_capabilities_;
PFN_libdecor_frame_set_visibility libdecor_frame_set_visibility_;
PFN_libdecor_frame_is_visible libdecor_frame_is_visible_;
PFN_libdecor_frame_get_xdg_toplevel libdecor_frame_get_xdg_toplevel_;
PFN_libdecor_configuration_get_content_size libdecor_configuration_get_content_size_;
PFN_libdecor_configuration_get_window_state libdecor_configuration_get_window_state_;
@@ -693,3 +732,5 @@ void _glfwUpdateBufferScaleFromOutputsWayland(_GLFWwindow* window);
void _glfwAddSeatListenerWayland(struct wl_seat* seat);
void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device);
GLFWbool _glfwWaitForEGLFrameWayland(_GLFWwindow* window);
+411 -155
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Wayland - www.glfw.org
// GLFW 3.6 Wayland - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
//
@@ -24,7 +24,9 @@
//
//========================================================================
#define _GNU_SOURCE
#if !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif
#include "internal.h"
@@ -55,6 +57,12 @@
#define GLFW_BORDER_SIZE 4
#define GLFW_CAPTION_HEIGHT 24
#define GLFW_PENDING_SURFACE 1
#define GLFW_PENDING_BUTTON 2
#define GLFW_PENDING_MOTION 4
#define GLFW_PENDING_SCROLL 8
#define GLFW_PENDING_DISCRETE 16
static int createTmpfileCloexec(char* tmpname)
{
int fd;
@@ -193,6 +201,16 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
return buffer;
}
static void callbackHandleDone(void* userData, struct wl_callback* callback, uint32_t data)
{
wl_callback_destroy(callback);
}
static const struct wl_callback_listener noopCallbackListener =
{
callbackHandleDone
};
static void createFallbackEdge(_GLFWwindow* window,
_GLFWfallbackEdgeWayland* edge,
struct wl_surface* parent,
@@ -253,6 +271,9 @@ static void createFallbackDecorations(_GLFWwindow* window)
static void destroyFallbackEdge(_GLFWfallbackEdgeWayland* edge)
{
if (edge->surface == _glfw.wl.pointerSurface)
_glfw.wl.pointerSurface = NULL;
if (edge->subsurface)
wl_subsurface_destroy(edge->subsurface);
if (edge->surface)
@@ -275,39 +296,35 @@ static void destroyFallbackDecorations(_GLFWwindow* window)
destroyFallbackEdge(&window->wl.fallback.bottom);
}
static void updateFallbackDecorationCursor(_GLFWwindow* window,
wl_fixed_t sx,
wl_fixed_t sy)
static void updateFallbackDecorationCursor(_GLFWwindow* window, double xpos, double ypos)
{
window->wl.fallback.pointerX = sx;
window->wl.fallback.pointerY = sy;
window->wl.fallback.pointerX = xpos;
window->wl.fallback.pointerY = ypos;
const double xpos = wl_fixed_to_double(sx);
const double ypos = wl_fixed_to_double(sy);
const char* cursorName = "left_ptr";
if (window->resizable)
{
if (window->wl.fallback.focus == window->wl.fallback.top.surface)
if (_glfw.wl.pointerSurface == window->wl.fallback.top.surface)
{
if (ypos < GLFW_BORDER_SIZE)
cursorName = "n-resize";
}
else if (window->wl.fallback.focus == window->wl.fallback.left.surface)
else if (_glfw.wl.pointerSurface == window->wl.fallback.left.surface)
{
if (ypos < GLFW_BORDER_SIZE)
cursorName = "nw-resize";
else
cursorName = "w-resize";
}
else if (window->wl.fallback.focus == window->wl.fallback.right.surface)
else if (_glfw.wl.pointerSurface == window->wl.fallback.right.surface)
{
if (ypos < GLFW_BORDER_SIZE)
cursorName = "ne-resize";
else
cursorName = "e-resize";
}
else if (window->wl.fallback.focus == window->wl.fallback.bottom.surface)
else if (_glfw.wl.pointerSurface == window->wl.fallback.bottom.surface)
{
if (xpos < GLFW_BORDER_SIZE)
cursorName = "sw-resize";
@@ -358,39 +375,41 @@ static void updateFallbackDecorationCursor(_GLFWwindow* window,
}
}
static void handleFallbackDecorationButton(_GLFWwindow* window,
uint32_t serial,
uint32_t button)
static void handleFallbackDecorationButton(_GLFWwindow* window, int button, int action)
{
const double xpos = wl_fixed_to_double(window->wl.fallback.pointerX);
const double ypos = wl_fixed_to_double(window->wl.fallback.pointerY);
if (action != GLFW_PRESS)
return;
if (button == BTN_LEFT)
const double xpos = window->wl.fallback.pointerX;
const double ypos = window->wl.fallback.pointerY;
const uint32_t serial = window->wl.fallback.buttonPressSerial;
if (button == GLFW_MOUSE_BUTTON_LEFT)
{
uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
if (window->wl.fallback.focus == window->wl.fallback.top.surface)
if (_glfw.wl.pointerSurface == window->wl.fallback.top.surface)
{
if (ypos < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
else
xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
}
else if (window->wl.fallback.focus == window->wl.fallback.left.surface)
else if (_glfw.wl.pointerSurface == window->wl.fallback.left.surface)
{
if (ypos < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
else
edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
}
else if (window->wl.fallback.focus == window->wl.fallback.right.surface)
else if (_glfw.wl.pointerSurface == window->wl.fallback.right.surface)
{
if (ypos < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
else
edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
}
else if (window->wl.fallback.focus == window->wl.fallback.bottom.surface)
else if (_glfw.wl.pointerSurface == window->wl.fallback.bottom.surface)
{
if (xpos < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
@@ -403,21 +422,19 @@ static void handleFallbackDecorationButton(_GLFWwindow* window,
if (edges != XDG_TOPLEVEL_RESIZE_EDGE_NONE)
xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat, serial, edges);
}
else if (button == BTN_RIGHT)
else if (button == GLFW_MOUSE_BUTTON_RIGHT)
{
if (!window->wl.xdg.toplevel)
return;
if (window->wl.fallback.focus != window->wl.fallback.top.surface)
if (_glfw.wl.pointerSurface != window->wl.fallback.top.surface)
return;
if (ypos < GLFW_BORDER_SIZE)
return;
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
_glfw.wl.seat, serial,
xpos,
ypos - GLFW_CAPTION_HEIGHT - GLFW_BORDER_SIZE);
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel, _glfw.wl.seat, serial,
xpos, ypos - GLFW_CAPTION_HEIGHT - GLFW_BORDER_SIZE);
}
}
@@ -461,8 +478,9 @@ static void resizeFramebuffer(_GLFWwindow* window)
{
if (window->wl.fractionalScale)
{
window->wl.fbWidth = (window->wl.width * window->wl.scalingNumerator) / 120;
window->wl.fbHeight = (window->wl.height * window->wl.scalingNumerator) / 120;
// Round halfway away from zero per fractional-scale-v1 protocol spec
window->wl.fbWidth = (window->wl.width * window->wl.scalingNumerator + 60) / 120;
window->wl.fbHeight = (window->wl.height * window->wl.scalingNumerator + 60) / 120;
}
else
{
@@ -879,6 +897,10 @@ void libdecorFrameHandleConfigure(struct libdecor_frame* frame,
libdecor_frame_commit(frame, frameState, config);
libdecor_state_free(frameState);
// NOTE: Frame visibility must only be set after a frame state has been committed
if (window->decorated != libdecor_frame_is_visible(window->wl.libdecor.frame))
libdecor_frame_set_visibility(window->wl.libdecor.frame, window->decorated);
if (window->wl.activated != activated)
{
window->wl.activated = activated;
@@ -960,36 +982,39 @@ static GLFWbool createLibdecorFrame(_GLFWwindow* window)
return GLFW_FALSE;
}
struct libdecor_state* frameState =
libdecor_state_new(window->wl.width, window->wl.height);
libdecor_frame_commit(window->wl.libdecor.frame, frameState, NULL);
libdecor_state_free(frameState);
if (strlen(window->wl.appId))
libdecor_frame_set_app_id(window->wl.libdecor.frame, window->wl.appId);
libdecor_frame_set_title(window->wl.libdecor.frame, window->title);
if (window->minwidth != GLFW_DONT_CARE &&
window->minheight != GLFW_DONT_CARE)
if (window->resizable)
{
libdecor_frame_set_min_content_size(window->wl.libdecor.frame,
window->minwidth,
window->minheight);
}
if (window->minwidth != GLFW_DONT_CARE &&
window->minheight != GLFW_DONT_CARE)
{
libdecor_frame_set_min_content_size(window->wl.libdecor.frame,
window->minwidth,
window->minheight);
}
if (window->maxwidth != GLFW_DONT_CARE &&
window->maxheight != GLFW_DONT_CARE)
{
libdecor_frame_set_max_content_size(window->wl.libdecor.frame,
window->maxwidth,
window->maxheight);
if (window->maxwidth != GLFW_DONT_CARE &&
window->maxheight != GLFW_DONT_CARE)
{
libdecor_frame_set_max_content_size(window->wl.libdecor.frame,
window->maxwidth,
window->maxheight);
}
}
if (!window->resizable)
else
{
libdecor_frame_unset_capabilities(window->wl.libdecor.frame,
LIBDECOR_ACTION_RESIZE);
libdecor_frame_set_min_content_size(window->wl.libdecor.frame,
window->wl.width,
window->wl.height);
libdecor_frame_set_max_content_size(window->wl.libdecor.frame,
window->wl.width,
window->wl.height);
}
if (window->monitor)
@@ -1000,12 +1025,11 @@ static GLFWbool createLibdecorFrame(_GLFWwindow* window)
}
else
{
// Frame visibility is applied in libdecorFrameHandleConfigure
if (window->wl.maximized)
libdecor_frame_set_maximized(window->wl.libdecor.frame);
if (!window->decorated)
libdecor_frame_set_visibility(window->wl.libdecor.frame, false);
setIdleInhibitor(window, GLFW_FALSE);
}
@@ -1267,14 +1291,16 @@ static void setCursorImage(_GLFWwindow* window,
wl_surface_commit(surface);
}
static void incrementCursorImage(_GLFWwindow* window)
static void incrementCursorImage(void)
{
_GLFWcursor* cursor;
if (!window || !window->wl.hovered)
if (!_glfw.wl.pointerSurface)
return;
cursor = window->wl.currentCursor;
_GLFWwindow* window = wl_surface_get_user_data(_glfw.wl.pointerSurface);
if (window->wl.surface != _glfw.wl.pointerSurface)
return;
_GLFWcursor* cursor = window->cursor;
if (cursor && cursor->wl.cursor)
{
cursor->wl.currentImage += 1;
@@ -1356,24 +1382,27 @@ static void handleEvents(double* timeout)
#endif
GLFWbool event = GLFW_FALSE;
enum { DISPLAY_FD, KEYREPEAT_FD, CURSOR_FD, LIBDECOR_FD };
enum { DISPLAY_FD, KEYREPEAT_FD, CURSOR_FD };
struct pollfd fds[] =
{
[DISPLAY_FD] = { wl_display_get_fd(_glfw.wl.display), POLLIN },
[KEYREPEAT_FD] = { _glfw.wl.keyRepeatTimerfd, POLLIN },
[CURSOR_FD] = { _glfw.wl.cursorTimerfd, POLLIN },
[LIBDECOR_FD] = { -1, POLLIN }
[CURSOR_FD] = { _glfw.wl.cursorTimerfd, POLLIN }
};
if (_glfw.wl.libdecor.context)
fds[LIBDECOR_FD].fd = libdecor_get_fd(_glfw.wl.libdecor.context);
while (!event)
{
if (_glfw.wl.libdecor.context)
{
// Dispatch unconditionally because it also processes non-Wayland events
if (libdecor_dispatch(_glfw.wl.libdecor.context, 0) > 0)
event = GLFW_TRUE;
}
while (wl_display_prepare_read(_glfw.wl.display) != 0)
{
if (wl_display_dispatch_pending(_glfw.wl.display) > 0)
return;
event = GLFW_TRUE;
}
// If an error other than EAGAIN happens, we have likely been disconnected
@@ -1392,6 +1421,11 @@ static void handleEvents(double* timeout)
return;
}
double immediate = 0.0;
if (event)
timeout = &immediate;
if (!_glfwPollPOSIX(fds, sizeof(fds) / sizeof(fds[0]), timeout))
{
wl_display_cancel_read(_glfw.wl.display);
@@ -1413,7 +1447,7 @@ static void handleEvents(double* timeout)
if (read(_glfw.wl.keyRepeatTimerfd, &repeats, sizeof(repeats)) == 8)
{
if(_glfw.wl.keyboardFocus)
if (_glfw.wl.keyboardFocus)
{
for (uint64_t i = 0; i < repeats; i++)
{
@@ -1436,13 +1470,7 @@ static void handleEvents(double* timeout)
uint64_t repeats;
if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8)
incrementCursorImage(_glfw.wl.pointerFocus);
}
if (fds[LIBDECOR_FD].revents & POLLIN)
{
if (libdecor_dispatch(_glfw.wl.libdecor.context, 0) > 0)
event = GLFW_TRUE;
incrementCursorImage();
}
}
}
@@ -1513,6 +1541,70 @@ static char* readDataOfferAsString(struct wl_data_offer* offer, const char* mime
return string;
}
static void processPointerEnterSurface(struct wl_surface* surface)
{
_glfw.wl.pointerSurface = surface;
_GLFWwindow* window = wl_surface_get_user_data(_glfw.wl.pointerSurface);
if (window->wl.surface == _glfw.wl.pointerSurface)
{
_glfwSetCursorWayland(window, window->cursor);
_glfwInputCursorEnter(window, GLFW_TRUE);
}
}
static void processPointerLeaveSurface(struct wl_surface* surface)
{
_glfw.wl.pointerSurface = NULL;
_GLFWwindow* window = wl_surface_get_user_data(surface);
if (window->wl.surface == surface)
_glfwInputCursorEnter(window, GLFW_FALSE);
else
{
if (window->wl.fallback.decorations)
window->wl.fallback.cursorName = NULL;
}
}
static void processPointerMotion(double xpos, double ypos)
{
_GLFWwindow* window = wl_surface_get_user_data(_glfw.wl.pointerSurface);
if (window->wl.surface == _glfw.wl.pointerSurface)
{
if (window->cursorMode != GLFW_CURSOR_DISABLED)
{
window->wl.cursorPosX = xpos;
window->wl.cursorPosY = ypos;
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY);
}
}
else
{
if (window->wl.fallback.decorations)
updateFallbackDecorationCursor(window, xpos, ypos);
}
}
static void processPointerButton(int button, int action)
{
_GLFWwindow* window = wl_surface_get_user_data(_glfw.wl.pointerSurface);
if (window->wl.surface == _glfw.wl.pointerSurface)
_glfwInputMouseClick(window, button, action, _glfw.wl.xkb.modifiers);
else
{
if (window->wl.fallback.decorations)
handleFallbackDecorationButton(window, button, action);
}
}
static void processPointerScroll(double xoffset, double yoffset)
{
_GLFWwindow* window = wl_surface_get_user_data(_glfw.wl.pointerSurface);
if (window->wl.surface == _glfw.wl.pointerSurface)
_glfwInputScroll(window, xoffset, yoffset);
}
static void pointerHandleEnter(void* userData,
struct wl_pointer* pointer,
uint32_t serial,
@@ -1527,32 +1619,23 @@ static void pointerHandleEnter(void* userData,
if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
return;
_GLFWwindow* window = wl_surface_get_user_data(surface);
_glfw.wl.serial = serial;
_glfw.wl.pointerEnterSerial = serial;
_glfw.wl.pointerFocus = window;
if (surface == window->wl.surface)
const double xpos = wl_fixed_to_double(sx);
const double ypos = wl_fixed_to_double(sy);
if (wl_pointer_get_version(pointer) >= WL_POINTER_FRAME_SINCE_VERSION)
{
window->wl.hovered = GLFW_TRUE;
_glfwSetCursorWayland(window, window->wl.currentCursor);
_glfwInputCursorEnter(window, GLFW_TRUE);
if (window->cursorMode != GLFW_CURSOR_DISABLED)
{
window->wl.cursorPosX = wl_fixed_to_double(sx);
window->wl.cursorPosY = wl_fixed_to_double(sy);
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY);
}
_glfw.wl.pending.events |= (GLFW_PENDING_SURFACE | GLFW_PENDING_MOTION);
_glfw.wl.pending.pointerSurface = surface;
_glfw.wl.pending.pointerX = xpos;
_glfw.wl.pending.pointerY = ypos;
}
else
{
if (window->wl.fallback.decorations)
{
window->wl.fallback.focus = surface;
updateFallbackDecorationCursor(window, sx, sy);
}
processPointerEnterSurface(surface);
processPointerMotion(xpos, ypos);
}
}
@@ -1567,26 +1650,15 @@ static void pointerHandleLeave(void* userData,
if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
return;
_GLFWwindow* window = _glfw.wl.pointerFocus;
if (!window)
return;
_glfw.wl.serial = serial;
_glfw.wl.pointerFocus = NULL;
if (window->wl.hovered)
if (wl_pointer_get_version(pointer) >= WL_POINTER_FRAME_SINCE_VERSION)
{
window->wl.hovered = GLFW_FALSE;
_glfwInputCursorEnter(window, GLFW_FALSE);
_glfw.wl.pending.events |= GLFW_PENDING_SURFACE;
_glfw.wl.pending.pointerSurface = NULL;
}
else
{
if (window->wl.fallback.decorations)
{
window->wl.fallback.focus = NULL;
window->wl.fallback.cursorName = NULL;
}
}
processPointerLeaveSurface(surface);
}
static void pointerHandleMotion(void* userData,
@@ -1595,51 +1667,52 @@ static void pointerHandleMotion(void* userData,
wl_fixed_t sx,
wl_fixed_t sy)
{
_GLFWwindow* window = _glfw.wl.pointerFocus;
if (!window)
if (!_glfw.wl.pointerSurface)
return;
if (window->cursorMode == GLFW_CURSOR_DISABLED)
return;
const double xpos = wl_fixed_to_double(sx);
const double ypos = wl_fixed_to_double(sy);
if (window->wl.hovered)
if (wl_pointer_get_version(pointer) >= WL_POINTER_FRAME_SINCE_VERSION)
{
window->wl.cursorPosX = wl_fixed_to_double(sx);
window->wl.cursorPosY = wl_fixed_to_double(sy);
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY);
_glfw.wl.pending.events |= GLFW_PENDING_MOTION;
_glfw.wl.pending.pointerX = xpos;
_glfw.wl.pending.pointerY = ypos;
}
else
{
if (window->wl.fallback.decorations)
updateFallbackDecorationCursor(window, sx, sy);
}
processPointerMotion(xpos, ypos);
}
static void pointerHandleButton(void* userData,
struct wl_pointer* pointer,
uint32_t serial,
uint32_t time,
uint32_t button,
uint32_t buttonID,
uint32_t state)
{
_GLFWwindow* window = _glfw.wl.pointerFocus;
if (!window)
if (!_glfw.wl.pointerSurface)
return;
if (window->wl.hovered)
{
_glfw.wl.serial = serial;
_glfw.wl.serial = serial;
_glfwInputMouseClick(window,
button - BTN_LEFT,
state == WL_POINTER_BUTTON_STATE_PRESSED,
_glfw.wl.xkb.modifiers);
const int button = buttonID - BTN_LEFT;
const int action = (state == WL_POINTER_BUTTON_STATE_PRESSED);
_GLFWwindow* window = wl_surface_get_user_data(_glfw.wl.pointerSurface);
if (window->wl.fallback.decorations)
{
if (action == GLFW_PRESS)
window->wl.fallback.buttonPressSerial = serial;
}
if (wl_pointer_get_version(pointer) >= WL_POINTER_FRAME_SINCE_VERSION)
{
_glfw.wl.pending.events |= GLFW_PENDING_BUTTON;
_glfw.wl.pending.button = button;
_glfw.wl.pending.action = action;
}
else
{
if (window->wl.fallback.decorations)
handleFallbackDecorationButton(window, serial, button);
}
processPointerButton(button, action);
}
static void pointerHandleAxis(void* userData,
@@ -1648,20 +1721,90 @@ static void pointerHandleAxis(void* userData,
uint32_t axis,
wl_fixed_t value)
{
_GLFWwindow* window = _glfw.wl.pointerFocus;
if (!window)
if (!_glfw.wl.pointerSurface)
return;
if (window->wl.hovered)
if (wl_pointer_get_version(pointer) >= WL_POINTER_FRAME_SINCE_VERSION)
{
_glfw.wl.pending.events |= GLFW_PENDING_SCROLL;
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
_glfw.wl.pending.scrollX = -wl_fixed_to_double(value) / 10.0;
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
_glfw.wl.pending.scrollY = -wl_fixed_to_double(value) / 10.0;
}
else
{
// NOTE: 10 units of motion per mouse wheel step seems to be a common ratio
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
_glfwInputScroll(window, -wl_fixed_to_double(value) / 10.0, 0.0);
processPointerScroll(-wl_fixed_to_double(value) / 10.0, 0.0);
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
_glfwInputScroll(window, 0.0, -wl_fixed_to_double(value) / 10.0);
processPointerScroll(0.0, -wl_fixed_to_double(value) / 10.0);
}
}
static void pointerHandleFrame(void* userData, struct wl_pointer* pointer)
{
if (_glfw.wl.pending.events & GLFW_PENDING_SURFACE)
{
if (_glfw.wl.pointerSurface)
processPointerLeaveSurface(_glfw.wl.pointerSurface);
if (_glfw.wl.pending.pointerSurface)
processPointerEnterSurface(_glfw.wl.pending.pointerSurface);
}
if (!_glfw.wl.pointerSurface)
return;
if (_glfw.wl.pending.events & GLFW_PENDING_MOTION)
processPointerMotion(_glfw.wl.pending.pointerX, _glfw.wl.pending.pointerY);
if (_glfw.wl.pending.events & GLFW_PENDING_BUTTON)
processPointerButton(_glfw.wl.pending.button, _glfw.wl.pending.action);
if (_glfw.wl.pending.events & GLFW_PENDING_DISCRETE)
processPointerScroll(_glfw.wl.pending.discreteX, _glfw.wl.pending.discreteY);
else if (_glfw.wl.pending.events & GLFW_PENDING_SCROLL)
processPointerScroll(_glfw.wl.pending.scrollX, _glfw.wl.pending.scrollY);
memset(&_glfw.wl.pending, 0, sizeof(_glfw.wl.pending));
}
static void pointerHandleAxisSource(void* userData,
struct wl_pointer* pointer,
uint32_t axisSource)
{
}
static void pointerHandleAxisStop(void* userData,
struct wl_pointer* pointer,
uint32_t time,
uint32_t axis)
{
}
static void pointerHandleAxisDiscrete(void* userData,
struct wl_pointer* pointer,
uint32_t axis,
int32_t discrete)
{
}
static void pointerHandleAxisValue120(void* data,
struct wl_pointer* pointer,
uint32_t axis,
int32_t value120)
{
if (!_glfw.wl.pointerSurface)
return;
_glfw.wl.pending.events |= GLFW_PENDING_DISCRETE;
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
_glfw.wl.pending.discreteX = -(value120 / 120.0);
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
_glfw.wl.pending.discreteY = -(value120 / 120.0);
}
static const struct wl_pointer_listener pointerListener =
{
pointerHandleEnter,
@@ -1669,6 +1812,11 @@ static const struct wl_pointer_listener pointerListener =
pointerHandleMotion,
pointerHandleButton,
pointerHandleAxis,
pointerHandleFrame,
pointerHandleAxisSource,
pointerHandleAxisStop,
pointerHandleAxisDiscrete,
pointerHandleAxisValue120
};
static void keyboardHandleKeymap(void* userData,
@@ -1691,8 +1839,9 @@ static void keyboardHandleKeymap(void* userData,
return;
}
mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
if (mapStr == MAP_FAILED) {
mapStr = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
if (mapStr == MAP_FAILED)
{
close(fd);
return;
}
@@ -1700,7 +1849,7 @@ static void keyboardHandleKeymap(void* userData,
keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context,
mapStr,
XKB_KEYMAP_FORMAT_TEXT_V1,
0);
XKB_KEYMAP_COMPILE_NO_FLAGS);
munmap(mapStr, size);
close(fd);
@@ -1838,7 +1987,9 @@ static void keyboardHandleKey(void* userData,
timer.it_value.tv_nsec = (_glfw.wl.keyRepeatDelay % 1000) * 1000000;
timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL);
}
} else if (scancode == _glfw.wl.keyRepeatScancode) {
}
else if (scancode == _glfw.wl.keyRepeatScancode)
{
timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL);
}
@@ -1929,7 +2080,11 @@ static void seatHandleCapabilities(void* userData,
}
else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && _glfw.wl.pointer)
{
wl_pointer_destroy(_glfw.wl.pointer);
if (wl_pointer_get_version(_glfw.wl.pointer) >= WL_POINTER_RELEASE_SINCE_VERSION)
wl_pointer_release(_glfw.wl.pointer);
else
wl_pointer_destroy(_glfw.wl.pointer);
_glfw.wl.pointer = NULL;
}
@@ -1937,10 +2092,21 @@ static void seatHandleCapabilities(void* userData,
{
_glfw.wl.keyboard = wl_seat_get_keyboard(seat);
wl_keyboard_add_listener(_glfw.wl.keyboard, &keyboardListener, NULL);
if (wl_keyboard_get_version(_glfw.wl.keyboard) <
WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
{
_glfw.wl.keyRepeatRate = 4;
_glfw.wl.keyRepeatDelay = 500;
}
}
else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && _glfw.wl.keyboard)
{
wl_keyboard_destroy(_glfw.wl.keyboard);
if (wl_keyboard_get_version(_glfw.wl.keyboard) >= WL_KEYBOARD_RELEASE_SINCE_VERSION)
wl_keyboard_release(_glfw.wl.keyboard);
else
wl_keyboard_destroy(_glfw.wl.keyboard);
_glfw.wl.keyboard = NULL;
}
}
@@ -2151,6 +2317,18 @@ static const struct xdg_activation_token_v1_listener xdgActivationListener =
xdgActivationHandleDone
};
static void callbackHandleFrame(void* userData, struct wl_callback* callback, uint32_t data)
{
_GLFWwindow* window = userData;
wl_callback_destroy(callback);
window->wl.egl.callback = NULL;
}
static const struct wl_callback_listener frameCallbackListener =
{
callbackHandleFrame
};
void _glfwAddSeatListenerWayland(struct wl_seat* seat)
{
wl_seat_add_listener(seat, &seatListener, NULL);
@@ -2161,6 +2339,42 @@ void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device)
wl_data_device_add_listener(device, &dataDeviceListener, NULL);
}
GLFWbool _glfwWaitForEGLFrameWayland(_GLFWwindow* window)
{
double timeout = 0.02;
while (window->wl.egl.callback)
{
if (wl_display_prepare_read_queue(_glfw.wl.display, window->wl.egl.queue) != 0)
{
wl_display_dispatch_queue_pending(_glfw.wl.display, window->wl.egl.queue);
continue;
}
if (!flushDisplay())
{
wl_display_cancel_read(_glfw.wl.display);
return GLFW_FALSE;
}
struct pollfd fd = { wl_display_get_fd(_glfw.wl.display), POLLIN };
if (!_glfwPollPOSIX(&fd, 1, &timeout))
{
wl_display_cancel_read(_glfw.wl.display);
return GLFW_FALSE;
}
wl_display_read_events(_glfw.wl.display);
wl_display_dispatch_queue_pending(_glfw.wl.display, window->wl.egl.queue);
}
window->wl.egl.callback = wl_surface_frame(window->wl.egl.wrapper);
wl_callback_add_listener(window->wl.egl.callback, &frameCallbackListener, window);
// If the window is hidden when the wait is over then don't swap
return window->wl.visible;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
@@ -2189,6 +2403,27 @@ GLFWbool _glfwCreateWindowWayland(_GLFWwindow* window,
return GLFW_FALSE;
}
window->wl.egl.queue = wl_display_create_queue(_glfw.wl.display);
if (!window->wl.egl.queue)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to create EGL frame queue");
return GLFW_FALSE;
}
window->wl.egl.wrapper = wl_proxy_create_wrapper(window->wl.surface);
if (!window->wl.egl.wrapper)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to create surface wrapper");
return GLFW_FALSE;
}
wl_proxy_set_queue((struct wl_proxy*) window->wl.egl.wrapper,
window->wl.egl.queue);
window->wl.egl.interval = 1;
if (!_glfwInitEGL())
return GLFW_FALSE;
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
@@ -2220,8 +2455,8 @@ GLFWbool _glfwCreateWindowWayland(_GLFWwindow* window,
void _glfwDestroyWindowWayland(_GLFWwindow* window)
{
if (window == _glfw.wl.pointerFocus)
_glfw.wl.pointerFocus = NULL;
if (window->wl.surface == _glfw.wl.pointerSurface)
_glfw.wl.pointerSurface = NULL;
if (window == _glfw.wl.keyboardFocus)
{
@@ -2260,6 +2495,15 @@ void _glfwDestroyWindowWayland(_GLFWwindow* window)
if (window->wl.fallback.buffer)
wl_buffer_destroy(window->wl.fallback.buffer);
if (window->wl.egl.callback)
wl_callback_destroy(window->wl.egl.callback);
if (window->wl.egl.wrapper)
wl_proxy_wrapper_destroy(window->wl.egl.wrapper);
if (window->wl.egl.queue)
wl_event_queue_destroy(window->wl.egl.queue);
if (window->wl.egl.window)
wl_egl_window_destroy(window->wl.egl.window);
@@ -2493,6 +2737,8 @@ void _glfwHideWindowWayland(_GLFWwindow* window)
wl_surface_attach(window->wl.surface, NULL, 0, 0);
wl_surface_commit(window->wl.surface);
flushDisplay();
}
}
@@ -2597,7 +2843,7 @@ GLFWbool _glfwWindowMaximizedWayland(_GLFWwindow* window)
GLFWbool _glfwWindowHoveredWayland(_GLFWwindow* window)
{
return window->wl.hovered;
return window->wl.surface == _glfw.wl.pointerSurface;
}
GLFWbool _glfwFramebufferTransparentWayland(_GLFWwindow* window)
@@ -2707,7 +2953,9 @@ void _glfwWaitEventsTimeoutWayland(double timeout)
void _glfwPostEmptyEventWayland(void)
{
wl_display_sync(_glfw.wl.display);
struct wl_callback* callback = wl_display_sync(_glfw.wl.display);
wl_callback_add_listener(callback, &noopCallbackListener, NULL);
flushDisplay();
}
@@ -2727,7 +2975,7 @@ void _glfwSetCursorPosWayland(_GLFWwindow* window, double x, double y)
void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode)
{
_glfwSetCursorWayland(window, window->wl.currentCursor);
_glfwSetCursorWayland(window, window->cursor);
}
const char* _glfwGetScancodeNameWayland(int scancode)
@@ -2974,10 +3222,16 @@ static void lockPointer(_GLFWwindow* window)
if (!_glfw.wl.relativePointerManager)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
"Wayland: The compositor does not support pointer locking");
"Wayland: The compositor does not support relative pointer motion");
return;
}
if (!_glfw.wl.pointerConstraints)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
"Wayland: The compositor does not support locking the pointer");
}
window->wl.relativePointer =
zwp_relative_pointer_manager_v1_get_relative_pointer(
_glfw.wl.relativePointerManager,
@@ -3025,6 +3279,12 @@ static const struct zwp_confined_pointer_v1_listener confinedPointerListener =
static void confinePointer(_GLFWwindow* window)
{
if (!_glfw.wl.pointerConstraints)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
"Wayland: The compositor does not support confining the pointer");
}
window->wl.confinedPointer =
zwp_pointer_constraints_v1_confine_pointer(
_glfw.wl.pointerConstraints,
@@ -3049,11 +3309,7 @@ void _glfwSetCursorWayland(_GLFWwindow* window, _GLFWcursor* cursor)
if (!_glfw.wl.pointer)
return;
window->wl.currentCursor = cursor;
// If we're not in the correct window just save the cursor
// the next time the pointer enters the window the cursor will change
if (!window->wl.hovered)
if (window->wl.surface != _glfw.wl.pointerSurface)
return;
// Update pointer lock to match cursor mode
+12 -48
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 X11 - www.glfw.org
// GLFW 3.6 X11 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -1592,65 +1592,29 @@ void _glfwTerminateX11(void)
_glfw.x11.display = NULL;
}
if (_glfw.x11.x11xcb.handle)
{
_glfwPlatformFreeModule(_glfw.x11.x11xcb.handle);
_glfw.x11.x11xcb.handle = NULL;
}
if (_glfw.x11.xcursor.handle)
{
_glfwPlatformFreeModule(_glfw.x11.xcursor.handle);
_glfw.x11.xcursor.handle = NULL;
}
if (_glfw.x11.randr.handle)
{
_glfwPlatformFreeModule(_glfw.x11.randr.handle);
_glfw.x11.randr.handle = NULL;
}
if (_glfw.x11.xinerama.handle)
{
_glfwPlatformFreeModule(_glfw.x11.xinerama.handle);
_glfw.x11.xinerama.handle = NULL;
}
if (_glfw.x11.xrender.handle)
{
_glfwPlatformFreeModule(_glfw.x11.xrender.handle);
_glfw.x11.xrender.handle = NULL;
}
if (_glfw.x11.vidmode.handle)
{
_glfwPlatformFreeModule(_glfw.x11.vidmode.handle);
_glfw.x11.vidmode.handle = NULL;
}
if (_glfw.x11.xi.handle)
{
_glfwPlatformFreeModule(_glfw.x11.xi.handle);
_glfw.x11.xi.handle = NULL;
}
_glfwTerminateOSMesa();
// NOTE: These need to be unloaded after XCloseDisplay, as they register
// cleanup callbacks that get called by that function
_glfwTerminateEGL();
_glfwTerminateGLX();
if (_glfw.x11.xlib.handle)
{
_glfwPlatformFreeModule(_glfw.x11.xlib.handle);
_glfw.x11.xlib.handle = NULL;
}
_glfwPlatformFreeModule(_glfw.x11.x11xcb.handle);
_glfwPlatformFreeModule(_glfw.x11.xcursor.handle);
_glfwPlatformFreeModule(_glfw.x11.randr.handle);
_glfwPlatformFreeModule(_glfw.x11.xinerama.handle);
_glfwPlatformFreeModule(_glfw.x11.xrender.handle);
_glfwPlatformFreeModule(_glfw.x11.xshape.handle);
_glfwPlatformFreeModule(_glfw.x11.vidmode.handle);
_glfwPlatformFreeModule(_glfw.x11.xi.handle);
_glfwPlatformFreeModule(_glfw.x11.xlib.handle);
if (_glfw.x11.emptyEventPipe[0] || _glfw.x11.emptyEventPipe[1])
{
close(_glfw.x11.emptyEventPipe[0]);
close(_glfw.x11.emptyEventPipe[1]);
}
memset(&_glfw.x11, 0, sizeof(_glfw.x11));
}
#endif // _GLFW_X11
+7 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 X11 - www.glfw.org
// GLFW 3.6 X11 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -151,6 +151,12 @@ void _glfwPollMonitorsX11(void)
}
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc);
if (!ci)
{
XRRFreeOutputInfo(oi);
continue;
}
if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
{
widthMM = oi->mm_height;
+16 -16
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 X11 - www.glfw.org
// GLFW 3.6 X11 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -452,9 +452,6 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(V
typedef VkResult (APIENTRY *PFN_vkCreateXcbSurfaceKHR)(VkInstance,const VkXcbSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t);
#include "xkb_unicode.h"
#include "posix_poll.h"
#define GLFW_X11_WINDOW_STATE _GLFWwindowX11 x11;
#define GLFW_X11_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11;
#define GLFW_X11_MONITOR_STATE _GLFWmonitorX11 x11;
@@ -463,6 +460,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(Vk
#define GLFW_GLX_CONTEXT_STATE _GLFWcontextGLX glx;
#define GLFW_GLX_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx;
#define GLFW_INVALID_CODEPOINT 0xffffffffu
// GLX-specific per-context data
//
@@ -505,18 +503,18 @@ typedef struct _GLFWlibraryGLX
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;
PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;
PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
GLFWbool SGI_swap_control;
GLFWbool EXT_swap_control;
GLFWbool MESA_swap_control;
GLFWbool ARB_multisample;
GLFWbool ARB_framebuffer_sRGB;
GLFWbool EXT_framebuffer_sRGB;
GLFWbool ARB_create_context;
GLFWbool ARB_create_context_profile;
GLFWbool ARB_create_context_robustness;
GLFWbool EXT_create_context_es2_profile;
GLFWbool ARB_create_context_no_error;
GLFWbool ARB_context_flush_control;
bool SGI_swap_control;
bool EXT_swap_control;
bool MESA_swap_control;
bool ARB_multisample;
bool ARB_framebuffer_sRGB;
bool EXT_framebuffer_sRGB;
bool ARB_create_context;
bool ARB_create_context_profile;
bool ARB_create_context_robustness;
bool EXT_create_context_es2_profile;
bool ARB_create_context_no_error;
bool ARB_context_flush_control;
} _GLFWlibraryGLX;
// X11-specific per-window data
@@ -985,6 +983,8 @@ unsigned long _glfwGetWindowPropertyX11(Window window,
unsigned char** value);
GLFWbool _glfwIsVisualTransparentX11(Visual* visual);
uint32_t _glfwKeySym2UnicodeX11(unsigned int keysym);
void _glfwGrabErrorHandlerX11(void);
void _glfwReleaseErrorHandlerX11(void);
void _glfwInputErrorX11(int error, const char* message);
+60 -34
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 X11 - www.glfw.org
// GLFW 3.6 X11 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -576,6 +576,10 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
height *= _glfw.x11.contentScaleY;
}
// The dimensions must be nonzero, or a BadValue error results.
width = _glfw_max(1, width);
height = _glfw_max(1, height);
int xpos = 0, ypos = 0;
if (wndconfig->xpos != GLFW_ANY_POSITION && wndconfig->ypos != GLFW_ANY_POSITION)
@@ -1304,7 +1308,7 @@ static void processEvent(XEvent *event)
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
const uint32_t codepoint = _glfwKeySym2UnicodeX11(keysym);
if (codepoint != GLFW_INVALID_CODEPOINT)
_glfwInputChar(window, codepoint, mods, plain);
}
@@ -2203,6 +2207,10 @@ void _glfwGetWindowSizeX11(_GLFWwindow* window, int* width, int* height)
void _glfwSetWindowSizeX11(_GLFWwindow* window, int width, int height)
{
// The dimensions must be nonzero, or a BadValue error results
width = _glfw_max(1, width);
height = _glfw_max(1, height);
if (window->monitor)
{
if (window->monitor->window == window)
@@ -2430,6 +2438,38 @@ void _glfwShowWindowX11(_GLFWwindow* window)
if (_glfwWindowVisibleX11(window))
return;
if (window->floating && _glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_ABOVE)
{
Atom* states = NULL;
const unsigned long count =
_glfwGetWindowPropertyX11(window->x11.handle,
_glfw.x11.NET_WM_STATE,
XA_ATOM, (unsigned char**) &states);
// NOTE: We don't check for failure as this property may not exist yet
// and that's fine (and we'll create it implicitly with append)
unsigned long i;
for (i = 0; i < count; i++)
{
if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
break;
}
if (i == count)
{
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeAppend,
(unsigned char*) &_glfw.x11.NET_WM_STATE_ABOVE,
1);
}
if (states)
XFree(states);
}
XMapWindow(_glfw.x11.display, window->x11.handle);
waitForVisibilityNotify(window);
}
@@ -2659,6 +2699,10 @@ void _glfwSetWindowFloatingX11(_GLFWwindow* window, GLFWbool enabled)
}
else
{
// NOTE: _NET_WM_STATE_ABOVE is added when the window is shown
if (enabled)
return;
Atom* states = NULL;
const unsigned long count =
_glfwGetWindowPropertyX11(window->x11.handle,
@@ -2669,38 +2713,20 @@ void _glfwSetWindowFloatingX11(_GLFWwindow* window, GLFWbool enabled)
// NOTE: We don't check for failure as this property may not exist yet
// and that's fine (and we'll create it implicitly with append)
if (enabled)
unsigned long i;
for (i = 0; i < count; i++)
{
unsigned long i;
for (i = 0; i < count; i++)
{
if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
break;
}
if (i == count)
{
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeAppend,
(unsigned char*) &_glfw.x11.NET_WM_STATE_ABOVE,
1);
}
if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
break;
}
else if (states)
if (i < count)
{
for (unsigned long i = 0; i < count; i++)
{
if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
{
states[i] = states[count - 1];
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeReplace, (unsigned char*) states, count - 1);
break;
}
}
states[i] = states[count - 1];
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeReplace, (unsigned char*) states, count - 1);
}
if (states)
@@ -2918,7 +2944,7 @@ const char* _glfwGetScancodeNameX11(int scancode)
if (keysym == NoSymbol)
return NULL;
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
const uint32_t codepoint = _glfwKeySym2UnicodeX11(keysym);
if (codepoint == GLFW_INVALID_CODEPOINT)
return NULL;
@@ -3318,8 +3344,6 @@ GLFWAPI Window glfwGetX11Window(GLFWwindow* handle)
GLFWAPI void glfwSetX11SelectionString(const char* string)
{
assert(string != NULL);
_GLFW_REQUIRE_INIT();
if (_glfw.platform.platformID != GLFW_PLATFORM_X11)
@@ -3328,6 +3352,8 @@ GLFWAPI void glfwSetX11SelectionString(const char* string)
return;
}
assert(string != NULL);
_glfw_free(_glfw.x11.primarySelectionString);
_glfw.x11.primarySelectionString = _glfw_strdup(string);
+4 -4
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 X11 - www.glfw.org
// GLFW 3.6 X11 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
@@ -27,7 +27,7 @@
#include "internal.h"
#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND)
#if defined(_GLFW_X11)
/*
* Marcus: This code was originally written by Markus G. Kuhn.
@@ -906,7 +906,7 @@ static const struct codepair {
// Convert XKB KeySym to Unicode
//
uint32_t _glfwKeySym2Unicode(unsigned int keysym)
uint32_t _glfwKeySym2UnicodeX11(unsigned int keysym)
{
int min = 0;
int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
@@ -939,5 +939,5 @@ uint32_t _glfwKeySym2Unicode(unsigned int keysym)
return GLFW_INVALID_CODEPOINT;
}
#endif // _GLFW_WAYLAND or _GLFW_X11
#endif // _GLFW_X11
-30
View File
@@ -1,30 +0,0 @@
//========================================================================
// GLFW 3.5 Linux - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#define GLFW_INVALID_CODEPOINT 0xffffffffu
uint32_t _glfwKeySym2Unicode(unsigned int keysym);
+75 -30
View File
@@ -23,7 +23,10 @@
//
//========================================================================
//
// This test is intended to verify that posting of empty events works
// This test is intended to verify that the posting of empty events works.
// Background colors are produced on a secondary thread, which then wakes
// the main thread with glfwPostEmptyEvent when a new one is available.
// This allows the main thread to wait for events unconditionally.
//
//========================================================================
@@ -37,25 +40,53 @@
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
static volatile int running = GLFW_TRUE;
struct State
{
mtx_t lock;
bool running;
bool needs_update;
int width;
int height;
float r, g, b;
};
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void generate_color(struct State* state)
{
const float r = (float) rand() / (float) RAND_MAX;
const float g = (float) rand() / (float) RAND_MAX;
const float b = (float) rand() / (float) RAND_MAX;
const float l = sqrtf(r * r + g * g + b * b);
mtx_lock(&state->lock);
state->r = r / l;
state->g = g / l;
state->b = b / l;
state->needs_update = true;
mtx_unlock(&state->lock);
}
static int thread_main(void* data)
{
struct timespec time;
struct State* const state = data;
while (running)
srand((unsigned int) time(NULL));
while (state->running)
{
generate_color(state);
glfwPostEmptyEvent();
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
time.tv_sec += 1;
thrd_sleep(&time, NULL);
glfwPostEmptyEvent();
}
return 0;
@@ -64,28 +95,38 @@ static int thread_main(void* data)
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
glfwSetWindowShouldClose(window, true);
}
static float nrand(void)
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
return (float) rand() / (float) RAND_MAX;
struct State* const state = glfwGetWindowUserPointer(window);
mtx_lock(&state->lock);
state->width = width;
state->height = height;
state->needs_update = true;
mtx_unlock(&state->lock);
}
int main(void)
{
int result;
thrd_t thread;
GLFWwindow* window;
struct State state = { .running = true };
srand((unsigned int) time(NULL));
if (mtx_init(&state.lock, mtx_plain) != thrd_success)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
generate_color(&state);
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
window = glfwCreateWindow(640, 480, "Empty Event Test", NULL, NULL);
GLFWwindow* window = glfwCreateWindow(640, 480, "Empty Event Test", NULL, NULL);
if (!window)
{
glfwTerminate();
@@ -95,8 +136,13 @@ int main(void)
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSetKeyCallback(window, key_callback);
glfwSetWindowUserPointer(window, &state);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwGetFramebufferSize(window, &state.width, &state.height);
if (thrd_create(&thread, thread_main, NULL) != thrd_success)
thrd_t color_thread;
if (thrd_create(&color_thread, thread_main, &state) != thrd_success)
{
fprintf(stderr, "Failed to create secondary thread\n");
@@ -104,28 +150,27 @@ int main(void)
exit(EXIT_FAILURE);
}
while (running)
while (!glfwWindowShouldClose(window))
{
int width, height;
float r = nrand(), g = nrand(), b = nrand();
float l = (float) sqrt(r * r + g * g + b * b);
if (state.needs_update)
{
mtx_lock(&state.lock);
glViewport(0, 0, state.width, state.height);
glClearColor(state.r, state.g, state.b, 1.f);
state.needs_update = false;
mtx_unlock(&state.lock);
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClearColor(r / l, g / l, b / l, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
}
glfwWaitEvents();
if (glfwWindowShouldClose(window))
running = GLFW_FALSE;
}
glfwHideWindow(window);
thrd_join(thread, &result);
glfwDestroyWindow(window);
state.running = false;
thrd_join(color_thread, NULL);
mtx_destroy(&state.lock);
glfwTerminate();
exit(EXIT_SUCCESS);
+4
View File
@@ -146,6 +146,10 @@ int main(void)
for (i = 0; i < count; i++)
thrd_join(threads[i].id, &result);
for (i = 0; i < count; i++)
glfwDestroyWindow(threads[i].window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
+30 -1
View File
@@ -36,6 +36,14 @@
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
static bool needs_update;
static void window_close_callback(GLFWwindow* window)
{
needs_update = true;
}
static void error_callback(int error, const char* description)
{
@@ -45,7 +53,15 @@ static void error_callback(int error, const char* description)
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, GLFW_TRUE);
needs_update = true;
}
}
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
needs_update = true;
}
static float nrand(void)
@@ -72,8 +88,11 @@ int main(void)
}
glfwMakeContextCurrent(window);
glfwSwapInterval(0);
gladLoadGL(glfwGetProcAddress);
glfwSetWindowCloseCallback(window, window_close_callback);
glfwSetKeyCallback(window, key_callback);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
while (!glfwWindowShouldClose(window))
{
@@ -87,8 +106,18 @@ int main(void)
glClearColor(r / l, g / l, b / l, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
needs_update = false;
glfwWaitEventsTimeout(1.0);
const double start = glfwGetTime();
while (!needs_update)
{
const double elapsed = glfwGetTime() - start;
if (elapsed >= 1.0)
needs_update = true;
else
glfwWaitEventsTimeout(1.0 - elapsed);
}
}
glfwDestroyWindow(window);