1
0
Fork 0
mirror of https://github.com/gwm17/glfw.git synced 2024-11-22 18:28:52 -05:00

Compare commits

...

118 Commits

Author SHA1 Message Date
Gordon McCann 7fdb858a47
Merge branch 'glfw:master' into master 2022-11-08 06:59:13 -05:00
Camilla Löwy dd8a678a66 Update Doxyfile template for Doxygen 1.9.5
This is mostly to disable Doxygen HTML output dark mode (for now).
2022-09-20 19:38:37 +02:00
Camilla Löwy 97b9e49637 Documentation work 2022-09-20 17:03:30 +02:00
Camilla Löwy b2b087cd8e Fix documented errors for gamma ramp functions
Fixes #2186
2022-09-20 17:02:51 +02:00
Camilla Löwy d299d9f788 Remove Doxyfile tags deprecated by Doxygen 1.9.5 2022-09-15 22:25:10 +02:00
Camilla Löwy ed1d9e1ca7 Document X11 WM_CLASS hint behavior
Fixes #2180
2022-09-15 22:25:10 +02:00
Camilla Löwy ab3ea8ac9f Win32: Remove unhelpful helper function 2022-09-15 22:25:10 +02:00
Camilla Löwy c812b9d87c Add conditional compilation for platform units
This is a step towards being able to compile GLFW manually without
needing to duplicate a lot of platform- or OS-specific logic.
2022-09-15 22:24:39 +02:00
Camilla Löwy 8a72918bcd Move helper macros to single point of use 2022-09-15 22:14:41 +02:00
Camilla Löwy ab1b1edfd0 EGL: Cleanup
Both config parameters are "desired", but one is older and never had its
name updated.

This commit at least makes it clearer that they are similar.
2022-09-15 22:14:41 +02:00
Camilla Löwy 93e93135f2 EGL: Add better error for no stereo 2022-09-15 22:14:41 +02:00
Camilla Löwy e057666642 EGL: Add better errors for client API mismatch
Because EGL ties client API support to configs, attempts to create
a context with an unavailable client API will fail with the unhelpful
"failed to find suitable config" error description.

This attempts to detect cases where there are usable configs for the
other client API and emit a hopefully more helpful error.

Related to #2173
2022-09-15 22:09:56 +02:00
Camilla Löwy 6b57e08bb0 Check if context creation APIs match when sharing 2022-08-22 19:17:12 +02:00
Camilla Löwy 2c0f34b60f WGL: Fix count of displayable pixel formats
We only care about displayable pixel formats (as defined in
WGL_ARB_pixel_format) for window context creation.

This changes pixel format enumeration to ignore non-displayable formats,
which are specified to be listed after displayable ones, by always using
the return value of DescribePixelFormat as the pixel format count.
2022-08-22 19:15:41 +02:00
Camilla Löwy ef6c9d8b4f Wayland: Fix window opacity on older systems
On systems lacking the EGL_EXT_present_opaque extension, some
compositors treat any buffer with an alpha channel as per-pixel
transparent.

This commit ignores any EGLConfig with an alpha channel if the extension
is missing and the window is created with GLFW_TRANSPARENT_FRAMEBUFFER
set to false.

This is technically not a breaking change since GLFW_ALPHA_BITS is not
a hard constraint, but it is still going to inconvenience anyone using
the framebuffer alpa channel to store other kinds of data.

Related to #1895
2022-08-01 19:19:51 +02:00
Camilla Löwy c18851f52e GLX: Add support for loading glvnd libGLX 2022-07-29 19:14:04 +02:00
Camilla Löwy 55aad3c37b EGL: Add support for loading glvnd libOpenGL 2022-07-29 19:14:04 +02:00
Camilla Löwy 0f9a9578f3 Add window hints for initial position
This adds window hints for the initial position, in screen coordinates,
of a window.  The special value GLFW_ANY_POSITION means the window
manager will be allowed to position the window.

It is not possible to set window positions on Wayland and GLFW will
always behave as if these hints are set to GLFW_ANY_POSITION.

Fixes #1603
Fixes #1747
2022-07-29 11:50:13 +02:00
Camilla Löwy 7d73629e50 X11: Preserve unrelated values in WM_NORMAL_HINTS
This stops GLFW overwriting the whole WM_NORMAL_HINTS property every
time it updates size-related parts of it.
2022-07-28 22:50:17 +02:00
Camilla Löwy 2efc598d70 Fix native access macros being mutually exclusive
The documentation was updated with the introduction of run-time platform
selection, but the preprocessor logic was not.
2022-07-28 15:56:47 +02:00
TheChocolateOre 2e12ef00bb
Fix typos and other issues in docs
This fixes spelling, grammar and punctuation issues, missing words and
stray words across the documentation.  A confusing sentence was removed
from the tutorial.

Closes #2085
2022-07-28 15:56:18 +02:00
Camilla Löwy 3a60992a41 Wayland: Add error for unsupported feature 2022-07-25 18:02:57 +02:00
Camilla Löwy 3a5c726d1b Wayland: Remove unreachable code
This platform function is only called if the cursor is enabled.
2022-07-25 18:02:57 +02:00
Camilla Löwy 7be6a2cabe Wayland: Clean up pointer helper function order 2022-07-25 18:02:57 +02:00
Camilla Löwy 488008e0a2 Add cursor mode GLFW_CURSOR_CAPTURED
This adds a cursor mode that provides a visible cursor confined to the
content area of the window.

Fixes #58
2022-07-25 18:02:57 +02:00
Camilla Löwy a46f829de8 Refactor cursor mode paths
This is the refactoring part of adding GLFW_CURSOR_CAPTURED, separated
out to help keep 3.3-stable similar to the main branch.

Related to #58.
2022-07-25 18:02:57 +02:00
Camilla Löwy 03af6b3d4c Wayland: Fix leaks of pointer related objects 2022-07-25 18:02:35 +02:00
Camilla Löwy 09ebf3f0bf Wayland: Fix error for missing protocol
A protocol not being available is not a platform error.  The platform is
doing fine; we're just sad that it lacks a feature we want.
2022-07-25 18:00:59 +02:00
Camilla Löwy e85b645b8a Wayland: Clean up pointer locking
Shorten names and allow C99 declarations.  Replace helper function with
the NULL check it was hiding.  Separate cursor hiding from pointer
locking.
2022-07-25 17:53:04 +02:00
Michael Pennington b9ed25d2e9 Wayland: Add GLFW_WAYLAND_APP_ID window hint
This adds a window hint string for the xdg_toplevel::app_id, which is
used by desktop environments to connect windows with application icons
and other information.  This is similar to the WM_CLASS property on X11.

A few very minor fixes were done by @elmindreda during merge.

Fixes #2121
Closes #2122
2022-07-24 17:51:54 +02:00
Camilla Löwy 26b85215c0 Wayland: Static function more static when static 2022-07-22 18:00:40 +02:00
Camilla Löwy 6987294df9 Wayland: Clean up cursor theme loading 2022-07-15 16:17:12 +02:00
Camilla Löwy 71be34a6c3 Wayland: Fix crash if mouse connected after init
The cursor theme was only loaded if the chosen seat had a mouse
(wl_pointer) during initialization.  If a mouse was connected only after
glfwInit, there would be no cursor theme but the rest of the cursor
related code assumed one had already been loaded.

This also moves the details of cursor theme loading out into a separate
function to declutter platform init.

Because the original cursor theme loading code checked whether we got
a wl_shm, and because the rest of the code just assumes we have
a wl_shm, initialization will now fail if there isn't one.

Fixes #1450
2022-07-15 16:17:12 +02:00
Camilla Löwy 7cc8b053b8 Wayland: Clean up shared memory buffer creation 2022-07-15 16:17:12 +02:00
Camilla Löwy 91a96ed434 Update changelog and add credit
Related to #2042
Related to #2043
2022-07-15 16:17:12 +02:00
Björn Hempel c424fe5589 Linux: Fix joystick without buttons being ignored
Joysticks in Linux without buttons were ignored by device enumeration.
Remove the mandatory button attribute from detection.

Fixes #2042
Closes #2043
2022-07-15 15:50:06 +02:00
Camilla Löwy c50d53160f Make events test window appear on Wayland 2022-07-13 21:54:55 +02:00
Camilla Löwy 40b5a8a37c Wayland: Fix reappearing key repeat
If the key or character callback performs actions that indirectly
updates the key repeat timer, those changes would be undone once the key
callback returned.

This fixes the order of operations so that key repeat is fully set up
before the key related events are emitted.
2022-07-13 21:54:55 +02:00
Camilla Löwy 9180923ea0 Wayland: Clean up key repeat logic 2022-07-13 21:54:55 +02:00
Camilla Löwy a1a73ee862 Wayland: Make text input logic static
Since the seat listener was moved into wl_window.c there is no reason
for text input to have external linkage.
2022-07-13 21:51:04 +02:00
Camilla Löwy e47cb7c1e2 Wayland: Update state before emitting events 2022-07-13 20:47:10 +02:00
Camilla Löwy 4df24735ef Wayland: Do not emit events for destroyed window
During platform window destruction, all of its callbacks have already
been removed, so emitting events for it does nothing.
2022-07-13 20:47:10 +02:00
Camilla Löwy d77aaa770f Wayland: Fix non-standard struct initialization 2022-07-13 12:53:25 +02:00
Camilla Löwy aa80d24d01 Documentation work
Fixes #1596
2022-07-12 19:08:01 +02:00
Camilla Löwy fd7e737216 Linux: Fix duplicate joystick objects
This fixes a regression introduced by
2c204ab52e.  This broke the check for
whether there is already a GLFW joystick object for a given input
device, making it always fail.
2022-07-12 11:53:13 +02:00
Camilla Löwy 6dd526fb1a Win32: Fix right Shift scancode when using CJK IME
Fixes #2050
2022-07-11 20:54:22 +02:00
Camilla Löwy 2796e61af7 Documentation work 2022-07-11 20:54:22 +02:00
Camilla Löwy 88a39006e3 Wayland: Cleanup 2022-07-11 20:54:21 +02:00
Camilla Löwy 5c948a6e6e Wayland: Fix comment typo 2022-07-11 20:54:21 +02:00
Camilla Löwy 8e725338bf Add credit
Related to #2150
2022-07-11 20:54:03 +02:00
JoelNiemela 060631c965 Fix typos in docs
Closes #2150
2022-07-11 20:52:43 +02:00
Camilla Löwy 36f0bf00a9 Cocoa: Fix build failure on OS X 10.11
The NSWindowCollectionBehaviorFullScreenNone enum value is missing from
system headers on 10.11 despite the documentation claiming it was added
in 10.7.

Unfortunately Apple has taken down all API release notes for versions
prior to 10.14.

This fixes a build failure introduced with
98d6e8485b.
2022-07-08 16:07:11 +02:00
Camilla Löwy 84e165ef64 Win32: Work around warnings on MSVC 19.32.x 2022-07-08 00:24:03 +02:00
Camilla Löwy 2db528d8cd Cocoa: Cleanup 2022-07-07 23:48:43 +02:00
Camilla Löwy 78b19548d9 Documentation work
Related to #2113
Related to #2120
2022-07-07 23:48:43 +02:00
Camilla Löwy dfb26023fc Update changelog and add credit
Related to #2113
Related to #2120
2022-07-07 23:48:42 +02:00
Nikita Fediuchin 9b7713cf92 Cocoa: Fix search path for private Vulkan loader
According to both Apple and LunarG, a private copy of the macOS Vulkan
loader libvulkan.1.dylib should be placed in the Frameworks directory
of the bundle and not its main executable directory.

This commit updates the dynamic loading path accordingly.

Fixes #2113
Closes #2120
2022-07-07 23:48:16 +02:00
Camilla Löwy 3b3d58df47 Add support for VK_KHR_portability_enumeration
The use of this extension is required to enable the MoltenVK physical
device as of Vulkan SDK 1.3.216.0.  This is because MoltenVK is still
very (very) slightly non-conformant.
2022-07-07 23:48:16 +02:00
Camilla Löwy 510a08cde2 Update glad to include Vulkan 1.3
Also add the VK_KHR_portability_enumeration extension, which will be
needed on macOS.
2022-07-07 23:48:16 +02:00
Camilla Löwy 0d599026d0 Cocoa: Fix clearing of unrelated window style bits
Whenever GLFW changed the window style mask, a new mask was created
from scratch based on the attributes set on the GLFW window object.
This caused us to potentially clear unrelated window style bits.

This was always wrong but became a critical issue when Cocoa began
throwing an exception if an application cleared the
NSWindowStyleMaskFullScreen while the window is in macOS fullscreen.

This commit reworks all style mask editing so it only changes the
relevant bits, preserving all others.

This is only a narrow bug fix to prevent crashes, intended for the
stable branch.  Our interaction with macOS fullscreen is still very
poor.  The next step after this is a set of patches that improve the
interaction between the current API and macOS fullscreen.

Fixes #1886
Fixes #2110
2022-07-07 23:47:48 +02:00
Camilla Löwy 6f8ec4075b Cocoa: Fix GLFW_MAXIMIZED for nonresizable windows
The reasoning here is that glfwRestoreWindow will change nothing for
a windowed non-resizable window on Cocoa, and silently refusing to
maximize seems slightly more like something other platforms would do.

This is possibly either the right thing to do or the wrong one.
2022-07-07 22:24:09 +02:00
Camilla Löwy 98d6e8485b Cocoa: Disable macOS fullscreen when non-resizable
Windows with GLFW_RESIZABLE set to false should not be resizable by the
user.
2022-07-07 22:23:54 +02:00
Camilla Löwy da6713cd09 Wayland: Do not decorate fullscreen windows
If a fullscreen window with GLFW_DECORATED set had its XDG decorations
changed to client mode by the compositor, it would seemingly receive
GLFW fallback decorations as if it was windowed mode.

This is possibly related to #2001.
2022-06-21 21:50:51 +02:00
Camilla Löwy d578c2ddfe Wayland: Only create EGL window if using EGL 2022-06-21 21:50:50 +02:00
Camilla Löwy 74b4ceb835 Wayland: Cleanup
This moves what is effectively showing the window to where that is done
on other platforms, i.e. last in the platform CreateWindow function.
2022-06-21 21:49:06 +02:00
Camilla Löwy c4fbe80d90 Wayland: Make function behavior match name
The logic that checks the decorated attribute belongs on the outside
along with other related checks (fullscreen, monitor, decoration mode).
2022-06-21 21:49:06 +02:00
Camilla Löwy be7f4513c0 Wayland: Remove premature surface commit calls
Note that the handling of configure events, acks and commits is still
not ideal.  This is just a small step in, hopefully, a good direction.

Fullscreen toggling via glfwSetWindowMonitor now works on Weston, but
mostly incidentally.
2022-06-21 21:49:06 +02:00
Camilla Löwy 47193f15de Wayland: Rename function to its purpose 2022-06-21 21:49:06 +02:00
Camilla Löwy 80dc0533cf Wayland: Use enum type to store enum value 2022-06-21 21:49:06 +02:00
Camilla Löwy 29b7669bc6 Wayland: Fix transition to server-side decorations 2022-06-21 21:49:06 +02:00
Camilla Löwy f35e2274cb Wayland: Fix GLFW_DECORATED for XDG decorations
On a compositor that supports server-side decorations, they were always
enabled in windowed mode, even if GLFW_DECORATED was cleared.
2022-06-21 21:49:06 +02:00
Camilla Löwy 3203599cac Wayland: Fix map before XDG decoration configure
If the xdg_toplevel has a decoration, we need to wait for its first
configure event as well before we are allowed to attach the first
buffer.

It seems racy to assume that this will always happen inside the first
surface configure sequence, so this commit makes that condition
explicit.  This may turn out to have been overly defensive.
2022-06-21 21:49:06 +02:00
Camilla Löwy 2df0ce07fa Wayland: Store and act on XDG decoration mode
Refer to the XDG decoration mode (or the lack of one) directly instead
of setting a boolean in a struct meant for the fallback decorations.

This makes things a bit more verbose but is in preparation for
a refactoring of all decoration paths.
2022-06-21 21:49:06 +02:00
Camilla Löwy 83a134a92f Wayland: Fix mapping failure on wlroots compositor
When showing a window that had already been shown once (and so already
had its shell objects), GLFW would attach a new buffer and commit it
before waiting for the next configure event.  This was a violation of
the XDG shell protocol.

This was allowed to work as intended on GNOME and KDE without error.
However wlroots based compositors would (correctly) emit an error.

Unfortunately, I haven't been able to find a way to get both KDE, GNOME
and Sway to send the configure event we need in order to map the
wl_surface again while keeping our existing shell objects, so with this
commit we now create them for each call to glfwShowWindow and destroy
them for each call to glfwHideWindow.

Fixes #1268
2022-06-21 21:49:05 +02:00
Camilla Löwy eb9c3bee71 Wayland: Rename fallback decoration functions
We are soon going to have three kinds of decorations; XDG, libdecor and
our last resort fallback ones.
2022-06-21 21:47:35 +02:00
Camilla Löwy 0cd1916de3 Wayland: Remove function only called once 2022-06-21 21:47:35 +02:00
Camilla Löwy 77819c0c54 Wayland: Fix maximized state lost while hidden
If a window was created as maximized, or created as hidden and then
iconified or maximized before first being shown, that state was lost and
the window was shown as restored.
2022-06-21 21:47:35 +02:00
Camilla Löwy e52046955d Wayland: Cleanup 2022-06-21 21:47:35 +02:00
Camilla Löwy 55fcfb1bb6 Wayland: Fix error for setting GLFW_FLOATING 2022-06-21 21:47:35 +02:00
Camilla Löwy 203002ef2c Wayland: Fix latent bug for glfwGetWindowTitle 2022-06-21 21:47:35 +02:00
Camilla Löwy 85f5a51912 Wayland: Fix events emitted before ack_configure
Window iconfication and maximization events were being emitted before
xdg_surface::configure, making it possible for user code to indirectly
commit surface changes from those event callbacks before
xdg_surface::ack_configure.

This postpones those events until after the ack has been sent.
2022-06-21 21:47:35 +02:00
Camilla Löwy 9ad9f5c52a Wayland: Fix missing error reporting 2022-06-21 21:47:32 +02:00
Camilla Löwy 5002522f73 Wayland: Cleanup
Make Wayland code use 'native' in the same senses as the rest of GLFW.
2022-06-21 21:44:15 +02:00
Camilla Löwy 91f18fb576 Wayland: Fix error from glfwSetWindowAspectRatio
The aspect ratio was applied during resize but any call to
glfwSetWindowAspectRatio emitted a GLFW_FEATURE_UNIMPLEMENTED error.
2022-06-21 20:46:06 +02:00
Camilla Löwy e37ba80b13 Wayland: Fix reporting of monitor scale changes
Content scale events would be emitted when a window surface entered or
left an output, but not when one of a window's current outputs had its
scale changed.
2022-06-21 20:46:06 +02:00
Camilla Löwy c3ad3d49ed Wayland: Fix duplicate monitor connection events
GLFW would report a monitor as connected each time its wl_output
received an update, for example if its scale changed.

This would also cause the monitor to be added to the monitor array
again, causing glfwTerminate to segfault when it attempted to destroy
its already destroyed wl_output.
2022-06-21 20:46:06 +02:00
Camilla Löwy 209f6cf093 Wayland: Add support for wl_output::name
We now use wl_output::name as the GLFW monitor name, on compositors that
provide this event.
2022-06-21 20:44:52 +02:00
Camilla Löwy 33d37782c6 Wayland: Cleanup 2022-06-21 16:00:33 +02:00
Camilla Löwy 229d628ec4 Wayland: Fix toggling of server-side decorations
This is a temporary local fix to have updates to GLFW_DECORATED mostly
work as intended.  The whole decoration state machine needs to be
restructured, but not by this commit.
2022-06-21 16:00:33 +02:00
Camilla Löwy c28d420060 Wayland: Remove duplicate fullscreen check
This check is already performed in shared code.
2022-06-21 16:00:20 +02:00
Camilla Löwy 18df0baea6 Wayland: Cleanup 2022-06-20 00:57:17 +02:00
Camilla Löwy a7b6f35500 Wayland: Fix size limits for fallback decorations
The size limits set on our XDG surface did not include the sizes of the
fallback decorations on all sides, when in use.  This led to its content
area being too small.

Related to #2127
2022-06-20 00:57:17 +02:00
Camilla Löwy 0f5b095042 Wayland: Fix erratic fallback decoration behavior
The handler for xdg_toplevel::configure treated the provided size as the
content area size when instead it is the size of the bounding rectangle
of the wl_surface and all its subsurfaces.

This caused the fallback decorations to try positioning themselves
outside themselves, causing feedback loops during interactive resizing.

Fixes #1991
Fixes #2115
Closes #2127
Related to #1914
2022-06-20 00:57:17 +02:00
Camilla Löwy 24cdc5afda Wayland: Rename window frame size constants 2022-06-20 00:57:17 +02:00
Camilla Löwy 75295f4878 Wayland: Remove unused code path 2022-06-20 00:57:17 +02:00
Camilla Löwy 040712ce99 Wayland: Cleanup 2022-06-20 00:57:17 +02:00
Camilla Löwy 2877fea550 Wayland: Remove superfluous comments
These are just repeating parts of the identifier.
2022-06-20 00:57:17 +02:00
Camilla Löwy e33db6d7aa Wayland: Fix resize events before ack_configure
The surface was resized and the size event was emitted before we had
sent xdg_surface::ack_configure.  If user code then called some GLFW
function that commited the surface, those changes would all get applied
to the wrong configure event.

This postpones size changes until after the ack.
2022-06-20 00:57:17 +02:00
Camilla Löwy afb127769a Wayland: Add tracking of XDG fullscreen state 2022-06-20 00:57:17 +02:00
Camilla Löwy ed39ff43f9 Wayland: Use named constants for version checks
The wayland-scanner output provides really nice, self-documenting
version macros, so we should use them whenever possible.
2022-06-20 00:57:17 +02:00
Camilla Löwy 98c9961f32 Wayland: Cleanup 2022-06-20 00:57:17 +02:00
Camilla Löwy 3bbb41eacc Wayland: Fix glfwInit closing stdin on failure
If platform initialization failed before either timer fd member had been
set to -1 or a valid fd, termination would close stdin.
2022-06-20 00:57:17 +02:00
Camilla Löwy 0b76e3a6f1 Wayland: Fix duplicate window content scale events
The window content scale event was emitted every time the window content
area was resized, even if its scale had not changed.
2022-06-20 00:57:17 +02:00
Camilla Löwy 6857995498 Wayland: Fix glfwSetWindowSize resizing fs windows
glfwSetWindowSize would change the size of fullscreen mode windows as
if they were windowed mode.
2022-06-20 00:57:17 +02:00
Camilla Löwy fdc72edf81 Wayland: Fix missing fullscreen code path
glfwRestoreWindow assumed it was only called in windowed mode.
2022-06-20 00:57:17 +02:00
Camilla Löwy f39ffefb6a Wayland: Fix maximization by user being ignored
The internal maximization state was not updated when an event was
received that the user had changed the maximization state of a window,
and no maximization events were emitted.

This affected both the GLFW_MAXIMIZED attribute and glfwRestoreWindow.
2022-06-20 00:57:17 +02:00
Camilla Löwy ddd087d662 Wayland: Fix behavior of leaving full screen mode
These changes make GLFW fullscreen more consistent, but unfortunately
also make GLFW even more oblivious to user-initiated XDG shell
fullscreen changes.

Fixes #1995
2022-06-20 00:57:17 +02:00
Camilla Löwy 523fdf50c1 Wayland: Cleanup 2022-06-20 00:57:17 +02:00
Camilla Löwy d3ede7b684 Add credit
Related to #2108
2022-06-10 00:14:05 +02:00
Camilla Löwy a465c1c32e Win32: Simplify window class handling
By using window class atoms, we only need to mention each window class
name once, also removing the need to define _GLFW_WNDCLASSNAME.  It can
still be defined by the user as before.
2022-06-09 18:39:37 +02:00
Camilla Löwy 2ae3e0c8d7 Win32: Add separate window class for helper window
The current window procedure needs to deal with messages both for user
created windows and the hidden helper window.

This commit separates out the device message handling of the helper
window, allowing both window procedures to be less complicated.
2022-06-08 23:56:20 +02:00
Camilla Löwy ad3dbeb65f Add basic assertions for event API arguments 2022-06-08 22:14:38 +02:00
Camilla Löwy 05f6c13d11 Add support for GLFW_NATIVE_INCLUDE_NONE macro
By default, the glfw3native.h header will include the platform-specific
headers necessary for the return types of GLFW native access functions.

Sometimes it is preferrable to declare those types

This commit adds support for the GLFW_NATIVE_INCLUDE_NONE macro, which
when defined disables the inclusion of all platform-specific headers.

Fixes #1348
2022-06-08 22:14:38 +02:00
Camilla Löwy edec334b32 Cocoa: Use system header to declare id type
Related to #1348
2022-06-08 22:14:38 +02:00
Camilla Löwy 26920a1a38 X11: Fix previous error handler not being restored
GLFW did not restore the previous Xlib error handler when removing its
own, instead resetting to the default handler.

This commit saves and restores the previous error handler.

None of this is thread-safe or could ever be.

Fixes #2108
2022-06-08 22:14:38 +02:00
Camilla Löwy 736a88b067 Fix return type of functions returning bool values 2022-06-08 22:14:38 +02:00
Camilla Löwy 2c204ab52e Fix joystick user pointer NULL during disconnect
The joystick code did not distinguish between the allocation status of
the GLFW joystick object and whether it is connection to an OS level
joystick object.

These are now tracked separately.

Fixes #2092
2022-06-08 22:14:38 +02:00
Camilla Löwy e9c58bc181 Wayland: Fix missing lock key modifier bits
The modifier bits for lock keys were only set when the corresponding key
was reported as held down or latched, but not when it was released and
locked.
2022-06-08 19:20:01 +02:00
73 changed files with 4756 additions and 1748 deletions

View File

@ -19,11 +19,13 @@ video tutorials.
- Nevyn Bengtsson - Nevyn Bengtsson
- Niklas Bergström - Niklas Bergström
- Denis Bernard - Denis Bernard
- BiBi
- Doug Binks - Doug Binks
- blanco - blanco
- Waris Boonyasiriwat - Waris Boonyasiriwat
- Kyle Brenneman - Kyle Brenneman
- Rok Breulj - Rok Breulj
- TheBrokenRail
- Kai Burjack - Kai Burjack
- Martin Capitanio - Martin Capitanio
- Nicolas Caramelli - Nicolas Caramelli
@ -31,6 +33,7 @@ video tutorials.
- Arturo Castro - Arturo Castro
- Chi-kwan Chan - Chi-kwan Chan
- TheChocolateOre - TheChocolateOre
- Ali Chraghi
- Joseph Chua - Joseph Chua
- Ian Clarkson - Ian Clarkson
- Michał Cichoń - Michał Cichoń
@ -59,6 +62,7 @@ video tutorials.
- Jan Ekström - Jan Ekström
- Siavash Eliasi - Siavash Eliasi
- Ahmad Fatoum - Ahmad Fatoum
- Nikita Fediuchin
- Felipe Ferreira - Felipe Ferreira
- Michael Fogleman - Michael Fogleman
- Jason Francis - Jason Francis
@ -79,10 +83,12 @@ video tutorials.
- Jonathan Hale - Jonathan Hale
- hdf89shfdfs - hdf89shfdfs
- Sylvain Hellegouarch - Sylvain Hellegouarch
- Björn Hempel
- Matthew Henry - Matthew Henry
- heromyth - heromyth
- Lucas Hinderberger - Lucas Hinderberger
- Paul Holden - Paul Holden
- Hajime Hoshi
- Warren Hu - Warren Hu
- Charles Huber - Charles Huber
- Brent Huisman - Brent Huisman
@ -121,6 +127,7 @@ video tutorials.
- lukect - lukect
- Tristam MacDonald - Tristam MacDonald
- Hans Mackowiak - Hans Mackowiak
- Ramiro Magno
- Дмитри Малышев - Дмитри Малышев
- Zbigniew Mandziejewicz - Zbigniew Mandziejewicz
- Adam Marcus - Adam Marcus
@ -137,6 +144,7 @@ video tutorials.
- Kenneth Miller - Kenneth Miller
- Bruce Mitchener - Bruce Mitchener
- Jack Moffitt - Jack Moffitt
- Ravi Mohan
- Jeff Molofee - Jeff Molofee
- Alexander Monakov - Alexander Monakov
- Pierre Morel - Pierre Morel
@ -144,10 +152,13 @@ video tutorials.
- Pierre Moulon - Pierre Moulon
- Martins Mozeiko - Martins Mozeiko
- Pascal Muetschard - Pascal Muetschard
- James Murphy
- Julian Møller - Julian Møller
- ndogxj - ndogxj
- F. Nedelec
- n3rdopolis - n3rdopolis
- Kristian Nielsen - Kristian Nielsen
- Joel Niemelä
- Kamil Nowakowski - Kamil Nowakowski
- onox - onox
- Denis Ovod - Denis Ovod
@ -157,8 +168,10 @@ video tutorials.
- Peoro - Peoro
- Braden Pellett - Braden Pellett
- Christopher Pelloux - Christopher Pelloux
- Michael Pennington
- Arturo J. Pérez - Arturo J. Pérez
- Vladimir Perminov - Vladimir Perminov
- Olivier Perret
- Anthony Pesch - Anthony Pesch
- Orson Peters - Orson Peters
- Emmanuel Gil Peyrot - Emmanuel Gil Peyrot
@ -172,10 +185,13 @@ video tutorials.
- Pablo Prietz - Pablo Prietz
- przemekmirek - przemekmirek
- pthom - pthom
- Martin Pulec
- Guillaume Racicot - Guillaume Racicot
- Christian Rauch
- Philip Rideout - Philip Rideout
- Eddie Ringle - Eddie Ringle
- Max Risuhin - Max Risuhin
- Joe Roback
- Jorge Rodriguez - Jorge Rodriguez
- Jari Ronkainen - Jari Ronkainen
- Luca Rood - Luca Rood
@ -229,6 +245,7 @@ video tutorials.
- Torsten Walluhn - Torsten Walluhn
- Patrick Walton - Patrick Walton
- Xo Wang - Xo Wang
- Andre Weissflog
- Jay Weisskopf - Jay Weisskopf
- Frank Wille - Frank Wille
- Andy Williams - Andy Williams

View File

@ -139,13 +139,21 @@ information on what to include when reporting a bug.
- Added `GLFW_POINTING_HAND_CURSOR` alias for `GLFW_HAND_CURSOR` (#427) - Added `GLFW_POINTING_HAND_CURSOR` alias for `GLFW_HAND_CURSOR` (#427)
- Added `GLFW_MOUSE_PASSTHROUGH` window hint for letting mouse input pass - Added `GLFW_MOUSE_PASSTHROUGH` window hint for letting mouse input pass
through the window (#1236,#1568) through the window (#1236,#1568)
- Added `GLFW_CURSOR_CAPTURED` cursor mode to confine the cursor to the window
content area (#58)
- Added `GLFW_POSITION_X` and `GLFW_POSITION_Y` window hints for initial position
(#1603,#1747)
- Added `GLFW_ANY_POSITION` hint value for letting the window manager choose (#1603,#1747)
- Added `GLFW_PLATFORM_UNAVAILABLE` error for platform detection failures (#1958) - Added `GLFW_PLATFORM_UNAVAILABLE` error for platform detection failures (#1958)
- Added `GLFW_FEATURE_UNAVAILABLE` error for platform limitations (#1692) - Added `GLFW_FEATURE_UNAVAILABLE` error for platform limitations (#1692)
- Added `GLFW_FEATURE_UNIMPLEMENTED` error for incomplete backends (#1692) - Added `GLFW_FEATURE_UNIMPLEMENTED` error for incomplete backends (#1692)
- Added `GLFW_WAYLAND_APP_ID` window hint string for Wayland app\_id selection
(#2121,#2122)
- Added `GLFW_ANGLE_PLATFORM_TYPE` init hint and `GLFW_ANGLE_PLATFORM_TYPE_*` - Added `GLFW_ANGLE_PLATFORM_TYPE` init hint and `GLFW_ANGLE_PLATFORM_TYPE_*`
values to select ANGLE backend (#1380) values to select ANGLE backend (#1380)
- Added `GLFW_X11_XCB_VULKAN_SURFACE` init hint for selecting X11 Vulkan - Added `GLFW_X11_XCB_VULKAN_SURFACE` init hint for selecting X11 Vulkan
surface extension (#1793) surface extension (#1793)
- Added `GLFW_NATIVE_INCLUDE_NONE` for disabling inclusion of native headers (#1348)
- Added `GLFW_BUILD_WIN32` CMake option for enabling Win32 support (#1958) - Added `GLFW_BUILD_WIN32` CMake option for enabling Win32 support (#1958)
- Added `GLFW_BUILD_COCOA` CMake option for enabling Cocoa support (#1958) - Added `GLFW_BUILD_COCOA` CMake option for enabling Cocoa support (#1958)
- Added `GLFW_BUILD_X11` CMake option for enabling X11 support (#1958) - Added `GLFW_BUILD_X11` CMake option for enabling X11 support (#1958)
@ -174,9 +182,11 @@ information on what to include when reporting a bug.
- Bugfix: Native access functions for context handles did not check that the API matched - Bugfix: Native access functions for context handles did not check that the API matched
- Bugfix: `glfwMakeContextCurrent` would access TLS slot before initialization - Bugfix: `glfwMakeContextCurrent` would access TLS slot before initialization
- Bugfix: `glfwSetGammaRamp` could emit `GLFW_INVALID_VALUE` before initialization - Bugfix: `glfwSetGammaRamp` could emit `GLFW_INVALID_VALUE` before initialization
- Bugfix: `glfwGetJoystickUserPointer` returned `NULL` during disconnection (#2092)
- [Win32] Added the `GLFW_WIN32_KEYBOARD_MENU` window hint for enabling access - [Win32] Added the `GLFW_WIN32_KEYBOARD_MENU` window hint for enabling access
to the window menu to the window menu
- [Win32] Added a version info resource to the GLFW DLL - [Win32] Added a version info resource to the GLFW DLL
- [Win32] Made hidden helper window use its own window class
- [Win32] Disabled framebuffer transparency on Windows 7 when DWM windows are - [Win32] Disabled framebuffer transparency on Windows 7 when DWM windows are
opaque (#1512) opaque (#1512)
- [Win32] Bugfix: `GLFW_INCLUDE_VULKAN` plus `VK_USE_PLATFORM_WIN32_KHR` caused - [Win32] Bugfix: `GLFW_INCLUDE_VULKAN` plus `VK_USE_PLATFORM_WIN32_KHR` caused
@ -218,12 +228,14 @@ information on what to include when reporting a bug.
match event scancode (#1993) match event scancode (#1993)
- [Win32] Bugfix: Instance-local operations used executable instance (#469,#1296,#1395) - [Win32] Bugfix: Instance-local operations used executable instance (#469,#1296,#1395)
- [Win32] Bugfix: The OSMesa library was not unloaded on termination - [Win32] Bugfix: The OSMesa library was not unloaded on termination
- [Win32] Bugfix: Right shift emitted `GLFW_KEY_UNKNOWN` when using a CJK IME (#2050)
- [Cocoa] Added support for `VK_EXT_metal_surface` (#1619) - [Cocoa] Added support for `VK_EXT_metal_surface` (#1619)
- [Cocoa] Added locating the Vulkan loader at runtime in an application bundle - [Cocoa] Added locating the Vulkan loader at runtime in an application bundle
- [Cocoa] Moved main menu creation to GLFW initialization time (#1649) - [Cocoa] Moved main menu creation to GLFW initialization time (#1649)
- [Cocoa] Changed `EGLNativeWindowType` from `NSView` to `CALayer` (#1169) - [Cocoa] Changed `EGLNativeWindowType` from `NSView` to `CALayer` (#1169)
- [Cocoa] Changed F13 key to report Print Screen for cross-platform consistency - [Cocoa] Changed F13 key to report Print Screen for cross-platform consistency
(#1786) (#1786)
- [Cocoa] Disabled macOS fullscreen when `GLFW_RESIZABLE` is false
- [Cocoa] Removed dependency on the CoreVideo framework - [Cocoa] Removed dependency on the CoreVideo framework
- [Cocoa] Bugfix: `glfwSetWindowSize` used a bottom-left anchor point (#1553) - [Cocoa] Bugfix: `glfwSetWindowSize` used a bottom-left anchor point (#1553)
- [Cocoa] Bugfix: Window remained on screen after destruction until event poll - [Cocoa] Bugfix: Window remained on screen after destruction until event poll
@ -250,6 +262,13 @@ information on what to include when reporting a bug.
- [Cocoa] Bugfix: `kUTTypeURL` was deprecated in macOS 12.0 (#2003) - [Cocoa] Bugfix: `kUTTypeURL` was deprecated in macOS 12.0 (#2003)
- [Cocoa] Bugfix: A connected Apple AirPlay would emit a useless error (#1791) - [Cocoa] Bugfix: A connected Apple AirPlay would emit a useless error (#1791)
- [Cocoa] Bugfix: The EGL and OSMesa libraries were not unloaded on termination - [Cocoa] Bugfix: The EGL and OSMesa libraries were not unloaded on termination
- [Cocoa] Bugfix: `GLFW_MAXIMIZED` was always true when `GLFW_RESIZABLE` was false
- [Cocoa] Bugfix: Changing `GLFW_DECORATED` in macOS fullscreen would abort
application (#1886)
- [Cocoa] Bugfix: Setting a monitor from macOS fullscreen would abort
application (#2110)
- [Cocoa] Bugfix: The Vulkan loader was not loaded from the `Frameworks` bundle
subdirectory (#2113,#2120)
- [X11] Bugfix: The CMake files did not check for the XInput headers (#1480) - [X11] Bugfix: The CMake files did not check for the XInput headers (#1480)
- [X11] Bugfix: Key names were not updated when the keyboard layout changed - [X11] Bugfix: Key names were not updated when the keyboard layout changed
(#1462,#1528) (#1462,#1528)
@ -291,9 +310,13 @@ information on what to include when reporting a bug.
- [X11] Bugfix: Left shift of int constant relied on undefined behavior (#1951) - [X11] Bugfix: Left shift of int constant relied on undefined behavior (#1951)
- [X11] Bugfix: The OSMesa libray was not unloaded on termination - [X11] Bugfix: The OSMesa libray was not unloaded on termination
- [X11] Bugfix: A malformed response during selection transfer could cause a segfault - [X11] Bugfix: A malformed response during selection transfer could cause a segfault
- [X11] Bugfix: Some calls would reset Xlib to the default error handler (#2108)
- [Wayland] Added dynamic loading of all Wayland libraries - [Wayland] Added dynamic loading of all Wayland libraries
- [Wayland] Added support for key names via xkbcommon - [Wayland] Added support for key names via xkbcommon
- [Wayland] Added support for file path drop events (#2040) - [Wayland] Added support for file path drop events (#2040)
- [Wayland] Added support for more human-readable monitor names where available
- [Wayland] Disabled alpha channel for opaque windows on systems lacking
`EGL_EXT_present_opaque` (#1895)
- [Wayland] Removed support for `wl_shell` (#1443) - [Wayland] Removed support for `wl_shell` (#1443)
- [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432) - [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432)
- [Wayland] Bugfix: `CLOCK_MONOTONIC` was not correctly enabled - [Wayland] Bugfix: `CLOCK_MONOTONIC` was not correctly enabled
@ -326,8 +349,42 @@ information on what to include when reporting a bug.
- [Wayland] Bugfix: MIME type matching was not performed for clipboard string - [Wayland] Bugfix: MIME type matching was not performed for clipboard string
- [Wayland] Bugfix: The OSMesa library was not unloaded on termination - [Wayland] Bugfix: The OSMesa library was not unloaded on termination
- [Wayland] Bugfix: `glfwCreateWindow` could emit `GLFW_FEATURE_UNAVAILABLE` - [Wayland] Bugfix: `glfwCreateWindow` could emit `GLFW_FEATURE_UNAVAILABLE`
- [Wayland] Bugfix: Lock key modifier bits were only set when lock keys were pressed
- [Wayland] Bugfix: A window leaving full screen mode would be iconified (#1995)
- [Wayland] Bugfix: A window leaving full screen mode ignored its desired size
- [Wayland] Bugfix: `glfwSetWindowMonitor` did not update windowed mode size
- [Wayland] Bugfix: `glfwRestoreWindow` would make a full screen window windowed
- [Wayland] Bugfix: A window maximized or restored by the user would enter an
inconsistent state
- [Wayland] Bugfix: Window maximization events were not emitted
- [Wayland] Bugfix: `glfwRestoreWindow` assumed it was always in windowed mode
- [Wayland] Bugfix: `glfwSetWindowSize` would resize a full screen window
- [Wayland] Bugfix: A window content scale event would be emitted every time
the window resized
- [Wayland] Bugfix: If `glfwInit` failed it would close stdin
- [Wayland] Bugfix: Manual resizing with fallback decorations behaved erratically
(#1991,#2115,#2127)
- [Wayland] Bugfix: Size limits included frame size for fallback decorations
- [Wayland] Bugfix: Updating `GLFW_DECORATED` had no effect on server-side
decorations
- [Wayland] Bugfix: A monitor would be reported as connected again if its scale
changed
- [Wayland] Bugfix: `glfwTerminate` would segfault if any monitor had changed
scale
- [Wayland] Bugfix: Window content scale events were not emitted when monitor
scale changed
- [Wayland] Bugfix: `glfwSetWindowAspectRatio` reported an error instead of
applying the specified ratio
- [Wayland] Bugfix: `GLFW_MAXIMIZED` window hint had no effect
- [Wayland] Bugfix: `glfwRestoreWindow` had no effect before first show
- [Wayland] Bugfix: Hiding and then showing a window caused program abort on
wlroots compositors (#1268)
- [Wayland] Bugfix: `GLFW_DECORATED` was ignored when showing a window with XDG
decorations
- [Wayland] Bugfix: Connecting a mouse after `glfwInit` would segfault (#1450)
- [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Removed use of deprecated function `gettimeofday`
- [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled
- [Linux] Bugfix: Joysticks without buttons were ignored (#2042,#2043)
- [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072) - [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072)
- [NSGL] Removed enforcement of forward-compatible flag for core contexts - [NSGL] Removed enforcement of forward-compatible flag for core contexts
- [NSGL] Bugfix: `GLFW_COCOA_RETINA_FRAMEBUFFER` had no effect on newer - [NSGL] Bugfix: `GLFW_COCOA_RETINA_FRAMEBUFFER` had no effect on newer
@ -339,7 +396,9 @@ information on what to include when reporting a bug.
(#442) (#442)
- [EGL] Added ANGLE backend selection via `EGL_ANGLE_platform_angle` extension - [EGL] Added ANGLE backend selection via `EGL_ANGLE_platform_angle` extension
(#1380) (#1380)
[EGL] Added loading of glvnd `libOpenGL.so.0` where available for OpenGL
- [EGL] Bugfix: The `GLFW_DOUBLEBUFFER` context attribute was ignored (#1843) - [EGL] Bugfix: The `GLFW_DOUBLEBUFFER` context attribute was ignored (#1843)
- [GLX] Added loading of glvnd `libGLX.so.0` where available
- [GLX] Bugfix: Context creation failed if GLX 1.4 was not exported by GLX library - [GLX] Bugfix: Context creation failed if GLX 1.4 was not exported by GLX library

2488
deps/glad/vulkan.h vendored

File diff suppressed because it is too large Load Diff

View File

@ -351,8 +351,8 @@ __Note:__ If you haven't already implemented the feature, check first if there
already is an open issue for it and if it's already being developed in an already is an open issue for it and if it's already being developed in an
[experimental branch](https://github.com/glfw/glfw/branches/all). [experimental branch](https://github.com/glfw/glfw/branches/all).
__There is no preferred patch size__. A one character change is just as welcome __There is no preferred patch size__. A one-character change is just as welcome
as one adding a thousand line one, if that is the appropriate size for the as one adding a thousand lines, if that is the appropriate size for the
feature. feature.
In addition to the code, a complete feature includes: In addition to the code, a complete feature includes:

View File

@ -1,4 +1,4 @@
# Doxyfile 1.8.18 # Doxyfile 1.9.5
# This file describes the settings to be used by the documentation system # This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project. # doxygen (www.doxygen.org) for a project.
@ -12,6 +12,16 @@
# For lists, items can also be appended using: # For lists, items can also be appended using:
# TAG += value [value, ...] # TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (\" \"). # Values that contain spaces should be placed between quotes (\" \").
#
# Note:
#
# Use doxygen to compare the used configuration file with the template
# configuration file:
# doxygen -x [configFile]
# Use doxygen to compare the used configuration file with the template
# configuration file without replacing the environment variables or CMake type
# replacement variables:
# doxygen -x_noenv [configFile]
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Project related configuration options # Project related configuration options
@ -60,16 +70,28 @@ PROJECT_LOGO =
OUTPUT_DIRECTORY = "@GLFW_BINARY_DIR@/docs" OUTPUT_DIRECTORY = "@GLFW_BINARY_DIR@/docs"
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
# directories (in 2 levels) under the output directory of each output format and # sub-directories (in 2 levels) under the output directory of each output format
# will distribute the generated files over these directories. Enabling this # and will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where # option can be useful when feeding doxygen a huge amount of source files, where
# putting all generated files in the same directory would otherwise causes # putting all generated files in the same directory would otherwise causes
# performance problems for the file system. # performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to
# control the number of sub-directories.
# The default value is: NO. # The default value is: NO.
CREATE_SUBDIRS = NO CREATE_SUBDIRS = NO
# Controls the number of sub-directories that will be created when
# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every
# level increment doubles the number of directories, resulting in 4096
# directories at level 8 which is the default and also the maximum value. The
# sub-directories are organized in 2 levels, the first level always has a fixed
# numer of 16 directories.
# Minimum value: 0, maximum value: 8, default value: 8.
# This tag requires that the tag CREATE_SUBDIRS is set to YES.
CREATE_SUBDIRS_LEVEL = 8
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
# characters to appear in the names of generated files. If set to NO, non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
@ -81,14 +103,14 @@ ALLOW_UNICODE_NAMES = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all # The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this # documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language. # information to generate all constant output in the proper language.
# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian,
# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English
# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek,
# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with
# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # English messages), Korean, Korean-en (Korean with English messages), Latvian,
# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese,
# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish,
# Ukrainian and Vietnamese. # Swedish, Turkish, Ukrainian and Vietnamese.
# The default value is: English. # The default value is: English.
OUTPUT_LANGUAGE = English OUTPUT_LANGUAGE = English
@ -209,6 +231,14 @@ QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO MULTILINE_CPP_IS_BRIEF = NO
# By default Python docstrings are displayed as preformatted text and doxygen's
# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
# doxygen's special commands can be used and the contents of the docstring
# documentation blocks is shown as doxygen documentation.
# The default value is: YES.
PYTHON_DOCSTRING = YES
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements. # documentation from any documented member that it re-implements.
# The default value is: YES. # The default value is: YES.
@ -232,16 +262,16 @@ TAB_SIZE = 8
# the documentation. An alias has the form: # the documentation. An alias has the form:
# name=value # name=value
# For example adding # For example adding
# "sideeffect=@par Side Effects:\n" # "sideeffect=@par Side Effects:^^"
# will allow you to put the command \sideeffect (or @sideeffect) in the # will allow you to put the command \sideeffect (or @sideeffect) in the
# documentation, which will result in a user-defined paragraph with heading # documentation, which will result in a user-defined paragraph with heading
# "Side Effects:". You can put \n's in the value part of an alias to insert # "Side Effects:". Note that you cannot put \n's in the value part of an alias
# newlines (in the resulting output). You can put ^^ in the value part of an # to insert newlines (in the resulting output). You can put ^^ in the value part
# alias to insert a newline as if a physical newline was in the original file. # of an alias to insert a newline as if a physical newline was in the original
# When you need a literal { or } or , in the value part of an alias you have to # file. When you need a literal { or } or , in the value part of an alias you
# escape them by means of a backslash (\), this can lead to conflicts with the # have to escape them by means of a backslash (\), this can lead to conflicts
# commands \{ and \} for these it is advised to use the version @{ and @} or use # with the commands \{ and \} for these it is advised to use the version @{ and
# a double escape (\\{ and \\}) # @} or use a double escape (\\{ and \\})
ALIASES = "thread_safety=@par Thread safety^^" \ ALIASES = "thread_safety=@par Thread safety^^" \
"pointer_lifetime=@par Pointer lifetime^^" \ "pointer_lifetime=@par Pointer lifetime^^" \
@ -297,8 +327,8 @@ OPTIMIZE_OUTPUT_SLICE = NO
# extension. Doxygen has a built-in mapping, but you can override or extend it # extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and # using this tag. The format is ext=language, where ext is a file extension, and
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, # language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, # Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: # VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
# tries to guess whether the code is fixed or free formatted code, this is the # tries to guess whether the code is fixed or free formatted code, this is the
# default for Fortran type files). For instance to make doxygen treat .inc files # default for Fortran type files). For instance to make doxygen treat .inc files
@ -308,7 +338,10 @@ OPTIMIZE_OUTPUT_SLICE = NO
# Note: For files without extension you can use no_extension as a placeholder. # Note: For files without extension you can use no_extension as a placeholder.
# #
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise # Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen. # the files are not read by doxygen. When specifying no_extension you should add
# * to the FILE_PATTERNS.
#
# Note see also the list of default file extension mappings.
EXTENSION_MAPPING = EXTENSION_MAPPING =
@ -442,6 +475,19 @@ TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0 LOOKUP_CACHE_SIZE = 0
# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use
# during processing. When set to 0 doxygen will based this on the number of
# cores available in the system. You can set it explicitly to a value larger
# than 0 to get more control over the balance between CPU load and processing
# speed. At this moment only the input processing can be done using multiple
# threads. Since this is still an experimental feature the default is set to 1,
# which effectively disables parallel processing. Please report any issues you
# encounter. Generating dot graphs in parallel is controlled by the
# DOT_NUM_THREADS setting.
# Minimum value: 0, maximum value: 32, default value: 1.
NUM_PROC_THREADS = 1
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Build related configuration options # Build related configuration options
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@ -505,6 +551,13 @@ EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO EXTRACT_ANON_NSPACES = NO
# If this flag is set to YES, the name of an unnamed parameter in a declaration
# will be determined by the corresponding definition. By default unnamed
# parameters remain unnamed in the output.
# The default value is: YES.
RESOLVE_UNNAMED_PARAMS = YES
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
# undocumented members inside documented classes or files. If set to NO these # undocumented members inside documented classes or files. If set to NO these
# members will be included in the various overviews, but no documentation # members will be included in the various overviews, but no documentation
@ -542,14 +595,22 @@ HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # With the correct setting of option CASE_SENSE_NAMES doxygen will better be
# names in lower-case letters. If set to YES, upper-case letters are also # able to match the capabilities of the underlying filesystem. In case the
# allowed. This is useful if you have classes or files whose names only differ # filesystem is case sensitive (i.e. it supports files in the same directory
# in case and if your file system supports case sensitive file names. Windows # whose names only differ in casing), the option must be set to YES to properly
# (including Cygwin) ands Mac users are advised to set this option to NO. # deal with such files in case they appear in the input. For filesystems that
# The default value is: system dependent. # are not case sensitive the option should be set to NO to properly deal with
# output files written for symbols that only differ in casing, such as for two
# classes, one named CLASS and the other named Class, and to also support
# references to files without having to specify the exact matching casing. On
# Windows (including Cygwin) and MacOS, users should typically set this option
# to NO, whereas on Linux or other Unix flavors it should typically be set to
# YES.
# Possible values are: SYSTEM, NO and YES.
# The default value is: SYSTEM.
CASE_SENSE_NAMES = YES CASE_SENSE_NAMES = SYSTEM
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
# their full class and namespace scopes in the documentation. If set to YES, the # their full class and namespace scopes in the documentation. If set to YES, the
@ -565,6 +626,12 @@ HIDE_SCOPE_NAMES = NO
HIDE_COMPOUND_REFERENCE= NO HIDE_COMPOUND_REFERENCE= NO
# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
# will show which file needs to be included to use the class.
# The default value is: YES.
SHOW_HEADERFILE = NO
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file. # the files that are included by a file in the documentation of that file.
# The default value is: YES. # The default value is: YES.
@ -722,7 +789,8 @@ FILE_VERSION_FILTER =
# output files in an output format independent way. To create the layout file # output files in an output format independent way. To create the layout file
# that represents doxygen's defaults, run doxygen with the -l option. You can # that represents doxygen's defaults, run doxygen with the -l option. You can
# optionally specify a file name after the option, if omitted DoxygenLayout.xml # optionally specify a file name after the option, if omitted DoxygenLayout.xml
# will be used as the name of the layout file. # will be used as the name of the layout file. See also section "Changing the
# layout of pages" for information.
# #
# Note that if you run doxygen from a directory containing a file called # Note that if you run doxygen from a directory containing a file called
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
@ -768,24 +836,35 @@ WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES WARN_IF_UNDOCUMENTED = YES
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
# potential errors in the documentation, such as not documenting some parameters # potential errors in the documentation, such as documenting some parameters in
# in a documented function, or documenting parameters that don't exist or using # a documented function twice, or documenting parameters that don't exist or
# markup commands wrongly. # using markup commands wrongly.
# The default value is: YES. # The default value is: YES.
WARN_IF_DOC_ERROR = YES WARN_IF_DOC_ERROR = YES
# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
# function parameter documentation. If set to NO, doxygen will accept that some
# parameters have no documentation without warning.
# The default value is: YES.
WARN_IF_INCOMPLETE_DOC = YES
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return # are documented, but have no documentation for their parameters or return
# value. If set to NO, doxygen will only warn about wrong or incomplete # value. If set to NO, doxygen will only warn about wrong parameter
# parameter documentation, but not about the absence of documentation. If # documentation, but not about the absence of documentation. If EXTRACT_ALL is
# EXTRACT_ALL is set to YES then this flag will automatically be disabled. # set to YES then this flag will automatically be disabled. See also
# WARN_IF_INCOMPLETE_DOC
# The default value is: NO. # The default value is: NO.
WARN_NO_PARAMDOC = YES WARN_NO_PARAMDOC = YES
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
# a warning is encountered. # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
# at the end of the doxygen process doxygen will return with a non-zero status.
# Possible values are: NO, YES and FAIL_ON_WARNINGS.
# The default value is: NO. # The default value is: NO.
WARN_AS_ERROR = NO WARN_AS_ERROR = NO
@ -796,13 +875,27 @@ WARN_AS_ERROR = NO
# and the warning text. Optionally the format may contain $version, which will # and the warning text. Optionally the format may contain $version, which will
# be replaced by the version of the file (if it could be obtained via # be replaced by the version of the file (if it could be obtained via
# FILE_VERSION_FILTER) # FILE_VERSION_FILTER)
# See also: WARN_LINE_FORMAT
# The default value is: $file:$line: $text. # The default value is: $file:$line: $text.
WARN_FORMAT = "$file:$line: $text" WARN_FORMAT = "$file:$line: $text"
# In the $text part of the WARN_FORMAT command it is possible that a reference
# to a more specific place is given. To make it easier to jump to this place
# (outside of doxygen) the user can define a custom "cut" / "paste" string.
# Example:
# WARN_LINE_FORMAT = "'vi $file +$line'"
# See also: WARN_FORMAT
# The default value is: at line $line of file $file.
WARN_LINE_FORMAT = "at line $line of file $file"
# The WARN_LOGFILE tag can be used to specify a file to which warning and error # The WARN_LOGFILE tag can be used to specify a file to which warning and error
# messages should be written. If left blank the output is written to standard # messages should be written. If left blank the output is written to standard
# error (stderr). # error (stderr). In case the file specified cannot be opened for writing the
# warning and error messages are written to standard error. When as file - is
# specified the warning and error messages are written to standard output
# (stdout).
WARN_LOGFILE = "@GLFW_BINARY_DIR@/docs/warnings.txt" WARN_LOGFILE = "@GLFW_BINARY_DIR@/docs/warnings.txt"
@ -821,12 +914,23 @@ INPUT = @GLFW_DOXYGEN_INPUT@
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv # libiconv (or the iconv built into libc) for the transcoding. See the libiconv
# documentation (see: https://www.gnu.org/software/libiconv/) for the list of # documentation (see:
# possible encodings. # https://www.gnu.org/software/libiconv/) for the list of possible encodings.
# See also: INPUT_FILE_ENCODING
# The default value is: UTF-8. # The default value is: UTF-8.
INPUT_ENCODING = UTF-8 INPUT_ENCODING = UTF-8
# This tag can be used to specify the character encoding of the source files
# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify
# character encoding on a per file pattern basis. Doxygen will compare the file
# name with each pattern and apply the encoding instead of the default
# INPUT_ENCODING) if there is a match. The character encodings are a list of the
# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding
# "INPUT_ENCODING" for further information on supported encodings.
INPUT_FILE_ENCODING =
# If the value of the INPUT tag contains directories, you can use the # If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
# *.h) to filter out the source-files in the directories. # *.h) to filter out the source-files in the directories.
@ -835,12 +939,14 @@ INPUT_ENCODING = UTF-8
# need to set EXTENSION_MAPPING for the extension otherwise the files are not # need to set EXTENSION_MAPPING for the extension otherwise the files are not
# read by doxygen. # read by doxygen.
# #
# Note the list of default checked file patterns might differ from the list of
# default file extension mappings.
#
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, # *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), # *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen # comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
# *.vhdl, *.ucf, *.qsf and *.ice. # *.vhdl, *.ucf, *.qsf and *.ice.
FILE_PATTERNS = *.h *.dox FILE_PATTERNS = *.h *.dox
@ -880,7 +986,7 @@ EXCLUDE_PATTERNS =
# (namespaces, classes, functions, etc.) that should be excluded from the # (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the # output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass, # wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test # ANamespace::AClass, ANamespace::*Test
# #
# Note that the wildcards are matched against the file with absolute path, so to # Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/* # exclude all test directories use the pattern */test/*
@ -928,6 +1034,11 @@ IMAGE_PATH =
# code is scanned, but not when the output code is generated. If lines are added # code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly. # or removed, the anchors will not be placed correctly.
# #
# Note that doxygen will use the data processed and written to standard output
# for further processing, therefore nothing else, like debug statements or used
# commands (so in case of a Windows batch file always use @echo OFF), should be
# written to standard output.
#
# Note that for custom extensions or not directly supported extensions you also # Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not # need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen. # properly processed by doxygen.
@ -969,6 +1080,15 @@ FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE = USE_MDFILE_AS_MAINPAGE =
# The Fortran standard specifies that for fixed formatted Fortran code all
# characters from position 72 are to be considered as comment. A common
# extension is to allow longer lines before the automatic comment starts. The
# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can
# be processed before the automatic comment starts.
# Minimum value: 7, maximum value: 10000, default value: 72.
FORTRAN_COMMENT_AFTER = 72
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Configuration options related to source browsing # Configuration options related to source browsing
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@ -1163,9 +1283,26 @@ HTML_EXTRA_STYLESHEET = "@GLFW_SOURCE_DIR@/docs/extra.css"
HTML_EXTRA_FILES = "@GLFW_SOURCE_DIR@/docs/spaces.svg" HTML_EXTRA_FILES = "@GLFW_SOURCE_DIR@/docs/spaces.svg"
# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
# should be rendered with a dark or light theme. Default setting AUTO_LIGHT
# enables light output unless the user preference is dark output. Other options
# are DARK to always use dark mode, LIGHT to always use light mode, AUTO_DARK to
# default to dark mode unless the user prefers light mode, and TOGGLE to let the
# user toggle between dark and light mode via a button.
# Possible values are: LIGHT Always generate light output., DARK Always generate
# dark output., AUTO_LIGHT Automatically set the mode according to the user
# preference, use light mode if no preference is set (the default)., AUTO_DARK
# Automatically set the mode according to the user preference, use dark mode if
# no preference is set. and TOGGLE Allow to user to switch between light and
# dark mode via a button..
# The default value is: AUTO_LIGHT.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE = LIGHT
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to # will adjust the colors in the style sheet and background images according to
# this color. Hue is specified as an angle on a colorwheel, see # this color. Hue is specified as an angle on a color-wheel, see
# https://en.wikipedia.org/wiki/Hue for more information. For instance the value # https://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again. # purple, and 360 is red again.
@ -1175,7 +1312,7 @@ HTML_EXTRA_FILES = "@GLFW_SOURCE_DIR@/docs/spaces.svg"
HTML_COLORSTYLE_HUE = 220 HTML_COLORSTYLE_HUE = 220
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
# in the HTML output. For a value of 0 the output will use grayscales only. A # in the HTML output. For a value of 0 the output will use gray-scales only. A
# value of 255 will produce the most vivid colors. # value of 255 will produce the most vivid colors.
# Minimum value: 0, maximum value: 255, default value: 100. # Minimum value: 0, maximum value: 255, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
@ -1236,10 +1373,11 @@ HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files will be # If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development # generated that can be used as input for Apple's Xcode 3 integrated development
# environment (see: https://developer.apple.com/xcode/), introduced with OSX # environment (see:
# 10.5 (Leopard). To create a documentation set, doxygen will generate a # https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
# Makefile in the HTML output directory. Running make will produce the docset in # create a documentation set, doxygen will generate a Makefile in the HTML
# that directory and running make install will install the docset in # output directory. Running make will produce the docset in that directory and
# running make install will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy # startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
# genXcode/_index.html for more information. # genXcode/_index.html for more information.
@ -1256,6 +1394,13 @@ GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs" DOCSET_FEEDNAME = "Doxygen generated docs"
# This tag determines the URL of the docset feed. A documentation feed provides
# an umbrella under which multiple documentation sets from a single provider
# (such as a company or product suite) can be grouped.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_FEEDURL =
# This tag specifies a string that should uniquely identify the documentation # This tag specifies a string that should uniquely identify the documentation
# set bundle. This should be a reverse domain-name style string, e.g. # set bundle. This should be a reverse domain-name style string, e.g.
# com.mycompany.MyDocSet. Doxygen will append .docset to the name. # com.mycompany.MyDocSet. Doxygen will append .docset to the name.
@ -1281,8 +1426,12 @@ DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The # additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on # on Windows. In the beginning of 2021 Microsoft took the original page, with
# Windows. # a.o. the download links, offline the HTML help workshop was already many years
# in maintenance mode). You can download the HTML help workshop from the web
# archives at Installation executable (see:
# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
# #
# The HTML Help Workshop contains a compiler that can convert all HTML output # The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
@ -1312,7 +1461,7 @@ CHM_FILE =
HHC_LOCATION = HHC_LOCATION =
# The GENERATE_CHI flag controls if a separate .chi index file is generated # The GENERATE_CHI flag controls if a separate .chi index file is generated
# (YES) or that it should be included in the master .chm file (NO). # (YES) or that it should be included in the main .chm file (NO).
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES. # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
@ -1357,7 +1506,8 @@ QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace # Project output. For more information please see Qt Help Project / Namespace
# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # (see:
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project. # The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES. # This tag requires that the tag GENERATE_QHP is set to YES.
@ -1365,8 +1515,8 @@ QHP_NAMESPACE = org.doxygen.Project
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual # Help Project output. For more information please see Qt Help Project / Virtual
# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- # Folders (see:
# folders). # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
# The default value is: doc. # The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES. # This tag requires that the tag GENERATE_QHP is set to YES.
@ -1374,16 +1524,16 @@ QHP_VIRTUAL_FOLDER = doc
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom # filter to add. For more information please see Qt Help Project / Custom
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- # Filters (see:
# filters). # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES. # This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME = QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom # custom filter to add. For more information please see Qt Help Project / Custom
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- # Filters (see:
# filters). # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES. # This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS = QHP_CUST_FILTER_ATTRS =
@ -1395,9 +1545,9 @@ QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS =
# The QHG_LOCATION tag can be used to specify the location of Qt's # The QHG_LOCATION tag can be used to specify the location (absolute path
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
# generated .qhp file. # run qhelpgenerator on the generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES. # This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION = QHG_LOCATION =
@ -1440,16 +1590,28 @@ DISABLE_INDEX = NO
# to work a browser that supports JavaScript, DHTML, CSS and frames is required # to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the # (i.e. any modern browser). Windows users are probably better off using the
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
# further fine-tune the look of the index. As an example, the default style # further fine tune the look of the index (see "Fine-tuning the output"). As an
# sheet generated by doxygen has an example that shows how to put an image at # example, the default style sheet generated by doxygen has an example that
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has # shows how to put an image at the root of the tree instead of the PROJECT_NAME.
# the same information as the tab index, you could consider setting # Since the tree basically has the same information as the tab index, you could
# DISABLE_INDEX to YES when enabling this option. # consider setting DISABLE_INDEX to YES when enabling this option.
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO GENERATE_TREEVIEW = NO
# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
# area (value NO) or if it should extend to the full height of the window (value
# YES). Setting this to YES gives a layout similar to
# https://docs.readthedocs.io with more room for contents, but less room for the
# project logo, title, and description. If either GENERATE_TREEVIEW or
# DISABLE_INDEX is set to NO, this option has no effect.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
FULL_SIDEBAR = NO
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation. # doxygen will group on one line in the generated HTML documentation.
# #
@ -1474,12 +1636,19 @@ TREEVIEW_WIDTH = 300
EXT_LINKS_IN_WINDOW = NO EXT_LINKS_IN_WINDOW = NO
# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
# addresses.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
OBFUSCATE_EMAILS = YES
# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg # If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see # tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for # https://inkscape.org) to generate formulas as SVG images instead of PNGs for
# the HTML output. These images will generally look nicer at scaled resolutions. # the HTML output. These images will generally look nicer at scaled resolutions.
# Possible values are: png The default and svg Looks nicer but requires the # Possible values are: png (the default) and svg (looks nicer but requires the
# pdf2svg tool. # pdf2svg or inkscape tool).
# The default value is: png. # The default value is: png.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
@ -1494,17 +1663,6 @@ HTML_FORMULA_FORMAT = png
FORMULA_FONTSIZE = 10 FORMULA_FONTSIZE = 10
# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
# generated for formulas are transparent PNGs. Transparent PNGs are not
# supported properly for IE 6.0, but are supported on all modern browsers.
#
# Note that when changing this option you need to delete any form_*.png files in
# the HTML output directory before the changes have effect.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_TRANSPARENT = YES
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands # The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
# to create new LaTeX commands to be used in formulas as building blocks. See # to create new LaTeX commands to be used in formulas as building blocks. See
# the section "Including formulas" for details. # the section "Including formulas" for details.
@ -1522,11 +1680,29 @@ FORMULA_MACROFILE =
USE_MATHJAX = NO USE_MATHJAX = NO
# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
# Note that the different versions of MathJax have different requirements with
# regards to the different settings, so it is possible that also other MathJax
# settings have to be changed when switching between the different MathJax
# versions.
# Possible values are: MathJax_2 and MathJax_3.
# The default value is: MathJax_2.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_VERSION = MathJax_2
# When MathJax is enabled you can set the default output format to be used for # When MathJax is enabled you can set the default output format to be used for
# the MathJax output. See the MathJax site (see: # the MathJax output. For more details about the output format see MathJax
# http://docs.mathjax.org/en/latest/output.html) for more details. # version 2 (see:
# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
# (see:
# http://docs.mathjax.org/en/latest/web/components/output.html).
# Possible values are: HTML-CSS (which is slower, but has the best # Possible values are: HTML-CSS (which is slower, but has the best
# compatibility), NativeMML (i.e. MathML) and SVG. # compatibility. This is the name for Mathjax version 2, for MathJax version 3
# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
# is the name for Mathjax version 3, for MathJax version 2 this will be
# translated into HTML-CSS) and SVG.
# The default value is: HTML-CSS. # The default value is: HTML-CSS.
# This tag requires that the tag USE_MATHJAX is set to YES. # This tag requires that the tag USE_MATHJAX is set to YES.
@ -1539,22 +1715,29 @@ MATHJAX_FORMAT = HTML-CSS
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
# Content Delivery Network so you can quickly see the result without installing # Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of # MathJax. However, it is strongly recommended to install a local copy of
# MathJax from https://www.mathjax.org before deployment. # MathJax from https://www.mathjax.org before deployment. The default value is:
# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. # - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
# This tag requires that the tag USE_MATHJAX is set to YES. # This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2 MATHJAX_RELPATH =
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example # extension names that should be enabled during MathJax rendering. For example
# for MathJax version 2 (see
# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
# For example for MathJax version 3 (see
# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
# MATHJAX_EXTENSIONS = ams
# This tag requires that the tag USE_MATHJAX is set to YES. # This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_EXTENSIONS = MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site # of code that will be used on startup of the MathJax code. See the MathJax site
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # (see:
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
# example see the documentation. # example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES. # This tag requires that the tag USE_MATHJAX is set to YES.
@ -1601,7 +1784,8 @@ SERVER_BASED_SEARCH = NO
# #
# Doxygen ships with an example indexer (doxyindexer) and search engine # Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library # (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: https://xapian.org/). # Xapian (see:
# https://xapian.org/).
# #
# See the section "External Indexing and Searching" for details. # See the section "External Indexing and Searching" for details.
# The default value is: NO. # The default value is: NO.
@ -1614,8 +1798,9 @@ EXTERNAL_SEARCH = NO
# #
# Doxygen ships with an example indexer (doxyindexer) and search engine # Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library # (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: https://xapian.org/). See the section "External Indexing and # Xapian (see:
# Searching" for details. # https://xapian.org/). See the section "External Indexing and Searching" for
# details.
# This tag requires that the tag SEARCHENGINE is set to YES. # This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL = SEARCHENGINE_URL =
@ -1724,29 +1909,31 @@ PAPER_TYPE = a4
EXTRA_PACKAGES = EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the # The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
# generated LaTeX document. The header should contain everything until the first # the generated LaTeX document. The header should contain everything until the
# chapter. If it is left blank doxygen will generate a standard header. See # first chapter. If it is left blank doxygen will generate a standard header. It
# section "Doxygen usage" for information on how to let doxygen write the # is highly recommended to start with a default header using
# default header to a separate file. # doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
# and then modify the file new_header.tex. See also section "Doxygen usage" for
# information on how to generate the default header that doxygen normally uses.
# #
# Note: Only use a user-defined header if you know what you are doing! The # Note: Only use a user-defined header if you know what you are doing!
# following commands have a special meaning inside the header: $title, # Note: The header is subject to change so you typically have to regenerate the
# $datetime, $date, $doxygenversion, $projectname, $projectnumber, # default header when upgrading to a newer version of doxygen. The following
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty # commands have a special meaning inside the header (and footer): For a
# string, for the replacement values of the other commands the user is referred # description of the possible markers and block names see the documentation.
# to HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES. # This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER = LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the # The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
# generated LaTeX document. The footer should contain everything after the last # the generated LaTeX document. The footer should contain everything after the
# chapter. If it is left blank doxygen will generate a standard footer. See # last chapter. If it is left blank doxygen will generate a standard footer. See
# LATEX_HEADER for more information on how to generate a default footer and what # LATEX_HEADER for more information on how to generate a default footer and what
# special commands can be used inside the footer. # special commands can be used inside the footer. See also section "Doxygen
# # usage" for information on how to generate the default footer that doxygen
# Note: Only use a user-defined footer if you know what you are doing! # normally uses. Note: Only use a user-defined footer if you know what you are
# doing!
# This tag requires that the tag GENERATE_LATEX is set to YES. # This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER = LATEX_FOOTER =
@ -1779,9 +1966,11 @@ LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate # If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
# the PDF file directly from the LaTeX files. Set this option to YES, to get a # specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
# higher quality PDF documentation. # files. Set this option to YES, to get a higher quality PDF documentation.
#
# See also section LATEX_CMD_NAME for selecting the engine.
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES. # This tag requires that the tag GENERATE_LATEX is set to YES.
@ -1789,8 +1978,7 @@ USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
# command to the generated LaTeX files. This will instruct LaTeX to keep running # command to the generated LaTeX files. This will instruct LaTeX to keep running
# if errors occur, instead of asking the user for help. This option is also used # if errors occur, instead of asking the user for help.
# when generating formulas in HTML.
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES. # This tag requires that the tag GENERATE_LATEX is set to YES.
@ -2065,7 +2253,8 @@ SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that # The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by the # contain include files that are not input files but should be processed by the
# preprocessor. # preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
# RECURSIVE has no effect here.
# This tag requires that the tag SEARCH_INCLUDES is set to YES. # This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH = INCLUDE_PATH =
@ -2199,35 +2388,50 @@ HAVE_DOT = NO
DOT_NUM_THREADS = 0 DOT_NUM_THREADS = 0
# When you want a differently looking font in the dot files that doxygen # DOT_COMMON_ATTR is common attributes for nodes, edges and labels of
# generates you can specify the font name using DOT_FONTNAME. You need to make # subgraphs. When you want a differently looking font in the dot files that
# sure dot is able to find the font, which can be done by putting it in a # doxygen generates you can specify fontname, fontcolor and fontsize attributes.
# standard location or by setting the DOTFONTPATH environment variable or by # For details please see <a href=https://graphviz.org/doc/info/attrs.html>Node,
# setting DOT_FONTPATH to the directory containing the font. # Edge and Graph Attributes specification</a> You need to make sure dot is able
# The default value is: Helvetica. # to find the font, which can be done by putting it in a standard location or by
# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
# directory containing the font. Default graphviz fontsize is 14.
# The default value is: fontname=Helvetica,fontsize=10.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTNAME = Helvetica DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10"
# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of # DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can
# dot graphs. # add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. <a
# Minimum value: 4, maximum value: 24, default value: 10. # href=https://graphviz.org/doc/info/arrows.html>Complete documentation about
# arrows shapes.</a>
# The default value is: labelfontname=Helvetica,labelfontsize=10.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTSIZE = 10 DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10"
# By default doxygen will tell dot to use the default font as specified with # DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes
# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set # around nodes set 'shape=plain' or 'shape=plaintext' <a
# the path where dot can find it using this tag. # href=https://www.graphviz.org/doc/info/shapes.html>Shapes specification</a>
# The default value is: shape=box,height=0.2,width=0.4.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
# You can set the path where dot can find font specified with fontname in
# DOT_COMMON_ATTR and others dot attributes.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTPATH = DOT_FONTPATH =
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for # If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
# each documented class showing the direct and indirect inheritance relations. # graph for each documented class showing the direct and indirect inheritance
# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. # relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
# to TEXT the direct and indirect inheritance relations will be shown as texts /
# links.
# Possible values are: NO, YES, TEXT and GRAPH.
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
CLASS_GRAPH = YES CLASS_GRAPH = YES
@ -2241,7 +2445,8 @@ CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES COLLABORATION_GRAPH = YES
# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for # If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
# groups, showing the direct groups dependencies. # groups, showing the direct groups dependencies. See also the chapter Grouping
# in the manual.
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
@ -2264,10 +2469,32 @@ UML_LOOK = NO
# but if the number exceeds 15, the total amount of fields shown is limited to # but if the number exceeds 15, the total amount of fields shown is limited to
# 10. # 10.
# Minimum value: 0, maximum value: 100, default value: 10. # Minimum value: 0, maximum value: 100, default value: 10.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag UML_LOOK is set to YES.
UML_LIMIT_NUM_FIELDS = 10 UML_LIMIT_NUM_FIELDS = 10
# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
# tag is set to YES, doxygen will add type and arguments for attributes and
# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
# will not generate fields with class member information in the UML graphs. The
# class diagrams will look similar to the default class diagrams but using UML
# notation for the relationships.
# Possible values are: NO, YES and NONE.
# The default value is: NO.
# This tag requires that the tag UML_LOOK is set to YES.
DOT_UML_DETAILS = NO
# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
# to display on a single line. If the actual line length exceeds this threshold
# significantly it will wrapped across multiple lines. Some heuristics are apply
# to avoid ugly line breaks.
# Minimum value: 0, maximum value: 1000, default value: 17.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_WRAP_THRESHOLD = 17
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and # If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
# collaboration graphs will show the relations between templates and their # collaboration graphs will show the relations between templates and their
# instances. # instances.
@ -2334,6 +2561,13 @@ GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES DIRECTORY_GRAPH = YES
# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
# of child directories generated in directory dependency graphs by dot.
# Minimum value: 1, maximum value: 25, default value: 1.
# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
DIR_GRAPH_MAX_DEPTH = 1
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. For an explanation of the image formats see the section # generated by dot. For an explanation of the image formats see the section
# output formats in the documentation of the dot tool (Graphviz (see: # output formats in the documentation of the dot tool (Graphviz (see:
@ -2387,10 +2621,10 @@ MSCFILE_DIRS =
DIAFILE_DIRS = DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the # When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
# path where java can find the plantuml.jar file. If left blank, it is assumed # path where java can find the plantuml.jar file or to the filename of jar file
# PlantUML is not used or called during a preprocessing step. Doxygen will # to be used. If left blank, it is assumed PlantUML is not used or called during
# generate a warning when it encounters a \startuml command in this case and # a preprocessing step. Doxygen will generate a warning when it encounters a
# will not generate output for the diagram. # \startuml command in this case and will not generate output for the diagram.
PLANTUML_JAR_PATH = PLANTUML_JAR_PATH =
@ -2428,18 +2662,6 @@ DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0 MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, because dot on Windows does not seem
# to support this out of the box.
#
# Warning: Depending on the platform used, enabling this option may lead to
# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
# read).
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_TRANSPARENT = NO
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output # Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This # files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support # makes dot run faster, but since only newer versions of dot (>1.8.10) support
@ -2452,14 +2674,18 @@ DOT_MULTI_TARGETS = NO
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page # If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
# explaining the meaning of the various boxes and arrows in the dot generated # explaining the meaning of the various boxes and arrows in the dot generated
# graphs. # graphs.
# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
# graphical representation for inheritance and collaboration diagrams is used.
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
GENERATE_LEGEND = YES GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot # If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
# files that are used to generate the various graphs. # files that are used to generate the various graphs.
#
# Note: This setting is not only used for dot files but also for msc temporary
# files.
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES DOT_CLEANUP = YES

View File

@ -26,7 +26,7 @@ GLFW.
@endcode @endcode
This header defines all the constants and declares all the types and function This header defines all the constants and declares all the types and function
prototypes of the GLFW API. By default it also includes the OpenGL header from prototypes of the GLFW API. By default, it also includes the OpenGL header from
your development environment. See [option macros](@ref build_macros) below for your development environment. See [option macros](@ref build_macros) below for
how to select OpenGL ES headers and more. how to select OpenGL ES headers and more.
@ -57,7 +57,7 @@ macros that disable similar headers below it.
Both of these mechanisms depend on the extension loader header defining a known Both of these mechanisms depend on the extension loader header defining a known
macro. If yours doesn't or you don't know which one your users will pick, the macro. If yours doesn't or you don't know which one your users will pick, the
@ref GLFW_INCLUDE_NONE macro will explicitly to prevent the GLFW header from @ref GLFW_INCLUDE_NONE macro will explicitly prevent the GLFW header from
including the OpenGL header. This will also allow you to include the two including the OpenGL header. This will also allow you to include the two
headers in any order. headers in any order.

View File

@ -152,7 +152,7 @@ formats. If GLX 1.3 is not supported, @ref glfwInit will fail.
GLFW uses the `GLX_MESA_swap_control,` `GLX_EXT_swap_control` and GLFW uses the `GLX_MESA_swap_control,` `GLX_EXT_swap_control` and
`GLX_SGI_swap_control` extensions to provide vertical retrace synchronization `GLX_SGI_swap_control` extensions to provide vertical retrace synchronization
(or _vsync_), in that order of preference. Where none of these extension are (or _vsync_), in that order of preference. When none of these extensions are
available, calling @ref glfwSwapInterval will have no effect. available, calling @ref glfwSwapInterval will have no effect.
GLFW uses the `GLX_ARB_multisample` extension to create contexts with GLFW uses the `GLX_ARB_multisample` extension to create contexts with
@ -219,8 +219,8 @@ extension is unavailable, the `GLFW_CONTEXT_RELEASE_BEHAVIOR` hint will have no
effect and the context will always be flushed when released. effect and the context will always be flushed when released.
GLFW uses the `WGL_ARB_framebuffer_sRGB` and `WGL_EXT_framebuffer_sRGB` GLFW uses the `WGL_ARB_framebuffer_sRGB` and `WGL_EXT_framebuffer_sRGB`
extensions to provide support for sRGB framebuffers. Where both of these extensions to provide support for sRGB framebuffers. When both of these
extension are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect. extensions are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect.
@section compat_osx OpenGL on macOS @section compat_osx OpenGL on macOS

View File

@ -45,7 +45,7 @@ Linux and FreeBSD you will need a few extra packages.
To compile GLFW for X11, you need to have the X11 development packages To compile GLFW for X11, you need to have the X11 development packages
installed. They are not needed to build or run programs that use GLFW. installed. They are not needed to build or run programs that use GLFW.
On Debian and derivates like Ubuntu and Linux Mint the `xorg-dev` meta-package On Debian and derivatives like Ubuntu and Linux Mint the `xorg-dev` meta-package
pulls in the development packages for all of X11. pulls in the development packages for all of X11.
@code{.sh} @code{.sh}
@ -83,7 +83,7 @@ development packages installed. They are not needed to build or run programs th
GLFW. You will also need to set the @ref GLFW_BUILD_WAYLAND CMake option in the next GLFW. You will also need to set the @ref GLFW_BUILD_WAYLAND CMake option in the next
step when generating build files. step when generating build files.
On Debian and derivates like Ubuntu and Linux Mint you will need the `libwayland-dev`, On Debian and derivatives like Ubuntu and Linux Mint you will need the `libwayland-dev`,
`libxkbcommon-dev` and `wayland-protocols` packages and the `xorg-dev` meta-package. `libxkbcommon-dev` and `wayland-protocols` packages and the `xorg-dev` meta-package.
These will pull in all other dependencies. These will pull in all other dependencies.
@ -142,7 +142,7 @@ If you wish change any CMake variables in the list, press _Configure_ and then
_Generate_ to have the new values take effect. The variable list will be _Generate_ to have the new values take effect. The variable list will be
populated after the first configure step. populated after the first configure step.
By default GLFW will use X11 on Linux and other Unix-like systems other than macOS. To By default, GLFW will use X11 on Linux and other Unix-like systems other than macOS. To
include support for Wayland as well, set the @ref GLFW_BUILD_WAYLAND option in the GLFW include support for Wayland as well, set the @ref GLFW_BUILD_WAYLAND option in the GLFW
section of the variable list, then apply the new value as described above. section of the variable list, then apply the new value as described above.
@ -176,7 +176,7 @@ flag.
cmake -S path/to/glfw -B path/to/build -G Xcode cmake -S path/to/glfw -B path/to/build -G Xcode
@endcode @endcode
By default GLFW will use X11 on Linux and other Unix-like systems other By default, GLFW will use X11 on Linux and other Unix-like systems other
than macOS. To also include support for Wayland, set the @ref GLFW_BUILD_WAYLAND CMake than macOS. To also include support for Wayland, set the @ref GLFW_BUILD_WAYLAND CMake
option. option.
@ -263,12 +263,12 @@ build GLFW as a static library, `SHARED` to build it as a shared library
@anchor GLFW_BUILD_EXAMPLES @anchor GLFW_BUILD_EXAMPLES
__GLFW_BUILD_EXAMPLES__ determines whether the GLFW examples are built __GLFW_BUILD_EXAMPLES__ determines whether the GLFW examples are built
along with the library. This is enabled by default unless GLFW is being built along with the library. This is enabled by default unless GLFW is being built
as a sub-project of a larger CMake project. as a subproject of a larger CMake project.
@anchor GLFW_BUILD_TESTS @anchor GLFW_BUILD_TESTS
__GLFW_BUILD_TESTS__ determines whether the GLFW test programs are __GLFW_BUILD_TESTS__ determines whether the GLFW test programs are
built along with the library. This is enabled by default unless GLFW is being built along with the library. This is enabled by default unless GLFW is being
built as a sub-project of a larger CMake project. built as a subproject of a larger CMake project.
@anchor GLFW_BUILD_DOCS @anchor GLFW_BUILD_DOCS
__GLFW_BUILD_DOCS__ determines whether the GLFW documentation is built along __GLFW_BUILD_DOCS__ determines whether the GLFW documentation is built along
@ -358,7 +358,7 @@ For more details see the
@section compile_manual Compiling GLFW manually @section compile_manual Compiling GLFW manually
If you wish to compile GLFW without its CMake build environment then you will have to do If you wish to compile GLFW without its CMake build environment then you will have to do
at least some of the platform detection yourself. There are preprocessor macros for at least some platform-detection yourself. There are preprocessor macros for
enabling support for the platforms (window systems) available. There are also optional, enabling support for the platforms (window systems) available. There are also optional,
platform-specific macros for various features. platform-specific macros for various features.

View File

@ -61,7 +61,7 @@ information. The name and number of this chapter unfortunately varies between
versions and APIs, but has at times been named _Shared Objects and Multiple versions and APIs, but has at times been named _Shared Objects and Multiple
Contexts_. Contexts_.
GLFW comes with a barebones object sharing example program called `sharing`. GLFW comes with a bare-bones object sharing example program called `sharing`.
@subsection context_offscreen Offscreen contexts @subsection context_offscreen Offscreen contexts
@ -189,7 +189,7 @@ it suppresses the development environment's OpenGL or OpenGL ES header.
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
@endcode @endcode
Finally you need to initialize glad once you have a suitable current context. Finally, you need to initialize glad once you have a suitable current context.
@code @code
window = glfwCreateWindow(640, 480, "My Window", NULL, NULL); window = glfwCreateWindow(640, 480, "My Window", NULL, NULL);
@ -205,7 +205,7 @@ gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
Once glad has been loaded, you have access to all OpenGL core and extension Once glad has been loaded, you have access to all OpenGL core and extension
functions supported by both the context you created and the glad loader you functions supported by both the context you created and the glad loader you
generated and you are ready to start rendering. generated. After that, you are ready to start rendering.
You can specify a minimum required OpenGL or OpenGL ES version with You can specify a minimum required OpenGL or OpenGL ES version with
[context hints](@ref window_hints_ctx). If your needs are more complex, you can [context hints](@ref window_hints_ctx). If your needs are more complex, you can

View File

@ -24,7 +24,7 @@ All input callbacks receive a window handle. By using the
or objects from your callbacks. or objects from your callbacks.
To get a better feel for how the various events callbacks behave, run the To get a better feel for how the various events callbacks behave, run the
`events` test program. It register every callback supported by GLFW and prints `events` test program. It registers every callback supported by GLFW and prints
out all arguments provided for every event, along with time and sequence out all arguments provided for every event, along with time and sequence
information. information.
@ -123,9 +123,21 @@ void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod
} }
@endcode @endcode
The action is one of `GLFW_PRESS`, `GLFW_REPEAT` or `GLFW_RELEASE`. The key The action is one of `GLFW_PRESS`, `GLFW_REPEAT` or `GLFW_RELEASE`. Events with
will be `GLFW_KEY_UNKNOWN` if GLFW lacks a key token for it, for example `GLFW_PRESS` and `GLFW_RELEASE` actions are emitted for every key press. Most
_E-mail_ and _Play_ keys. keys will also emit events with `GLFW_REPEAT` actions while a key is held down.
Key events with `GLFW_REPEAT` actions are intended for text input. They are
emitted at the rate set in the user's keyboard settings. At most one key is
repeated even if several keys are held down. `GLFW_REPEAT` actions should not
be relied on to know which keys are being held down or to drive animation.
Instead you should either save the state of relevant keys based on `GLFW_PRESS`
and `GLFW_RELEASE` actions, or call @ref glfwGetKey, which provides basic cached
key state.
The key will be one of the existing [key tokens](@ref keys), or
`GLFW_KEY_UNKNOWN` if GLFW lacks a token for it, for example _E-mail_ and _Play_
keys.
The scancode is unique for every key, regardless of whether it has a key token. The scancode is unique for every key, regardless of whether it has a key token.
Scancodes are platform-specific but consistent over time, so keys will have Scancodes are platform-specific but consistent over time, so keys will have
@ -300,6 +312,16 @@ glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
This mode puts no limit on the motion of the cursor. This mode puts no limit on the motion of the cursor.
If you wish the cursor to be visible but confined to the content area of the
window, set the cursor mode to `GLFW_CURSOR_CAPTURED`.
@code
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_CAPTURED);
@endcode
The cursor will behave normally inside the content area but will not be able to
leave unless the window loses focus.
To exit out of either of these special modes, restore the `GLFW_CURSOR_NORMAL` To exit out of either of these special modes, restore the `GLFW_CURSOR_NORMAL`
cursor mode. cursor mode.
@ -307,6 +329,8 @@ cursor mode.
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
@endcode @endcode
If the cursor was disabled, this will move it back to its last visible position.
@anchor GLFW_RAW_MOUSE_MOTION @anchor GLFW_RAW_MOUSE_MOTION
@subsection raw_mouse_motion Raw mouse motion @subsection raw_mouse_motion Raw mouse motion
@ -370,7 +394,7 @@ sequential rows, starting from the top-left corner.
@subsubsection cursor_standard Standard cursor creation @subsubsection cursor_standard Standard cursor creation
A cursor with a [standard shape](@ref shapes) from the current system cursor A cursor with a [standard shape](@ref shapes) from the current system cursor
theme can be can be created with @ref glfwCreateStandardCursor. theme can be created with @ref glfwCreateStandardCursor.
@code @code
GLFWcursor* url_cursor = glfwCreateStandardCursor(GLFW_POINTING_HAND_CURSOR); GLFWcursor* url_cursor = glfwCreateStandardCursor(GLFW_POINTING_HAND_CURSOR);

View File

@ -162,7 +162,7 @@ GLFW can be compiled for more than one platform (window system) at once. This l
a single library binary support both X11 and Wayland on Linux and other Unix-like systems. a single library binary support both X11 and Wayland on Linux and other Unix-like systems.
You can control platform selection via the @ref GLFW_PLATFORM initialization hint. By You can control platform selection via the @ref GLFW_PLATFORM initialization hint. By
default this is set to @ref GLFW_ANY_PLATFORM, which will look for supported window default, this is set to @ref GLFW_ANY_PLATFORM, which will look for supported window
systems in order of priority and select the first one it finds. It can also be set to any systems in order of priority and select the first one it finds. It can also be set to any
specific platform to have GLFW only look for that one. specific platform to have GLFW only look for that one.
@ -269,9 +269,9 @@ This will destroy any remaining window, monitor and cursor objects, restore any
modified gamma ramps, re-enable the screensaver if it had been disabled and free modified gamma ramps, re-enable the screensaver if it had been disabled and free
any other resources allocated by GLFW. any other resources allocated by GLFW.
Once the library is terminated, it is as if it had never been initialized and Once the library is terminated, it is as if it had never been initialized, therefore
you will need to initialize it again before being able to use GLFW. If the you will need to initialize it again before being able to use GLFW. If the
library was not initialized or had already been terminated, it return library was not initialized or had already been terminated, it returns
immediately. immediately.
@ -391,14 +391,14 @@ which monitor the window is currently considered to be on.
This section describes the conditions under which GLFW can be expected to This section describes the conditions under which GLFW can be expected to
function, barring bugs in the operating system or drivers. Use of GLFW outside function, barring bugs in the operating system or drivers. Use of GLFW outside
of these limits may work on some platforms, or on some machines, or some of the these limits may work on some platforms, or on some machines, or some of the
time, or on some versions of GLFW, but it may break at any time and this will time, or on some versions of GLFW, but it may break at any time and this will
not be considered a bug. not be considered a bug.
@subsection lifetime Pointer lifetimes @subsection lifetime Pointer lifetimes
GLFW will never free any pointer you provide to it and you must never free any GLFW will never free any pointer you provide to it, and you must never free any
pointer it provides to you. pointer it provides to you.
Many GLFW functions return pointers to dynamically allocated structures, strings Many GLFW functions return pointers to dynamically allocated structures, strings
@ -602,15 +602,15 @@ The format of the string is as follows:
- The names of the always supported context creation APIs EGL and OSMesa - 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 - Any additional compile-time options, APIs and (on Windows) what compiler was used
For example, GLFW 3.4 compiled as a DLL for Windows with MinGW may have a version string For example, compiling GLFW 3.4 with MinGW as a DLL for Windows, may result in a version string
like this: like this:
@code @code
3.4.0 Win32 WGL Null EGL OSMesa MinGW DLL 3.4.0 Win32 WGL Null EGL OSMesa MinGW DLL
@endcode @endcode
While GLFW compiled as as static library for Linux with both Wayland and X11 enabled may Compiling GLFW as a static library for Linux, with both Wayland and X11 enabled, may
have a version string like this: result in a version string like this:
@code @code
3.4.0 Wayland X11 GLX Null EGL OSMesa monotonic 3.4.0 Wayland X11 GLX Null EGL OSMesa monotonic

View File

@ -138,7 +138,7 @@ glfwGetMonitorPhysicalSize(monitor, &width_mm, &height_mm);
@endcode @endcode
While this can be used to calculate the raw DPI of a monitor, this is often not While this can be used to calculate the raw DPI of a monitor, this is often not
useful. Instead use the [monitor content scale](@ref monitor_scale) and useful. Instead, use the [monitor content scale](@ref monitor_scale) and
[window content scale](@ref window_scale) to scale your content. [window content scale](@ref window_scale) to scale your content.
@ -261,7 +261,7 @@ To experiment with gamma correction via the @ref glfwSetGamma function, run the
`gamma` test program. `gamma` test program.
@note The software controlled gamma ramp is applied _in addition_ to the @note The software controlled gamma ramp is applied _in addition_ to the
hardware gamma correction, which today is usually an approximation of sRGB hardware gamma correction, which today is typically an approximation of sRGB
gamma. This means that setting a perfectly linear ramp, or gamma 1.0, will gamma. This means that setting a perfectly linear ramp, or gamma 1.0, will
produce the default (usually sRGB-like) behavior. produce the default (usually sRGB-like) behavior.

View File

@ -243,7 +243,7 @@ while (!glfwWindowShouldClose(window))
@endcode @endcode
The close callback no longer returns a value. Instead, it is called after the The close callback no longer returns a value. Instead, it is called after the
close flag has been set so it can override its value, if it chooses to, before close flag has been set, so it can optionally override its value, before
event processing completes. You may however not call @ref glfwDestroyWindow event processing completes. You may however not call @ref glfwDestroyWindow
from the close callback (or any other window related callback). from the close callback (or any other window related callback).
@ -350,11 +350,11 @@ from a repeat. Note that @ref glfwGetKey still returns only `GLFW_PRESS` or
GLFW 3 key tokens map to physical keys, unlike in GLFW 2 where they mapped to GLFW 3 key tokens map to physical keys, unlike in GLFW 2 where they mapped to
the values generated by the current keyboard layout. The tokens are named the values generated by the current keyboard layout. The tokens are named
according to the values they would have using the standard US layout, but this according to the values they would have in the standard US layout, but this
is only a convenience, as most programmers are assumed to know that layout. is only a convenience, as most programmers are assumed to know that layout.
This means that (for example) `GLFW_KEY_LEFT_BRACKET` is always a single key and This means that (for example) `GLFW_KEY_LEFT_BRACKET` is always a single key and
is the same key in the same place regardless of what keyboard layouts the users is the same key in the same place regardless of what keyboard layouts the users
of your program has. of your program have.
The key input facility was never meant for text input, although using it that The key input facility was never meant for text input, although using it that
way worked slightly better in GLFW 2. If you were using it to input text, you way worked slightly better in GLFW 2. If you were using it to input text, you

View File

@ -21,7 +21,7 @@ support for a given platform is compiled in with @ref glfwPlatformSupported.
GLFW now provides the standard cursor shapes @ref GLFW_RESIZE_NWSE_CURSOR and GLFW now provides the standard cursor shapes @ref GLFW_RESIZE_NWSE_CURSOR and
@ref GLFW_RESIZE_NESW_CURSOR for diagonal resizing, @ref GLFW_RESIZE_ALL_CURSOR @ref GLFW_RESIZE_NESW_CURSOR for diagonal resizing, @ref GLFW_RESIZE_ALL_CURSOR
for omni-directional resizing and @ref GLFW_NOT_ALLOWED_CURSOR for showing an for omnidirectional resizing and @ref GLFW_NOT_ALLOWED_CURSOR for showing an
action is not allowed. action is not allowed.
Unlike the original set, these shapes may not be available everywhere and Unlike the original set, these shapes may not be available everywhere and
@ -43,6 +43,12 @@ to whatever window is behind it. This can also be changed after window
creation with the matching [window attribute](@ref GLFW_MOUSE_PASSTHROUGH_attrib). creation with the matching [window attribute](@ref GLFW_MOUSE_PASSTHROUGH_attrib).
@subsubsection wayland_app_id_34 Wayland app_id specification
GLFW now supports specifying the app_id for a Wayland window using the
[GLFW_WAYLAND_APP_ID](@ref GLFW_WAYLAND_APP_ID_hint) window hint string.
@subsubsection features_34_angle_backend Support for ANGLE rendering backend selection @subsubsection features_34_angle_backend Support for ANGLE rendering backend selection
GLFW now provides the GLFW now provides the
@ -52,6 +58,14 @@ requesting a specific rendering backend when using
contexts. contexts.
@subsubsection captured_cursor_34 Captured cursor mode
GLFW now supports confining the cursor to the window content area with the @ref
GLFW_CURSOR_CAPTURED cursor mode.
For more information see @ref cursor_mode.
@subsubsection features_34_init_allocator Support for custom memory allocator @subsubsection features_34_init_allocator Support for custom memory allocator
GLFW now supports plugging a custom memory allocator at initialization with @ref GLFW now supports plugging a custom memory allocator at initialization with @ref
@ -62,6 +76,14 @@ function pointers corresponding to the standard library functions `malloc`,
For more information see @ref init_allocator. For more information see @ref init_allocator.
@subsubsection features_34_position_hint Window hints for initial position
GLFW now provides the @ref GLFW_POSITION_X and @ref GLFW_POSITION_Y window hints for
specifying the initial position of the window. This removes the need to create a hidden
window, move it and then show it. The default value of these hints is
`GLFW_ANY_POSITION`, which selects the previous behavior.
@subsubsection features_34_win32_keymenu Support for keyboard access to Windows window menu @subsubsection features_34_win32_keymenu Support for keyboard access to Windows window menu
GLFW now provides the GLFW now provides the
@ -78,7 +100,7 @@ applications.
Because GLFW now supports runtime selection of platform (window system), a library binary Because GLFW now supports runtime selection of platform (window system), a library binary
may export native access functions for multiple platforms. Starting with version 3.4 you may export native access functions for multiple platforms. Starting with version 3.4 you
must not assume that GLFW is running on a platform just because it exports native access must not assume that GLFW is running on a platform just because it exports native access
functions for it. After initialization you can query the selected platform with @ref functions for it. After initialization, you can query the selected platform with @ref
glfwGetPlatform. glfwGetPlatform.
@ -104,7 +126,20 @@ To work around this, call any joystick function before waiting for events, for
example by setting a [joystick callback](@ref joystick_event). example by setting a [joystick callback](@ref joystick_event).
@subsubsection standalone_34 Tests and examples are disabled when built as a sub-project @subsubsection wayland_alpha_34 Frambuffer may lack alpha channel on older Wayland systems
On Wayland, when creating an EGL context on a machine lacking the new
`EGL_EXT_present_opaque` extension, the @ref GLFW_ALPHA_BITS window hint will be
ignored and the framebuffer will have no alpha channel. This is because some
Wayland compositors treat any buffer with an alpha channel as per-pixel
transparent.
If you want a per-pixel transparent window, see the
[GLFW_TRANSPARENT_FRAMEBUFFER](@ref GLFW_TRANSPARENT_FRAMEBUFFER_hint) window
hint.
@subsubsection standalone_34 Tests and examples are disabled when built as a subproject
GLFW now does not build the tests and examples when it is added as GLFW now does not build the tests and examples when it is added as
a subdirectory of another CMake project. To enable these, set the @ref a subdirectory of another CMake project. To enable these, set the @ref
@ -138,7 +173,7 @@ GLFW_TRANSPARENT_FRAMEBUFFER on Windows 7 if DWM transparency is off
(the Transparency setting under Personalization > Window Color). (the Transparency setting under Personalization > Window Color).
@subsubsection emptyevents_34 Empty events on X11 no longer roundtrip to server @subsubsection emptyevents_34 Empty events on X11 no longer round-trip to server
Events posted with @ref glfwPostEmptyEvent now use a separate unnamed pipe Events posted with @ref glfwPostEmptyEvent now use a separate unnamed pipe
instead of sending an X11 client event to the helper window. instead of sending an X11 client event to the helper window.
@ -228,6 +263,10 @@ then GLFW will fail to initialize.
- @ref GLFW_ANGLE_PLATFORM_TYPE_VULKAN - @ref GLFW_ANGLE_PLATFORM_TYPE_VULKAN
- @ref GLFW_ANGLE_PLATFORM_TYPE_METAL - @ref GLFW_ANGLE_PLATFORM_TYPE_METAL
- @ref GLFW_X11_XCB_VULKAN_SURFACE - @ref GLFW_X11_XCB_VULKAN_SURFACE
- @ref GLFW_CURSOR_CAPTURED
- @ref GLFW_POSITION_X
- @ref GLFW_POSITION_Y
- @ref GLFW_ANY_POSITION
@section news_archive Release notes for earlier versions @section news_archive Release notes for earlier versions

View File

@ -149,10 +149,6 @@ if (!window)
} }
@endcode @endcode
The window handle is passed to all window related functions and is provided to
along to all window related callbacks, so they can tell which window received
the event.
When a window and context is no longer needed, destroy it. When a window and context is no longer needed, destroy it.
@code @code
@ -238,7 +234,7 @@ events as described below.
@subsection quick_render Rendering with OpenGL @subsection quick_render Rendering with OpenGL
Once you have a current OpenGL context, you can use OpenGL normally. In this Once you have a current OpenGL context, you can use OpenGL normally. In this
tutorial, a multi-colored rotating triangle will be rendered. The framebuffer tutorial, a multicolored rotating triangle will be rendered. The framebuffer
size needs to be retrieved for `glViewport`. size needs to be retrieved for `glViewport`.
@code @code

View File

@ -37,8 +37,8 @@ By default, GLFW will load the Vulkan loader dynamically at runtime via its stan
`vulkan-1.dll` on Windows, `libvulkan.so.1` on Linux and other Unix-like systems and `vulkan-1.dll` on Windows, `libvulkan.so.1` on Linux and other Unix-like systems and
`libvulkan.1.dylib` on macOS. `libvulkan.1.dylib` on macOS.
@macos GLFW will also look up and search the executable subdirectory of your application @macos GLFW will also look up and search the `Frameworks` subdirectory of your
bundle. application bundle.
If your code is using a Vulkan loader with a different name or in a non-standard location If your code is using a Vulkan loader with a different name or in a non-standard location
you will need to direct GLFW to it. Pass your version of `vkGetInstanceProcAddr` to @ref you will need to direct GLFW to it. Pass your version of `vkGetInstanceProcAddr` to @ref
@ -142,7 +142,7 @@ PFN_vkGetDeviceProcAddr pfnGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)
glfwGetInstanceProcAddress(instance, "vkGetDeviceProcAddr"); glfwGetInstanceProcAddress(instance, "vkGetDeviceProcAddr");
@endcode @endcode
Device-specific functions may execute a little bit faster, due to not having to Device-specific functions may execute a little faster, due to not having to
dispatch internally based on the device passed to them. For more information dispatch internally based on the device passed to them. For more information
about `vkGetDeviceProcAddr`, see the Vulkan documentation. about `vkGetDeviceProcAddr`, see the Vulkan documentation.
@ -188,6 +188,13 @@ check whether any extensions you wish to enable are already in the returned
array, as it is an error to specify an extension more than once in the array, as it is an error to specify an extension more than once in the
`VkInstanceCreateInfo` struct. `VkInstanceCreateInfo` struct.
@macos MoltenVK is (as of July 2022) not yet a fully conformant implementation
of Vulkan. As of Vulkan SDK 1.3.216.0, this means you must also enable the
`VK_KHR_portability_enumeration` instance extension and set the
`VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR` bit in the instance creation
info flags for MoltenVK to show up in the list of physical devices. For more
information, see the Vulkan and MoltenVK documentation.
@section vulkan_present Querying for Vulkan presentation support @section vulkan_present Querying for Vulkan presentation support

View File

@ -256,6 +256,14 @@ This is only supported for undecorated windows. Decorated windows with this
enabled will behave differently between platforms. Possible values are enabled will behave differently between platforms. Possible values are
`GLFW_TRUE` and `GLFW_FALSE`. `GLFW_TRUE` and `GLFW_FALSE`.
@anchor GLFW_POSITION_X
@anchor GLFW_POSITION_Y
__GLFW_POSITION_X__ and __GLFW_POSITION_Y__ specify the desired initial position
of the window. The window manager may modify or ignore these coordinates. If
either or both of these hints are set to `GLFW_ANY_POSITION` then the window
manager will position the window where it thinks the user will prefer it.
Possible values are any valid screen coordinates and `GLFW_ANY_POSITION`.
@subsubsection window_hints_fb Framebuffer related hints @subsubsection window_hints_fb Framebuffer related hints
@ -489,9 +497,17 @@ should also declare this in its `Info.plist` by setting the
@anchor GLFW_X11_CLASS_NAME_hint @anchor GLFW_X11_CLASS_NAME_hint
@anchor GLFW_X11_INSTANCE_NAME_hint @anchor GLFW_X11_INSTANCE_NAME_hint
__GLFW_X11_CLASS_NAME__ and __GLFW_X11_INSTANCE_NAME__ specifies the desired __GLFW_X11_CLASS_NAME__ and __GLFW_X11_INSTANCE_NAME__ specifies the desired
ASCII encoded class and instance parts of the ICCCM `WM_CLASS` window property. ASCII encoded class and instance parts of the ICCCM `WM_CLASS` window property. Both
hints need to be set to something other than an empty string for them to take effect.
These are set with @ref glfwWindowHintString. These are set with @ref glfwWindowHintString.
@subsubsection window_hints_wayland Wayland specific window hints
@anchor GLFW_WAYLAND_APP_ID_hint
__GLFW_WAYLAND_APP_ID__ specifies the Wayland app_id for a window, used
by window managers to identify types of windows. This is set with
@ref glfwWindowHintString.
@subsubsection window_hints_values Supported and default values @subsubsection window_hints_values Supported and default values
@ -509,6 +525,8 @@ GLFW_TRANSPARENT_FRAMEBUFFER | `GLFW_FALSE` | `GLFW_TRUE` or `GL
GLFW_FOCUS_ON_SHOW | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_FOCUS_ON_SHOW | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_SCALE_TO_MONITOR | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_SCALE_TO_MONITOR | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_MOUSE_PASSTHROUGH | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_MOUSE_PASSTHROUGH | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_POSITION_X | `GLFW_ANY_POSITION` | Any valid screen x-coordinate or `GLFW_ANY_POSITION`
GLFW_POSITION_Y | `GLFW_ANY_POSITION` | Any valid screen y-coordinate or `GLFW_ANY_POSITION`
GLFW_RED_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` GLFW_RED_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_GREEN_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` GLFW_GREEN_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_BLUE_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` GLFW_BLUE_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
@ -540,6 +558,7 @@ GLFW_COCOA_FRAME_NAME | `""` | A UTF-8 encoded fr
GLFW_COCOA_GRAPHICS_SWITCHING | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_COCOA_GRAPHICS_SWITCHING | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_X11_CLASS_NAME | `""` | An ASCII encoded `WM_CLASS` class name GLFW_X11_CLASS_NAME | `""` | An ASCII encoded `WM_CLASS` class name
GLFW_X11_INSTANCE_NAME | `""` | An ASCII encoded `WM_CLASS` instance name GLFW_X11_INSTANCE_NAME | `""` | An ASCII encoded `WM_CLASS` instance name
GLFW_WAYLAND_APP_ID | `""` | An ASCII encoded Wayland `app_id` name
@section window_events Window event processing @section window_events Window event processing
@ -790,7 +809,20 @@ are undefined if they conflict.
@subsection window_pos Window position @subsection window_pos Window position
The position of a windowed-mode window can be changed with @ref By default, the window manager chooses the position of new windowed mode
windows, based on its size and which monitor the user appears to be working on.
This is most often the right choice. If you need to create a window at
a specific position, you can set the desired position with the @ref
GLFW_POSITION_X and @ref GLFW_POSITION_Y window hints.
@code
glfwWindowHint(GLFW_POSITION_X, 70);
glfwWindowHint(GLFW_POSITION_Y, 83);
@endcode
To restore the previous behavior, set these hints to `GLFW_ANY_POSITION`.
The position of a windowed mode window can be changed with @ref
glfwSetWindowPos. This moves the window so that the upper-left corner of its glfwSetWindowPos. This moves the window so that the upper-left corner of its
content area has the specified [screen coordinates](@ref coordinate_systems). content area has the specified [screen coordinates](@ref coordinate_systems).
The window system may put limitations on window placement. The window system may put limitations on window placement.

View File

@ -44,7 +44,6 @@ int main(int argc, char** argv)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
glfwGetMonitorWorkarea(glfwGetPrimaryMonitor(), &xpos, &ypos, NULL, &height); glfwGetMonitorWorkarea(glfwGetPrimaryMonitor(), &xpos, &ypos, NULL, &height);
@ -66,6 +65,9 @@ int main(int argc, char** argv)
if (i > 0) if (i > 0)
glfwWindowHint(GLFW_FOCUS_ON_SHOW, GLFW_FALSE); glfwWindowHint(GLFW_FOCUS_ON_SHOW, GLFW_FALSE);
glfwWindowHint(GLFW_POSITION_X, xpos + size * (1 + (i & 1)));
glfwWindowHint(GLFW_POSITION_Y, ypos + size * (1 + (i >> 1)));
windows[i] = glfwCreateWindow(size, size, "Multi-Window Example", NULL, NULL); windows[i] = glfwCreateWindow(size, size, "Multi-Window Example", NULL, NULL);
if (!windows[i]) if (!windows[i])
{ {
@ -75,9 +77,6 @@ int main(int argc, char** argv)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
glfwSetWindowPos(windows[i],
xpos + size * (1 + (i & 1)),
ypos + size * (1 + (i >> 1)));
glfwSetInputMode(windows[i], GLFW_STICKY_KEYS, GLFW_TRUE); glfwSetInputMode(windows[i], GLFW_STICKY_KEYS, GLFW_TRUE);
glfwMakeContextCurrent(windows[i]); glfwMakeContextCurrent(windows[i]);
@ -85,9 +84,6 @@ int main(int argc, char** argv)
glClearColor(colors[i].r, colors[i].g, colors[i].b, 1.f); glClearColor(colors[i].r, colors[i].g, colors[i].b, 1.f);
} }
for (int i = 0; i < 4; i++)
glfwShowWindow(windows[i]);
for (;;) for (;;)
{ {
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)

View File

@ -927,6 +927,18 @@ extern "C" {
*/ */
#define GLFW_MOUSE_PASSTHROUGH 0x0002000D #define GLFW_MOUSE_PASSTHROUGH 0x0002000D
/*! @brief Initial position x-coordinate window hint.
*
* Initial position x-coordinate [window hint](@ref GLFW_POSITION_X).
*/
#define GLFW_POSITION_X 0x0002000E
/*! @brief Initial position y-coordinate window hint.
*
* Initial position y-coordinate [window hint](@ref GLFW_POSITION_Y).
*/
#define GLFW_POSITION_Y 0x0002000F
/*! @brief Framebuffer bit depth hint. /*! @brief Framebuffer bit depth hint.
* *
* Framebuffer bit depth [hint](@ref GLFW_RED_BITS). * Framebuffer bit depth [hint](@ref GLFW_RED_BITS).
@ -1105,6 +1117,12 @@ extern "C" {
*/ */
#define GLFW_X11_INSTANCE_NAME 0x00024002 #define GLFW_X11_INSTANCE_NAME 0x00024002
#define GLFW_WIN32_KEYBOARD_MENU 0x00025001 #define GLFW_WIN32_KEYBOARD_MENU 0x00025001
/*! @brief Wayland specific
* [window hint](@ref GLFW_WAYLAND_APP_ID_hint).
*
* Allows specification of the Wayland app_id.
*/
#define GLFW_WAYLAND_APP_ID 0x00026001
/*! @} */ /*! @} */
#define GLFW_NO_API 0 #define GLFW_NO_API 0
@ -1128,6 +1146,7 @@ extern "C" {
#define GLFW_CURSOR_NORMAL 0x00034001 #define GLFW_CURSOR_NORMAL 0x00034001
#define GLFW_CURSOR_HIDDEN 0x00034002 #define GLFW_CURSOR_HIDDEN 0x00034002
#define GLFW_CURSOR_DISABLED 0x00034003 #define GLFW_CURSOR_DISABLED 0x00034003
#define GLFW_CURSOR_CAPTURED 0x00034004
#define GLFW_ANY_RELEASE_BEHAVIOR 0 #define GLFW_ANY_RELEASE_BEHAVIOR 0
#define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001 #define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001
@ -1145,6 +1164,8 @@ extern "C" {
#define GLFW_ANGLE_PLATFORM_TYPE_VULKAN 0x00037007 #define GLFW_ANGLE_PLATFORM_TYPE_VULKAN 0x00037007
#define GLFW_ANGLE_PLATFORM_TYPE_METAL 0x00037008 #define GLFW_ANGLE_PLATFORM_TYPE_METAL 0x00037008
#define GLFW_ANY_POSITION 0x80000000
/*! @defgroup shapes Standard cursor shapes /*! @defgroup shapes Standard cursor shapes
* @brief Standard system cursor shapes. * @brief Standard system cursor shapes.
* *
@ -2814,11 +2835,11 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
* @param[in] monitor The monitor whose gamma ramp to set. * @param[in] monitor The monitor whose gamma ramp to set.
* @param[in] gamma The desired exponent. * @param[in] gamma The desired exponent.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_INVALID_VALUE,
* GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. * @ref GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland Gamma handling is a privileged protocol, this function * @remark @wayland Gamma handling is a privileged protocol, this function
* will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR. * will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
@ -2838,11 +2859,11 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma);
* @return The current gamma ramp, or `NULL` if an * @return The current gamma ramp, or `NULL` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_PLATFORM_ERROR
* GLFW_PLATFORM_ERROR. * and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland Gamma handling is a privileged protocol, this function * @remark @wayland Gamma handling is a privileged protocol, this function
* will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR while * will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE while
* returning `NULL`. * returning `NULL`.
* *
* @pointer_lifetime The returned structure and its arrays are allocated and * @pointer_lifetime The returned structure and its arrays are allocated and
@ -2877,8 +2898,8 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
* @param[in] monitor The monitor whose gamma ramp to set. * @param[in] monitor The monitor whose gamma ramp to set.
* @param[in] ramp The gamma ramp to use. * @param[in] ramp The gamma ramp to use.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_PLATFORM_ERROR
* GLFW_PLATFORM_ERROR. * and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark The size of the specified gamma ramp should match the size of the * @remark The size of the specified gamma ramp should match the size of the
* current ramp for that monitor. * current ramp for that monitor.
@ -2886,7 +2907,7 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
* @remark @win32 The gamma ramp size must be 256. * @remark @win32 The gamma ramp size must be 256.
* *
* @remark @wayland Gamma handling is a privileged protocol, this function * @remark @wayland Gamma handling is a privileged protocol, this function
* will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR. * will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE.
* *
* @pointer_lifetime The specified gamma ramp is copied before this function * @pointer_lifetime The specified gamma ramp is copied before this function
* returns. * returns.
@ -3029,10 +3050,10 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
* OpenGL or OpenGL ES context. * OpenGL or OpenGL ES context.
* *
* By default, newly created windows use the placement recommended by the * By default, newly created windows use the placement recommended by the
* window system. To create the window at a specific position, make it * window system. To create the window at a specific position, set the @ref
* initially invisible using the [GLFW_VISIBLE](@ref GLFW_VISIBLE_hint) window * GLFW_POSITION_X and @ref GLFW_POSITION_Y window hints before creation. To
* hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * restore the default behavior, set either or both hints back to
* it. * `GLFW_ANY_POSITION`.
* *
* As long as at least one full screen window is not iconified, the screensaver * As long as at least one full screen window is not iconified, the screensaver
* is prohibited from starting. * is prohibited from starting.
@ -3671,8 +3692,9 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity);
* previously restored. If the window is already iconified, this function does * previously restored. If the window is already iconified, this function does
* nothing. * nothing.
* *
* If the specified window is a full screen window, the original monitor * If the specified window is a full screen window, GLFW restores the original
* resolution is restored until the window is restored. * video mode of the monitor. The window's desired video mode is set again
* when the window is restored.
* *
* @param[in] window The window to iconify. * @param[in] window The window to iconify.
* *
@ -3702,8 +3724,8 @@ GLFWAPI void glfwIconifyWindow(GLFWwindow* window);
* (minimized) or maximized. If the window is already restored, this function * (minimized) or maximized. If the window is already restored, this function
* does nothing. * does nothing.
* *
* If the specified window is a full screen window, the resolution chosen for * If the specified window is an iconified full screen window, its desired
* the window is restored on the selected monitor. * video mode is set again for its monitor when the window is restored.
* *
* @param[in] window The window to restore. * @param[in] window The window to restore.
* *
@ -3971,6 +3993,9 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int
* errors. However, this function should not fail as long as it is passed * errors. However, this function should not fail as long as it is passed
* valid arguments and the library has been [initialized](@ref intro_init). * valid arguments and the library has been [initialized](@ref intro_init).
* *
* @remark @wayland The Wayland protocol provides no way to check whether a
* window is iconfied, so @ref GLFW_ICONIFIED always returns `GLFW_FALSE`.
*
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
* @sa @ref window_attribs * @sa @ref window_attribs
@ -4005,7 +4030,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
* @param[in] value `GLFW_TRUE` or `GLFW_FALSE`. * @param[in] value `GLFW_TRUE` or `GLFW_FALSE`.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_PLATFORM_ERROR and @ref
* GLFW_FEATURE_UNAVAILABLE.
* *
* @remark Calling @ref glfwGetWindowAttrib will always return the latest * @remark Calling @ref glfwGetWindowAttrib will always return the latest
* value, even if that value is ignored by the current mode of the window. * value, even if that value is ignored by the current mode of the window.
@ -4556,6 +4582,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
* - `GLFW_CURSOR_DISABLED` hides and grabs the cursor, providing virtual * - `GLFW_CURSOR_DISABLED` hides and grabs the cursor, providing virtual
* and unlimited cursor movement. This is useful for implementing for * and unlimited cursor movement. This is useful for implementing for
* example 3D camera controls. * example 3D camera controls.
* - `GLFW_CURSOR_CAPTURED` makes the cursor visible and confines it to the
* content area of the window.
* *
* If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to
* enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are
@ -4730,8 +4758,7 @@ GLFWAPI int glfwGetKeyScancode(int key);
* *
* This function returns the last state reported for the specified key to the * This function returns the last state reported for the specified key to the
* specified window. The returned state is one of `GLFW_PRESS` or * specified window. The returned state is one of `GLFW_PRESS` or
* `GLFW_RELEASE`. The higher-level action `GLFW_REPEAT` is only reported to * `GLFW_RELEASE`. The action `GLFW_REPEAT` is only reported to the key callback.
* the key callback.
* *
* If the @ref GLFW_STICKY_KEYS input mode is enabled, this function returns * If the @ref GLFW_STICKY_KEYS input mode is enabled, this function returns
* `GLFW_PRESS` the first time you call it for a key that was pressed, even if * `GLFW_PRESS` the first time you call it for a key that was pressed, even if
@ -4855,11 +4882,11 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
* @param[in] ypos The desired y-coordinate, relative to the top edge of the * @param[in] ypos The desired y-coordinate, relative to the top edge of the
* content area. * content area.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland This function will only work when the cursor mode is * @remark @wayland This function will only work when the cursor mode is
* `GLFW_CURSOR_DISABLED`, otherwise it will do nothing. * `GLFW_CURSOR_DISABLED`, otherwise it will emit @ref GLFW_FEATURE_UNAVAILABLE.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *

View File

@ -74,6 +74,16 @@ extern "C" {
* and which platform-specific headers to include. It is then up your (by * and which platform-specific headers to include. It is then up your (by
* definition platform-specific) code to handle which of these should be * definition platform-specific) code to handle which of these should be
* defined. * defined.
*
* If you do not want the platform-specific headers to be included, define
* `GLFW_NATIVE_INCLUDE_NONE` before including the @ref glfw3native.h header.
*
* @code
* #define GLFW_EXPOSE_NATIVE_WIN32
* #define GLFW_EXPOSE_NATIVE_WGL
* #define GLFW_NATIVE_INCLUDE_NONE
* #include <GLFW/glfw3native.h>
* @endcode
*/ */
@ -81,61 +91,71 @@ extern "C" {
* System headers and types * System headers and types
*************************************************************************/ *************************************************************************/
#if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL) #if !defined(GLFW_NATIVE_INCLUDE_NONE)
/* This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
* example to allow applications to correctly declare a GL_KHR_debug callback)
* but windows.h assumes no one will define APIENTRY before it does
*/
#if defined(GLFW_APIENTRY_DEFINED)
#undef APIENTRY
#undef GLFW_APIENTRY_DEFINED
#endif
#include <windows.h>
#elif defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL)
#if defined(__OBJC__)
#import <Cocoa/Cocoa.h>
#else
#include <ApplicationServices/ApplicationServices.h>
typedef void* id;
#endif
#elif defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
#include <wayland-client.h>
#endif
#if defined(GLFW_EXPOSE_NATIVE_WGL) #if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL)
/* WGL is declared by windows.h */ /* This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
#endif * example to allow applications to correctly declare a GL_KHR_debug callback)
#if defined(GLFW_EXPOSE_NATIVE_NSGL) * but windows.h assumes no one will define APIENTRY before it does
/* NSGL is declared by Cocoa.h */ */
#endif #if defined(GLFW_APIENTRY_DEFINED)
#if defined(GLFW_EXPOSE_NATIVE_GLX) #undef APIENTRY
/* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by #undef GLFW_APIENTRY_DEFINED
* default it also acts as an OpenGL header #endif
* However, glx.h will include gl.h, which will define it unconditionally #include <windows.h>
*/
#if defined(GLFW_GLAPIENTRY_DEFINED)
#undef GLAPIENTRY
#undef GLFW_GLAPIENTRY_DEFINED
#endif #endif
#include <GL/glx.h>
#endif #if defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL)
#if defined(GLFW_EXPOSE_NATIVE_EGL) #if defined(__OBJC__)
#include <EGL/egl.h> #import <Cocoa/Cocoa.h>
#endif #else
#if defined(GLFW_EXPOSE_NATIVE_OSMESA) #include <ApplicationServices/ApplicationServices.h>
/* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by #include <objc/objc.h>
* default it also acts as an OpenGL header #endif
* However, osmesa.h will include gl.h, which will define it unconditionally
*/
#if defined(GLFW_GLAPIENTRY_DEFINED)
#undef GLAPIENTRY
#undef GLFW_GLAPIENTRY_DEFINED
#endif #endif
#include <GL/osmesa.h>
#endif #if defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#endif
#if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
#include <wayland-client.h>
#endif
#if defined(GLFW_EXPOSE_NATIVE_WGL)
/* WGL is declared by windows.h */
#endif
#if defined(GLFW_EXPOSE_NATIVE_NSGL)
/* NSGL is declared by Cocoa.h */
#endif
#if defined(GLFW_EXPOSE_NATIVE_GLX)
/* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by
* default it also acts as an OpenGL header
* However, glx.h will include gl.h, which will define it unconditionally
*/
#if defined(GLFW_GLAPIENTRY_DEFINED)
#undef GLAPIENTRY
#undef GLFW_GLAPIENTRY_DEFINED
#endif
#include <GL/glx.h>
#endif
#if defined(GLFW_EXPOSE_NATIVE_EGL)
#include <EGL/egl.h>
#endif
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
/* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by
* default it also acts as an OpenGL header
* However, osmesa.h will include gl.h, which will define it unconditionally
*/
#if defined(GLFW_GLAPIENTRY_DEFINED)
#undef GLAPIENTRY
#undef GLFW_GLAPIENTRY_DEFINED
#endif
#include <GL/osmesa.h>
#endif
#endif /*GLFW_NATIVE_INCLUDE_NONE*/
/************************************************************************* /*************************************************************************

View File

@ -27,6 +27,9 @@
//======================================================================== //========================================================================
#include "internal.h" #include "internal.h"
#if defined(_GLFW_COCOA)
#include <sys/param.h> // For MAXPATHLEN #include <sys/param.h> // For MAXPATHLEN
// Needed for _NSGetProgname // Needed for _NSGetProgname
@ -460,18 +463,26 @@ void* _glfwLoadLocalVulkanLoaderCocoa(void)
if (!bundle) if (!bundle)
return NULL; return NULL;
CFURLRef url = CFURLRef frameworksUrl = CFBundleCopyPrivateFrameworksURL(bundle);
CFBundleCopyAuxiliaryExecutableURL(bundle, CFSTR("libvulkan.1.dylib")); if (!frameworksUrl)
if (!url)
return NULL; return NULL;
CFURLRef loaderUrl = CFURLCreateCopyAppendingPathComponent(
kCFAllocatorDefault, frameworksUrl, CFSTR("libvulkan.1.dylib"), false);
if (!loaderUrl)
{
CFRelease(frameworksUrl);
return NULL;
}
char path[PATH_MAX]; char path[PATH_MAX];
void* handle = NULL; void* handle = NULL;
if (CFURLGetFileSystemRepresentation(url, true, (UInt8*) path, sizeof(path) - 1)) if (CFURLGetFileSystemRepresentation(loaderUrl, true, (UInt8*) path, sizeof(path) - 1))
handle = _glfwPlatformLoadModule(path); handle = _glfwPlatformLoadModule(path);
CFRelease(url); CFRelease(loaderUrl);
CFRelease(frameworksUrl);
return handle; return handle;
} }
@ -682,3 +693,5 @@ void _glfwTerminateCocoa(void)
} // autoreleasepool } // autoreleasepool
} }
#endif // _GLFW_COCOA

View File

@ -31,8 +31,6 @@
#define GLFW_COCOA_JOYSTICK_STATE _GLFWjoystickNS ns; #define GLFW_COCOA_JOYSTICK_STATE _GLFWjoystickNS ns;
#define GLFW_COCOA_LIBRARY_JOYSTICK_STATE #define GLFW_COCOA_LIBRARY_JOYSTICK_STATE
#define GLFW_BUILD_COCOA_MAPPINGS
// Cocoa-specific per-joystick data // Cocoa-specific per-joystick data
// //
typedef struct _GLFWjoystickNS typedef struct _GLFWjoystickNS
@ -45,7 +43,7 @@ typedef struct _GLFWjoystickNS
GLFWbool _glfwInitJoysticksCocoa(void); GLFWbool _glfwInitJoysticksCocoa(void);
void _glfwTerminateJoysticksCocoa(void); void _glfwTerminateJoysticksCocoa(void);
int _glfwPollJoystickCocoa(_GLFWjoystick* js, int mode); GLFWbool _glfwPollJoystickCocoa(_GLFWjoystick* js, int mode);
const char* _glfwGetMappingNameCocoa(void); const char* _glfwGetMappingNameCocoa(void);
void _glfwUpdateGamepadGUIDCocoa(char* guid); void _glfwUpdateGamepadGUIDCocoa(char* guid);

View File

@ -29,6 +29,8 @@
#include "internal.h" #include "internal.h"
#if defined(_GLFW_COCOA)
#include <unistd.h> #include <unistd.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
@ -96,8 +98,7 @@ static CFComparisonResult compareElements(const void* fp,
// //
static void closeJoystick(_GLFWjoystick* js) static void closeJoystick(_GLFWjoystick* js)
{ {
if (!js->present) _glfwInputJoystick(js, GLFW_DISCONNECTED);
return;
for (int i = 0; i < CFArrayGetCount(js->ns.axes); i++) for (int i = 0; i < CFArrayGetCount(js->ns.axes); i++)
_glfw_free((void*) CFArrayGetValueAtIndex(js->ns.axes, i)); _glfw_free((void*) CFArrayGetValueAtIndex(js->ns.axes, i));
@ -112,7 +113,6 @@ static void closeJoystick(_GLFWjoystick* js)
CFRelease(js->ns.hats); CFRelease(js->ns.hats);
_glfwFreeJoystick(js); _glfwFreeJoystick(js);
_glfwInputJoystick(js, GLFW_DISCONNECTED);
} }
// Callback for user-initiated joystick addition // Callback for user-initiated joystick addition
@ -289,9 +289,9 @@ static void removeCallback(void* context,
{ {
for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{ {
if (_glfw.joysticks[jid].ns.device == device) if (_glfw.joysticks[jid].connected && _glfw.joysticks[jid].ns.device == device)
{ {
closeJoystick(_glfw.joysticks + jid); closeJoystick(&_glfw.joysticks[jid]);
break; break;
} }
} }
@ -382,7 +382,10 @@ GLFWbool _glfwInitJoysticksCocoa(void)
void _glfwTerminateJoysticksCocoa(void) void _glfwTerminateJoysticksCocoa(void)
{ {
for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
closeJoystick(_glfw.joysticks + jid); {
if (_glfw.joysticks[jid].connected)
closeJoystick(&_glfw.joysticks[jid]);
}
if (_glfw.ns.hidManager) if (_glfw.ns.hidManager)
{ {
@ -392,7 +395,7 @@ void _glfwTerminateJoysticksCocoa(void)
} }
int _glfwPollJoystickCocoa(_GLFWjoystick* js, int mode) GLFWbool _glfwPollJoystickCocoa(_GLFWjoystick* js, int mode)
{ {
if (mode & _GLFW_POLL_AXES) if (mode & _GLFW_POLL_AXES)
{ {
@ -455,7 +458,7 @@ int _glfwPollJoystickCocoa(_GLFWjoystick* js, int mode)
} }
} }
return js->present; return js->connected;
} }
const char* _glfwGetMappingNameCocoa(void) const char* _glfwGetMappingNameCocoa(void)
@ -475,3 +478,5 @@ void _glfwUpdateGamepadGUIDCocoa(char* guid)
} }
} }
#endif // _GLFW_COCOA

View File

@ -29,6 +29,8 @@
#include "internal.h" #include "internal.h"
#if defined(_GLFW_COCOA)
#include <stdlib.h> #include <stdlib.h>
#include <limits.h> #include <limits.h>
#include <math.h> #include <math.h>
@ -625,3 +627,5 @@ GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* handle)
return monitor->ns.displayID; return monitor->ns.displayID;
} }
#endif // _GLFW_COCOA

View File

@ -214,7 +214,7 @@ GLFWbool _glfwConnectCocoa(int platformID, _GLFWplatform* platform);
int _glfwInitCocoa(void); int _glfwInitCocoa(void);
void _glfwTerminateCocoa(void); void _glfwTerminateCocoa(void);
int _glfwCreateWindowCocoa(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); GLFWbool _glfwCreateWindowCocoa(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig);
void _glfwDestroyWindowCocoa(_GLFWwindow* window); void _glfwDestroyWindowCocoa(_GLFWwindow* window);
void _glfwSetWindowTitleCocoa(_GLFWwindow* window, const char* title); void _glfwSetWindowTitleCocoa(_GLFWwindow* window, const char* title);
void _glfwSetWindowIconCocoa(_GLFWwindow* window, int count, const GLFWimage* images); void _glfwSetWindowIconCocoa(_GLFWwindow* window, int count, const GLFWimage* images);
@ -235,12 +235,12 @@ void _glfwHideWindowCocoa(_GLFWwindow* window);
void _glfwRequestWindowAttentionCocoa(_GLFWwindow* window); void _glfwRequestWindowAttentionCocoa(_GLFWwindow* window);
void _glfwFocusWindowCocoa(_GLFWwindow* window); void _glfwFocusWindowCocoa(_GLFWwindow* window);
void _glfwSetWindowMonitorCocoa(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); void _glfwSetWindowMonitorCocoa(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
int _glfwWindowFocusedCocoa(_GLFWwindow* window); GLFWbool _glfwWindowFocusedCocoa(_GLFWwindow* window);
int _glfwWindowIconifiedCocoa(_GLFWwindow* window); GLFWbool _glfwWindowIconifiedCocoa(_GLFWwindow* window);
int _glfwWindowVisibleCocoa(_GLFWwindow* window); GLFWbool _glfwWindowVisibleCocoa(_GLFWwindow* window);
int _glfwWindowMaximizedCocoa(_GLFWwindow* window); GLFWbool _glfwWindowMaximizedCocoa(_GLFWwindow* window);
int _glfwWindowHoveredCocoa(_GLFWwindow* window); GLFWbool _glfwWindowHoveredCocoa(_GLFWwindow* window);
int _glfwFramebufferTransparentCocoa(_GLFWwindow* window); GLFWbool _glfwFramebufferTransparentCocoa(_GLFWwindow* window);
void _glfwSetWindowResizableCocoa(_GLFWwindow* window, GLFWbool enabled); void _glfwSetWindowResizableCocoa(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowDecoratedCocoa(_GLFWwindow* window, GLFWbool enabled); void _glfwSetWindowDecoratedCocoa(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowFloatingCocoa(_GLFWwindow* window, GLFWbool enabled); void _glfwSetWindowFloatingCocoa(_GLFWwindow* window, GLFWbool enabled);
@ -261,8 +261,8 @@ void _glfwSetCursorPosCocoa(_GLFWwindow* window, double xpos, double ypos);
void _glfwSetCursorModeCocoa(_GLFWwindow* window, int mode); void _glfwSetCursorModeCocoa(_GLFWwindow* window, int mode);
const char* _glfwGetScancodeNameCocoa(int scancode); const char* _glfwGetScancodeNameCocoa(int scancode);
int _glfwGetKeyScancodeCocoa(int key); int _glfwGetKeyScancodeCocoa(int key);
int _glfwCreateCursorCocoa(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot); GLFWbool _glfwCreateCursorCocoa(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
int _glfwCreateStandardCursorCocoa(_GLFWcursor* cursor, int shape); GLFWbool _glfwCreateStandardCursorCocoa(_GLFWcursor* cursor, int shape);
void _glfwDestroyCursorCocoa(_GLFWcursor* cursor); void _glfwDestroyCursorCocoa(_GLFWcursor* cursor);
void _glfwSetCursorCocoa(_GLFWwindow* window, _GLFWcursor* cursor); void _glfwSetCursorCocoa(_GLFWwindow* window, _GLFWcursor* cursor);
void _glfwSetClipboardStringCocoa(const char* string); void _glfwSetClipboardStringCocoa(const char* string);
@ -273,7 +273,7 @@ EGLNativeDisplayType _glfwGetEGLNativeDisplayCocoa(void);
EGLNativeWindowType _glfwGetEGLNativeWindowCocoa(_GLFWwindow* window); EGLNativeWindowType _glfwGetEGLNativeWindowCocoa(_GLFWwindow* window);
void _glfwGetRequiredInstanceExtensionsCocoa(char** extensions); void _glfwGetRequiredInstanceExtensionsCocoa(char** extensions);
int _glfwGetPhysicalDevicePresentationSupportCocoa(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); GLFWbool _glfwGetPhysicalDevicePresentationSupportCocoa(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
void _glfwFreeMonitorCocoa(_GLFWmonitor* monitor); void _glfwFreeMonitorCocoa(_GLFWmonitor* monitor);

View File

@ -28,6 +28,8 @@
#include "internal.h" #include "internal.h"
#if defined(GLFW_BUILD_COCOA_TIMER)
#include <mach/mach_time.h> #include <mach/mach_time.h>
@ -53,3 +55,5 @@ uint64_t _glfwPlatformGetTimerFrequency(void)
return _glfw.timer.ns.frequency; return _glfw.timer.ns.frequency;
} }
#endif // GLFW_BUILD_COCOA_TIMER

View File

@ -28,28 +28,14 @@
#include "internal.h" #include "internal.h"
#if defined(_GLFW_COCOA)
#include <float.h> #include <float.h>
#include <string.h> #include <string.h>
// Returns the style mask corresponding to the window settings // HACK: This enum value is missing from framework headers on OS X 10.11 despite
// // having been (according to documentation) added in Mac OS X 10.7
static NSUInteger getStyleMask(_GLFWwindow* window) #define NSWindowCollectionBehaviorFullScreenNone (1 << 9)
{
NSUInteger styleMask = NSWindowStyleMaskMiniaturizable;
if (window->monitor || !window->decorated)
styleMask |= NSWindowStyleMaskBorderless;
else
{
styleMask |= NSWindowStyleMaskTitled |
NSWindowStyleMaskClosable;
if (window->resizable)
styleMask |= NSWindowStyleMaskResizable;
}
return styleMask;
}
// Returns whether the cursor is in the content area of the specified window // Returns whether the cursor is in the content area of the specified window
// //
@ -807,11 +793,35 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
contentRect = NSMakeRect(xpos, ypos, mode.width, mode.height); contentRect = NSMakeRect(xpos, ypos, mode.width, mode.height);
} }
else else
contentRect = NSMakeRect(0, 0, wndconfig->width, wndconfig->height); {
if (wndconfig->xpos == GLFW_ANY_POSITION ||
wndconfig->ypos == GLFW_ANY_POSITION)
{
contentRect = NSMakeRect(0, 0, wndconfig->width, wndconfig->height);
}
else
{
const int xpos = wndconfig->xpos;
const int ypos = _glfwTransformYCocoa(wndconfig->ypos + wndconfig->height - 1);
contentRect = NSMakeRect(xpos, ypos, wndconfig->width, wndconfig->height);
}
}
NSUInteger styleMask = NSWindowStyleMaskMiniaturizable;
if (window->monitor || !window->decorated)
styleMask |= NSWindowStyleMaskBorderless;
else
{
styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
if (window->resizable)
styleMask |= NSWindowStyleMaskResizable;
}
window->ns.object = [[GLFWWindow alloc] window->ns.object = [[GLFWWindow alloc]
initWithContentRect:contentRect initWithContentRect:contentRect
styleMask:getStyleMask(window) styleMask:styleMask
backing:NSBackingStoreBuffered backing:NSBackingStoreBuffered
defer:NO]; defer:NO];
@ -825,10 +835,14 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
[window->ns.object setLevel:NSMainMenuWindowLevel + 1]; [window->ns.object setLevel:NSMainMenuWindowLevel + 1];
else else
{ {
[(NSWindow*) window->ns.object center]; if (wndconfig->xpos == GLFW_ANY_POSITION ||
_glfw.ns.cascadePoint = wndconfig->ypos == GLFW_ANY_POSITION)
NSPointToCGPoint([window->ns.object cascadeTopLeftFromPoint: {
NSPointFromCGPoint(_glfw.ns.cascadePoint)]); [(NSWindow*) window->ns.object center];
_glfw.ns.cascadePoint =
NSPointToCGPoint([window->ns.object cascadeTopLeftFromPoint:
NSPointFromCGPoint(_glfw.ns.cascadePoint)]);
}
if (wndconfig->resizable) if (wndconfig->resizable)
{ {
@ -837,6 +851,12 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
NSWindowCollectionBehaviorManaged; NSWindowCollectionBehaviorManaged;
[window->ns.object setCollectionBehavior:behavior]; [window->ns.object setCollectionBehavior:behavior];
} }
else
{
const NSWindowCollectionBehavior behavior =
NSWindowCollectionBehaviorFullScreenNone;
[window->ns.object setCollectionBehavior:behavior];
}
if (wndconfig->floating) if (wndconfig->floating)
[window->ns.object setLevel:NSFloatingWindowLevel]; [window->ns.object setLevel:NSFloatingWindowLevel];
@ -893,10 +913,10 @@ float _glfwTransformYCocoa(float y)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
int _glfwCreateWindowCocoa(_GLFWwindow* window, GLFWbool _glfwCreateWindowCocoa(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig, const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) const _GLFWfbconfig* fbconfig)
{ {
@autoreleasepool { @autoreleasepool {
@ -1235,9 +1255,10 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
{ {
const NSRect contentRect = const NSRect contentRect =
NSMakeRect(xpos, _glfwTransformYCocoa(ypos + height - 1), width, height); NSMakeRect(xpos, _glfwTransformYCocoa(ypos + height - 1), width, height);
const NSUInteger styleMask = [window->ns.object styleMask];
const NSRect frameRect = const NSRect frameRect =
[window->ns.object frameRectForContentRect:contentRect [window->ns.object frameRectForContentRect:contentRect
styleMask:getStyleMask(window)]; styleMask:styleMask];
[window->ns.object setFrame:frameRect display:YES]; [window->ns.object setFrame:frameRect display:YES];
} }
@ -1254,7 +1275,27 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
// TODO: Solve this in a less terrible way // TODO: Solve this in a less terrible way
_glfwPollEventsCocoa(); _glfwPollEventsCocoa();
const NSUInteger styleMask = getStyleMask(window); NSUInteger styleMask = [window->ns.object styleMask];
if (window->monitor)
{
styleMask &= ~(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
styleMask |= NSWindowStyleMaskBorderless;
}
else
{
if (window->decorated)
{
styleMask &= ~NSWindowStyleMaskBorderless;
styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
}
if (window->resizable)
styleMask |= NSWindowStyleMaskResizable;
else
styleMask &= ~NSWindowStyleMaskResizable;
}
[window->ns.object setStyleMask:styleMask]; [window->ns.object setStyleMask:styleMask];
// HACK: Changing the style mask can cause the first responder to be cleared // HACK: Changing the style mask can cause the first responder to be cleared
[window->ns.object makeFirstResponder:window->ns.view]; [window->ns.object makeFirstResponder:window->ns.view];
@ -1300,6 +1341,20 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
else else
[window->ns.object setLevel:NSNormalWindowLevel]; [window->ns.object setLevel:NSNormalWindowLevel];
if (window->resizable)
{
const NSWindowCollectionBehavior behavior =
NSWindowCollectionBehaviorFullScreenPrimary |
NSWindowCollectionBehaviorManaged;
[window->ns.object setCollectionBehavior:behavior];
}
else
{
const NSWindowCollectionBehavior behavior =
NSWindowCollectionBehaviorFullScreenNone;
[window->ns.object setCollectionBehavior:behavior];
}
[window->ns.object setHasShadow:YES]; [window->ns.object setHasShadow:YES];
// HACK: Clearing NSWindowStyleMaskTitled resets and disables the window // HACK: Clearing NSWindowStyleMaskTitled resets and disables the window
// title property but the miniwindow title property is unaffected // title property but the miniwindow title property is unaffected
@ -1309,35 +1364,40 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
} // autoreleasepool } // autoreleasepool
} }
int _glfwWindowFocusedCocoa(_GLFWwindow* window) GLFWbool _glfwWindowFocusedCocoa(_GLFWwindow* window)
{ {
@autoreleasepool { @autoreleasepool {
return [window->ns.object isKeyWindow]; return [window->ns.object isKeyWindow];
} // autoreleasepool } // autoreleasepool
} }
int _glfwWindowIconifiedCocoa(_GLFWwindow* window) GLFWbool _glfwWindowIconifiedCocoa(_GLFWwindow* window)
{ {
@autoreleasepool { @autoreleasepool {
return [window->ns.object isMiniaturized]; return [window->ns.object isMiniaturized];
} // autoreleasepool } // autoreleasepool
} }
int _glfwWindowVisibleCocoa(_GLFWwindow* window) GLFWbool _glfwWindowVisibleCocoa(_GLFWwindow* window)
{ {
@autoreleasepool { @autoreleasepool {
return [window->ns.object isVisible]; return [window->ns.object isVisible];
} // autoreleasepool } // autoreleasepool
} }
int _glfwWindowMaximizedCocoa(_GLFWwindow* window) GLFWbool _glfwWindowMaximizedCocoa(_GLFWwindow* window)
{ {
@autoreleasepool { @autoreleasepool {
return [window->ns.object isZoomed];
if (window->resizable)
return [window->ns.object isZoomed];
else
return GLFW_FALSE;
} // autoreleasepool } // autoreleasepool
} }
int _glfwWindowHoveredCocoa(_GLFWwindow* window) GLFWbool _glfwWindowHoveredCocoa(_GLFWwindow* window)
{ {
@autoreleasepool { @autoreleasepool {
@ -1355,7 +1415,7 @@ int _glfwWindowHoveredCocoa(_GLFWwindow* window)
} // autoreleasepool } // autoreleasepool
} }
int _glfwFramebufferTransparentCocoa(_GLFWwindow* window) GLFWbool _glfwFramebufferTransparentCocoa(_GLFWwindow* window)
{ {
@autoreleasepool { @autoreleasepool {
return ![window->ns.object isOpaque] && ![window->ns.view isOpaque]; return ![window->ns.object isOpaque] && ![window->ns.view isOpaque];
@ -1365,15 +1425,46 @@ int _glfwFramebufferTransparentCocoa(_GLFWwindow* window)
void _glfwSetWindowResizableCocoa(_GLFWwindow* window, GLFWbool enabled) void _glfwSetWindowResizableCocoa(_GLFWwindow* window, GLFWbool enabled)
{ {
@autoreleasepool { @autoreleasepool {
[window->ns.object setStyleMask:getStyleMask(window)];
const NSUInteger styleMask = [window->ns.object styleMask];
if (enabled)
{
[window->ns.object setStyleMask:(styleMask | NSWindowStyleMaskResizable)];
const NSWindowCollectionBehavior behavior =
NSWindowCollectionBehaviorFullScreenPrimary |
NSWindowCollectionBehaviorManaged;
[window->ns.object setCollectionBehavior:behavior];
}
else
{
[window->ns.object setStyleMask:(styleMask & ~NSWindowStyleMaskResizable)];
const NSWindowCollectionBehavior behavior =
NSWindowCollectionBehaviorFullScreenNone;
[window->ns.object setCollectionBehavior:behavior];
}
} // autoreleasepool } // autoreleasepool
} }
void _glfwSetWindowDecoratedCocoa(_GLFWwindow* window, GLFWbool enabled) void _glfwSetWindowDecoratedCocoa(_GLFWwindow* window, GLFWbool enabled)
{ {
@autoreleasepool { @autoreleasepool {
[window->ns.object setStyleMask:getStyleMask(window)];
NSUInteger styleMask = [window->ns.object styleMask];
if (enabled)
{
styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
styleMask &= ~NSWindowStyleMaskBorderless;
}
else
{
styleMask |= NSWindowStyleMaskBorderless;
styleMask &= ~(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
}
[window->ns.object setStyleMask:styleMask];
[window->ns.object makeFirstResponder:window->ns.view]; [window->ns.object makeFirstResponder:window->ns.view];
} // autoreleasepool } // autoreleasepool
} }
@ -1546,8 +1637,16 @@ void _glfwSetCursorPosCocoa(_GLFWwindow* window, double x, double y)
void _glfwSetCursorModeCocoa(_GLFWwindow* window, int mode) void _glfwSetCursorModeCocoa(_GLFWwindow* window, int mode)
{ {
@autoreleasepool { @autoreleasepool {
if (mode == GLFW_CURSOR_CAPTURED)
{
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED,
"Cocoa: Captured cursor mode not yet implemented");
}
if (_glfwWindowFocusedCocoa(window)) if (_glfwWindowFocusedCocoa(window))
updateCursorMode(window); updateCursorMode(window);
} // autoreleasepool } // autoreleasepool
} }
@ -1605,9 +1704,9 @@ int _glfwGetKeyScancodeCocoa(int key)
return _glfw.ns.scancodes[key]; return _glfw.ns.scancodes[key];
} }
int _glfwCreateCursorCocoa(_GLFWcursor* cursor, GLFWbool _glfwCreateCursorCocoa(_GLFWcursor* cursor,
const GLFWimage* image, const GLFWimage* image,
int xhot, int yhot) int xhot, int yhot)
{ {
@autoreleasepool { @autoreleasepool {
@ -1649,7 +1748,7 @@ int _glfwCreateCursorCocoa(_GLFWcursor* cursor,
} // autoreleasepool } // autoreleasepool
} }
int _glfwCreateStandardCursorCocoa(_GLFWcursor* cursor, int shape) GLFWbool _glfwCreateStandardCursorCocoa(_GLFWcursor* cursor, int shape)
{ {
@autoreleasepool { @autoreleasepool {
@ -1832,9 +1931,9 @@ void _glfwGetRequiredInstanceExtensionsCocoa(char** extensions)
} }
} }
int _glfwGetPhysicalDevicePresentationSupportCocoa(VkInstance instance, GLFWbool _glfwGetPhysicalDevicePresentationSupportCocoa(VkInstance instance,
VkPhysicalDevice device, VkPhysicalDevice device,
uint32_t queuefamily) uint32_t queuefamily)
{ {
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -1950,3 +2049,5 @@ GLFWAPI id glfwGetCocoaWindow(GLFWwindow* handle)
return window->ns.object; return window->ns.object;
} }
#endif // _GLFW_COCOA

View File

@ -48,16 +48,6 @@
// //
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
{ {
if (ctxconfig->share)
{
if (ctxconfig->client == GLFW_NO_API ||
ctxconfig->share->context.client == GLFW_NO_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return GLFW_FALSE;
}
}
if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API && if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
ctxconfig->source != GLFW_EGL_CONTEXT_API && ctxconfig->source != GLFW_EGL_CONTEXT_API &&
ctxconfig->source != GLFW_OSMESA_CONTEXT_API) ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
@ -78,6 +68,23 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
return GLFW_FALSE; return GLFW_FALSE;
} }
if (ctxconfig->share)
{
if (ctxconfig->client == GLFW_NO_API ||
ctxconfig->share->context.client == GLFW_NO_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return GLFW_FALSE;
}
if (ctxconfig->source != ctxconfig->share->context.source)
{
_glfwInputError(GLFW_INVALID_ENUM,
"Context creation APIs do not match between contexts");
return GLFW_FALSE;
}
}
if (ctxconfig->client == GLFW_OPENGL_API) if (ctxconfig->client == GLFW_OPENGL_API)
{ {
if ((ctxconfig->major < 1 || ctxconfig->minor < 0) || if ((ctxconfig->major < 1 || ctxconfig->minor < 0) ||

View File

@ -88,13 +88,30 @@ static int getEGLConfigAttrib(EGLConfig config, int attrib)
// Return the EGLConfig most closely matching the specified hints // Return the EGLConfig most closely matching the specified hints
// //
static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* desired, const _GLFWfbconfig* fbconfig,
EGLConfig* result) EGLConfig* result)
{ {
EGLConfig* nativeConfigs; EGLConfig* nativeConfigs;
_GLFWfbconfig* usableConfigs; _GLFWfbconfig* usableConfigs;
const _GLFWfbconfig* closest; const _GLFWfbconfig* closest;
int i, nativeCount, usableCount; int i, nativeCount, usableCount, apiBit;
GLFWbool wrongApiAvailable = GLFW_FALSE;
if (ctxconfig->client == GLFW_OPENGL_ES_API)
{
if (ctxconfig->major == 1)
apiBit = EGL_OPENGL_ES_BIT;
else
apiBit = EGL_OPENGL_ES2_BIT;
}
else
apiBit = EGL_OPENGL_BIT;
if (fbconfig->stereo)
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE, "EGL: Stereo rendering not supported");
return GLFW_FALSE;
}
eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount); eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
if (!nativeCount) if (!nativeCount)
@ -132,7 +149,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
if (!vi.visualid) if (!vi.visualid)
continue; continue;
if (desired->transparent) if (fbconfig->transparent)
{ {
int count; int count;
XVisualInfo* vis = XVisualInfo* vis =
@ -146,23 +163,10 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
} }
#endif // _GLFW_X11 #endif // _GLFW_X11
if (ctxconfig->client == GLFW_OPENGL_ES_API) if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & apiBit))
{ {
if (ctxconfig->major == 1) wrongApiAvailable = GLFW_TRUE;
{ continue;
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))
continue;
}
else
{
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))
continue;
}
}
else if (ctxconfig->client == GLFW_OPENGL_API)
{
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
continue;
} }
u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE); u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE);
@ -173,16 +177,60 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE); u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE);
u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE); u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
#if defined(_GLFW_WAYLAND)
if (_glfw.platform.platformID == GLFW_PLATFORM_WAYLAND)
{
// NOTE: The wl_surface opaque region is no guarantee that its buffer
// is presented as opaque, if it also has an alpha channel
// HACK: If EGL_EXT_present_opaque is unavailable, ignore any config
// with an alpha channel to ensure the buffer is opaque
if (!_glfw.egl.EXT_present_opaque)
{
if (!fbconfig->transparent && u->alphaBits > 0)
continue;
}
}
#endif // _GLFW_WAYLAND
u->samples = getEGLConfigAttrib(n, EGL_SAMPLES); u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);
u->doublebuffer = desired->doublebuffer; u->doublebuffer = fbconfig->doublebuffer;
u->handle = (uintptr_t) n; u->handle = (uintptr_t) n;
usableCount++; usableCount++;
} }
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount); closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);
if (closest) if (closest)
*result = (EGLConfig) closest->handle; *result = (EGLConfig) closest->handle;
else
{
if (wrongApiAvailable)
{
if (ctxconfig->client == GLFW_OPENGL_ES_API)
{
if (ctxconfig->major == 1)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to find support for OpenGL ES 1.x");
}
else
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to find support for OpenGL ES 2 or later");
}
}
else
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to find support for OpenGL");
}
}
else
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"EGL: Failed to find a suitable EGLConfig");
}
}
_glfw_free(nativeConfigs); _glfw_free(nativeConfigs);
_glfw_free(usableConfigs); _glfw_free(usableConfigs);
@ -535,11 +583,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
share = ctxconfig->share->context.egl.handle; share = ctxconfig->share->context.egl.handle;
if (!chooseEGLConfig(ctxconfig, fbconfig, &config)) if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"EGL: Failed to find a suitable EGLConfig");
return GLFW_FALSE; return GLFW_FALSE;
}
if (ctxconfig->client == GLFW_OPENGL_ES_API) if (ctxconfig->client == GLFW_OPENGL_ES_API)
{ {
@ -737,6 +781,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
#elif defined(__OpenBSD__) || defined(__NetBSD__) #elif defined(__OpenBSD__) || defined(__NetBSD__)
"libGL.so", "libGL.so",
#else #else
"libOpenGL.so.0",
"libGL.so.1", "libGL.so.1",
#endif #endif
NULL NULL
@ -799,11 +844,7 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
const long vimask = VisualScreenMask | VisualIDMask; const long vimask = VisualScreenMask | VisualIDMask;
if (!chooseEGLConfig(ctxconfig, fbconfig, &native)) if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"EGL: Failed to find a suitable EGLConfig");
return GLFW_FALSE; return GLFW_FALSE;
}
eglGetConfigAttrib(_glfw.egl.display, native, eglGetConfigAttrib(_glfw.egl.display, native,
EGL_NATIVE_VISUAL_ID, &visualID); EGL_NATIVE_VISUAL_ID, &visualID);

View File

@ -29,6 +29,8 @@
#include "internal.h" #include "internal.h"
#if defined(_GLFW_X11)
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
@ -226,7 +228,10 @@ static GLFWglproc getProcAddressGLX(const char* procname)
else if (_glfw.glx.GetProcAddressARB) else if (_glfw.glx.GetProcAddressARB)
return _glfw.glx.GetProcAddressARB((const GLubyte*) procname); return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
else else
{
// NOTE: glvnd provides GLX 1.4, so this can only happen with libGL
return _glfwPlatformGetModuleSymbol(_glfw.glx.handle, procname); return _glfwPlatformGetModuleSymbol(_glfw.glx.handle, procname);
}
} }
static void destroyContextGLX(_GLFWwindow* window) static void destroyContextGLX(_GLFWwindow* window)
@ -262,6 +267,7 @@ GLFWbool _glfwInitGLX(void)
#elif defined(__OpenBSD__) || defined(__NetBSD__) #elif defined(__OpenBSD__) || defined(__NetBSD__)
"libGL.so", "libGL.so",
#else #else
"libGLX.so.0",
"libGL.so.1", "libGL.so.1",
"libGL.so", "libGL.so",
#endif #endif
@ -710,3 +716,5 @@ GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle)
return window->context.glx.window; return window->context.glx.window;
} }
#endif // _GLFW_X11

View File

@ -44,6 +44,13 @@
#define _GLFW_JOYSTICK_BUTTON 2 #define _GLFW_JOYSTICK_BUTTON 2
#define _GLFW_JOYSTICK_HATBIT 3 #define _GLFW_JOYSTICK_HATBIT 3
#define GLFW_MOD_MASK (GLFW_MOD_SHIFT | \
GLFW_MOD_CONTROL | \
GLFW_MOD_ALT | \
GLFW_MOD_SUPER | \
GLFW_MOD_CAPS_LOCK | \
GLFW_MOD_NUM_LOCK)
// Initializes the platform joystick API if it has not been already // Initializes the platform joystick API if it has not been already
// //
static GLFWbool initJoysticks(void) static GLFWbool initJoysticks(void)
@ -266,6 +273,12 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
// //
void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods) void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods)
{ {
assert(window != NULL);
assert(key >= 0 || key == GLFW_KEY_UNKNOWN);
assert(key <= GLFW_KEY_LAST);
assert(action == GLFW_PRESS || action == GLFW_RELEASE);
assert(mods == (mods & GLFW_MOD_MASK));
if (key >= 0 && key <= GLFW_KEY_LAST) if (key >= 0 && key <= GLFW_KEY_LAST)
{ {
GLFWbool repeated = GLFW_FALSE; GLFWbool repeated = GLFW_FALSE;
@ -297,6 +310,10 @@ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int m
// //
void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool plain) void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool plain)
{ {
assert(window != NULL);
assert(mods == (mods & GLFW_MOD_MASK));
assert(plain == GLFW_TRUE || plain == GLFW_FALSE);
if (codepoint < 32 || (codepoint > 126 && codepoint < 160)) if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
return; return;
@ -317,6 +334,12 @@ void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool
// //
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset) 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);
if (window->callbacks.scroll) if (window->callbacks.scroll)
window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset); window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
} }
@ -325,6 +348,12 @@ void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
// //
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods) void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
{ {
assert(window != NULL);
assert(button >= 0);
assert(button <= GLFW_MOUSE_BUTTON_LAST);
assert(action == GLFW_PRESS || action == GLFW_RELEASE);
assert(mods == (mods & GLFW_MOD_MASK));
if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST) if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
return; return;
@ -345,6 +374,12 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
// //
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos) void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
{ {
assert(window != NULL);
assert(xpos > -FLT_MAX);
assert(xpos < FLT_MAX);
assert(ypos > -FLT_MAX);
assert(ypos < FLT_MAX);
if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos) if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)
return; return;
@ -359,6 +394,9 @@ void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
// //
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered) void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
{ {
assert(window != NULL);
assert(entered == GLFW_TRUE || entered == GLFW_FALSE);
if (window->callbacks.cursorEnter) if (window->callbacks.cursorEnter)
window->callbacks.cursorEnter((GLFWwindow*) window, entered); window->callbacks.cursorEnter((GLFWwindow*) window, entered);
} }
@ -367,6 +405,10 @@ void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
// //
void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths) void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
{ {
assert(window != NULL);
assert(count > 0);
assert(paths != NULL);
if (window->callbacks.drop) if (window->callbacks.drop)
window->callbacks.drop((GLFWwindow*) window, count, paths); window->callbacks.drop((GLFWwindow*) window, count, paths);
} }
@ -375,16 +417,26 @@ void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
// //
void _glfwInputJoystick(_GLFWjoystick* js, int event) void _glfwInputJoystick(_GLFWjoystick* js, int event)
{ {
const int jid = (int) (js - _glfw.joysticks); assert(js != NULL);
assert(event == GLFW_CONNECTED || event == GLFW_DISCONNECTED);
if (event == GLFW_CONNECTED)
js->connected = GLFW_TRUE;
else if (event == GLFW_DISCONNECTED)
js->connected = GLFW_FALSE;
if (_glfw.callbacks.joystick) if (_glfw.callbacks.joystick)
_glfw.callbacks.joystick(jid, event); _glfw.callbacks.joystick((int) (js - _glfw.joysticks), event);
} }
// Notifies shared code of the new value of a joystick axis // Notifies shared code of the new value of a joystick axis
// //
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value) void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value)
{ {
assert(js != NULL);
assert(axis >= 0);
assert(axis < js->axisCount);
js->axes[axis] = value; js->axes[axis] = value;
} }
@ -392,6 +444,11 @@ void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value)
// //
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value) void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value)
{ {
assert(js != NULL);
assert(button >= 0);
assert(button < js->buttonCount);
assert(value == GLFW_PRESS || value == GLFW_RELEASE);
js->buttons[button] = value; js->buttons[button] = value;
} }
@ -399,7 +456,18 @@ void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value)
// //
void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value) void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
{ {
const int base = js->buttonCount + hat * 4; int base;
assert(js != NULL);
assert(hat >= 0);
assert(hat < js->hatCount);
// Valid hat values only use the least significant nibble and have at most two bits
// set, which can be considered adjacent plus an arbitrary rotation within the nibble
assert((value & 0xf0) == 0);
assert((value & ((value << 2) | (value >> 2))) == 0);
base = js->buttonCount + hat * 4;
js->buttons[base + 0] = (value & 0x01) ? GLFW_PRESS : GLFW_RELEASE; js->buttons[base + 0] = (value & 0x01) ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[base + 1] = (value & 0x02) ? GLFW_PRESS : GLFW_RELEASE; js->buttons[base + 1] = (value & 0x02) ? GLFW_PRESS : GLFW_RELEASE;
@ -442,7 +510,7 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{ {
if (!_glfw.joysticks[jid].present) if (!_glfw.joysticks[jid].allocated)
break; break;
} }
@ -450,7 +518,7 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
return NULL; return NULL;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
js->present = GLFW_TRUE; js->allocated = GLFW_TRUE;
js->axes = _glfw_calloc(axisCount, sizeof(float)); js->axes = _glfw_calloc(axisCount, sizeof(float));
js->buttons = _glfw_calloc(buttonCount + (size_t) hatCount * 4, 1); js->buttons = _glfw_calloc(buttonCount + (size_t) hatCount * 4, 1);
js->hats = _glfw_calloc(hatCount, 1); js->hats = _glfw_calloc(hatCount, 1);
@ -528,7 +596,8 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
{ {
if (value != GLFW_CURSOR_NORMAL && if (value != GLFW_CURSOR_NORMAL &&
value != GLFW_CURSOR_HIDDEN && value != GLFW_CURSOR_HIDDEN &&
value != GLFW_CURSOR_DISABLED) value != GLFW_CURSOR_DISABLED &&
value != GLFW_CURSOR_CAPTURED)
{ {
_glfwInputError(GLFW_INVALID_ENUM, _glfwInputError(GLFW_INVALID_ENUM,
"Invalid cursor mode 0x%08X", "Invalid cursor mode 0x%08X",
@ -972,7 +1041,7 @@ GLFWAPI int glfwJoystickPresent(int jid)
return GLFW_FALSE; return GLFW_FALSE;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->connected)
return GLFW_FALSE; return GLFW_FALSE;
return _glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE); return _glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE);
@ -1000,7 +1069,7 @@ GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
return NULL; return NULL;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->connected)
return NULL; return NULL;
if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_AXES)) if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_AXES))
@ -1032,7 +1101,7 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
return NULL; return NULL;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->connected)
return NULL; return NULL;
if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_BUTTONS)) if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_BUTTONS))
@ -1068,7 +1137,7 @@ GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
return NULL; return NULL;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->connected)
return NULL; return NULL;
if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_BUTTONS)) if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_BUTTONS))
@ -1097,7 +1166,7 @@ GLFWAPI const char* glfwGetJoystickName(int jid)
return NULL; return NULL;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->connected)
return NULL; return NULL;
if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE)) if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE))
@ -1125,7 +1194,7 @@ GLFWAPI const char* glfwGetJoystickGUID(int jid)
return NULL; return NULL;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->connected)
return NULL; return NULL;
if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE)) if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE))
@ -1144,7 +1213,7 @@ GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer)
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->allocated)
return; return;
js->userPointer = pointer; js->userPointer = pointer;
@ -1160,7 +1229,7 @@ GLFWAPI void* glfwGetJoystickUserPointer(int jid)
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->allocated)
return NULL; return NULL;
return js->userPointer; return js->userPointer;
@ -1230,7 +1299,7 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string)
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{ {
_GLFWjoystick* js = _glfw.joysticks + jid; _GLFWjoystick* js = _glfw.joysticks + jid;
if (js->present) if (js->connected)
js->mapping = findValidMapping(js); js->mapping = findValidMapping(js);
} }
@ -1256,7 +1325,7 @@ GLFWAPI int glfwJoystickIsGamepad(int jid)
return GLFW_FALSE; return GLFW_FALSE;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->connected)
return GLFW_FALSE; return GLFW_FALSE;
if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE)) if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE))
@ -1284,7 +1353,7 @@ GLFWAPI const char* glfwGetGamepadName(int jid)
return NULL; return NULL;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->connected)
return NULL; return NULL;
if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE)) if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE))
@ -1319,7 +1388,7 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
return GLFW_FALSE; return GLFW_FALSE;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->connected)
return GLFW_FALSE; return GLFW_FALSE;
if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_ALL)) if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_ALL))

View File

@ -330,13 +330,6 @@ typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const c
#include "platform.h" #include "platform.h"
// Constructs a version number string from the public header macros
#define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r
#define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r)
#define _GLFW_VERSION_NUMBER _GLFW_MAKE_VERSION(GLFW_VERSION_MAJOR, \
GLFW_VERSION_MINOR, \
GLFW_VERSION_REVISION)
// Checks for whether the library has been initialized // Checks for whether the library has been initialized
#define _GLFW_REQUIRE_INIT() \ #define _GLFW_REQUIRE_INIT() \
if (!_glfw.initialized) \ if (!_glfw.initialized) \
@ -396,6 +389,8 @@ struct _GLFWinitconfig
// //
struct _GLFWwndconfig struct _GLFWwndconfig
{ {
int xpos;
int ypos;
int width; int width;
int height; int height;
const char* title; const char* title;
@ -421,6 +416,9 @@ struct _GLFWwndconfig
struct { struct {
GLFWbool keymenu; GLFWbool keymenu;
} win32; } win32;
struct {
char appId[256];
} wl;
}; };
// Context configuration // Context configuration
@ -634,7 +632,8 @@ struct _GLFWmapping
// //
struct _GLFWjoystick struct _GLFWjoystick
{ {
GLFWbool present; GLFWbool allocated;
GLFWbool connected;
float* axes; float* axes;
int axisCount; int axisCount;
unsigned char* buttons; unsigned char* buttons;
@ -680,8 +679,8 @@ struct _GLFWplatform
void (*setCursorMode)(_GLFWwindow*,int); void (*setCursorMode)(_GLFWwindow*,int);
void (*setRawMouseMotion)(_GLFWwindow*,GLFWbool); void (*setRawMouseMotion)(_GLFWwindow*,GLFWbool);
GLFWbool (*rawMouseMotionSupported)(void); GLFWbool (*rawMouseMotionSupported)(void);
int (*createCursor)(_GLFWcursor*,const GLFWimage*,int,int); GLFWbool (*createCursor)(_GLFWcursor*,const GLFWimage*,int,int);
int (*createStandardCursor)(_GLFWcursor*,int); GLFWbool (*createStandardCursor)(_GLFWcursor*,int);
void (*destroyCursor)(_GLFWcursor*); void (*destroyCursor)(_GLFWcursor*);
void (*setCursor)(_GLFWwindow*,_GLFWcursor*); void (*setCursor)(_GLFWwindow*,_GLFWcursor*);
const char* (*getScancodeName)(int); const char* (*getScancodeName)(int);
@ -690,7 +689,7 @@ struct _GLFWplatform
const char* (*getClipboardString)(void); const char* (*getClipboardString)(void);
GLFWbool (*initJoysticks)(void); GLFWbool (*initJoysticks)(void);
void (*terminateJoysticks)(void); void (*terminateJoysticks)(void);
int (*pollJoystick)(_GLFWjoystick*,int); GLFWbool (*pollJoystick)(_GLFWjoystick*,int);
const char* (*getMappingName)(void); const char* (*getMappingName)(void);
void (*updateGamepadGUID)(char*); void (*updateGamepadGUID)(char*);
// monitor // monitor
@ -703,7 +702,7 @@ struct _GLFWplatform
GLFWbool (*getGammaRamp)(_GLFWmonitor*,GLFWgammaramp*); GLFWbool (*getGammaRamp)(_GLFWmonitor*,GLFWgammaramp*);
void (*setGammaRamp)(_GLFWmonitor*,const GLFWgammaramp*); void (*setGammaRamp)(_GLFWmonitor*,const GLFWgammaramp*);
// window // window
int (*createWindow)(_GLFWwindow*,const _GLFWwndconfig*,const _GLFWctxconfig*,const _GLFWfbconfig*); GLFWbool (*createWindow)(_GLFWwindow*,const _GLFWwndconfig*,const _GLFWctxconfig*,const _GLFWfbconfig*);
void (*destroyWindow)(_GLFWwindow*); void (*destroyWindow)(_GLFWwindow*);
void (*setWindowTitle)(_GLFWwindow*,const char*); void (*setWindowTitle)(_GLFWwindow*,const char*);
void (*setWindowIcon)(_GLFWwindow*,int,const GLFWimage*); void (*setWindowIcon)(_GLFWwindow*,int,const GLFWimage*);
@ -724,12 +723,12 @@ struct _GLFWplatform
void (*requestWindowAttention)(_GLFWwindow*); void (*requestWindowAttention)(_GLFWwindow*);
void (*focusWindow)(_GLFWwindow*); void (*focusWindow)(_GLFWwindow*);
void (*setWindowMonitor)(_GLFWwindow*,_GLFWmonitor*,int,int,int,int,int); void (*setWindowMonitor)(_GLFWwindow*,_GLFWmonitor*,int,int,int,int,int);
int (*windowFocused)(_GLFWwindow*); GLFWbool (*windowFocused)(_GLFWwindow*);
int (*windowIconified)(_GLFWwindow*); GLFWbool (*windowIconified)(_GLFWwindow*);
int (*windowVisible)(_GLFWwindow*); GLFWbool (*windowVisible)(_GLFWwindow*);
int (*windowMaximized)(_GLFWwindow*); GLFWbool (*windowMaximized)(_GLFWwindow*);
int (*windowHovered)(_GLFWwindow*); GLFWbool (*windowHovered)(_GLFWwindow*);
int (*framebufferTransparent)(_GLFWwindow*); GLFWbool (*framebufferTransparent)(_GLFWwindow*);
float (*getWindowOpacity)(_GLFWwindow*); float (*getWindowOpacity)(_GLFWwindow*);
void (*setWindowResizable)(_GLFWwindow*,GLFWbool); void (*setWindowResizable)(_GLFWwindow*,GLFWbool);
void (*setWindowDecorated)(_GLFWwindow*,GLFWbool); void (*setWindowDecorated)(_GLFWwindow*,GLFWbool);
@ -746,7 +745,7 @@ struct _GLFWplatform
EGLNativeWindowType (*getEGLNativeWindow)(_GLFWwindow*); EGLNativeWindowType (*getEGLNativeWindow)(_GLFWwindow*);
// vulkan // vulkan
void (*getRequiredInstanceExtensions)(char**); void (*getRequiredInstanceExtensions)(char**);
int (*getPhysicalDevicePresentationSupport)(VkInstance,VkPhysicalDevice,uint32_t); GLFWbool (*getPhysicalDevicePresentationSupport)(VkInstance,VkPhysicalDevice,uint32_t);
VkResult (*createWindowSurface)(VkInstance,_GLFWwindow*,const VkAllocationCallbacks*,VkSurfaceKHR*); VkResult (*createWindowSurface)(VkInstance,_GLFWwindow*,const VkAllocationCallbacks*,VkSurfaceKHR*);
}; };

View File

@ -29,6 +29,8 @@
#include "internal.h" #include "internal.h"
#if defined(GLFW_BUILD_LINUX_JOYSTICK)
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/inotify.h> #include <sys/inotify.h>
@ -128,7 +130,7 @@ static GLFWbool openJoystickDevice(const char* path)
{ {
for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{ {
if (!_glfw.joysticks[jid].present) if (!_glfw.joysticks[jid].connected)
continue; continue;
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0) if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
return GLFW_FALSE; return GLFW_FALSE;
@ -157,7 +159,7 @@ static GLFWbool openJoystickDevice(const char* path)
} }
// Ensure this device supports the events expected of a joystick // Ensure this device supports the events expected of a joystick
if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits)) if (!isBitSet(EV_ABS, evBits))
{ {
close(linjs.fd); close(linjs.fd);
return GLFW_FALSE; return GLFW_FALSE;
@ -245,9 +247,9 @@ static GLFWbool openJoystickDevice(const char* path)
// //
static void closeJoystick(_GLFWjoystick* js) static void closeJoystick(_GLFWjoystick* js)
{ {
_glfwInputJoystick(js, GLFW_DISCONNECTED);
close(js->linjs.fd); close(js->linjs.fd);
_glfwFreeJoystick(js); _glfwFreeJoystick(js);
_glfwInputJoystick(js, GLFW_DISCONNECTED);
} }
// Lexically compare joysticks by name; used by qsort // Lexically compare joysticks by name; used by qsort
@ -366,7 +368,7 @@ void _glfwTerminateJoysticksLinux(void)
for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{ {
_GLFWjoystick* js = _glfw.joysticks + jid; _GLFWjoystick* js = _glfw.joysticks + jid;
if (js->present) if (js->connected)
closeJoystick(js); closeJoystick(js);
} }
@ -380,7 +382,7 @@ void _glfwTerminateJoysticksLinux(void)
} }
} }
int _glfwPollJoystickLinux(_GLFWjoystick* js, int mode) GLFWbool _glfwPollJoystickLinux(_GLFWjoystick* js, int mode)
{ {
// Read all queued events (non-blocking) // Read all queued events (non-blocking)
for (;;) for (;;)
@ -417,7 +419,7 @@ int _glfwPollJoystickLinux(_GLFWjoystick* js, int mode)
handleAbsEvent(js, e.code, e.value); handleAbsEvent(js, e.code, e.value);
} }
return js->present; return js->connected;
} }
const char* _glfwGetMappingNameLinux(void) const char* _glfwGetMappingNameLinux(void)
@ -429,3 +431,5 @@ void _glfwUpdateGamepadGUIDLinux(char* guid)
{ {
} }
#endif // GLFW_BUILD_LINUX_JOYSTICK

View File

@ -31,8 +31,6 @@
#define GLFW_LINUX_JOYSTICK_STATE _GLFWjoystickLinux linjs; #define GLFW_LINUX_JOYSTICK_STATE _GLFWjoystickLinux linjs;
#define GLFW_LINUX_LIBRARY_JOYSTICK_STATE _GLFWlibraryLinux linjs; #define GLFW_LINUX_LIBRARY_JOYSTICK_STATE _GLFWlibraryLinux linjs;
#define GLFW_BUILD_LINUX_MAPPINGS
// Linux-specific joystick data // Linux-specific joystick data
// //
typedef struct _GLFWjoystickLinux typedef struct _GLFWjoystickLinux
@ -59,7 +57,7 @@ void _glfwDetectJoystickConnectionLinux(void);
GLFWbool _glfwInitJoysticksLinux(void); GLFWbool _glfwInitJoysticksLinux(void);
void _glfwTerminateJoysticksLinux(void); void _glfwTerminateJoysticksLinux(void);
int _glfwPollJoystickLinux(_GLFWjoystick* js, int mode); GLFWbool _glfwPollJoystickLinux(_GLFWjoystick* js, int mode);
const char* _glfwGetMappingNameLinux(void); const char* _glfwGetMappingNameLinux(void);
void _glfwUpdateGamepadGUIDLinux(char* guid); void _glfwUpdateGamepadGUIDLinux(char* guid);

View File

@ -60,7 +60,7 @@
const char* _glfwDefaultMappings[] = const char* _glfwDefaultMappings[] =
{ {
#if defined(GLFW_BUILD_WIN32_MAPPINGS) #if defined(_GLFW_WIN32)
"03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,", "03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,",
"03000000c82d00002038000000000000,8bitdo,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,", "03000000c82d00002038000000000000,8bitdo,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",
"03000000c82d00000951000000000000,8BitDo Dogbone Modkit,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows,", "03000000c82d00000951000000000000,8BitDo Dogbone Modkit,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows,",
@ -426,9 +426,9 @@ const char* _glfwDefaultMappings[] =
"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
#endif // GLFW_BUILD_WIN32_MAPPINGS #endif // _GLFW_WIN32
#if defined(GLFW_BUILD_COCOA_MAPPINGS) #if defined(_GLFW_COCOA)
"030000008f0e00000300000009010000,2In1 USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,", "030000008f0e00000300000009010000,2In1 USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,",
"03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,", "03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",
"03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,", "03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",
@ -598,9 +598,9 @@ const char* _glfwDefaultMappings[] =
"03000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,", "03000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,",
"03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,", "03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
"03000000120c0000101e000000010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,", "03000000120c0000101e000000010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
#endif // GLFW_BUILD_COCOA_MAPPINGS #endif // _GLFW_COCOA
#if defined(GLFW_BUILD_LINUX_MAPPINGS) #if defined(GLFW_BUILD_LINUX_JOYSTICK)
"03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,", "03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
"05000000c82d00001038000000010000,8Bitdo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,", "05000000c82d00001038000000010000,8Bitdo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
"05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux,", "05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux,",
@ -996,6 +996,6 @@ const char* _glfwDefaultMappings[] =
"03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,", "03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,",
"03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
"03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
#endif // GLFW_BUILD_LINUX_MAPPINGS #endif // GLFW_BUILD_LINUX_JOYSTICK
}; };

View File

@ -60,7 +60,7 @@
const char* _glfwDefaultMappings[] = const char* _glfwDefaultMappings[] =
{ {
#if defined(GLFW_BUILD_WIN32_MAPPINGS) #if defined(_GLFW_WIN32)
@GLFW_WIN32_MAPPINGS@ @GLFW_WIN32_MAPPINGS@
"78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
@ -69,14 +69,14 @@ const char* _glfwDefaultMappings[] =
"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
#endif // GLFW_BUILD_WIN32_MAPPINGS #endif // _GLFW_WIN32
#if defined(GLFW_BUILD_COCOA_MAPPINGS) #if defined(_GLFW_COCOA)
@GLFW_COCOA_MAPPINGS@ @GLFW_COCOA_MAPPINGS@
#endif // GLFW_BUILD_COCOA_MAPPINGS #endif // _GLFW_COCOA
#if defined(GLFW_BUILD_LINUX_MAPPINGS) #if defined(GLFW_BUILD_LINUX_JOYSTICK)
@GLFW_LINUX_MAPPINGS@ @GLFW_LINUX_MAPPINGS@
#endif // GLFW_BUILD_LINUX_MAPPINGS #endif // GLFW_BUILD_LINUX_JOYSTICK
}; };

View File

@ -96,6 +96,10 @@ static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
// //
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement) void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
{ {
assert(monitor != NULL);
assert(action == GLFW_CONNECTED || action == GLFW_DISCONNECTED);
assert(placement == _GLFW_INSERT_FIRST || placement == _GLFW_INSERT_LAST);
if (action == GLFW_CONNECTED) if (action == GLFW_CONNECTED)
{ {
_glfw.monitorCount++; _glfw.monitorCount++;
@ -155,6 +159,7 @@ void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
// //
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window) void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
{ {
assert(monitor != NULL);
monitor->window = window; monitor->window = window;
} }

View File

@ -28,6 +28,8 @@
#include "internal.h" #include "internal.h"
#if defined(_GLFW_COCOA)
#include <unistd.h> #include <unistd.h>
#include <math.h> #include <math.h>
@ -374,3 +376,5 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle)
return window->context.nsgl.object; return window->context.nsgl.object;
} }
#endif // _GLFW_COCOA

View File

@ -42,7 +42,7 @@ void _glfwTerminateJoysticksNull(void)
{ {
} }
int _glfwPollJoystickNull(_GLFWjoystick* js, int mode) GLFWbool _glfwPollJoystickNull(_GLFWjoystick* js, int mode)
{ {
return GLFW_FALSE; return GLFW_FALSE;
} }

View File

@ -26,7 +26,7 @@
GLFWbool _glfwInitJoysticksNull(void); GLFWbool _glfwInitJoysticksNull(void);
void _glfwTerminateJoysticksNull(void); void _glfwTerminateJoysticksNull(void);
int _glfwPollJoystickNull(_GLFWjoystick* js, int mode); GLFWbool _glfwPollJoystickNull(_GLFWjoystick* js, int mode);
const char* _glfwGetMappingNameNull(void); const char* _glfwGetMappingNameNull(void);
void _glfwUpdateGamepadGUIDNull(char* guid); void _glfwUpdateGamepadGUIDNull(char* guid);

View File

@ -85,7 +85,7 @@ void _glfwGetVideoModeNull(_GLFWmonitor* monitor, GLFWvidmode* mode);
GLFWbool _glfwGetGammaRampNull(_GLFWmonitor* monitor, GLFWgammaramp* ramp); GLFWbool _glfwGetGammaRampNull(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
void _glfwSetGammaRampNull(_GLFWmonitor* monitor, const GLFWgammaramp* ramp); void _glfwSetGammaRampNull(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
int _glfwCreateWindowNull(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); GLFWbool _glfwCreateWindowNull(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig);
void _glfwDestroyWindowNull(_GLFWwindow* window); void _glfwDestroyWindowNull(_GLFWwindow* window);
void _glfwSetWindowTitleNull(_GLFWwindow* window, const char* title); void _glfwSetWindowTitleNull(_GLFWwindow* window, const char* title);
void _glfwSetWindowIconNull(_GLFWwindow* window, int count, const GLFWimage* images); void _glfwSetWindowIconNull(_GLFWwindow* window, int count, const GLFWimage* images);
@ -102,9 +102,9 @@ void _glfwGetWindowContentScaleNull(_GLFWwindow* window, float* xscale, float* y
void _glfwIconifyWindowNull(_GLFWwindow* window); void _glfwIconifyWindowNull(_GLFWwindow* window);
void _glfwRestoreWindowNull(_GLFWwindow* window); void _glfwRestoreWindowNull(_GLFWwindow* window);
void _glfwMaximizeWindowNull(_GLFWwindow* window); void _glfwMaximizeWindowNull(_GLFWwindow* window);
int _glfwWindowMaximizedNull(_GLFWwindow* window); GLFWbool _glfwWindowMaximizedNull(_GLFWwindow* window);
int _glfwWindowHoveredNull(_GLFWwindow* window); GLFWbool _glfwWindowHoveredNull(_GLFWwindow* window);
int _glfwFramebufferTransparentNull(_GLFWwindow* window); GLFWbool _glfwFramebufferTransparentNull(_GLFWwindow* window);
void _glfwSetWindowResizableNull(_GLFWwindow* window, GLFWbool enabled); void _glfwSetWindowResizableNull(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowDecoratedNull(_GLFWwindow* window, GLFWbool enabled); void _glfwSetWindowDecoratedNull(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowFloatingNull(_GLFWwindow* window, GLFWbool enabled); void _glfwSetWindowFloatingNull(_GLFWwindow* window, GLFWbool enabled);
@ -118,9 +118,9 @@ void _glfwRequestWindowAttentionNull(_GLFWwindow* window);
void _glfwRequestWindowAttentionNull(_GLFWwindow* window); void _glfwRequestWindowAttentionNull(_GLFWwindow* window);
void _glfwHideWindowNull(_GLFWwindow* window); void _glfwHideWindowNull(_GLFWwindow* window);
void _glfwFocusWindowNull(_GLFWwindow* window); void _glfwFocusWindowNull(_GLFWwindow* window);
int _glfwWindowFocusedNull(_GLFWwindow* window); GLFWbool _glfwWindowFocusedNull(_GLFWwindow* window);
int _glfwWindowIconifiedNull(_GLFWwindow* window); GLFWbool _glfwWindowIconifiedNull(_GLFWwindow* window);
int _glfwWindowVisibleNull(_GLFWwindow* window); GLFWbool _glfwWindowVisibleNull(_GLFWwindow* window);
void _glfwPollEventsNull(void); void _glfwPollEventsNull(void);
void _glfwWaitEventsNull(void); void _glfwWaitEventsNull(void);
void _glfwWaitEventsTimeoutNull(double timeout); void _glfwWaitEventsTimeoutNull(double timeout);
@ -128,8 +128,8 @@ void _glfwPostEmptyEventNull(void);
void _glfwGetCursorPosNull(_GLFWwindow* window, double* xpos, double* ypos); void _glfwGetCursorPosNull(_GLFWwindow* window, double* xpos, double* ypos);
void _glfwSetCursorPosNull(_GLFWwindow* window, double x, double y); void _glfwSetCursorPosNull(_GLFWwindow* window, double x, double y);
void _glfwSetCursorModeNull(_GLFWwindow* window, int mode); void _glfwSetCursorModeNull(_GLFWwindow* window, int mode);
int _glfwCreateCursorNull(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot); GLFWbool _glfwCreateCursorNull(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
int _glfwCreateStandardCursorNull(_GLFWcursor* cursor, int shape); GLFWbool _glfwCreateStandardCursorNull(_GLFWcursor* cursor, int shape);
void _glfwDestroyCursorNull(_GLFWcursor* cursor); void _glfwDestroyCursorNull(_GLFWcursor* cursor);
void _glfwSetCursorNull(_GLFWwindow* window, _GLFWcursor* cursor); void _glfwSetCursorNull(_GLFWwindow* window, _GLFWcursor* cursor);
void _glfwSetClipboardStringNull(const char* string); void _glfwSetClipboardStringNull(const char* string);
@ -142,7 +142,7 @@ EGLNativeDisplayType _glfwGetEGLNativeDisplayNull(void);
EGLNativeWindowType _glfwGetEGLNativeWindowNull(_GLFWwindow* window); EGLNativeWindowType _glfwGetEGLNativeWindowNull(_GLFWwindow* window);
void _glfwGetRequiredInstanceExtensionsNull(char** extensions); void _glfwGetRequiredInstanceExtensionsNull(char** extensions);
int _glfwGetPhysicalDevicePresentationSupportNull(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); GLFWbool _glfwGetPhysicalDevicePresentationSupportNull(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
VkResult _glfwCreateWindowSurfaceNull(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); VkResult _glfwCreateWindowSurfaceNull(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
void _glfwPollMonitorsNull(void); void _glfwPollMonitorsNull(void);

View File

@ -82,8 +82,17 @@ static int createNativeWindow(_GLFWwindow* window,
fitToMonitor(window); fitToMonitor(window);
else else
{ {
window->null.xpos = 17; if (wndconfig->xpos == GLFW_ANY_POSITION && wndconfig->ypos == GLFW_ANY_POSITION)
window->null.ypos = 17; {
window->null.xpos = 17;
window->null.ypos = 17;
}
else
{
window->null.xpos = wndconfig->xpos;
window->null.ypos = wndconfig->ypos;
}
window->null.width = wndconfig->width; window->null.width = wndconfig->width;
window->null.height = wndconfig->height; window->null.height = wndconfig->height;
} }
@ -103,10 +112,10 @@ static int createNativeWindow(_GLFWwindow* window,
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
int _glfwCreateWindowNull(_GLFWwindow* window, GLFWbool _glfwCreateWindowNull(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig, const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) const _GLFWfbconfig* fbconfig)
{ {
if (!createNativeWindow(window, wndconfig, fbconfig)) if (!createNativeWindow(window, wndconfig, fbconfig))
return GLFW_FALSE; return GLFW_FALSE;
@ -362,12 +371,12 @@ void _glfwMaximizeWindowNull(_GLFWwindow* window)
} }
} }
int _glfwWindowMaximizedNull(_GLFWwindow* window) GLFWbool _glfwWindowMaximizedNull(_GLFWwindow* window)
{ {
return window->null.maximized; return window->null.maximized;
} }
int _glfwWindowHoveredNull(_GLFWwindow* window) GLFWbool _glfwWindowHoveredNull(_GLFWwindow* window)
{ {
return _glfw.null.xcursor >= window->null.xpos && return _glfw.null.xcursor >= window->null.xpos &&
_glfw.null.ycursor >= window->null.ypos && _glfw.null.ycursor >= window->null.ypos &&
@ -375,7 +384,7 @@ int _glfwWindowHoveredNull(_GLFWwindow* window)
_glfw.null.ycursor <= window->null.ypos + window->null.height - 1; _glfw.null.ycursor <= window->null.ypos + window->null.height - 1;
} }
int _glfwFramebufferTransparentNull(_GLFWwindow* window) GLFWbool _glfwFramebufferTransparentNull(_GLFWwindow* window)
{ {
return window->null.transparent; return window->null.transparent;
} }
@ -461,17 +470,17 @@ void _glfwFocusWindowNull(_GLFWwindow* window)
_glfwInputWindowFocus(window, GLFW_TRUE); _glfwInputWindowFocus(window, GLFW_TRUE);
} }
int _glfwWindowFocusedNull(_GLFWwindow* window) GLFWbool _glfwWindowFocusedNull(_GLFWwindow* window)
{ {
return _glfw.null.focusedWindow == window; return _glfw.null.focusedWindow == window;
} }
int _glfwWindowIconifiedNull(_GLFWwindow* window) GLFWbool _glfwWindowIconifiedNull(_GLFWwindow* window)
{ {
return window->null.iconified; return window->null.iconified;
} }
int _glfwWindowVisibleNull(_GLFWwindow* window) GLFWbool _glfwWindowVisibleNull(_GLFWwindow* window)
{ {
return window->null.visible; return window->null.visible;
} }
@ -510,14 +519,14 @@ void _glfwSetCursorModeNull(_GLFWwindow* window, int mode)
{ {
} }
int _glfwCreateCursorNull(_GLFWcursor* cursor, GLFWbool _glfwCreateCursorNull(_GLFWcursor* cursor,
const GLFWimage* image, const GLFWimage* image,
int xhot, int yhot) int xhot, int yhot)
{ {
return GLFW_TRUE; return GLFW_TRUE;
} }
int _glfwCreateStandardCursorNull(_GLFWcursor* cursor, int shape) GLFWbool _glfwCreateStandardCursorNull(_GLFWcursor* cursor, int shape)
{ {
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -693,9 +702,9 @@ void _glfwGetRequiredInstanceExtensionsNull(char** extensions)
{ {
} }
int _glfwGetPhysicalDevicePresentationSupportNull(VkInstance instance, GLFWbool _glfwGetPhysicalDevicePresentationSupportNull(VkInstance instance,
VkPhysicalDevice device, VkPhysicalDevice device,
uint32_t queuefamily) uint32_t queuefamily)
{ {
return GLFW_FALSE; return GLFW_FALSE;
} }

View File

@ -29,6 +29,10 @@
#include "internal.h" #include "internal.h"
// These construct a string literal from individual numeric constants
#define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r
#define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r)
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -146,7 +150,9 @@ GLFWAPI int glfwPlatformSupported(int platformID)
GLFWAPI const char* glfwGetVersionString(void) GLFWAPI const char* glfwGetVersionString(void)
{ {
return _GLFW_VERSION_NUMBER return _GLFW_MAKE_VERSION(GLFW_VERSION_MAJOR,
GLFW_VERSION_MINOR,
GLFW_VERSION_REVISION)
#if defined(_GLFW_WIN32) #if defined(_GLFW_WIN32)
" Win32 WGL" " Win32 WGL"
#endif #endif

View File

@ -25,6 +25,18 @@
// //
//======================================================================== //========================================================================
#if defined(GLFW_BUILD_WIN32_TIMER) || \
defined(GLFW_BUILD_WIN32_MODULE) || \
defined(GLFW_BUILD_WIN32_THREAD) || \
defined(GLFW_BUILD_COCOA_TIMER) || \
defined(GLFW_BUILD_POSIX_TIMER) || \
defined(GLFW_BUILD_POSIX_MODULE) || \
defined(GLFW_BUILD_POSIX_THREAD) || \
defined(GLFW_BUILD_POSIX_POLL) || \
defined(GLFW_BUILD_LINUX_JOYSTICK)
#error "You must not define these; define zero or more _GLFW_<platform> macros instead"
#endif
#include "null_platform.h" #include "null_platform.h"
#if defined(_GLFW_WIN32) #if defined(_GLFW_WIN32)
@ -86,6 +98,10 @@
#endif #endif
#if (defined(_GLFW_X11) || defined(_GLFW_WAYLAND)) && defined(__linux__) #if (defined(_GLFW_X11) || defined(_GLFW_WAYLAND)) && defined(__linux__)
#define GLFW_BUILD_LINUX_JOYSTICK
#endif
#if defined(GLFW_BUILD_LINUX_JOYSTICK)
#include "linux_joystick.h" #include "linux_joystick.h"
#else #else
#define GLFW_LINUX_JOYSTICK_STATE #define GLFW_LINUX_JOYSTICK_STATE
@ -141,23 +157,47 @@
GLFW_GLX_LIBRARY_CONTEXT_STATE GLFW_GLX_LIBRARY_CONTEXT_STATE
#if defined(_WIN32) #if defined(_WIN32)
#define GLFW_BUILD_WIN32_THREAD
#else
#define GLFW_BUILD_POSIX_THREAD
#endif
#if defined(GLFW_BUILD_WIN32_THREAD)
#include "win32_thread.h" #include "win32_thread.h"
#define GLFW_PLATFORM_TLS_STATE GLFW_WIN32_TLS_STATE #define GLFW_PLATFORM_TLS_STATE GLFW_WIN32_TLS_STATE
#define GLFW_PLATFORM_MUTEX_STATE GLFW_WIN32_MUTEX_STATE #define GLFW_PLATFORM_MUTEX_STATE GLFW_WIN32_MUTEX_STATE
#else #elif defined(GLFW_BUILD_POSIX_THREAD)
#include "posix_thread.h" #include "posix_thread.h"
#define GLFW_PLATFORM_TLS_STATE GLFW_POSIX_TLS_STATE #define GLFW_PLATFORM_TLS_STATE GLFW_POSIX_TLS_STATE
#define GLFW_PLATFORM_MUTEX_STATE GLFW_POSIX_MUTEX_STATE #define GLFW_PLATFORM_MUTEX_STATE GLFW_POSIX_MUTEX_STATE
#endif #endif
#if defined(_WIN32) #if defined(_WIN32)
#define GLFW_BUILD_WIN32_TIMER
#elif defined(__APPLE__)
#define GLFW_BUILD_COCOA_TIMER
#else
#define GLFW_BUILD_POSIX_TIMER
#endif
#if defined(GLFW_BUILD_WIN32_TIMER)
#include "win32_time.h" #include "win32_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_WIN32_LIBRARY_TIMER_STATE #define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_WIN32_LIBRARY_TIMER_STATE
#elif defined(__APPLE__) #elif defined(GLFW_BUILD_COCOA_TIMER)
#include "cocoa_time.h" #include "cocoa_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_COCOA_LIBRARY_TIMER_STATE #define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_COCOA_LIBRARY_TIMER_STATE
#else #elif defined(GLFW_BUILD_POSIX_TIMER)
#include "posix_time.h" #include "posix_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_POSIX_LIBRARY_TIMER_STATE #define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_POSIX_LIBRARY_TIMER_STATE
#endif #endif
#if defined(_WIN32)
#define GLFW_BUILD_WIN32_MODULE
#else
#define GLFW_BUILD_POSIX_MODULE
#endif
#if defined(_GLFW_WAYLAND) || defined(_GLFW_X11)
#define GLFW_BUILD_POSIX_POLL
#endif

View File

@ -28,6 +28,8 @@
#include "internal.h" #include "internal.h"
#if defined(GLFW_BUILD_POSIX_MODULE)
#include <dlfcn.h> #include <dlfcn.h>
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -49,3 +51,5 @@ GLFWproc _glfwPlatformGetModuleSymbol(void* module, const char* name)
return dlsym(module, name); return dlsym(module, name);
} }
#endif // GLFW_BUILD_POSIX_MODULE

View File

@ -30,6 +30,8 @@
#include "internal.h" #include "internal.h"
#if defined(GLFW_BUILD_POSIX_POLL)
#include <signal.h> #include <signal.h>
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
@ -79,3 +81,5 @@ GLFWbool _glfwPollPOSIX(struct pollfd* fds, nfds_t count, double* timeout)
} }
} }
#endif // GLFW_BUILD_POSIX_POLL

View File

@ -29,6 +29,8 @@
#include "internal.h" #include "internal.h"
#if defined(GLFW_BUILD_POSIX_THREAD)
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
@ -103,3 +105,5 @@ void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
pthread_mutex_unlock(&mutex->posix.handle); pthread_mutex_unlock(&mutex->posix.handle);
} }
#endif // GLFW_BUILD_POSIX_THREAD

View File

@ -29,6 +29,8 @@
#include "internal.h" #include "internal.h"
#if defined(GLFW_BUILD_POSIX_TIMER)
#include <unistd.h> #include <unistd.h>
#include <sys/time.h> #include <sys/time.h>
@ -61,3 +63,5 @@ uint64_t _glfwPlatformGetTimerFrequency(void)
return _glfw.timer.posix.frequency; return _glfw.timer.posix.frequency;
} }
#endif // GLFW_BUILD_POSIX_TIMER

View File

@ -29,6 +29,8 @@
#include "internal.h" #include "internal.h"
#if defined(_GLFW_WIN32)
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
@ -72,18 +74,13 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
int attribs[40]; int attribs[40];
int values[sizeof(attribs) / sizeof(attribs[0])]; int values[sizeof(attribs) / sizeof(attribs[0])];
nativeCount = DescribePixelFormat(window->context.wgl.dc,
1,
sizeof(PIXELFORMATDESCRIPTOR),
NULL);
if (_glfw.wgl.ARB_pixel_format) if (_glfw.wgl.ARB_pixel_format)
{ {
const int attrib = WGL_NUMBER_PIXEL_FORMATS_ARB;
if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc,
1, 0, 1, &attrib, &nativeCount))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve pixel format attribute");
return 0;
}
ADD_ATTRIB(WGL_SUPPORT_OPENGL_ARB); ADD_ATTRIB(WGL_SUPPORT_OPENGL_ARB);
ADD_ATTRIB(WGL_DRAW_TO_WINDOW_ARB); ADD_ATTRIB(WGL_DRAW_TO_WINDOW_ARB);
ADD_ATTRIB(WGL_PIXEL_TYPE_ARB); ADD_ATTRIB(WGL_PIXEL_TYPE_ARB);
@ -121,13 +118,6 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
ADD_ATTRIB(WGL_COLORSPACE_EXT); ADD_ATTRIB(WGL_COLORSPACE_EXT);
} }
} }
else
{
nativeCount = DescribePixelFormat(window->context.wgl.dc,
1,
sizeof(PIXELFORMATDESCRIPTOR),
NULL);
}
usableConfigs = _glfw_calloc(nativeCount, sizeof(_GLFWfbconfig)); usableConfigs = _glfw_calloc(nativeCount, sizeof(_GLFWfbconfig));
@ -788,3 +778,5 @@ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
return window->context.wgl.handle; return window->context.wgl.handle;
} }
#endif // _GLFW_WIN32

View File

@ -29,6 +29,8 @@
#include "internal.h" #include "internal.h"
#if defined(_GLFW_WIN32)
#include <stdlib.h> #include <stdlib.h>
static const GUID _glfw_GUID_DEVINTERFACE_HID = static const GUID _glfw_GUID_DEVINTERFACE_HID =
@ -331,15 +333,64 @@ static void createKeyTables(void)
} }
} }
// Window procedure for the hidden helper window
//
static LRESULT CALLBACK helperWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DISPLAYCHANGE:
_glfwPollMonitorsWin32();
break;
case WM_DEVICECHANGE:
{
if (!_glfw.joysticksInitialized)
break;
if (wParam == DBT_DEVICEARRIVAL)
{
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
_glfwDetectJoystickConnectionWin32();
}
else if (wParam == DBT_DEVICEREMOVECOMPLETE)
{
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
_glfwDetectJoystickDisconnectionWin32();
}
break;
}
}
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
// Creates a dummy window for behind-the-scenes work // Creates a dummy window for behind-the-scenes work
// //
static GLFWbool createHelperWindow(void) static GLFWbool createHelperWindow(void)
{ {
MSG msg; MSG msg;
WNDCLASSEXW wc = { sizeof(wc) };
wc.style = CS_OWNDC;
wc.lpfnWndProc = (WNDPROC) helperWindowProc;
wc.hInstance = _glfw.win32.instance;
wc.lpszClassName = L"GLFW3 Helper";
_glfw.win32.helperWindowClass = RegisterClassExW(&wc);
if (!_glfw.win32.helperWindowClass)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WIn32: Failed to register helper window class");
return GLFW_FALSE;
}
_glfw.win32.helperWindowHandle = _glfw.win32.helperWindowHandle =
CreateWindowExW(WS_EX_OVERLAPPEDWINDOW, CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
_GLFW_WNDCLASSNAME, MAKEINTATOM(_glfw.win32.helperWindowClass),
L"GLFW message window", L"GLFW message window",
WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
0, 0, 1, 1, 0, 0, 1, 1,
@ -647,9 +698,6 @@ int _glfwInitWin32(void)
else if (IsWindowsVistaOrGreater()) else if (IsWindowsVistaOrGreater())
SetProcessDPIAware(); SetProcessDPIAware();
if (!_glfwRegisterWindowClassWin32())
return GLFW_FALSE;
if (!createHelperWindow()) if (!createHelperWindow())
return GLFW_FALSE; return GLFW_FALSE;
@ -664,8 +712,10 @@ void _glfwTerminateWin32(void)
if (_glfw.win32.helperWindowHandle) if (_glfw.win32.helperWindowHandle)
DestroyWindow(_glfw.win32.helperWindowHandle); DestroyWindow(_glfw.win32.helperWindowHandle);
if (_glfw.win32.helperWindowClass)
_glfwUnregisterWindowClassWin32(); UnregisterClassW(MAKEINTATOM(_glfw.win32.helperWindowClass), _glfw.win32.instance);
if (_glfw.win32.mainWindowClass)
UnregisterClassW(MAKEINTATOM(_glfw.win32.mainWindowClass), _glfw.win32.instance);
_glfw_free(_glfw.win32.clipboardString); _glfw_free(_glfw.win32.clipboardString);
_glfw_free(_glfw.win32.rawInput); _glfw_free(_glfw.win32.rawInput);
@ -677,3 +727,5 @@ void _glfwTerminateWin32(void)
freeLibraries(); freeLibraries();
} }
#endif // _GLFW_WIN32

View File

@ -29,6 +29,8 @@
#include "internal.h" #include "internal.h"
#if defined(_GLFW_WIN32)
#include <stdio.h> #include <stdio.h>
#include <math.h> #include <math.h>
@ -256,6 +258,8 @@ static GLFWbool supportsXInput(const GUID* guid)
// //
static void closeJoystick(_GLFWjoystick* js) static void closeJoystick(_GLFWjoystick* js)
{ {
_glfwInputJoystick(js, GLFW_DISCONNECTED);
if (js->win32.device) if (js->win32.device)
{ {
IDirectInputDevice8_Unacquire(js->win32.device); IDirectInputDevice8_Unacquire(js->win32.device);
@ -263,9 +267,7 @@ static void closeJoystick(_GLFWjoystick* js)
} }
_glfw_free(js->win32.objects); _glfw_free(js->win32.objects);
_glfwFreeJoystick(js); _glfwFreeJoystick(js);
_glfwInputJoystick(js, GLFW_DISCONNECTED);
} }
// DirectInput device object enumeration callback // DirectInput device object enumeration callback
@ -357,7 +359,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{ {
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (js->present) if (js->connected)
{ {
if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0) if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
return DIENUM_CONTINUE; return DIENUM_CONTINUE;
@ -508,7 +510,7 @@ void _glfwDetectJoystickConnectionWin32(void)
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{ {
if (_glfw.joysticks[jid].present && if (_glfw.joysticks[jid].connected &&
_glfw.joysticks[jid].win32.device == NULL && _glfw.joysticks[jid].win32.device == NULL &&
_glfw.joysticks[jid].win32.index == index) _glfw.joysticks[jid].win32.index == index)
{ {
@ -560,7 +562,7 @@ void _glfwDetectJoystickDisconnectionWin32(void)
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{ {
_GLFWjoystick* js = _glfw.joysticks + jid; _GLFWjoystick* js = _glfw.joysticks + jid;
if (js->present) if (js->connected)
_glfwPollJoystickWin32(js, _GLFW_POLL_PRESENCE); _glfwPollJoystickWin32(js, _GLFW_POLL_PRESENCE);
} }
} }
@ -601,7 +603,7 @@ void _glfwTerminateJoysticksWin32(void)
IDirectInput8_Release(_glfw.win32.dinput8.api); IDirectInput8_Release(_glfw.win32.dinput8.api);
} }
int _glfwPollJoystickWin32(_GLFWjoystick* js, int mode) GLFWbool _glfwPollJoystickWin32(_GLFWjoystick* js, int mode)
{ {
if (js->win32.device) if (js->win32.device)
{ {
@ -756,3 +758,5 @@ void _glfwUpdateGamepadGUIDWin32(char* guid)
} }
} }
#endif // _GLFW_WIN32

View File

@ -27,8 +27,6 @@
#define GLFW_WIN32_JOYSTICK_STATE _GLFWjoystickWin32 win32; #define GLFW_WIN32_JOYSTICK_STATE _GLFWjoystickWin32 win32;
#define GLFW_WIN32_LIBRARY_JOYSTICK_STATE #define GLFW_WIN32_LIBRARY_JOYSTICK_STATE
#define GLFW_BUILD_WIN32_MAPPINGS
// Joystick element (axis, button or slider) // Joystick element (axis, button or slider)
// //
typedef struct _GLFWjoyobjectWin32 typedef struct _GLFWjoyobjectWin32

View File

@ -28,6 +28,8 @@
#include "internal.h" #include "internal.h"
#if defined(GLFW_BUILD_WIN32_MODULE)
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -47,3 +49,5 @@ GLFWproc _glfwPlatformGetModuleSymbol(void* module, const char* name)
return (GLFWproc) GetProcAddress((HMODULE) module, name); return (GLFWproc) GetProcAddress((HMODULE) module, name);
} }
#endif // GLFW_BUILD_WIN32_MODULE

View File

@ -29,6 +29,8 @@
#include "internal.h" #include "internal.h"
#if defined(_GLFW_WIN32)
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
@ -545,3 +547,5 @@ GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* handle)
return monitor->win32.publicDisplayName; return monitor->win32.publicDisplayName;
} }
#endif // _GLFW_WIN32

View File

@ -358,10 +358,6 @@ typedef struct VkWin32SurfaceCreateInfoKHR
typedef VkResult (APIENTRY *PFN_vkCreateWin32SurfaceKHR)(VkInstance,const VkWin32SurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*); typedef VkResult (APIENTRY *PFN_vkCreateWin32SurfaceKHR)(VkInstance,const VkWin32SurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t); typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t);
#if !defined(_GLFW_WNDCLASSNAME)
#define _GLFW_WNDCLASSNAME L"GLFW30"
#endif
#define GLFW_WIN32_WINDOW_STATE _GLFWwindowWin32 win32; #define GLFW_WIN32_WINDOW_STATE _GLFWwindowWin32 win32;
#define GLFW_WIN32_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32; #define GLFW_WIN32_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32;
#define GLFW_WIN32_MONITOR_STATE _GLFWmonitorWin32 win32; #define GLFW_WIN32_MONITOR_STATE _GLFWmonitorWin32 win32;
@ -444,6 +440,8 @@ typedef struct _GLFWlibraryWin32
{ {
HINSTANCE instance; HINSTANCE instance;
HWND helperWindowHandle; HWND helperWindowHandle;
ATOM helperWindowClass;
ATOM mainWindowClass;
HDEVNOTIFY deviceNotificationHandle; HDEVNOTIFY deviceNotificationHandle;
int acquiredMonitorCount; int acquiredMonitorCount;
char* clipboardString; char* clipboardString;
@ -454,6 +452,8 @@ typedef struct _GLFWlibraryWin32
double restoreCursorPosX, restoreCursorPosY; double restoreCursorPosX, restoreCursorPosY;
// The window whose disabled cursor mode is active // The window whose disabled cursor mode is active
_GLFWwindow* disabledCursorWindow; _GLFWwindow* disabledCursorWindow;
// The window the cursor is captured in
_GLFWwindow* capturedCursorWindow;
RAWINPUT* rawInput; RAWINPUT* rawInput;
int rawInputSize; int rawInputSize;
UINT mouseTrailSize; UINT mouseTrailSize;
@ -527,9 +527,6 @@ GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform);
int _glfwInitWin32(void); int _glfwInitWin32(void);
void _glfwTerminateWin32(void); void _glfwTerminateWin32(void);
GLFWbool _glfwRegisterWindowClassWin32(void);
void _glfwUnregisterWindowClassWin32(void);
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source); WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source); char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp); BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp);
@ -542,7 +539,7 @@ void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor); void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
void _glfwGetHMONITORContentScaleWin32(HMONITOR handle, float* xscale, float* yscale); void _glfwGetHMONITORContentScaleWin32(HMONITOR handle, float* xscale, float* yscale);
int _glfwCreateWindowWin32(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); GLFWbool _glfwCreateWindowWin32(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig);
void _glfwDestroyWindowWin32(_GLFWwindow* window); void _glfwDestroyWindowWin32(_GLFWwindow* window);
void _glfwSetWindowTitleWin32(_GLFWwindow* window, const char* title); void _glfwSetWindowTitleWin32(_GLFWwindow* window, const char* title);
void _glfwSetWindowIconWin32(_GLFWwindow* window, int count, const GLFWimage* images); void _glfwSetWindowIconWin32(_GLFWwindow* window, int count, const GLFWimage* images);
@ -563,12 +560,12 @@ void _glfwHideWindowWin32(_GLFWwindow* window);
void _glfwRequestWindowAttentionWin32(_GLFWwindow* window); void _glfwRequestWindowAttentionWin32(_GLFWwindow* window);
void _glfwFocusWindowWin32(_GLFWwindow* window); void _glfwFocusWindowWin32(_GLFWwindow* window);
void _glfwSetWindowMonitorWin32(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); void _glfwSetWindowMonitorWin32(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
int _glfwWindowFocusedWin32(_GLFWwindow* window); GLFWbool _glfwWindowFocusedWin32(_GLFWwindow* window);
int _glfwWindowIconifiedWin32(_GLFWwindow* window); GLFWbool _glfwWindowIconifiedWin32(_GLFWwindow* window);
int _glfwWindowVisibleWin32(_GLFWwindow* window); GLFWbool _glfwWindowVisibleWin32(_GLFWwindow* window);
int _glfwWindowMaximizedWin32(_GLFWwindow* window); GLFWbool _glfwWindowMaximizedWin32(_GLFWwindow* window);
int _glfwWindowHoveredWin32(_GLFWwindow* window); GLFWbool _glfwWindowHoveredWin32(_GLFWwindow* window);
int _glfwFramebufferTransparentWin32(_GLFWwindow* window); GLFWbool _glfwFramebufferTransparentWin32(_GLFWwindow* window);
void _glfwSetWindowResizableWin32(_GLFWwindow* window, GLFWbool enabled); void _glfwSetWindowResizableWin32(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowDecoratedWin32(_GLFWwindow* window, GLFWbool enabled); void _glfwSetWindowDecoratedWin32(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowFloatingWin32(_GLFWwindow* window, GLFWbool enabled); void _glfwSetWindowFloatingWin32(_GLFWwindow* window, GLFWbool enabled);
@ -589,8 +586,8 @@ void _glfwSetCursorPosWin32(_GLFWwindow* window, double xpos, double ypos);
void _glfwSetCursorModeWin32(_GLFWwindow* window, int mode); void _glfwSetCursorModeWin32(_GLFWwindow* window, int mode);
const char* _glfwGetScancodeNameWin32(int scancode); const char* _glfwGetScancodeNameWin32(int scancode);
int _glfwGetKeyScancodeWin32(int key); int _glfwGetKeyScancodeWin32(int key);
int _glfwCreateCursorWin32(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot); GLFWbool _glfwCreateCursorWin32(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
int _glfwCreateStandardCursorWin32(_GLFWcursor* cursor, int shape); GLFWbool _glfwCreateStandardCursorWin32(_GLFWcursor* cursor, int shape);
void _glfwDestroyCursorWin32(_GLFWcursor* cursor); void _glfwDestroyCursorWin32(_GLFWcursor* cursor);
void _glfwSetCursorWin32(_GLFWwindow* window, _GLFWcursor* cursor); void _glfwSetCursorWin32(_GLFWwindow* window, _GLFWcursor* cursor);
void _glfwSetClipboardStringWin32(const char* string); void _glfwSetClipboardStringWin32(const char* string);
@ -601,7 +598,7 @@ EGLNativeDisplayType _glfwGetEGLNativeDisplayWin32(void);
EGLNativeWindowType _glfwGetEGLNativeWindowWin32(_GLFWwindow* window); EGLNativeWindowType _glfwGetEGLNativeWindowWin32(_GLFWwindow* window);
void _glfwGetRequiredInstanceExtensionsWin32(char** extensions); void _glfwGetRequiredInstanceExtensionsWin32(char** extensions);
int _glfwGetPhysicalDevicePresentationSupportWin32(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); GLFWbool _glfwGetPhysicalDevicePresentationSupportWin32(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
VkResult _glfwCreateWindowSurfaceWin32(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); VkResult _glfwCreateWindowSurfaceWin32(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
void _glfwFreeMonitorWin32(_GLFWmonitor* monitor); void _glfwFreeMonitorWin32(_GLFWmonitor* monitor);
@ -615,7 +612,7 @@ void _glfwSetGammaRampWin32(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
GLFWbool _glfwInitJoysticksWin32(void); GLFWbool _glfwInitJoysticksWin32(void);
void _glfwTerminateJoysticksWin32(void); void _glfwTerminateJoysticksWin32(void);
int _glfwPollJoystickWin32(_GLFWjoystick* js, int mode); GLFWbool _glfwPollJoystickWin32(_GLFWjoystick* js, int mode);
const char* _glfwGetMappingNameWin32(void); const char* _glfwGetMappingNameWin32(void);
void _glfwUpdateGamepadGUIDWin32(char* guid); void _glfwUpdateGamepadGUIDWin32(char* guid);

View File

@ -29,6 +29,8 @@
#include "internal.h" #include "internal.h"
#if defined(GLFW_BUILD_WIN32_THREAD)
#include <assert.h> #include <assert.h>
@ -96,3 +98,5 @@ void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
LeaveCriticalSection(&mutex->win32.section); LeaveCriticalSection(&mutex->win32.section);
} }
#endif // GLFW_BUILD_WIN32_THREAD

View File

@ -29,6 +29,7 @@
#include "internal.h" #include "internal.h"
#if defined(GLFW_BUILD_WIN32_TIMER)
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW platform API ////// ////// GLFW platform API //////
@ -51,3 +52,5 @@ uint64_t _glfwPlatformGetTimerFrequency(void)
return _glfw.timer.win32.frequency; return _glfw.timer.win32.frequency;
} }
#endif // GLFW_BUILD_WIN32_TIMER

View File

@ -29,6 +29,8 @@
#include "internal.h" #include "internal.h"
#if defined(_GLFW_WIN32)
#include <limits.h> #include <limits.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -184,53 +186,38 @@ static HICON createIcon(const GLFWimage* image, int xhot, int yhot, GLFWbool ico
return handle; return handle;
} }
// Translate content area size to full window size according to styles and DPI
//
static void getFullWindowSize(DWORD style, DWORD exStyle,
int contentWidth, int contentHeight,
int* fullWidth, int* fullHeight,
UINT dpi)
{
RECT rect = { 0, 0, contentWidth, contentHeight };
if (_glfwIsWindows10Version1607OrGreaterWin32())
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
else
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
*fullWidth = rect.right - rect.left;
*fullHeight = rect.bottom - rect.top;
}
// Enforce the content area aspect ratio based on which edge is being dragged // Enforce the content area aspect ratio based on which edge is being dragged
// //
static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area) static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
{ {
int xoff, yoff; RECT frame = {0};
UINT dpi = USER_DEFAULT_SCREEN_DPI;
const float ratio = (float) window->numer / (float) window->denom; const float ratio = (float) window->numer / (float) window->denom;
const DWORD style = getWindowStyle(window);
const DWORD exStyle = getWindowExStyle(window);
if (_glfwIsWindows10Version1607OrGreaterWin32()) if (_glfwIsWindows10Version1607OrGreaterWin32())
dpi = GetDpiForWindow(window->win32.handle); {
AdjustWindowRectExForDpi(&frame, style, FALSE, exStyle,
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window), GetDpiForWindow(window->win32.handle));
0, 0, &xoff, &yoff, dpi); }
else
AdjustWindowRectEx(&frame, style, FALSE, exStyle);
if (edge == WMSZ_LEFT || edge == WMSZ_BOTTOMLEFT || if (edge == WMSZ_LEFT || edge == WMSZ_BOTTOMLEFT ||
edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT) edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT)
{ {
area->bottom = area->top + yoff + area->bottom = area->top + (frame.bottom - frame.top) +
(int) ((area->right - area->left - xoff) / ratio); (int) (((area->right - area->left) - (frame.right - frame.left)) / ratio);
} }
else if (edge == WMSZ_TOPLEFT || edge == WMSZ_TOPRIGHT) else if (edge == WMSZ_TOPLEFT || edge == WMSZ_TOPRIGHT)
{ {
area->top = area->bottom - yoff - area->top = area->bottom - (frame.bottom - frame.top) -
(int) ((area->right - area->left - xoff) / ratio); (int) (((area->right - area->left) - (frame.right - frame.left)) / ratio);
} }
else if (edge == WMSZ_TOP || edge == WMSZ_BOTTOM) else if (edge == WMSZ_TOP || edge == WMSZ_BOTTOM)
{ {
area->right = area->left + xoff + area->right = area->left + (frame.right - frame.left) +
(int) ((area->bottom - area->top - yoff) * ratio); (int) (((area->bottom - area->top) - (frame.bottom - frame.top)) * ratio);
} }
} }
@ -238,7 +225,8 @@ static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
// //
static void updateCursorImage(_GLFWwindow* window) static void updateCursorImage(_GLFWwindow* window)
{ {
if (window->cursorMode == GLFW_CURSOR_NORMAL) if (window->cursorMode == GLFW_CURSOR_NORMAL ||
window->cursorMode == GLFW_CURSOR_CAPTURED)
{ {
if (window->cursor) if (window->cursor)
SetCursor(window->cursor->win32.handle); SetCursor(window->cursor->win32.handle);
@ -249,20 +237,24 @@ static void updateCursorImage(_GLFWwindow* window)
SetCursor(NULL); SetCursor(NULL);
} }
// Updates the cursor clip rect // Sets the cursor clip rect to the window content area
// //
static void updateClipRect(_GLFWwindow* window) static void captureCursor(_GLFWwindow* window)
{ {
if (window) RECT clipRect;
{ GetClientRect(window->win32.handle, &clipRect);
RECT clipRect; ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);
GetClientRect(window->win32.handle, &clipRect); ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);
ClientToScreen(window->win32.handle, (POINT*) &clipRect.left); ClipCursor(&clipRect);
ClientToScreen(window->win32.handle, (POINT*) &clipRect.right); _glfw.win32.capturedCursorWindow = window;
ClipCursor(&clipRect); }
}
else // Disabled clip cursor
ClipCursor(NULL); //
static void releaseCursor(void)
{
ClipCursor(NULL);
_glfw.win32.capturedCursorWindow = NULL;
} }
// Enables WM_INPUT messages for the mouse for the specified window // Enables WM_INPUT messages for the mouse for the specified window
@ -301,7 +293,7 @@ static void disableCursor(_GLFWwindow* window)
&_glfw.win32.restoreCursorPosY); &_glfw.win32.restoreCursorPosY);
updateCursorImage(window); updateCursorImage(window);
_glfwCenterCursorInContentArea(window); _glfwCenterCursorInContentArea(window);
updateClipRect(window); captureCursor(window);
if (window->rawMouseMotion) if (window->rawMouseMotion)
enableRawMouseMotion(window); enableRawMouseMotion(window);
@ -315,7 +307,7 @@ static void enableCursor(_GLFWwindow* window)
disableRawMouseMotion(window); disableRawMouseMotion(window);
_glfw.win32.disabledCursorWindow = NULL; _glfw.win32.disabledCursorWindow = NULL;
updateClipRect(NULL); releaseCursor();
_glfwSetCursorPosWin32(window, _glfwSetCursorPosWin32(window,
_glfw.win32.restoreCursorPosX, _glfw.win32.restoreCursorPosX,
_glfw.win32.restoreCursorPosY); _glfw.win32.restoreCursorPosY);
@ -533,59 +525,26 @@ static void maximizeWindowManually(_GLFWwindow* window)
SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED); SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
} }
// Window callback function (handles window messages) // Window procedure for user-created windows
// //
static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
_GLFWwindow* window = GetPropW(hWnd, L"GLFW"); _GLFWwindow* window = GetPropW(hWnd, L"GLFW");
if (!window) if (!window)
{ {
// This is the message handling for the hidden helper window if (uMsg == WM_NCCREATE)
// and for a regular window during its initial creation
switch (uMsg)
{ {
case WM_NCCREATE: if (_glfwIsWindows10Version1607OrGreaterWin32())
{ {
if (_glfwIsWindows10Version1607OrGreaterWin32()) const CREATESTRUCTW* cs = (const CREATESTRUCTW*) lParam;
{ const _GLFWwndconfig* wndconfig = cs->lpCreateParams;
const CREATESTRUCTW* cs = (const CREATESTRUCTW*) lParam;
const _GLFWwndconfig* wndconfig = cs->lpCreateParams;
// On per-monitor DPI aware V1 systems, only enable // On per-monitor DPI aware V1 systems, only enable
// non-client scaling for windows that scale the client area // non-client scaling for windows that scale the client area
// We need WM_GETDPISCALEDSIZE from V2 to keep the client // We need WM_GETDPISCALEDSIZE from V2 to keep the client
// area static when the non-client area is scaled // area static when the non-client area is scaled
if (wndconfig && wndconfig->scaleToMonitor) if (wndconfig && wndconfig->scaleToMonitor)
EnableNonClientDpiScaling(hWnd); EnableNonClientDpiScaling(hWnd);
}
break;
}
case WM_DISPLAYCHANGE:
_glfwPollMonitorsWin32();
break;
case WM_DEVICECHANGE:
{
if (!_glfw.joysticksInitialized)
break;
if (wParam == DBT_DEVICEARRIVAL)
{
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
_glfwDetectJoystickConnectionWin32();
}
else if (wParam == DBT_DEVICEREMOVECOMPLETE)
{
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
_glfwDetectJoystickDisconnectionWin32();
}
break;
} }
} }
@ -615,6 +574,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
{ {
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
disableCursor(window); disableCursor(window);
else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
captureCursor(window);
window->win32.frameAction = GLFW_FALSE; window->win32.frameAction = GLFW_FALSE;
} }
@ -633,6 +594,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
disableCursor(window); disableCursor(window);
else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
captureCursor(window);
return 0; return 0;
} }
@ -641,6 +604,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
{ {
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
enableCursor(window); enableCursor(window);
else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
releaseCursor();
if (window->monitor && window->autoIconify) if (window->monitor && window->autoIconify)
_glfwIconifyWindowWin32(window); _glfwIconifyWindowWin32(window);
@ -760,6 +725,10 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
if (scancode == 0x146) if (scancode == 0x146)
scancode = 0x45; scancode = 0x45;
// HACK: CJK IME sets the extended bit for right Shift
if (scancode == 0x136)
scancode = 0x36;
key = _glfw.win32.keycodes[scancode]; key = _glfw.win32.keycodes[scancode];
// The Ctrl keys require special handling // The Ctrl keys require special handling
@ -1006,6 +975,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
// resizing the window or using the window menu // resizing the window or using the window menu
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
enableCursor(window); enableCursor(window);
else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
releaseCursor();
break; break;
} }
@ -1020,6 +991,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
// resizing the window or using the menu // resizing the window or using the menu
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
disableCursor(window); disableCursor(window);
else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
captureCursor(window);
break; break;
} }
@ -1033,8 +1006,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
(window->win32.maximized && (window->win32.maximized &&
wParam != SIZE_RESTORED); wParam != SIZE_RESTORED);
if (_glfw.win32.disabledCursorWindow == window) if (_glfw.win32.capturedCursorWindow == window)
updateClipRect(window); captureCursor(window);
if (window->win32.iconified != iconified) if (window->win32.iconified != iconified)
_glfwInputWindowIconify(window, iconified); _glfwInputWindowIconify(window, iconified);
@ -1069,8 +1042,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
case WM_MOVE: case WM_MOVE:
{ {
if (_glfw.win32.disabledCursorWindow == window) if (_glfw.win32.capturedCursorWindow == window)
updateClipRect(window); captureCursor(window);
// NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as
// those macros do not handle negative window positions correctly // those macros do not handle negative window positions correctly
@ -1094,31 +1067,34 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
case WM_GETMINMAXINFO: case WM_GETMINMAXINFO:
{ {
int xoff, yoff; RECT frame = {0};
UINT dpi = USER_DEFAULT_SCREEN_DPI;
MINMAXINFO* mmi = (MINMAXINFO*) lParam; MINMAXINFO* mmi = (MINMAXINFO*) lParam;
const DWORD style = getWindowStyle(window);
const DWORD exStyle = getWindowExStyle(window);
if (window->monitor) if (window->monitor)
break; break;
if (_glfwIsWindows10Version1607OrGreaterWin32()) if (_glfwIsWindows10Version1607OrGreaterWin32())
dpi = GetDpiForWindow(window->win32.handle); {
AdjustWindowRectExForDpi(&frame, style, FALSE, exStyle,
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window), GetDpiForWindow(window->win32.handle));
0, 0, &xoff, &yoff, dpi); }
else
AdjustWindowRectEx(&frame, style, FALSE, exStyle);
if (window->minwidth != GLFW_DONT_CARE && if (window->minwidth != GLFW_DONT_CARE &&
window->minheight != GLFW_DONT_CARE) window->minheight != GLFW_DONT_CARE)
{ {
mmi->ptMinTrackSize.x = window->minwidth + xoff; mmi->ptMinTrackSize.x = window->minwidth + frame.right - frame.left;
mmi->ptMinTrackSize.y = window->minheight + yoff; mmi->ptMinTrackSize.y = window->minheight + frame.bottom - frame.top;
} }
if (window->maxwidth != GLFW_DONT_CARE && if (window->maxwidth != GLFW_DONT_CARE &&
window->maxheight != GLFW_DONT_CARE) window->maxheight != GLFW_DONT_CARE)
{ {
mmi->ptMaxTrackSize.x = window->maxwidth + xoff; mmi->ptMaxTrackSize.x = window->maxwidth + frame.right - frame.left;
mmi->ptMaxTrackSize.y = window->maxheight + yoff; mmi->ptMaxTrackSize.y = window->maxheight + frame.bottom - frame.top;
} }
if (!window->decorated) if (!window->decorated)
@ -1277,11 +1253,44 @@ static int createNativeWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig, const _GLFWwndconfig* wndconfig,
const _GLFWfbconfig* fbconfig) const _GLFWfbconfig* fbconfig)
{ {
int xpos, ypos, fullWidth, fullHeight; int frameX, frameY, frameWidth, frameHeight;
WCHAR* wideTitle; WCHAR* wideTitle;
DWORD style = getWindowStyle(window); DWORD style = getWindowStyle(window);
DWORD exStyle = getWindowExStyle(window); DWORD exStyle = getWindowExStyle(window);
if (!_glfw.win32.mainWindowClass)
{
WNDCLASSEXW wc = { sizeof(wc) };
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = windowProc;
wc.hInstance = _glfw.win32.instance;
wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
#if defined(_GLFW_WNDCLASSNAME)
wc.lpszClassName = _GLFW_WNDCLASSNAME;
#else
wc.lpszClassName = L"GLFW30";
#endif
// Load user-provided icon if available
wc.hIcon = LoadImageW(GetModuleHandleW(NULL),
L"GLFW_ICON", IMAGE_ICON,
0, 0, LR_DEFAULTSIZE | LR_SHARED);
if (!wc.hIcon)
{
// No user-provided icon found, load default icon
wc.hIcon = LoadImageW(NULL,
IDI_APPLICATION, IMAGE_ICON,
0, 0, LR_DEFAULTSIZE | LR_SHARED);
}
_glfw.win32.mainWindowClass = RegisterClassExW(&wc);
if (!_glfw.win32.mainWindowClass)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to register window class");
return GLFW_FALSE;
}
}
if (window->monitor) if (window->monitor)
{ {
MONITORINFO mi = { sizeof(mi) }; MONITORINFO mi = { sizeof(mi) };
@ -1290,24 +1299,34 @@ static int createNativeWindow(_GLFWwindow* window,
// NOTE: This window placement is temporary and approximate, as the // NOTE: This window placement is temporary and approximate, as the
// correct position and size cannot be known until the monitor // correct position and size cannot be known until the monitor
// video mode has been picked in _glfwSetVideoModeWin32 // video mode has been picked in _glfwSetVideoModeWin32
xpos = mi.rcMonitor.left; frameX = mi.rcMonitor.left;
ypos = mi.rcMonitor.top; frameY = mi.rcMonitor.top;
fullWidth = mi.rcMonitor.right - mi.rcMonitor.left; frameWidth = mi.rcMonitor.right - mi.rcMonitor.left;
fullHeight = mi.rcMonitor.bottom - mi.rcMonitor.top; frameHeight = mi.rcMonitor.bottom - mi.rcMonitor.top;
} }
else else
{ {
xpos = CW_USEDEFAULT; RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
ypos = CW_USEDEFAULT;
window->win32.maximized = wndconfig->maximized; window->win32.maximized = wndconfig->maximized;
if (wndconfig->maximized) if (wndconfig->maximized)
style |= WS_MAXIMIZE; style |= WS_MAXIMIZE;
getFullWindowSize(style, exStyle, AdjustWindowRectEx(&rect, style, FALSE, exStyle);
wndconfig->width, wndconfig->height,
&fullWidth, &fullHeight, if (wndconfig->xpos == GLFW_ANY_POSITION && wndconfig->ypos == GLFW_ANY_POSITION)
USER_DEFAULT_SCREEN_DPI); {
frameX = CW_USEDEFAULT;
frameY = CW_USEDEFAULT;
}
else
{
frameX = wndconfig->xpos + rect.left;
frameY = wndconfig->ypos + rect.top;
}
frameWidth = rect.right - rect.left;
frameHeight = rect.bottom - rect.top;
} }
wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title); wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);
@ -1315,11 +1334,11 @@ static int createNativeWindow(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
window->win32.handle = CreateWindowExW(exStyle, window->win32.handle = CreateWindowExW(exStyle,
_GLFW_WNDCLASSNAME, MAKEINTATOM(_glfw.win32.mainWindowClass),
wideTitle, wideTitle,
style, style,
xpos, ypos, frameX, frameY,
fullWidth, fullHeight, frameWidth, frameHeight,
NULL, // No parent window NULL, // No parent window
NULL, // No window menu NULL, // No window menu
_glfw.win32.instance, _glfw.win32.instance,
@ -1420,53 +1439,10 @@ static int createNativeWindow(_GLFWwindow* window,
return GLFW_TRUE; return GLFW_TRUE;
} }
// Registers the GLFW window class GLFWbool _glfwCreateWindowWin32(_GLFWwindow* window,
// const _GLFWwndconfig* wndconfig,
GLFWbool _glfwRegisterWindowClassWin32(void) const _GLFWctxconfig* ctxconfig,
{ const _GLFWfbconfig* fbconfig)
WNDCLASSEXW wc;
ZeroMemory(&wc, sizeof(wc));
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = windowProc;
wc.hInstance = _glfw.win32.instance;
wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
wc.lpszClassName = _GLFW_WNDCLASSNAME;
// Load user-provided icon if available
wc.hIcon = LoadImageW(GetModuleHandleW(NULL),
L"GLFW_ICON", IMAGE_ICON,
0, 0, LR_DEFAULTSIZE | LR_SHARED);
if (!wc.hIcon)
{
// No user-provided icon found, load default icon
wc.hIcon = LoadImageW(NULL,
IDI_APPLICATION, IMAGE_ICON,
0, 0, LR_DEFAULTSIZE | LR_SHARED);
}
if (!RegisterClassExW(&wc))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to register window class");
return GLFW_FALSE;
}
return GLFW_TRUE;
}
// Unregisters the GLFW window class
//
void _glfwUnregisterWindowClassWin32(void)
{
UnregisterClassW(_GLFW_WNDCLASSNAME, _glfw.win32.instance);
}
int _glfwCreateWindowWin32(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{ {
if (!createNativeWindow(window, wndconfig, fbconfig)) if (!createNativeWindow(window, wndconfig, fbconfig))
return GLFW_FALSE; return GLFW_FALSE;
@ -1534,7 +1510,10 @@ void _glfwDestroyWindowWin32(_GLFWwindow* window)
window->context.destroy(window); window->context.destroy(window);
if (_glfw.win32.disabledCursorWindow == window) if (_glfw.win32.disabledCursorWindow == window)
_glfw.win32.disabledCursorWindow = NULL; enableCursor(window);
if (_glfw.win32.capturedCursorWindow == window)
releaseCursor();
if (window->win32.handle) if (window->win32.handle)
{ {
@ -1900,32 +1879,32 @@ void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
} }
} }
int _glfwWindowFocusedWin32(_GLFWwindow* window) GLFWbool _glfwWindowFocusedWin32(_GLFWwindow* window)
{ {
return window->win32.handle == GetActiveWindow(); return window->win32.handle == GetActiveWindow();
} }
int _glfwWindowIconifiedWin32(_GLFWwindow* window) GLFWbool _glfwWindowIconifiedWin32(_GLFWwindow* window)
{ {
return IsIconic(window->win32.handle); return IsIconic(window->win32.handle);
} }
int _glfwWindowVisibleWin32(_GLFWwindow* window) GLFWbool _glfwWindowVisibleWin32(_GLFWwindow* window)
{ {
return IsWindowVisible(window->win32.handle); return IsWindowVisible(window->win32.handle);
} }
int _glfwWindowMaximizedWin32(_GLFWwindow* window) GLFWbool _glfwWindowMaximizedWin32(_GLFWwindow* window)
{ {
return IsZoomed(window->win32.handle); return IsZoomed(window->win32.handle);
} }
int _glfwWindowHoveredWin32(_GLFWwindow* window) GLFWbool _glfwWindowHoveredWin32(_GLFWwindow* window)
{ {
return cursorInContentArea(window); return cursorInContentArea(window);
} }
int _glfwFramebufferTransparentWin32(_GLFWwindow* window) GLFWbool _glfwFramebufferTransparentWin32(_GLFWwindow* window)
{ {
BOOL composition, opaque; BOOL composition, opaque;
DWORD color; DWORD color;
@ -2181,14 +2160,40 @@ void _glfwSetCursorPosWin32(_GLFWwindow* window, double xpos, double ypos)
void _glfwSetCursorModeWin32(_GLFWwindow* window, int mode) void _glfwSetCursorModeWin32(_GLFWwindow* window, int mode)
{ {
if (mode == GLFW_CURSOR_DISABLED) if (_glfwWindowFocusedWin32(window))
{ {
if (_glfwWindowFocusedWin32(window)) if (mode == GLFW_CURSOR_DISABLED)
disableCursor(window); {
_glfwGetCursorPosWin32(window,
&_glfw.win32.restoreCursorPosX,
&_glfw.win32.restoreCursorPosY);
_glfwCenterCursorInContentArea(window);
if (window->rawMouseMotion)
enableRawMouseMotion(window);
}
else if (_glfw.win32.disabledCursorWindow == window)
{
if (window->rawMouseMotion)
disableRawMouseMotion(window);
}
if (mode == GLFW_CURSOR_DISABLED || mode == GLFW_CURSOR_CAPTURED)
captureCursor(window);
else
releaseCursor();
if (mode == GLFW_CURSOR_DISABLED)
_glfw.win32.disabledCursorWindow = window;
else if (_glfw.win32.disabledCursorWindow == window)
{
_glfw.win32.disabledCursorWindow = NULL;
_glfwSetCursorPosWin32(window,
_glfw.win32.restoreCursorPosX,
_glfw.win32.restoreCursorPosY);
}
} }
else if (_glfw.win32.disabledCursorWindow == window)
enableCursor(window); if (cursorInContentArea(window))
else if (cursorInContentArea(window))
updateCursorImage(window); updateCursorImage(window);
} }
@ -2209,9 +2214,9 @@ int _glfwGetKeyScancodeWin32(int key)
return _glfw.win32.scancodes[key]; return _glfw.win32.scancodes[key];
} }
int _glfwCreateCursorWin32(_GLFWcursor* cursor, GLFWbool _glfwCreateCursorWin32(_GLFWcursor* cursor,
const GLFWimage* image, const GLFWimage* image,
int xhot, int yhot) int xhot, int yhot)
{ {
cursor->win32.handle = (HCURSOR) createIcon(image, xhot, yhot, GLFW_FALSE); cursor->win32.handle = (HCURSOR) createIcon(image, xhot, yhot, GLFW_FALSE);
if (!cursor->win32.handle) if (!cursor->win32.handle)
@ -2220,7 +2225,7 @@ int _glfwCreateCursorWin32(_GLFWcursor* cursor,
return GLFW_TRUE; return GLFW_TRUE;
} }
int _glfwCreateStandardCursorWin32(_GLFWcursor* cursor, int shape) GLFWbool _glfwCreateStandardCursorWin32(_GLFWcursor* cursor, int shape)
{ {
int id = 0; int id = 0;
@ -2428,9 +2433,9 @@ void _glfwGetRequiredInstanceExtensionsWin32(char** extensions)
extensions[1] = "VK_KHR_win32_surface"; extensions[1] = "VK_KHR_win32_surface";
} }
int _glfwGetPhysicalDevicePresentationSupportWin32(VkInstance instance, GLFWbool _glfwGetPhysicalDevicePresentationSupportWin32(VkInstance instance,
VkPhysicalDevice device, VkPhysicalDevice device,
uint32_t queuefamily) uint32_t queuefamily)
{ {
PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR
vkGetPhysicalDeviceWin32PresentationSupportKHR = vkGetPhysicalDeviceWin32PresentationSupportKHR =
@ -2495,3 +2500,5 @@ GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle)
return window->win32.handle; return window->win32.handle;
} }
#endif // _GLFW_WIN32

View File

@ -44,6 +44,9 @@
// //
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
{ {
assert(window != NULL);
assert(focused == GLFW_TRUE || focused == GLFW_FALSE);
if (window->callbacks.focus) if (window->callbacks.focus)
window->callbacks.focus((GLFWwindow*) window, focused); window->callbacks.focus((GLFWwindow*) window, focused);
@ -73,6 +76,8 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
// //
void _glfwInputWindowPos(_GLFWwindow* window, int x, int y) void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
{ {
assert(window != NULL);
if (window->callbacks.pos) if (window->callbacks.pos)
window->callbacks.pos((GLFWwindow*) window, x, y); window->callbacks.pos((GLFWwindow*) window, x, y);
} }
@ -82,6 +87,10 @@ void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
// //
void _glfwInputWindowSize(_GLFWwindow* window, int width, int height) void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
{ {
assert(window != NULL);
assert(width >= 0);
assert(height >= 0);
if (window->callbacks.size) if (window->callbacks.size)
window->callbacks.size((GLFWwindow*) window, width, height); window->callbacks.size((GLFWwindow*) window, width, height);
} }
@ -90,6 +99,9 @@ void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
// //
void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified) void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
{ {
assert(window != NULL);
assert(iconified == GLFW_TRUE || iconified == GLFW_FALSE);
if (window->callbacks.iconify) if (window->callbacks.iconify)
window->callbacks.iconify((GLFWwindow*) window, iconified); window->callbacks.iconify((GLFWwindow*) window, iconified);
} }
@ -98,6 +110,9 @@ void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
// //
void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized) void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)
{ {
assert(window != NULL);
assert(maximized == GLFW_TRUE || maximized == GLFW_FALSE);
if (window->callbacks.maximize) if (window->callbacks.maximize)
window->callbacks.maximize((GLFWwindow*) window, maximized); window->callbacks.maximize((GLFWwindow*) window, maximized);
} }
@ -107,6 +122,10 @@ void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)
// //
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height) void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
{ {
assert(window != NULL);
assert(width >= 0);
assert(height >= 0);
if (window->callbacks.fbsize) if (window->callbacks.fbsize)
window->callbacks.fbsize((GLFWwindow*) window, width, height); window->callbacks.fbsize((GLFWwindow*) window, width, height);
} }
@ -116,6 +135,12 @@ void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
// //
void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale) void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale)
{ {
assert(window != NULL);
assert(xscale > 0.f);
assert(xscale < FLT_MAX);
assert(yscale > 0.f);
assert(yscale < FLT_MAX);
if (window->callbacks.scale) if (window->callbacks.scale)
window->callbacks.scale((GLFWwindow*) window, xscale, yscale); window->callbacks.scale((GLFWwindow*) window, xscale, yscale);
} }
@ -124,6 +149,8 @@ void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscal
// //
void _glfwInputWindowDamage(_GLFWwindow* window) void _glfwInputWindowDamage(_GLFWwindow* window)
{ {
assert(window != NULL);
if (window->callbacks.refresh) if (window->callbacks.refresh)
window->callbacks.refresh((GLFWwindow*) window); window->callbacks.refresh((GLFWwindow*) window);
} }
@ -132,6 +159,8 @@ void _glfwInputWindowDamage(_GLFWwindow* window)
// //
void _glfwInputWindowCloseRequest(_GLFWwindow* window) void _glfwInputWindowCloseRequest(_GLFWwindow* window)
{ {
assert(window != NULL);
window->shouldClose = GLFW_TRUE; window->shouldClose = GLFW_TRUE;
if (window->callbacks.close) if (window->callbacks.close)
@ -142,6 +171,7 @@ void _glfwInputWindowCloseRequest(_GLFWwindow* window)
// //
void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor) void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor)
{ {
assert(window != NULL);
window->monitor = monitor; window->monitor = monitor;
} }
@ -244,6 +274,8 @@ void glfwDefaultWindowHints(void)
_glfw.hints.window.autoIconify = GLFW_TRUE; _glfw.hints.window.autoIconify = GLFW_TRUE;
_glfw.hints.window.centerCursor = GLFW_TRUE; _glfw.hints.window.centerCursor = GLFW_TRUE;
_glfw.hints.window.focusOnShow = GLFW_TRUE; _glfw.hints.window.focusOnShow = GLFW_TRUE;
_glfw.hints.window.xpos = GLFW_ANY_POSITION;
_glfw.hints.window.ypos = GLFW_ANY_POSITION;
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil, // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
// double buffered // double buffered
@ -338,6 +370,12 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_VISIBLE: case GLFW_VISIBLE:
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
return; return;
case GLFW_POSITION_X:
_glfw.hints.window.xpos = value;
return;
case GLFW_POSITION_Y:
_glfw.hints.window.ypos = value;
return;
case GLFW_COCOA_RETINA_FRAMEBUFFER: case GLFW_COCOA_RETINA_FRAMEBUFFER:
_glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
return; return;
@ -417,6 +455,10 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value)
strncpy(_glfw.hints.window.x11.instanceName, value, strncpy(_glfw.hints.window.x11.instanceName, value,
sizeof(_glfw.hints.window.x11.instanceName) - 1); sizeof(_glfw.hints.window.x11.instanceName) - 1);
return; return;
case GLFW_WAYLAND_APP_ID:
strncpy(_glfw.hints.window.wl.appId, value,
sizeof(_glfw.hints.window.wl.appId) - 1);
return;
} }
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint string 0x%08X", hint); _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint string 0x%08X", hint);

View File

@ -28,6 +28,8 @@
#include "internal.h" #include "internal.h"
#if defined(_GLFW_WAYLAND)
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <linux/input.h> #include <linux/input.h>
@ -184,11 +186,9 @@ static void registryHandleGlobalRemove(void* userData,
struct wl_registry* registry, struct wl_registry* registry,
uint32_t name) uint32_t name)
{ {
_GLFWmonitor* monitor;
for (int i = 0; i < _glfw.monitorCount; ++i) for (int i = 0; i < _glfw.monitorCount; ++i)
{ {
monitor = _glfw.monitors[i]; _GLFWmonitor* monitor = _glfw.monitors[i];
if (monitor->wl.name == name) if (monitor->wl.name == name)
{ {
_glfwInputMonitor(monitor, GLFW_DISCONNECTED, 0); _glfwInputMonitor(monitor, GLFW_DISCONNECTED, 0);
@ -337,6 +337,38 @@ static void createKeyTables(void)
} }
} }
static GLFWbool loadCursorTheme(void)
{
int cursorSize = 32;
const char* sizeString = getenv("XCURSOR_SIZE");
if (sizeString)
{
errno = 0;
const long cursorSizeLong = strtol(sizeString, NULL, 10);
if (errno == 0 && cursorSizeLong > 0 && cursorSizeLong < INT_MAX)
cursorSize = (int) cursorSizeLong;
}
const char* themeName = getenv("XCURSOR_THEME");
_glfw.wl.cursorTheme = wl_cursor_theme_load(themeName, cursorSize, _glfw.wl.shm);
if (!_glfw.wl.cursorTheme)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to load default cursor theme");
return GLFW_FALSE;
}
// If this happens to be NULL, we just fallback to the scale=1 version.
_glfw.wl.cursorThemeHiDPI =
wl_cursor_theme_load(themeName, cursorSize * 2, _glfw.wl.shm);
_glfw.wl.cursorSurface = wl_compositor_create_surface(_glfw.wl.compositor);
_glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
return GLFW_TRUE;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW platform API ////// ////// GLFW platform API //////
@ -362,7 +394,7 @@ GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform)
_glfwGetKeyScancodeWayland, _glfwGetKeyScancodeWayland,
_glfwSetClipboardStringWayland, _glfwSetClipboardStringWayland,
_glfwGetClipboardStringWayland, _glfwGetClipboardStringWayland,
#if defined(__linux__) #if defined(_GLFW_LINUX_JOYSTICK)
_glfwInitJoysticksLinux, _glfwInitJoysticksLinux,
_glfwTerminateJoysticksLinux, _glfwTerminateJoysticksLinux,
_glfwPollJoystickLinux, _glfwPollJoystickLinux,
@ -473,11 +505,9 @@ GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform)
int _glfwInitWayland(void) int _glfwInitWayland(void)
{ {
const char* cursorTheme; // These must be set before any failure checks
const char* cursorSizeStr; _glfw.wl.keyRepeatTimerfd = -1;
char* cursorSizeEnd; _glfw.wl.cursorTimerfd = -1;
long cursorSizeLong;
int cursorSize;
_glfw.wl.client.display_flush = (PFN_wl_display_flush) _glfw.wl.client.display_flush = (PFN_wl_display_flush)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_flush"); _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_flush");
@ -597,10 +627,10 @@ int _glfwInitWayland(void)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_key_get_syms"); _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_key_get_syms");
_glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask) _glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_update_mask"); _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_update_mask");
_glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_serialize_mods");
_glfw.wl.xkb.state_key_get_layout = (PFN_xkb_state_key_get_layout) _glfw.wl.xkb.state_key_get_layout = (PFN_xkb_state_key_get_layout)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_key_get_layout"); _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_key_get_layout");
_glfw.wl.xkb.state_mod_index_is_active = (PFN_xkb_state_mod_index_is_active)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_mod_index_is_active");
_glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale) _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale"); _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");
_glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref) _glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref)
@ -635,9 +665,13 @@ int _glfwInitWayland(void)
// Sync so we got all initial output events // Sync so we got all initial output events
wl_display_roundtrip(_glfw.wl.display); wl_display_roundtrip(_glfw.wl.display);
_glfw.wl.timerfd = -1; #ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
if (_glfw.wl.seatVersion >= 4) if (_glfw.wl.seatVersion >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
_glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); {
_glfw.wl.keyRepeatTimerfd =
timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
}
#endif
if (!_glfw.wl.wmBase) if (!_glfw.wl.wmBase)
{ {
@ -646,34 +680,16 @@ int _glfwInitWayland(void)
return GLFW_FALSE; return GLFW_FALSE;
} }
if (_glfw.wl.pointer && _glfw.wl.shm) if (!_glfw.wl.shm)
{ {
cursorTheme = getenv("XCURSOR_THEME"); _glfwInputError(GLFW_PLATFORM_ERROR,
cursorSizeStr = getenv("XCURSOR_SIZE"); "Wayland: Failed to find wl_shm in your compositor");
cursorSize = 32; return GLFW_FALSE;
if (cursorSizeStr)
{
errno = 0;
cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10);
if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX)
cursorSize = (int)cursorSizeLong;
}
_glfw.wl.cursorTheme =
wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm);
if (!_glfw.wl.cursorTheme)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to load default cursor theme");
return GLFW_FALSE;
}
// If this happens to be NULL, we just fallback to the scale=1 version.
_glfw.wl.cursorThemeHiDPI =
wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm);
_glfw.wl.cursorSurface =
wl_compositor_create_surface(_glfw.wl.compositor);
_glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
} }
if (!loadCursorTheme())
return GLFW_FALSE;
if (_glfw.wl.seat && _glfw.wl.dataDeviceManager) if (_glfw.wl.seat && _glfw.wl.dataDeviceManager)
{ {
_glfw.wl.dataDevice = _glfw.wl.dataDevice =
@ -769,11 +785,13 @@ void _glfwTerminateWayland(void)
wl_display_disconnect(_glfw.wl.display); wl_display_disconnect(_glfw.wl.display);
} }
if (_glfw.wl.timerfd >= 0) if (_glfw.wl.keyRepeatTimerfd >= 0)
close(_glfw.wl.timerfd); close(_glfw.wl.keyRepeatTimerfd);
if (_glfw.wl.cursorTimerfd >= 0) if (_glfw.wl.cursorTimerfd >= 0)
close(_glfw.wl.cursorTimerfd); close(_glfw.wl.cursorTimerfd);
_glfw_free(_glfw.wl.clipboardString); _glfw_free(_glfw.wl.clipboardString);
} }
#endif // _GLFW_WAYLAND

View File

@ -28,6 +28,8 @@
#include "internal.h" #include "internal.h"
#if defined(_GLFW_WAYLAND)
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -55,7 +57,8 @@ static void outputHandleGeometry(void* userData,
monitor->widthMM = physicalWidth; monitor->widthMM = physicalWidth;
monitor->heightMM = physicalHeight; monitor->heightMM = physicalHeight;
snprintf(monitor->name, sizeof(monitor->name), "%s %s", make, model); if (strlen(monitor->name) == 0)
snprintf(monitor->name, sizeof(monitor->name), "%s %s", make, model);
} }
static void outputHandleMode(void* userData, static void outputHandleMode(void* userData,
@ -96,6 +99,12 @@ static void outputHandleDone(void* userData, struct wl_output* output)
monitor->heightMM = (int) (mode->height * 25.4f / 96.f); monitor->heightMM = (int) (mode->height * 25.4f / 96.f);
} }
for (int i = 0; i < _glfw.monitorCount; i++)
{
if (_glfw.monitors[i] == monitor)
return;
}
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST); _glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
} }
@ -106,14 +115,47 @@ static void outputHandleScale(void* userData,
struct _GLFWmonitor* monitor = userData; struct _GLFWmonitor* monitor = userData;
monitor->wl.scale = factor; monitor->wl.scale = factor;
for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next)
{
for (int i = 0; i < window->wl.monitorsCount; i++)
{
if (window->wl.monitors[i] == monitor)
{
_glfwUpdateContentScaleWayland(window);
break;
}
}
}
} }
#ifdef WL_OUTPUT_NAME_SINCE_VERSION
void outputHandleName(void* userData, struct wl_output* wl_output, const char* name)
{
struct _GLFWmonitor* monitor = userData;
strncpy(monitor->name, name, sizeof(monitor->name) - 1);
}
void outputHandleDescription(void* userData,
struct wl_output* wl_output,
const char* description)
{
}
#endif // WL_OUTPUT_NAME_SINCE_VERSION
static const struct wl_output_listener outputListener = static const struct wl_output_listener outputListener =
{ {
outputHandleGeometry, outputHandleGeometry,
outputHandleMode, outputHandleMode,
outputHandleDone, outputHandleDone,
outputHandleScale, outputHandleScale,
#ifdef WL_OUTPUT_NAME_SINCE_VERSION
outputHandleName,
outputHandleDescription,
#endif
}; };
@ -123,9 +165,6 @@ static const struct wl_output_listener outputListener =
void _glfwAddOutputWayland(uint32_t name, uint32_t version) void _glfwAddOutputWayland(uint32_t name, uint32_t version)
{ {
_GLFWmonitor* monitor;
struct wl_output* output;
if (version < 2) if (version < 2)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
@ -133,19 +172,21 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
return; return;
} }
// The actual name of this output will be set in the geometry handler. #ifdef WL_OUTPUT_NAME_SINCE_VERSION
monitor = _glfwAllocMonitor("", 0, 0); version = _glfw_min(version, WL_OUTPUT_NAME_SINCE_VERSION);
#else
version = 2;
#endif
output = wl_registry_bind(_glfw.wl.registry, struct wl_output* output = wl_registry_bind(_glfw.wl.registry,
name, name,
&wl_output_interface, &wl_output_interface,
2); version);
if (!output) if (!output)
{
_glfwFreeMonitor(monitor);
return; return;
}
// The actual name of this output will be set in the geometry handler
_GLFWmonitor* monitor = _glfwAllocMonitor("", 0, 0);
monitor->wl.scale = 1; monitor->wl.scale = 1;
monitor->wl.output = output; monitor->wl.output = output;
monitor->wl.name = name; monitor->wl.name = name;
@ -231,3 +272,5 @@ GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle)
return monitor->wl.output; return monitor->wl.output;
} }
#endif // _GLFW_WAYLAND

View File

@ -167,8 +167,8 @@ typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
typedef void (* PFN_xkb_state_unref)(struct xkb_state*); typedef void (* PFN_xkb_state_unref)(struct xkb_state*);
typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**); typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t); typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component);
typedef xkb_layout_index_t (* PFN_xkb_state_key_get_layout)(struct xkb_state*,xkb_keycode_t); typedef xkb_layout_index_t (* PFN_xkb_state_key_get_layout)(struct xkb_state*,xkb_keycode_t);
typedef int (* PFN_xkb_state_mod_index_is_active)(struct xkb_state*,xkb_mod_index_t,enum xkb_state_component);
#define xkb_context_new _glfw.wl.xkb.context_new #define xkb_context_new _glfw.wl.xkb.context_new
#define xkb_context_unref _glfw.wl.xkb.context_unref #define xkb_context_unref _glfw.wl.xkb.context_unref
#define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string #define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string
@ -180,8 +180,8 @@ typedef xkb_layout_index_t (* PFN_xkb_state_key_get_layout)(struct xkb_state*,xk
#define xkb_state_unref _glfw.wl.xkb.state_unref #define xkb_state_unref _glfw.wl.xkb.state_unref
#define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms #define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms
#define xkb_state_update_mask _glfw.wl.xkb.state_update_mask #define xkb_state_update_mask _glfw.wl.xkb.state_update_mask
#define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods
#define xkb_state_key_get_layout _glfw.wl.xkb.state_key_get_layout #define xkb_state_key_get_layout _glfw.wl.xkb.state_key_get_layout
#define xkb_state_mod_index_is_active _glfw.wl.xkb.state_mod_index_is_active
typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags); typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*); typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
@ -198,11 +198,6 @@ typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_st
#define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status #define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status
#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym #define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
#define _GLFW_DECORATION_WIDTH 4
#define _GLFW_DECORATION_TOP 24
#define _GLFW_DECORATION_VERTICAL (_GLFW_DECORATION_TOP + _GLFW_DECORATION_WIDTH)
#define _GLFW_DECORATION_HORIZONTAL (2 * _GLFW_DECORATION_WIDTH)
typedef enum _GLFWdecorationSideWayland typedef enum _GLFWdecorationSideWayland
{ {
mainWindow, mainWindow,
@ -233,22 +228,37 @@ typedef struct _GLFWwindowWayland
int width, height; int width, height;
GLFWbool visible; GLFWbool visible;
GLFWbool maximized; GLFWbool maximized;
GLFWbool activated;
GLFWbool fullscreen;
GLFWbool hovered; GLFWbool hovered;
GLFWbool transparent; GLFWbool transparent;
struct wl_surface* surface; struct wl_surface* surface;
struct wl_egl_window* native;
struct wl_callback* callback; struct wl_callback* callback;
struct {
struct wl_egl_window* window;
} egl;
struct {
int width, height;
GLFWbool maximized;
GLFWbool iconified;
GLFWbool activated;
GLFWbool fullscreen;
} pending;
struct { struct {
struct xdg_surface* surface; struct xdg_surface* surface;
struct xdg_toplevel* toplevel; struct xdg_toplevel* toplevel;
struct zxdg_toplevel_decoration_v1* decoration; struct zxdg_toplevel_decoration_v1* decoration;
uint32_t decorationMode;
} xdg; } xdg;
_GLFWcursor* currentCursor; _GLFWcursor* currentCursor;
double cursorPosX, cursorPosY; double cursorPosX, cursorPosY;
char* title; char* title;
char* appId;
// We need to track the monitors the window spans on to calculate the // We need to track the monitors the window spans on to calculate the
// optimal scaling factor. // optimal scaling factor.
@ -257,20 +267,16 @@ typedef struct _GLFWwindowWayland
int monitorsCount; int monitorsCount;
int monitorsSize; int monitorsSize;
struct { struct zwp_relative_pointer_v1* relativePointer;
struct zwp_relative_pointer_v1* relativePointer; struct zwp_locked_pointer_v1* lockedPointer;
struct zwp_locked_pointer_v1* lockedPointer; struct zwp_confined_pointer_v1* confinedPointer;
} pointerLock;
struct zwp_idle_inhibitor_v1* idleInhibitor; struct zwp_idle_inhibitor_v1* idleInhibitor;
GLFWbool wasFullscreen;
struct { struct {
GLFWbool serverSide;
struct wl_buffer* buffer; struct wl_buffer* buffer;
_GLFWdecorationWayland top, left, right, bottom; _GLFWdecorationWayland top, left, right, bottom;
int focus; _GLFWdecorationSideWayland focus;
} decorations; } decorations;
} _GLFWwindowWayland; } _GLFWwindowWayland;
@ -316,12 +322,12 @@ typedef struct _GLFWlibraryWayland
uint32_t serial; uint32_t serial;
uint32_t pointerEnterSerial; uint32_t pointerEnterSerial;
int32_t keyboardRepeatRate; int keyRepeatTimerfd;
int32_t keyboardRepeatDelay; int32_t keyRepeatRate;
int keyboardLastKey; int32_t keyRepeatDelay;
int keyboardLastScancode; int keyRepeatScancode;
char* clipboardString; char* clipboardString;
int timerfd;
short int keycodes[256]; short int keycodes[256];
short int scancodes[GLFW_KEY_LAST + 1]; short int scancodes[GLFW_KEY_LAST + 1];
char keynames[GLFW_KEY_LAST + 1][5]; char keynames[GLFW_KEY_LAST + 1][5];
@ -334,12 +340,12 @@ typedef struct _GLFWlibraryWayland
struct xkb_compose_state* composeState; struct xkb_compose_state* composeState;
xkb_mod_mask_t controlMask; xkb_mod_index_t controlIndex;
xkb_mod_mask_t altMask; xkb_mod_index_t altIndex;
xkb_mod_mask_t shiftMask; xkb_mod_index_t shiftIndex;
xkb_mod_mask_t superMask; xkb_mod_index_t superIndex;
xkb_mod_mask_t capsLockMask; xkb_mod_index_t capsLockIndex;
xkb_mod_mask_t numLockMask; xkb_mod_index_t numLockIndex;
unsigned int modifiers; unsigned int modifiers;
PFN_xkb_context_new context_new; PFN_xkb_context_new context_new;
@ -353,8 +359,8 @@ typedef struct _GLFWlibraryWayland
PFN_xkb_state_unref state_unref; PFN_xkb_state_unref state_unref;
PFN_xkb_state_key_get_syms state_key_get_syms; PFN_xkb_state_key_get_syms state_key_get_syms;
PFN_xkb_state_update_mask state_update_mask; PFN_xkb_state_update_mask state_update_mask;
PFN_xkb_state_serialize_mods state_serialize_mods;
PFN_xkb_state_key_get_layout state_key_get_layout; PFN_xkb_state_key_get_layout state_key_get_layout;
PFN_xkb_state_mod_index_is_active state_mod_index_is_active;
PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale; PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;
PFN_xkb_compose_table_unref compose_table_unref; PFN_xkb_compose_table_unref compose_table_unref;
@ -436,7 +442,7 @@ GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform);
int _glfwInitWayland(void); int _glfwInitWayland(void);
void _glfwTerminateWayland(void); void _glfwTerminateWayland(void);
int _glfwCreateWindowWayland(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); GLFWbool _glfwCreateWindowWayland(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig);
void _glfwDestroyWindowWayland(_GLFWwindow* window); void _glfwDestroyWindowWayland(_GLFWwindow* window);
void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title); void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title);
void _glfwSetWindowIconWayland(_GLFWwindow* window, int count, const GLFWimage* images); void _glfwSetWindowIconWayland(_GLFWwindow* window, int count, const GLFWimage* images);
@ -457,12 +463,12 @@ void _glfwHideWindowWayland(_GLFWwindow* window);
void _glfwRequestWindowAttentionWayland(_GLFWwindow* window); void _glfwRequestWindowAttentionWayland(_GLFWwindow* window);
void _glfwFocusWindowWayland(_GLFWwindow* window); void _glfwFocusWindowWayland(_GLFWwindow* window);
void _glfwSetWindowMonitorWayland(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); void _glfwSetWindowMonitorWayland(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
int _glfwWindowFocusedWayland(_GLFWwindow* window); GLFWbool _glfwWindowFocusedWayland(_GLFWwindow* window);
int _glfwWindowIconifiedWayland(_GLFWwindow* window); GLFWbool _glfwWindowIconifiedWayland(_GLFWwindow* window);
int _glfwWindowVisibleWayland(_GLFWwindow* window); GLFWbool _glfwWindowVisibleWayland(_GLFWwindow* window);
int _glfwWindowMaximizedWayland(_GLFWwindow* window); GLFWbool _glfwWindowMaximizedWayland(_GLFWwindow* window);
int _glfwWindowHoveredWayland(_GLFWwindow* window); GLFWbool _glfwWindowHoveredWayland(_GLFWwindow* window);
int _glfwFramebufferTransparentWayland(_GLFWwindow* window); GLFWbool _glfwFramebufferTransparentWayland(_GLFWwindow* window);
void _glfwSetWindowResizableWayland(_GLFWwindow* window, GLFWbool enabled); void _glfwSetWindowResizableWayland(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowDecoratedWayland(_GLFWwindow* window, GLFWbool enabled); void _glfwSetWindowDecoratedWayland(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowFloatingWayland(_GLFWwindow* window, GLFWbool enabled); void _glfwSetWindowFloatingWayland(_GLFWwindow* window, GLFWbool enabled);
@ -483,8 +489,8 @@ void _glfwSetCursorPosWayland(_GLFWwindow* window, double xpos, double ypos);
void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode); void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode);
const char* _glfwGetScancodeNameWayland(int scancode); const char* _glfwGetScancodeNameWayland(int scancode);
int _glfwGetKeyScancodeWayland(int key); int _glfwGetKeyScancodeWayland(int key);
int _glfwCreateCursorWayland(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot); GLFWbool _glfwCreateCursorWayland(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
int _glfwCreateStandardCursorWayland(_GLFWcursor* cursor, int shape); GLFWbool _glfwCreateStandardCursorWayland(_GLFWcursor* cursor, int shape);
void _glfwDestroyCursorWayland(_GLFWcursor* cursor); void _glfwDestroyCursorWayland(_GLFWcursor* cursor);
void _glfwSetCursorWayland(_GLFWwindow* window, _GLFWcursor* cursor); void _glfwSetCursorWayland(_GLFWwindow* window, _GLFWcursor* cursor);
void _glfwSetClipboardStringWayland(const char* string); void _glfwSetClipboardStringWayland(const char* string);
@ -495,7 +501,7 @@ EGLNativeDisplayType _glfwGetEGLNativeDisplayWayland(void);
EGLNativeWindowType _glfwGetEGLNativeWindowWayland(_GLFWwindow* window); EGLNativeWindowType _glfwGetEGLNativeWindowWayland(_GLFWwindow* window);
void _glfwGetRequiredInstanceExtensionsWayland(char** extensions); void _glfwGetRequiredInstanceExtensionsWayland(char** extensions);
int _glfwGetPhysicalDevicePresentationSupportWayland(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); GLFWbool _glfwGetPhysicalDevicePresentationSupportWayland(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
VkResult _glfwCreateWindowSurfaceWayland(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); VkResult _glfwCreateWindowSurfaceWayland(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
void _glfwFreeMonitorWayland(_GLFWmonitor* monitor); void _glfwFreeMonitorWayland(_GLFWmonitor* monitor);
@ -508,7 +514,7 @@ GLFWbool _glfwGetGammaRampWayland(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp); void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
void _glfwAddOutputWayland(uint32_t name, uint32_t version); void _glfwAddOutputWayland(uint32_t name, uint32_t version);
GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode); void _glfwUpdateContentScaleWayland(_GLFWwindow* window);
void _glfwAddSeatListenerWayland(struct wl_seat* seat); void _glfwAddSeatListenerWayland(struct wl_seat* seat);
void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device); void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device);

File diff suppressed because it is too large Load Diff

View File

@ -29,6 +29,8 @@
#include "internal.h" #include "internal.h"
#if defined(_GLFW_X11)
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
@ -37,6 +39,7 @@
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <assert.h>
// Translate the X11 KeySyms for a key to a GLFW key code // Translate the X11 KeySyms for a key to a GLFW key code
@ -1095,8 +1098,9 @@ static int errorHandler(Display *display, XErrorEvent* event)
// //
void _glfwGrabErrorHandlerX11(void) void _glfwGrabErrorHandlerX11(void)
{ {
assert(_glfw.x11.errorHandler == NULL);
_glfw.x11.errorCode = Success; _glfw.x11.errorCode = Success;
XSetErrorHandler(errorHandler); _glfw.x11.errorHandler = XSetErrorHandler(errorHandler);
} }
// Clears the X error handler callback // Clears the X error handler callback
@ -1105,7 +1109,8 @@ void _glfwReleaseErrorHandlerX11(void)
{ {
// Synchronize to make sure all commands are processed // Synchronize to make sure all commands are processed
XSync(_glfw.x11.display, False); XSync(_glfw.x11.display, False);
XSetErrorHandler(NULL); XSetErrorHandler(_glfw.x11.errorHandler);
_glfw.x11.errorHandler = NULL;
} }
// Reports the specified error, appending information about the last X error // Reports the specified error, appending information about the last X error
@ -1179,7 +1184,7 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform)
_glfwGetKeyScancodeX11, _glfwGetKeyScancodeX11,
_glfwSetClipboardStringX11, _glfwSetClipboardStringX11,
_glfwGetClipboardStringX11, _glfwGetClipboardStringX11,
#if defined(__linux__) #if defined(_GLFW_LINUX_JOYSTICK)
_glfwInitJoysticksLinux, _glfwInitJoysticksLinux,
_glfwTerminateJoysticksLinux, _glfwTerminateJoysticksLinux,
_glfwPollJoystickLinux, _glfwPollJoystickLinux,
@ -1649,3 +1654,5 @@ void _glfwTerminateX11(void)
} }
} }
#endif // _GLFW_X11

View File

@ -29,6 +29,8 @@
#include "internal.h" #include "internal.h"
#if defined(_GLFW_X11)
#include <limits.h> #include <limits.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -614,3 +616,5 @@ GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* handle)
return monitor->x11.output; return monitor->x11.output;
} }
#endif // _GLFW_X11

View File

@ -480,7 +480,6 @@ typedef struct _GLFWlibraryGLX
int eventBase; int eventBase;
int errorBase; int errorBase;
// dlopen handle for libGL.so.1
void* handle; void* handle;
// GLX 1.3 functions // GLX 1.3 functions
@ -567,6 +566,8 @@ typedef struct _GLFWlibraryX11
XContext context; XContext context;
// XIM input method // XIM input method
XIM im; XIM im;
// The previous X error handler, to be restored later
XErrorHandler errorHandler;
// Most recent error code received by X error handler // Most recent error code received by X error handler
int errorCode; int errorCode;
// Primary selection string (while the primary selection is owned) // Primary selection string (while the primary selection is owned)
@ -900,7 +901,7 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform);
int _glfwInitX11(void); int _glfwInitX11(void);
void _glfwTerminateX11(void); void _glfwTerminateX11(void);
int _glfwCreateWindowX11(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); GLFWbool _glfwCreateWindowX11(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig);
void _glfwDestroyWindowX11(_GLFWwindow* window); void _glfwDestroyWindowX11(_GLFWwindow* window);
void _glfwSetWindowTitleX11(_GLFWwindow* window, const char* title); void _glfwSetWindowTitleX11(_GLFWwindow* window, const char* title);
void _glfwSetWindowIconX11(_GLFWwindow* window, int count, const GLFWimage* images); void _glfwSetWindowIconX11(_GLFWwindow* window, int count, const GLFWimage* images);
@ -921,12 +922,12 @@ void _glfwHideWindowX11(_GLFWwindow* window);
void _glfwRequestWindowAttentionX11(_GLFWwindow* window); void _glfwRequestWindowAttentionX11(_GLFWwindow* window);
void _glfwFocusWindowX11(_GLFWwindow* window); void _glfwFocusWindowX11(_GLFWwindow* window);
void _glfwSetWindowMonitorX11(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); void _glfwSetWindowMonitorX11(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
int _glfwWindowFocusedX11(_GLFWwindow* window); GLFWbool _glfwWindowFocusedX11(_GLFWwindow* window);
int _glfwWindowIconifiedX11(_GLFWwindow* window); GLFWbool _glfwWindowIconifiedX11(_GLFWwindow* window);
int _glfwWindowVisibleX11(_GLFWwindow* window); GLFWbool _glfwWindowVisibleX11(_GLFWwindow* window);
int _glfwWindowMaximizedX11(_GLFWwindow* window); GLFWbool _glfwWindowMaximizedX11(_GLFWwindow* window);
int _glfwWindowHoveredX11(_GLFWwindow* window); GLFWbool _glfwWindowHoveredX11(_GLFWwindow* window);
int _glfwFramebufferTransparentX11(_GLFWwindow* window); GLFWbool _glfwFramebufferTransparentX11(_GLFWwindow* window);
void _glfwSetWindowResizableX11(_GLFWwindow* window, GLFWbool enabled); void _glfwSetWindowResizableX11(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowDecoratedX11(_GLFWwindow* window, GLFWbool enabled); void _glfwSetWindowDecoratedX11(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowFloatingX11(_GLFWwindow* window, GLFWbool enabled); void _glfwSetWindowFloatingX11(_GLFWwindow* window, GLFWbool enabled);
@ -947,8 +948,8 @@ void _glfwSetCursorPosX11(_GLFWwindow* window, double xpos, double ypos);
void _glfwSetCursorModeX11(_GLFWwindow* window, int mode); void _glfwSetCursorModeX11(_GLFWwindow* window, int mode);
const char* _glfwGetScancodeNameX11(int scancode); const char* _glfwGetScancodeNameX11(int scancode);
int _glfwGetKeyScancodeX11(int key); int _glfwGetKeyScancodeX11(int key);
int _glfwCreateCursorX11(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot); GLFWbool _glfwCreateCursorX11(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
int _glfwCreateStandardCursorX11(_GLFWcursor* cursor, int shape); GLFWbool _glfwCreateStandardCursorX11(_GLFWcursor* cursor, int shape);
void _glfwDestroyCursorX11(_GLFWcursor* cursor); void _glfwDestroyCursorX11(_GLFWcursor* cursor);
void _glfwSetCursorX11(_GLFWwindow* window, _GLFWcursor* cursor); void _glfwSetCursorX11(_GLFWwindow* window, _GLFWcursor* cursor);
void _glfwSetClipboardStringX11(const char* string); void _glfwSetClipboardStringX11(const char* string);
@ -959,7 +960,7 @@ EGLNativeDisplayType _glfwGetEGLNativeDisplayX11(void);
EGLNativeWindowType _glfwGetEGLNativeWindowX11(_GLFWwindow* window); EGLNativeWindowType _glfwGetEGLNativeWindowX11(_GLFWwindow* window);
void _glfwGetRequiredInstanceExtensionsX11(char** extensions); void _glfwGetRequiredInstanceExtensionsX11(char** extensions);
int _glfwGetPhysicalDevicePresentationSupportX11(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); GLFWbool _glfwGetPhysicalDevicePresentationSupportX11(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
VkResult _glfwCreateWindowSurfaceX11(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); VkResult _glfwCreateWindowSurfaceX11(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
void _glfwFreeMonitorX11(_GLFWmonitor* monitor); void _glfwFreeMonitorX11(_GLFWmonitor* monitor);

View File

@ -29,6 +29,8 @@
#include "internal.h" #include "internal.h"
#if defined(_GLFW_X11)
#include <X11/cursorfont.h> #include <X11/cursorfont.h>
#include <X11/Xmd.h> #include <X11/Xmd.h>
@ -86,7 +88,7 @@ static GLFWbool waitForAnyEvent(double* timeout)
{ _glfw.x11.emptyEventPipe[0], POLLIN } { _glfw.x11.emptyEventPipe[0], POLLIN }
}; };
#if defined(__linux__) #if defined(_GLFW_LINUX_JOYSTICK)
if (_glfw.joysticksInitialized) if (_glfw.joysticksInitialized)
fds[count++] = (struct pollfd) { _glfw.linjs.inotify, POLLIN }; fds[count++] = (struct pollfd) { _glfw.linjs.inotify, POLLIN };
#endif #endif
@ -270,6 +272,11 @@ static void updateNormalHints(_GLFWwindow* window, int width, int height)
{ {
XSizeHints* hints = XAllocSizeHints(); XSizeHints* hints = XAllocSizeHints();
long supplied;
XGetWMNormalHints(_glfw.x11.display, window->x11.handle, hints, &supplied);
hints->flags &= ~(PMinSize | PMaxSize | PAspect);
if (!window->monitor) if (!window->monitor)
{ {
if (window->resizable) if (window->resizable)
@ -306,9 +313,6 @@ static void updateNormalHints(_GLFWwindow* window, int width, int height)
} }
} }
hints->flags |= PWinGravity;
hints->win_gravity = StaticGravity;
XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints); XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);
XFree(hints); XFree(hints);
} }
@ -453,7 +457,8 @@ static char* convertLatin1toUTF8(const char* source)
// //
static void updateCursorImage(_GLFWwindow* window) static void updateCursorImage(_GLFWwindow* window)
{ {
if (window->cursorMode == GLFW_CURSOR_NORMAL) if (window->cursorMode == GLFW_CURSOR_NORMAL ||
window->cursorMode == GLFW_CURSOR_CAPTURED)
{ {
if (window->cursor) if (window->cursor)
{ {
@ -470,6 +475,25 @@ static void updateCursorImage(_GLFWwindow* window)
} }
} }
// Grabs the cursor and confines it to the window
//
static void captureCursor(_GLFWwindow* window)
{
XGrabPointer(_glfw.x11.display, window->x11.handle, True,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync,
window->x11.handle,
None,
CurrentTime);
}
// Ungrabs the cursor
//
static void releaseCursor(void)
{
XUngrabPointer(_glfw.x11.display, CurrentTime);
}
// Enable XI2 raw mouse motion events // Enable XI2 raw mouse motion events
// //
static void enableRawMouseMotion(_GLFWwindow* window) static void enableRawMouseMotion(_GLFWwindow* window)
@ -512,12 +536,7 @@ static void disableCursor(_GLFWwindow* window)
&_glfw.x11.restoreCursorPosY); &_glfw.x11.restoreCursorPosY);
updateCursorImage(window); updateCursorImage(window);
_glfwCenterCursorInContentArea(window); _glfwCenterCursorInContentArea(window);
XGrabPointer(_glfw.x11.display, window->x11.handle, True, captureCursor(window);
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync,
window->x11.handle,
_glfw.x11.hiddenCursorHandle,
CurrentTime);
} }
// Exit disabled cursor mode for the specified window // Exit disabled cursor mode for the specified window
@ -528,7 +547,7 @@ static void enableCursor(_GLFWwindow* window)
disableRawMouseMotion(window); disableRawMouseMotion(window);
_glfw.x11.disabledCursorWindow = NULL; _glfw.x11.disabledCursorWindow = NULL;
XUngrabPointer(_glfw.x11.display, CurrentTime); releaseCursor();
_glfwSetCursorPosX11(window, _glfwSetCursorPosX11(window,
_glfw.x11.restoreCursorPosX, _glfw.x11.restoreCursorPosX,
_glfw.x11.restoreCursorPosY); _glfw.x11.restoreCursorPosY);
@ -558,6 +577,14 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
height *= _glfw.x11.contentScaleY; height *= _glfw.x11.contentScaleY;
} }
int xpos = 0, ypos = 0;
if (wndconfig->xpos != GLFW_ANY_POSITION && wndconfig->ypos != GLFW_ANY_POSITION)
{
xpos = wndconfig->xpos;
ypos = wndconfig->ypos;
}
// Create a colormap based on the visual used by the current context // Create a colormap based on the visual used by the current context
window->x11.colormap = XCreateColormap(_glfw.x11.display, window->x11.colormap = XCreateColormap(_glfw.x11.display,
_glfw.x11.root, _glfw.x11.root,
@ -578,7 +605,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
window->x11.parent = _glfw.x11.root; window->x11.parent = _glfw.x11.root;
window->x11.handle = XCreateWindow(_glfw.x11.display, window->x11.handle = XCreateWindow(_glfw.x11.display,
_glfw.x11.root, _glfw.x11.root,
0, 0, // Position xpos, ypos,
width, height, width, height,
0, // Border width 0, // Border width
depth, // Color depth depth, // Color depth
@ -681,7 +708,37 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
XFree(hints); XFree(hints);
} }
updateNormalHints(window, width, height); // Set ICCCM WM_NORMAL_HINTS property
{
XSizeHints* hints = XAllocSizeHints();
if (!hints)
{
_glfwInputError(GLFW_OUT_OF_MEMORY, "X11: Failed to allocate size hints");
return GLFW_FALSE;
}
if (!wndconfig->resizable)
{
hints->flags |= (PMinSize | PMaxSize);
hints->min_width = hints->max_width = width;
hints->min_height = hints->max_height = height;
}
// HACK: Explicitly setting PPosition to any value causes some WMs, notably
// Compiz and Metacity, to honor the position of unmapped windows
if (wndconfig->xpos != GLFW_ANY_POSITION && wndconfig->ypos != GLFW_ANY_POSITION)
{
hints->flags |= PPosition;
hints->x = 0;
hints->y = 0;
}
hints->flags |= PWinGravity;
hints->win_gravity = StaticGravity;
XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);
XFree(hints);
}
// Set ICCCM WM_CLASS property // Set ICCCM WM_CLASS property
{ {
@ -1691,6 +1748,8 @@ static void processEvent(XEvent *event)
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
disableCursor(window); disableCursor(window);
else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
captureCursor(window);
if (window->x11.ic) if (window->x11.ic)
XSetICFocus(window->x11.ic); XSetICFocus(window->x11.ic);
@ -1711,6 +1770,8 @@ static void processEvent(XEvent *event)
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
enableCursor(window); enableCursor(window);
else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
releaseCursor();
if (window->x11.ic) if (window->x11.ic)
XUnsetICFocus(window->x11.ic); XUnsetICFocus(window->x11.ic);
@ -1895,10 +1956,10 @@ void _glfwCreateInputContextX11(_GLFWwindow* window)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
int _glfwCreateWindowX11(_GLFWwindow* window, GLFWbool _glfwCreateWindowX11(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig, const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) const _GLFWfbconfig* fbconfig)
{ {
Visual* visual = NULL; Visual* visual = NULL;
int depth; int depth;
@ -1986,7 +2047,7 @@ int _glfwCreateWindowX11(_GLFWwindow* window,
void _glfwDestroyWindowX11(_GLFWwindow* window) void _glfwDestroyWindowX11(_GLFWwindow* window)
{ {
if (_glfw.x11.disabledCursorWindow == window) if (_glfw.x11.disabledCursorWindow == window)
_glfw.x11.disabledCursorWindow = NULL; enableCursor(window);
if (window->monitor) if (window->monitor)
releaseMonitor(window); releaseMonitor(window);
@ -2462,7 +2523,7 @@ void _glfwSetWindowMonitorX11(_GLFWwindow* window,
XFlush(_glfw.x11.display); XFlush(_glfw.x11.display);
} }
int _glfwWindowFocusedX11(_GLFWwindow* window) GLFWbool _glfwWindowFocusedX11(_GLFWwindow* window)
{ {
Window focused; Window focused;
int state; int state;
@ -2471,19 +2532,19 @@ int _glfwWindowFocusedX11(_GLFWwindow* window)
return window->x11.handle == focused; return window->x11.handle == focused;
} }
int _glfwWindowIconifiedX11(_GLFWwindow* window) GLFWbool _glfwWindowIconifiedX11(_GLFWwindow* window)
{ {
return getWindowState(window) == IconicState; return getWindowState(window) == IconicState;
} }
int _glfwWindowVisibleX11(_GLFWwindow* window) GLFWbool _glfwWindowVisibleX11(_GLFWwindow* window)
{ {
XWindowAttributes wa; XWindowAttributes wa;
XGetWindowAttributes(_glfw.x11.display, window->x11.handle, &wa); XGetWindowAttributes(_glfw.x11.display, window->x11.handle, &wa);
return wa.map_state == IsViewable; return wa.map_state == IsViewable;
} }
int _glfwWindowMaximizedX11(_GLFWwindow* window) GLFWbool _glfwWindowMaximizedX11(_GLFWwindow* window)
{ {
Atom* states; Atom* states;
GLFWbool maximized = GLFW_FALSE; GLFWbool maximized = GLFW_FALSE;
@ -2517,7 +2578,7 @@ int _glfwWindowMaximizedX11(_GLFWwindow* window)
return maximized; return maximized;
} }
int _glfwWindowHoveredX11(_GLFWwindow* window) GLFWbool _glfwWindowHoveredX11(_GLFWwindow* window)
{ {
Window w = _glfw.x11.root; Window w = _glfw.x11.root;
while (w) while (w)
@ -2545,7 +2606,7 @@ int _glfwWindowHoveredX11(_GLFWwindow* window)
return GLFW_FALSE; return GLFW_FALSE;
} }
int _glfwFramebufferTransparentX11(_GLFWwindow* window) GLFWbool _glfwFramebufferTransparentX11(_GLFWwindow* window)
{ {
if (!window->x11.transparent) if (!window->x11.transparent)
return GLFW_FALSE; return GLFW_FALSE;
@ -2722,7 +2783,7 @@ void _glfwPollEventsX11(void)
{ {
drainEmptyEvents(); drainEmptyEvents();
#if defined(__linux__) #if defined(_GLFW_LINUX_JOYSTICK)
if (_glfw.joysticksInitialized) if (_glfw.joysticksInitialized)
_glfwDetectJoystickConnectionLinux(); _glfwDetectJoystickConnectionLinux();
#endif #endif
@ -2800,16 +2861,40 @@ void _glfwSetCursorPosX11(_GLFWwindow* window, double x, double y)
void _glfwSetCursorModeX11(_GLFWwindow* window, int mode) void _glfwSetCursorModeX11(_GLFWwindow* window, int mode)
{ {
if (mode == GLFW_CURSOR_DISABLED) if (_glfwWindowFocusedX11(window))
{ {
if (_glfwWindowFocusedX11(window)) if (mode == GLFW_CURSOR_DISABLED)
disableCursor(window); {
} _glfwGetCursorPosX11(window,
else if (_glfw.x11.disabledCursorWindow == window) &_glfw.x11.restoreCursorPosX,
enableCursor(window); &_glfw.x11.restoreCursorPosY);
else _glfwCenterCursorInContentArea(window);
updateCursorImage(window); if (window->rawMouseMotion)
enableRawMouseMotion(window);
}
else if (_glfw.x11.disabledCursorWindow == window)
{
if (window->rawMouseMotion)
disableRawMouseMotion(window);
}
if (mode == GLFW_CURSOR_DISABLED || mode == GLFW_CURSOR_CAPTURED)
captureCursor(window);
else
releaseCursor();
if (mode == GLFW_CURSOR_DISABLED)
_glfw.x11.disabledCursorWindow = window;
else if (_glfw.x11.disabledCursorWindow == window)
{
_glfw.x11.disabledCursorWindow = NULL;
_glfwSetCursorPosX11(window,
_glfw.x11.restoreCursorPosX,
_glfw.x11.restoreCursorPosY);
}
}
updateCursorImage(window);
XFlush(_glfw.x11.display); XFlush(_glfw.x11.display);
} }
@ -2848,9 +2933,9 @@ int _glfwGetKeyScancodeX11(int key)
return _glfw.x11.scancodes[key]; return _glfw.x11.scancodes[key];
} }
int _glfwCreateCursorX11(_GLFWcursor* cursor, GLFWbool _glfwCreateCursorX11(_GLFWcursor* cursor,
const GLFWimage* image, const GLFWimage* image,
int xhot, int yhot) int xhot, int yhot)
{ {
cursor->x11.handle = _glfwCreateNativeCursorX11(image, xhot, yhot); cursor->x11.handle = _glfwCreateNativeCursorX11(image, xhot, yhot);
if (!cursor->x11.handle) if (!cursor->x11.handle)
@ -2859,7 +2944,7 @@ int _glfwCreateCursorX11(_GLFWcursor* cursor,
return GLFW_TRUE; return GLFW_TRUE;
} }
int _glfwCreateStandardCursorX11(_GLFWcursor* cursor, int shape) GLFWbool _glfwCreateStandardCursorX11(_GLFWcursor* cursor, int shape)
{ {
if (_glfw.x11.xcursor.handle) if (_glfw.x11.xcursor.handle)
{ {
@ -2965,7 +3050,8 @@ void _glfwDestroyCursorX11(_GLFWcursor* cursor)
void _glfwSetCursorX11(_GLFWwindow* window, _GLFWcursor* cursor) void _glfwSetCursorX11(_GLFWwindow* window, _GLFWcursor* cursor)
{ {
if (window->cursorMode == GLFW_CURSOR_NORMAL) if (window->cursorMode == GLFW_CURSOR_NORMAL ||
window->cursorMode == GLFW_CURSOR_CAPTURED)
{ {
updateCursorImage(window); updateCursorImage(window);
XFlush(_glfw.x11.display); XFlush(_glfw.x11.display);
@ -3066,9 +3152,9 @@ void _glfwGetRequiredInstanceExtensionsX11(char** extensions)
extensions[1] = "VK_KHR_xlib_surface"; extensions[1] = "VK_KHR_xlib_surface";
} }
int _glfwGetPhysicalDevicePresentationSupportX11(VkInstance instance, GLFWbool _glfwGetPhysicalDevicePresentationSupportX11(VkInstance instance,
VkPhysicalDevice device, VkPhysicalDevice device,
uint32_t queuefamily) uint32_t queuefamily)
{ {
VisualID visualID = XVisualIDFromVisual(DefaultVisual(_glfw.x11.display, VisualID visualID = XVisualIDFromVisual(DefaultVisual(_glfw.x11.display,
_glfw.x11.screen)); _glfw.x11.screen));
@ -3265,3 +3351,5 @@ GLFWAPI const char* glfwGetX11SelectionString(void)
return getSelectionString(_glfw.x11.PRIMARY); return getSelectionString(_glfw.x11.PRIMARY);
} }
#endif // _GLFW_X11

View File

@ -29,6 +29,7 @@
#include "internal.h" #include "internal.h"
#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND)
/* /*
* Marcus: This code was originally written by Markus G. Kuhn. * Marcus: This code was originally written by Markus G. Kuhn.
@ -940,3 +941,5 @@ uint32_t _glfwKeySym2Unicode(unsigned int keysym)
return GLFW_INVALID_CODEPOINT; return GLFW_INVALID_CODEPOINT;
} }
#endif // _GLFW_WAYLAND or _GLFW_X11

View File

@ -172,7 +172,8 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
case GLFW_KEY_ESCAPE: case GLFW_KEY_ESCAPE:
{ {
if (glfwGetInputMode(window, GLFW_CURSOR) != GLFW_CURSOR_DISABLED) const int mode = glfwGetInputMode(window, GLFW_CURSOR);
if (mode != GLFW_CURSOR_DISABLED && mode != GLFW_CURSOR_CAPTURED)
{ {
glfwSetWindowShouldClose(window, GLFW_TRUE); glfwSetWindowShouldClose(window, GLFW_TRUE);
break; break;
@ -197,6 +198,11 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
printf("(( cursor is hidden ))\n"); printf("(( cursor is hidden ))\n");
break; break;
case GLFW_KEY_C:
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_CAPTURED);
printf("(( cursor is captured ))\n");
break;
case GLFW_KEY_R: case GLFW_KEY_R:
if (!glfwRawMouseMotionSupported()) if (!glfwRawMouseMotionSupported())
break; break;

View File

@ -642,7 +642,7 @@ int main(int argc, char** argv)
glfwMakeContextCurrent(slots[i].window); glfwMakeContextCurrent(slots[i].window);
gladLoadGL(glfwGetProcAddress); gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(1); glfwSwapBuffers(slots[i].window);
} }
printf("Main loop starting\n"); printf("Main loop starting\n");

View File

@ -255,21 +255,6 @@ static void list_context_extensions(int client, int major, int minor)
} }
} }
static void list_vulkan_instance_extensions(void)
{
printf("Vulkan instance extensions:\n");
uint32_t ep_count;
vkEnumerateInstanceExtensionProperties(NULL, &ep_count, NULL);
VkExtensionProperties* ep = calloc(ep_count, sizeof(VkExtensionProperties));
vkEnumerateInstanceExtensionProperties(NULL, &ep_count, ep);
for (uint32_t i = 0; i < ep_count; i++)
printf(" %s (spec version %u)\n", ep[i].extensionName, ep[i].specVersion);
free(ep);
}
static void list_vulkan_instance_layers(void) static void list_vulkan_instance_layers(void)
{ {
printf("Vulkan instance layers:\n"); printf("Vulkan instance layers:\n");
@ -290,21 +275,6 @@ static void list_vulkan_instance_layers(void)
free(lp); free(lp);
} }
static void list_vulkan_device_extensions(VkInstance instance, VkPhysicalDevice device)
{
printf("Vulkan device extensions:\n");
uint32_t ep_count;
vkEnumerateDeviceExtensionProperties(device, NULL, &ep_count, NULL);
VkExtensionProperties* ep = calloc(ep_count, sizeof(VkExtensionProperties));
vkEnumerateDeviceExtensionProperties(device, NULL, &ep_count, ep);
for (uint32_t i = 0; i < ep_count; i++)
printf(" %s (spec version %u)\n", ep[i].extensionName, ep[i].specVersion);
free(ep);
}
static void list_vulkan_device_layers(VkInstance instance, VkPhysicalDevice device) static void list_vulkan_device_layers(VkInstance instance, VkPhysicalDevice device)
{ {
printf("Vulkan device layers:\n"); printf("Vulkan device layers:\n");
@ -953,20 +923,51 @@ int main(int argc, char** argv)
VK_VERSION_MAJOR(loader_version), VK_VERSION_MAJOR(loader_version),
VK_VERSION_MINOR(loader_version)); VK_VERSION_MINOR(loader_version));
uint32_t re_count; uint32_t glfw_re_count;
const char** re = glfwGetRequiredInstanceExtensions(&re_count); const char** glfw_re = glfwGetRequiredInstanceExtensions(&glfw_re_count);
if (re) uint32_t re_count = glfw_re_count;
const char** re = calloc(glfw_re_count, sizeof(char*));
if (glfw_re)
{ {
printf("Vulkan window surface required instance extensions:\n"); printf("Vulkan window surface required instance extensions:\n");
for (uint32_t i = 0; i < re_count; i++) for (uint32_t i = 0; i < glfw_re_count; i++)
printf(" %s\n", re[i]); {
printf(" %s\n", glfw_re[i]);
re[i] = glfw_re[i];
}
} }
else else
printf("Vulkan window surface extensions missing\n"); printf("Vulkan window surface extensions missing\n");
uint32_t ep_count;
vkEnumerateInstanceExtensionProperties(NULL, &ep_count, NULL);
VkExtensionProperties* ep = calloc(ep_count, sizeof(VkExtensionProperties));
vkEnumerateInstanceExtensionProperties(NULL, &ep_count, ep);
if (list_extensions) if (list_extensions)
list_vulkan_instance_extensions(); {
printf("Vulkan instance extensions:\n");
for (uint32_t i = 0; i < ep_count; i++)
printf(" %s (spec version %u)\n", ep[i].extensionName, ep[i].specVersion);
}
bool portability_enumeration = false;
for (uint32_t i = 0; i < ep_count; i++)
{
if (strcmp(ep[i].extensionName, "VK_KHR_portability_enumeration") != 0)
continue;
re_count++;
re = realloc((void*) re, sizeof(char*) * re_count);
re[re_count - 1] = "VK_KHR_portability_enumeration";
portability_enumeration = true;
}
free(ep);
if (list_layers) if (list_layers)
list_vulkan_instance_layers(); list_vulkan_instance_layers();
@ -987,6 +988,9 @@ int main(int argc, char** argv)
ici.enabledExtensionCount = re_count; ici.enabledExtensionCount = re_count;
ici.ppEnabledExtensionNames = re; ici.ppEnabledExtensionNames = re;
if (portability_enumeration)
ici.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
VkInstance instance = VK_NULL_HANDLE; VkInstance instance = VK_NULL_HANDLE;
if (vkCreateInstance(&ici, NULL, &instance) != VK_SUCCESS) if (vkCreateInstance(&ici, NULL, &instance) != VK_SUCCESS)
@ -995,9 +999,11 @@ int main(int argc, char** argv)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
free((void*) re);
gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, instance); gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, instance);
if (re) if (glfw_re_count)
{ {
VkSurfaceKHR surface = VK_NULL_HANDLE; VkSurfaceKHR surface = VK_NULL_HANDLE;
@ -1020,16 +1026,44 @@ int main(int argc, char** argv)
VkPhysicalDeviceProperties pdp; VkPhysicalDeviceProperties pdp;
vkGetPhysicalDeviceProperties(pd[i], &pdp); vkGetPhysicalDeviceProperties(pd[i], &pdp);
printf("Vulkan %s device: \"%s\" (API version %i.%i)\n",
get_device_type_name(pdp.deviceType),
pdp.deviceName,
VK_VERSION_MAJOR(pdp.apiVersion),
VK_VERSION_MINOR(pdp.apiVersion));
uint32_t qfp_count; uint32_t qfp_count;
vkGetPhysicalDeviceQueueFamilyProperties(pd[i], &qfp_count, NULL); vkGetPhysicalDeviceQueueFamilyProperties(pd[i], &qfp_count, NULL);
if (re) uint32_t ep_count;
vkEnumerateDeviceExtensionProperties(pd[i], NULL, &ep_count, NULL);
VkExtensionProperties* ep = calloc(ep_count, sizeof(VkExtensionProperties));
vkEnumerateDeviceExtensionProperties(pd[i], NULL, &ep_count, ep);
if (portability_enumeration)
{
bool conformant = true;
for (uint32_t j = 0; j < ep_count; j++)
{
if (strcmp(ep[j].extensionName, "VK_KHR_portability_subset") == 0)
{
conformant = false;
break;
}
}
printf("Vulkan %s %s device: \"%s\" (API version %i.%i)\n",
conformant ? "conformant" : "non-conformant",
get_device_type_name(pdp.deviceType),
pdp.deviceName,
VK_VERSION_MAJOR(pdp.apiVersion),
VK_VERSION_MINOR(pdp.apiVersion));
}
else
{
printf("Vulkan %s device: \"%s\" (API version %i.%i)\n",
get_device_type_name(pdp.deviceType),
pdp.deviceName,
VK_VERSION_MAJOR(pdp.apiVersion),
VK_VERSION_MINOR(pdp.apiVersion));
}
if (glfw_re_count)
{ {
printf("Vulkan device queue family presentation support:\n"); printf("Vulkan device queue family presentation support:\n");
for (uint32_t j = 0; j < qfp_count; j++) for (uint32_t j = 0; j < qfp_count; j++)
@ -1043,7 +1077,13 @@ int main(int argc, char** argv)
} }
if (list_extensions) if (list_extensions)
list_vulkan_device_extensions(instance, pd[i]); {
printf("Vulkan device extensions:\n");
for (uint32_t j = 0; j < ep_count; j++)
printf(" %s (spec version %u)\n", ep[j].extensionName, ep[j].specVersion);
}
free(ep);
if (list_layers) if (list_layers)
list_vulkan_device_layers(instance, pd[i]); list_vulkan_device_layers(instance, pd[i]);

View File

@ -96,10 +96,11 @@ int main(void)
if (!glfwInit()) if (!glfwInit())
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
glfwWindowHint(GLFW_POSITION_X, 200 + 250 * i);
glfwWindowHint(GLFW_POSITION_Y, 200);
threads[i].window = glfwCreateWindow(200, 200, threads[i].window = glfwCreateWindow(200, 200,
threads[i].title, threads[i].title,
NULL, NULL); NULL, NULL);
@ -110,9 +111,6 @@ int main(void)
} }
glfwSetKeyCallback(threads[i].window, key_callback); glfwSetKeyCallback(threads[i].window, key_callback);
glfwSetWindowPos(threads[i].window, 200 + 250 * i, 200);
glfwShowWindow(threads[i].window);
} }
glfwMakeContextCurrent(threads[0].window); glfwMakeContextCurrent(threads[0].window);

View File

@ -1561,6 +1561,7 @@ static VkBool32 demo_check_layers(uint32_t check_count, const char **check_names
static void demo_init_vk(struct demo *demo) { static void demo_init_vk(struct demo *demo) {
VkResult err; VkResult err;
VkBool32 portability_enumeration = VK_FALSE;
uint32_t i = 0; uint32_t i = 0;
uint32_t required_extension_count = 0; uint32_t required_extension_count = 0;
uint32_t instance_extension_count = 0; uint32_t instance_extension_count = 0;
@ -1668,6 +1669,13 @@ static void demo_init_vk(struct demo *demo) {
} }
} }
assert(demo->enabled_extension_count < 64); assert(demo->enabled_extension_count < 64);
if (!strcmp(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
instance_extensions[i].extensionName)) {
demo->extension_names[demo->enabled_extension_count++] =
VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME;
portability_enumeration = VK_TRUE;
}
assert(demo->enabled_extension_count < 64);
} }
free(instance_extensions); free(instance_extensions);
@ -1692,6 +1700,9 @@ static void demo_init_vk(struct demo *demo) {
.ppEnabledExtensionNames = (const char *const *)demo->extension_names, .ppEnabledExtensionNames = (const char *const *)demo->extension_names,
}; };
if (portability_enumeration)
inst_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
uint32_t gpu_count; uint32_t gpu_count;
err = vkCreateInstance(&inst_info, NULL, &demo->inst); err = vkCreateInstance(&inst_info, NULL, &demo->inst);