mirror of
https://github.com/glfw/glfw.git
synced 2024-11-26 06:14:35 +00:00
Merge branch 'glfw:master' into taskbar-progress
This commit is contained in:
commit
fb4c22ed9c
@ -166,6 +166,7 @@ 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
|
- Olivier Perret
|
||||||
|
@ -139,9 +139,16 @@ 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
|
||||||
@ -387,7 +394,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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
|
||||||
@ -312,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.
|
||||||
|
|
||||||
@ -319,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
|
||||||
@ -382,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);
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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,7 @@ 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 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 +160,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 +250,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
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
@ -492,6 +500,13 @@ __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.
|
||||||
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 +524,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 +557,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 +808,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.
|
||||||
|
@ -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++)
|
||||||
|
@ -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.
|
||||||
*
|
*
|
||||||
@ -3035,10 +3056,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.
|
||||||
@ -4568,6 +4589,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
|
||||||
|
@ -103,17 +103,23 @@ extern "C" {
|
|||||||
#undef GLFW_APIENTRY_DEFINED
|
#undef GLFW_APIENTRY_DEFINED
|
||||||
#endif
|
#endif
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#elif defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL)
|
#endif
|
||||||
|
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL)
|
||||||
#if defined(__OBJC__)
|
#if defined(__OBJC__)
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
#else
|
#else
|
||||||
#include <ApplicationServices/ApplicationServices.h>
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
#include <objc/objc.h>
|
#include <objc/objc.h>
|
||||||
#endif
|
#endif
|
||||||
#elif defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
|
#endif
|
||||||
|
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/extensions/Xrandr.h>
|
#include <X11/extensions/Xrandr.h>
|
||||||
#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
|
#endif
|
||||||
|
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -791,7 +791,19 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
contentRect = NSMakeRect(xpos, ypos, mode.width, mode.height);
|
contentRect = NSMakeRect(xpos, ypos, mode.width, mode.height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (wndconfig->xpos == GLFW_ANY_POSITION ||
|
||||||
|
wndconfig->ypos == GLFW_ANY_POSITION)
|
||||||
|
{
|
||||||
contentRect = NSMakeRect(0, 0, wndconfig->width, wndconfig->height);
|
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;
|
NSUInteger styleMask = NSWindowStyleMaskMiniaturizable;
|
||||||
|
|
||||||
@ -820,11 +832,15 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
if (window->monitor)
|
if (window->monitor)
|
||||||
[window->ns.object setLevel:NSMainMenuWindowLevel + 1];
|
[window->ns.object setLevel:NSMainMenuWindowLevel + 1];
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (wndconfig->xpos == GLFW_ANY_POSITION ||
|
||||||
|
wndconfig->ypos == GLFW_ANY_POSITION)
|
||||||
{
|
{
|
||||||
[(NSWindow*) window->ns.object center];
|
[(NSWindow*) window->ns.object center];
|
||||||
_glfw.ns.cascadePoint =
|
_glfw.ns.cascadePoint =
|
||||||
NSPointToCGPoint([window->ns.object cascadeTopLeftFromPoint:
|
NSPointToCGPoint([window->ns.object cascadeTopLeftFromPoint:
|
||||||
NSPointFromCGPoint(_glfw.ns.cascadePoint)]);
|
NSPointFromCGPoint(_glfw.ns.cascadePoint)]);
|
||||||
|
}
|
||||||
|
|
||||||
if (wndconfig->resizable)
|
if (wndconfig->resizable)
|
||||||
{
|
{
|
||||||
@ -1625,8 +1641,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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,6 +737,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
|
||||||
|
@ -226,7 +226,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 +265,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
|
||||||
|
@ -596,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",
|
||||||
|
@ -396,6 +396,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 +423,9 @@ struct _GLFWwndconfig
|
|||||||
struct {
|
struct {
|
||||||
GLFWbool keymenu;
|
GLFWbool keymenu;
|
||||||
} win32;
|
} win32;
|
||||||
|
struct {
|
||||||
|
char appId[256];
|
||||||
|
} wl;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Context configuration
|
// Context configuration
|
||||||
|
@ -81,9 +81,18 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||||||
if (window->monitor)
|
if (window->monitor)
|
||||||
fitToMonitor(window);
|
fitToMonitor(window);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (wndconfig->xpos == GLFW_ANY_POSITION && wndconfig->ypos == GLFW_ANY_POSITION)
|
||||||
{
|
{
|
||||||
window->null.xpos = 17;
|
window->null.xpos = 17;
|
||||||
window->null.ypos = 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;
|
||||||
}
|
}
|
||||||
|
@ -456,6 +456,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;
|
||||||
|
@ -238,7 +238,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 +250,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;
|
RECT clipRect;
|
||||||
GetClientRect(window->win32.handle, &clipRect);
|
GetClientRect(window->win32.handle, &clipRect);
|
||||||
ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);
|
ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);
|
||||||
ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);
|
ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);
|
||||||
ClipCursor(&clipRect);
|
ClipCursor(&clipRect);
|
||||||
}
|
_glfw.win32.capturedCursorWindow = window;
|
||||||
else
|
}
|
||||||
|
|
||||||
|
// Disabled clip cursor
|
||||||
|
//
|
||||||
|
static void releaseCursor(void)
|
||||||
|
{
|
||||||
ClipCursor(NULL);
|
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 +306,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 +320,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);
|
||||||
@ -582,6 +587,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;
|
||||||
}
|
}
|
||||||
@ -600,6 +607,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;
|
||||||
}
|
}
|
||||||
@ -608,6 +617,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);
|
||||||
@ -977,6 +988,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;
|
||||||
}
|
}
|
||||||
@ -991,6 +1004,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;
|
||||||
}
|
}
|
||||||
@ -1004,8 +1019,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);
|
||||||
@ -1040,8 +1055,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
|
||||||
@ -1313,17 +1328,27 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
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);
|
{
|
||||||
|
xpos = CW_USEDEFAULT;
|
||||||
|
ypos = CW_USEDEFAULT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xpos = wndconfig->xpos + rect.left;
|
||||||
|
ypos = wndconfig->ypos + rect.top;
|
||||||
|
}
|
||||||
|
|
||||||
|
fullWidth = rect.right - rect.left;
|
||||||
|
fullHeight = rect.bottom - rect.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);
|
wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);
|
||||||
@ -1511,7 +1536,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.TaskbarList)
|
if (window->win32.TaskbarList)
|
||||||
window->win32.TaskbarList->lpVtbl->Release(window->win32.TaskbarList);
|
window->win32.TaskbarList->lpVtbl->Release(window->win32.TaskbarList);
|
||||||
@ -2178,14 +2206,40 @@ void _glfwSetCursorPosWin32(_GLFWwindow* window, double xpos, double ypos)
|
|||||||
|
|
||||||
void _glfwSetCursorModeWin32(_GLFWwindow* window, int mode)
|
void _glfwSetCursorModeWin32(_GLFWwindow* window, int mode)
|
||||||
{
|
{
|
||||||
|
if (_glfwWindowFocusedWin32(window))
|
||||||
|
{
|
||||||
if (mode == GLFW_CURSOR_DISABLED)
|
if (mode == GLFW_CURSOR_DISABLED)
|
||||||
{
|
{
|
||||||
if (_glfwWindowFocusedWin32(window))
|
_glfwGetCursorPosWin32(window,
|
||||||
disableCursor(window);
|
&_glfw.win32.restoreCursorPosX,
|
||||||
|
&_glfw.win32.restoreCursorPosY);
|
||||||
|
_glfwCenterCursorInContentArea(window);
|
||||||
|
if (window->rawMouseMotion)
|
||||||
|
enableRawMouseMotion(window);
|
||||||
}
|
}
|
||||||
else if (_glfw.win32.disabledCursorWindow == window)
|
else if (_glfw.win32.disabledCursorWindow == window)
|
||||||
enableCursor(window);
|
{
|
||||||
else if (cursorInContentArea(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursorInContentArea(window))
|
||||||
updateCursorImage(window);
|
updateCursorImage(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
src/window.c
12
src/window.c
@ -274,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
|
||||||
@ -368,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;
|
||||||
@ -447,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);
|
||||||
|
@ -258,6 +258,7 @@ typedef struct _GLFWwindowWayland
|
|||||||
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.
|
||||||
@ -266,10 +267,9 @@ 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;
|
||||||
} pointerLock;
|
struct zwp_confined_pointer_v1* confinedPointer;
|
||||||
|
|
||||||
struct zwp_idle_inhibitor_v1* idleInhibitor;
|
struct zwp_idle_inhibitor_v1* idleInhibitor;
|
||||||
|
|
||||||
|
160
src/wl_window.c
160
src/wl_window.c
@ -614,6 +614,9 @@ static GLFWbool createShellObjects(_GLFWwindow* window)
|
|||||||
|
|
||||||
xdg_toplevel_add_listener(window->wl.xdg.toplevel, &xdgToplevelListener, window);
|
xdg_toplevel_add_listener(window->wl.xdg.toplevel, &xdgToplevelListener, window);
|
||||||
|
|
||||||
|
if (window->wl.appId)
|
||||||
|
xdg_toplevel_set_app_id(window->wl.xdg.toplevel, window->wl.appId);
|
||||||
|
|
||||||
if (window->wl.title)
|
if (window->wl.title)
|
||||||
xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title);
|
xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title);
|
||||||
|
|
||||||
@ -728,6 +731,7 @@ static GLFWbool createNativeSurface(_GLFWwindow* window,
|
|||||||
window->wl.height = wndconfig->height;
|
window->wl.height = wndconfig->height;
|
||||||
window->wl.scale = 1;
|
window->wl.scale = 1;
|
||||||
window->wl.title = _glfw_strdup(wndconfig->title);
|
window->wl.title = _glfw_strdup(wndconfig->title);
|
||||||
|
window->wl.appId = _glfw_strdup(wndconfig->wl.appId);
|
||||||
|
|
||||||
window->wl.maximized = wndconfig->maximized;
|
window->wl.maximized = wndconfig->maximized;
|
||||||
|
|
||||||
@ -1850,6 +1854,15 @@ void _glfwDestroyWindowWayland(_GLFWwindow* window)
|
|||||||
if (window->wl.idleInhibitor)
|
if (window->wl.idleInhibitor)
|
||||||
zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);
|
zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);
|
||||||
|
|
||||||
|
if (window->wl.relativePointer)
|
||||||
|
zwp_relative_pointer_v1_destroy(window->wl.relativePointer);
|
||||||
|
|
||||||
|
if (window->wl.lockedPointer)
|
||||||
|
zwp_locked_pointer_v1_destroy(window->wl.lockedPointer);
|
||||||
|
|
||||||
|
if (window->wl.confinedPointer)
|
||||||
|
zwp_confined_pointer_v1_destroy(window->wl.confinedPointer);
|
||||||
|
|
||||||
if (window->context.destroy)
|
if (window->context.destroy)
|
||||||
window->context.destroy(window);
|
window->context.destroy(window);
|
||||||
|
|
||||||
@ -1865,6 +1878,7 @@ void _glfwDestroyWindowWayland(_GLFWwindow* window)
|
|||||||
wl_surface_destroy(window->wl.surface);
|
wl_surface_destroy(window->wl.surface);
|
||||||
|
|
||||||
_glfw_free(window->wl.title);
|
_glfw_free(window->wl.title);
|
||||||
|
_glfw_free(window->wl.appId);
|
||||||
_glfw_free(window->wl.monitors);
|
_glfw_free(window->wl.monitors);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2242,16 +2256,10 @@ void _glfwGetCursorPosWayland(_GLFWwindow* window, double* xpos, double* ypos)
|
|||||||
*ypos = window->wl.cursorPosY;
|
*ypos = window->wl.cursorPosY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLFWbool isPointerLocked(_GLFWwindow* window);
|
|
||||||
|
|
||||||
void _glfwSetCursorPosWayland(_GLFWwindow* window, double x, double y)
|
void _glfwSetCursorPosWayland(_GLFWwindow* window, double x, double y)
|
||||||
{
|
{
|
||||||
if (isPointerLocked(window))
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||||
{
|
"Wayland: The platform does not support setting the cursor position");
|
||||||
zwp_locked_pointer_v1_set_cursor_position_hint(
|
|
||||||
window->wl.pointerLock.lockedPointer,
|
|
||||||
wl_fixed_from_double(x), wl_fixed_from_double(y));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode)
|
void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode)
|
||||||
@ -2485,22 +2493,6 @@ static void lockedPointerHandleLocked(void* userData,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unlockPointer(_GLFWwindow* window)
|
|
||||||
{
|
|
||||||
struct zwp_relative_pointer_v1* relativePointer =
|
|
||||||
window->wl.pointerLock.relativePointer;
|
|
||||||
struct zwp_locked_pointer_v1* lockedPointer =
|
|
||||||
window->wl.pointerLock.lockedPointer;
|
|
||||||
|
|
||||||
zwp_relative_pointer_v1_destroy(relativePointer);
|
|
||||||
zwp_locked_pointer_v1_destroy(lockedPointer);
|
|
||||||
|
|
||||||
window->wl.pointerLock.relativePointer = NULL;
|
|
||||||
window->wl.pointerLock.lockedPointer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lockPointer(_GLFWwindow* window);
|
|
||||||
|
|
||||||
static void lockedPointerHandleUnlocked(void* userData,
|
static void lockedPointerHandleUnlocked(void* userData,
|
||||||
struct zwp_locked_pointer_v1* lockedPointer)
|
struct zwp_locked_pointer_v1* lockedPointer)
|
||||||
{
|
{
|
||||||
@ -2514,52 +2506,81 @@ static const struct zwp_locked_pointer_v1_listener lockedPointerListener =
|
|||||||
|
|
||||||
static void lockPointer(_GLFWwindow* window)
|
static void lockPointer(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
struct zwp_relative_pointer_v1* relativePointer;
|
|
||||||
struct zwp_locked_pointer_v1* lockedPointer;
|
|
||||||
|
|
||||||
if (!_glfw.wl.relativePointerManager)
|
if (!_glfw.wl.relativePointerManager)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||||
"Wayland: no relative pointer manager");
|
"Wayland: The compositor does not support pointer locking");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
relativePointer =
|
window->wl.relativePointer =
|
||||||
zwp_relative_pointer_manager_v1_get_relative_pointer(
|
zwp_relative_pointer_manager_v1_get_relative_pointer(
|
||||||
_glfw.wl.relativePointerManager,
|
_glfw.wl.relativePointerManager,
|
||||||
_glfw.wl.pointer);
|
_glfw.wl.pointer);
|
||||||
zwp_relative_pointer_v1_add_listener(relativePointer,
|
zwp_relative_pointer_v1_add_listener(window->wl.relativePointer,
|
||||||
&relativePointerListener,
|
&relativePointerListener,
|
||||||
window);
|
window);
|
||||||
|
|
||||||
lockedPointer =
|
window->wl.lockedPointer =
|
||||||
zwp_pointer_constraints_v1_lock_pointer(
|
zwp_pointer_constraints_v1_lock_pointer(
|
||||||
_glfw.wl.pointerConstraints,
|
_glfw.wl.pointerConstraints,
|
||||||
window->wl.surface,
|
window->wl.surface,
|
||||||
_glfw.wl.pointer,
|
_glfw.wl.pointer,
|
||||||
NULL,
|
NULL,
|
||||||
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
|
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
|
||||||
zwp_locked_pointer_v1_add_listener(lockedPointer,
|
zwp_locked_pointer_v1_add_listener(window->wl.lockedPointer,
|
||||||
&lockedPointerListener,
|
&lockedPointerListener,
|
||||||
window);
|
window);
|
||||||
|
|
||||||
window->wl.pointerLock.relativePointer = relativePointer;
|
|
||||||
window->wl.pointerLock.lockedPointer = lockedPointer;
|
|
||||||
|
|
||||||
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial,
|
|
||||||
NULL, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLFWbool isPointerLocked(_GLFWwindow* window)
|
static void unlockPointer(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
return window->wl.pointerLock.lockedPointer != NULL;
|
zwp_relative_pointer_v1_destroy(window->wl.relativePointer);
|
||||||
|
window->wl.relativePointer = NULL;
|
||||||
|
|
||||||
|
zwp_locked_pointer_v1_destroy(window->wl.lockedPointer);
|
||||||
|
window->wl.lockedPointer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void confinedPointerHandleConfined(void* userData,
|
||||||
|
struct zwp_confined_pointer_v1* confinedPointer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void confinedPointerHandleUnconfined(void* userData,
|
||||||
|
struct zwp_confined_pointer_v1* confinedPointer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct zwp_confined_pointer_v1_listener confinedPointerListener =
|
||||||
|
{
|
||||||
|
confinedPointerHandleConfined,
|
||||||
|
confinedPointerHandleUnconfined
|
||||||
|
};
|
||||||
|
|
||||||
|
static void confinePointer(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
window->wl.confinedPointer =
|
||||||
|
zwp_pointer_constraints_v1_confine_pointer(
|
||||||
|
_glfw.wl.pointerConstraints,
|
||||||
|
window->wl.surface,
|
||||||
|
_glfw.wl.pointer,
|
||||||
|
NULL,
|
||||||
|
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
|
||||||
|
|
||||||
|
zwp_confined_pointer_v1_add_listener(window->wl.confinedPointer,
|
||||||
|
&confinedPointerListener,
|
||||||
|
window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unconfinePointer(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
zwp_confined_pointer_v1_destroy(window->wl.confinedPointer);
|
||||||
|
window->wl.confinedPointer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwSetCursorWayland(_GLFWwindow* window, _GLFWcursor* cursor)
|
void _glfwSetCursorWayland(_GLFWwindow* window, _GLFWcursor* cursor)
|
||||||
{
|
{
|
||||||
struct wl_cursor* defaultCursor;
|
|
||||||
struct wl_cursor* defaultCursorHiDPI = NULL;
|
|
||||||
|
|
||||||
if (!_glfw.wl.pointer)
|
if (!_glfw.wl.pointer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2570,29 +2591,55 @@ void _glfwSetCursorWayland(_GLFWwindow* window, _GLFWcursor* cursor)
|
|||||||
if (window != _glfw.wl.pointerFocus || window->wl.decorations.focus != mainWindow)
|
if (window != _glfw.wl.pointerFocus || window->wl.decorations.focus != mainWindow)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Unlock possible pointer lock if no longer disabled.
|
// Update pointer lock to match cursor mode
|
||||||
if (window->cursorMode != GLFW_CURSOR_DISABLED && isPointerLocked(window))
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
|
{
|
||||||
|
if (window->wl.confinedPointer)
|
||||||
|
unconfinePointer(window);
|
||||||
|
if (!window->wl.lockedPointer)
|
||||||
|
lockPointer(window);
|
||||||
|
}
|
||||||
|
else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
|
||||||
|
{
|
||||||
|
if (window->wl.lockedPointer)
|
||||||
unlockPointer(window);
|
unlockPointer(window);
|
||||||
|
if (!window->wl.confinedPointer)
|
||||||
|
confinePointer(window);
|
||||||
|
}
|
||||||
|
else if (window->cursorMode == GLFW_CURSOR_NORMAL ||
|
||||||
|
window->cursorMode == GLFW_CURSOR_HIDDEN)
|
||||||
|
{
|
||||||
|
if (window->wl.lockedPointer)
|
||||||
|
unlockPointer(window);
|
||||||
|
else if (window->wl.confinedPointer)
|
||||||
|
unconfinePointer(window);
|
||||||
|
}
|
||||||
|
|
||||||
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
if (window->cursorMode == GLFW_CURSOR_NORMAL ||
|
||||||
|
window->cursorMode == GLFW_CURSOR_CAPTURED)
|
||||||
{
|
{
|
||||||
if (cursor)
|
if (cursor)
|
||||||
setCursorImage(window, &cursor->wl);
|
setCursorImage(window, &cursor->wl);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
defaultCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,
|
struct wl_cursor* defaultCursor =
|
||||||
"left_ptr");
|
wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme, "left_ptr");
|
||||||
if (!defaultCursor)
|
if (!defaultCursor)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Standard cursor not found");
|
"Wayland: Standard cursor not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct wl_cursor* defaultCursorHiDPI = NULL;
|
||||||
if (_glfw.wl.cursorThemeHiDPI)
|
if (_glfw.wl.cursorThemeHiDPI)
|
||||||
|
{
|
||||||
defaultCursorHiDPI =
|
defaultCursorHiDPI =
|
||||||
wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI,
|
wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI, "left_ptr");
|
||||||
"left_ptr");
|
}
|
||||||
_GLFWcursorWayland cursorWayland = {
|
|
||||||
|
_GLFWcursorWayland cursorWayland =
|
||||||
|
{
|
||||||
defaultCursor,
|
defaultCursor,
|
||||||
defaultCursorHiDPI,
|
defaultCursorHiDPI,
|
||||||
NULL,
|
NULL,
|
||||||
@ -2600,15 +2647,12 @@ void _glfwSetCursorWayland(_GLFWwindow* window, _GLFWcursor* cursor)
|
|||||||
0, 0,
|
0, 0,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
setCursorImage(window, &cursorWayland);
|
setCursorImage(window, &cursorWayland);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
else if (window->cursorMode == GLFW_CURSOR_HIDDEN ||
|
||||||
{
|
window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
if (!isPointerLocked(window))
|
|
||||||
lockPointer(window);
|
|
||||||
}
|
|
||||||
else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
|
|
||||||
{
|
{
|
||||||
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial, NULL, 0, 0);
|
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial, NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
124
src/x11_window.c
124
src/x11_window.c
@ -270,6 +270,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 +311,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 +455,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 +473,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 +534,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 +545,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 +575,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 +603,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 +706,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 +1746,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 +1768,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);
|
||||||
@ -1986,7 +2045,7 @@ GLFWbool _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);
|
||||||
@ -2805,16 +2864,40 @@ void _glfwSetCursorPosX11(_GLFWwindow* window, double x, double y)
|
|||||||
|
|
||||||
void _glfwSetCursorModeX11(_GLFWwindow* window, int mode)
|
void _glfwSetCursorModeX11(_GLFWwindow* window, int mode)
|
||||||
{
|
{
|
||||||
|
if (_glfwWindowFocusedX11(window))
|
||||||
|
{
|
||||||
if (mode == GLFW_CURSOR_DISABLED)
|
if (mode == GLFW_CURSOR_DISABLED)
|
||||||
{
|
{
|
||||||
if (_glfwWindowFocusedX11(window))
|
_glfwGetCursorPosX11(window,
|
||||||
disableCursor(window);
|
&_glfw.x11.restoreCursorPosX,
|
||||||
|
&_glfw.x11.restoreCursorPosY);
|
||||||
|
_glfwCenterCursorInContentArea(window);
|
||||||
|
if (window->rawMouseMotion)
|
||||||
|
enableRawMouseMotion(window);
|
||||||
}
|
}
|
||||||
else if (_glfw.x11.disabledCursorWindow == window)
|
else if (_glfw.x11.disabledCursorWindow == window)
|
||||||
enableCursor(window);
|
{
|
||||||
else
|
if (window->rawMouseMotion)
|
||||||
updateCursorImage(window);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2970,7 +3053,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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user