Merge branch 'master' into multi-context-windows

This commit is contained in:
Doug Binks 2020-09-04 17:44:36 +01:00
commit e2016291f1
44 changed files with 1436 additions and 628 deletions

1
.gitignore vendored
View File

@ -100,5 +100,6 @@ tests/threads
tests/timeout tests/timeout
tests/title tests/title
tests/triangle-vulkan tests/triangle-vulkan
tests/window
tests/windows tests/windows

View File

@ -17,6 +17,7 @@ matrix:
- libxinerama-dev - libxinerama-dev
- libxcursor-dev - libxcursor-dev
- libxi-dev - libxi-dev
- libxext-dev
env: env:
- BUILD_SHARED_LIBS=ON - BUILD_SHARED_LIBS=ON
- CFLAGS=-Werror - CFLAGS=-Werror
@ -30,18 +31,18 @@ matrix:
- libxinerama-dev - libxinerama-dev
- libxcursor-dev - libxcursor-dev
- libxi-dev - libxi-dev
- libxext-dev
env: env:
- BUILD_SHARED_LIBS=OFF - BUILD_SHARED_LIBS=OFF
- CFLAGS=-Werror - CFLAGS=-Werror
- os: linux - os: linux
dist: xenial dist: focal
name: "Wayland shared library" name: "Wayland shared library"
addons: addons:
apt: apt:
sources:
- ppa:kubuntu-ppa/backports
packages: packages:
- extra-cmake-modules - extra-cmake-modules
- wayland-protocols
- libwayland-dev - libwayland-dev
- libxkbcommon-dev - libxkbcommon-dev
- libegl1-mesa-dev - libegl1-mesa-dev
@ -50,14 +51,13 @@ matrix:
- BUILD_SHARED_LIBS=ON - BUILD_SHARED_LIBS=ON
- CFLAGS=-Werror - CFLAGS=-Werror
- os: linux - os: linux
dist: xenial dist: focal
name: "Wayland static library" name: "Wayland static library"
addons: addons:
apt: apt:
sources:
- ppa:kubuntu-ppa/backports
packages: packages:
- extra-cmake-modules - extra-cmake-modules
- wayland-protocols
- libwayland-dev - libwayland-dev
- libxkbcommon-dev - libxkbcommon-dev
- libegl1-mesa-dev - libegl1-mesa-dev
@ -106,12 +106,6 @@ script:
fi fi
- mkdir build - mkdir build
- cd build - cd build
- if test -n "${USE_WAYLAND}"; then
git clone git://anongit.freedesktop.org/wayland/wayland-protocols;
pushd wayland-protocols;
git checkout 1.15 && ./autogen.sh --prefix=/usr && make && sudo make install;
popd;
fi
- cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} -DGLFW_USE_WAYLAND=${USE_WAYLAND} -DGLFW_USE_OSMESA=${USE_OSMESA} .. - cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} -DGLFW_USE_WAYLAND=${USE_WAYLAND} -DGLFW_USE_OSMESA=${USE_OSMESA} ..
- cmake --build . - cmake --build .
notifications: notifications:

View File

@ -8,6 +8,10 @@ if (POLICY CMP0054)
cmake_policy(SET CMP0054 NEW) cmake_policy(SET CMP0054 NEW)
endif() endif()
if (POLICY CMP0069)
cmake_policy(SET CMP0069 NEW)
endif()
if (POLICY CMP0077) if (POLICY CMP0077)
cmake_policy(SET CMP0077 NEW) cmake_policy(SET CMP0077 NEW)
endif() endif()
@ -176,6 +180,11 @@ if (_GLFW_X11)
if (NOT X11_Xi_INCLUDE_PATH) if (NOT X11_Xi_INCLUDE_PATH)
message(FATAL_ERROR "XInput headers not found; install libxi development package") message(FATAL_ERROR "XInput headers not found; install libxi development package")
endif() endif()
# Check for X Shape (custom window input shape)
if (NOT X11_Xshape_INCLUDE_PATH)
message(FATAL_ERROR "X Shape headers not found; install libxext development package")
endif()
endif() endif()
#-------------------------------------------------------------------- #--------------------------------------------------------------------

View File

@ -124,10 +124,13 @@ information on what to include when reporting a bug.
- Added `GLFW_RESIZE_EW_CURSOR` alias for `GLFW_HRESIZE_CURSOR` (#427) - Added `GLFW_RESIZE_EW_CURSOR` alias for `GLFW_HRESIZE_CURSOR` (#427)
- Added `GLFW_RESIZE_NS_CURSOR` alias for `GLFW_VRESIZE_CURSOR` (#427) - Added `GLFW_RESIZE_NS_CURSOR` alias for `GLFW_VRESIZE_CURSOR` (#427)
- 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
through the window (#1236,#1568)
- 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_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)
- Made joystick subsystem initialize at first use (#1284,#1646)
- Updated the minimum required CMake version to 3.1 - Updated the minimum required CMake version to 3.1
- Disabled tests and examples by default when built as a CMake subdirectory - Disabled tests and examples by default when built as a CMake subdirectory
- Bugfix: The CMake config-file package used an absolute path and was not - Bugfix: The CMake config-file package used an absolute path and was not
@ -140,6 +143,8 @@ information on what to include when reporting a bug.
- [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] Disabled framebuffer transparency on Windows 7 when DWM windows are
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
symbol redefinition (#1524) symbol redefinition (#1524)
- [Win32] Bugfix: The cursor position event was emitted before its cursor enter - [Win32] Bugfix: The cursor position event was emitted before its cursor enter
@ -167,6 +172,8 @@ information on what to include when reporting a bug.
would abort (#1649) would abort (#1649)
- [Cocoa] Bugfix: Non-BMP Unicode codepoint input was reported as UTF-16 - [Cocoa] Bugfix: Non-BMP Unicode codepoint input was reported as UTF-16
(#1635) (#1635)
- [Cocoa] Bugfix: Failing to retrieve the refresh rate of built-in displays
could leak memory
- [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)
@ -196,12 +203,16 @@ information on what to include when reporting a bug.
- [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
- [Wayland] Bugfix: Repeated keys could be reported with `NULL` window (#1704) - [Wayland] Bugfix: Repeated keys could be reported with `NULL` window (#1704)
- [Wayland] Bugfix: Retrieving partial framebuffer size would segfault
- [Wayland] Bugfix: Scrolling offsets were inverted compared to other platforms
(#1463)
- [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled
- [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
macOS versions (#1442) macOS versions (#1442)
- [NSGL] Bugfix: Workaround for swap interval on 10.14 broke on 10.12 (#1483) - [NSGL] Bugfix: Workaround for swap interval on 10.14 broke on 10.12 (#1483)
- [EGL] Added platform selection via the `EGL_EXT_platform_base` extension - [EGL] Added platform selection via the `EGL_EXT_platform_base` extension
(#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)
@ -342,6 +353,7 @@ skills.
- ndogxj - ndogxj
- Kristian Nielsen - Kristian Nielsen
- Kamil Nowakowski - Kamil Nowakowski
- onox
- Denis Ovod - Denis Ovod
- Ozzy - Ozzy
- Andri Pálsson - Andri Pálsson

621
deps/nuklear.h vendored

File diff suppressed because it is too large Load Diff

View File

@ -230,7 +230,7 @@ nk_glfw3_mouse_button_callback(GLFWwindow* window, int button, int action, int m
} }
NK_INTERN void NK_INTERN void
nk_glfw3_clipbard_paste(nk_handle usr, struct nk_text_edit *edit) nk_glfw3_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
{ {
const char *text = glfwGetClipboardString(glfw.win); const char *text = glfwGetClipboardString(glfw.win);
if (text) nk_textedit_paste(edit, text, nk_strlen(text)); if (text) nk_textedit_paste(edit, text, nk_strlen(text));
@ -238,7 +238,7 @@ nk_glfw3_clipbard_paste(nk_handle usr, struct nk_text_edit *edit)
} }
NK_INTERN void NK_INTERN void
nk_glfw3_clipbard_copy(nk_handle usr, const char *text, int len) nk_glfw3_clipboard_copy(nk_handle usr, const char *text, int len)
{ {
char *str = 0; char *str = 0;
(void)usr; (void)usr;
@ -261,8 +261,8 @@ nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state init_state)
glfwSetMouseButtonCallback(win, nk_glfw3_mouse_button_callback); glfwSetMouseButtonCallback(win, nk_glfw3_mouse_button_callback);
} }
nk_init_default(&glfw.ctx, 0); nk_init_default(&glfw.ctx, 0);
glfw.ctx.clip.copy = nk_glfw3_clipbard_copy; glfw.ctx.clip.copy = nk_glfw3_clipboard_copy;
glfw.ctx.clip.paste = nk_glfw3_clipbard_paste; glfw.ctx.clip.paste = nk_glfw3_clipboard_paste;
glfw.ctx.clip.userdata = nk_handle_ptr(0); glfw.ctx.clip.userdata = nk_handle_ptr(0);
nk_buffer_init_default(&glfw.ogl.cmds); nk_buffer_init_default(&glfw.ogl.cmds);

File diff suppressed because one or more lines are too long

View File

@ -159,11 +159,17 @@ h3 {
.glfwheader { .glfwheader {
font-size:16px; font-size:16px;
height:64px; min-height:64px;
max-width:920px; max-width:920px;
min-width:800px;
padding:0 32px; padding:0 32px;
margin:0 auto; margin:0 auto;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-items: center;
align-content: stretch;
} }
#glfwhome { #glfwhome {
@ -176,7 +182,7 @@ h3 {
.glfwnavbar { .glfwnavbar {
list-style-type:none; list-style-type:none;
margin:0 auto; margin:0 0 0 auto;
float:right; float:right;
} }
@ -191,6 +197,10 @@ h3 {
color:@header-footer-link-color; color:@header-footer-link-color;
} }
.glfwnavbar {
padding-left: 0;
}
#glfwhome,.glfwnavbar a,.glfwnavbar a:visited { #glfwhome,.glfwnavbar a,.glfwnavbar a:visited {
transition:.35s ease; transition:.35s ease;
} }
@ -211,14 +221,12 @@ address.footer {
#main-nav { #main-nav {
max-width:960px; max-width:960px;
min-width:800px;
margin:0 auto; margin:0 auto;
font-size:13px; font-size:13px;
} }
#main-menu { #main-menu {
max-width:920px; max-width:920px;
min-width:800px;
margin:0 auto; margin:0 auto;
font-size:13px; font-size:13px;
} }
@ -233,9 +241,13 @@ address.footer {
} }
#main-menu { #main-menu {
height:36px; min-height:36px;
display:block; display: flex;
position:relative; flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-items: center;
align-content: stretch;
} }
#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li { #main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li {
@ -250,6 +262,10 @@ address.footer {
color:@default-link-color; color:@default-link-color;
} }
#main-menu > li:last-child {
margin: 0 0 0 auto;
}
.contents { .contents {
min-height:590px; min-height:590px;
} }

View File

@ -1,7 +1,8 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"> <html lang="en">
<head> <head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=9"/> <meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen $doxygenversion"/> <meta name="generator" content="Doxygen $doxygenversion"/>
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME--> <!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->

View File

@ -550,10 +550,10 @@ int present = glfwJoystickPresent(GLFW_JOYSTICK_1);
Each joystick has zero or more axes, zero or more buttons, zero or more hats, Each joystick has zero or more axes, zero or more buttons, zero or more hats,
a human-readable name, a user pointer and an SDL compatible GUID. a human-readable name, a user pointer and an SDL compatible GUID.
When GLFW is initialized, detected joysticks are added to the beginning of Detected joysticks are added to the beginning of the array. Once a joystick is
the array. Once a joystick is detected, it keeps its assigned ID until it is detected, it keeps its assigned ID until it is disconnected or the library is
disconnected or the library is terminated, so as joysticks are connected and terminated, so as joysticks are connected and disconnected, there may appear
disconnected, there may appear gaps in the IDs. gaps in the IDs.
Joystick axis, button and hat state is updated when polled and does not require Joystick axis, button and hat state is updated when polled and does not require
a window to be created or events to be processed. However, if you want joystick a window to be created or events to be processed. However, if you want joystick
@ -648,7 +648,7 @@ const char* name = glfwGetJoystickName(GLFW_JOYSTICK_4);
@endcode @endcode
Joystick names are not guaranteed to be unique. Two joysticks of the same model Joystick names are not guaranteed to be unique. Two joysticks of the same model
and make may have the same name. Only the [joystick token](@ref joysticks) is and make may have the same name. Only the [joystick ID](@ref joysticks) is
guaranteed to be unique, and only until that joystick is disconnected. guaranteed to be unique, and only until that joystick is disconnected.

View File

@ -22,8 +22,8 @@ There are also guides for the other areas of GLFW.
Before most GLFW functions may be called, the library must be initialized. Before most GLFW functions may be called, the library must be initialized.
This initialization checks what features are available on the machine, This initialization checks what features are available on the machine,
enumerates monitors and joysticks, initializes the timer and performs any enumerates monitors, initializes the timer and performs any required
required platform-specific initialization. platform-specific initialization.
Only the following functions may be called before the library has been Only the following functions may be called before the library has been
successfully initialized, and only from the main thread. successfully initialized, and only from the main thread.

View File

@ -362,8 +362,8 @@ should be using the character callback instead, on both GLFW 2 and 3. This will
give you the characters being input, as opposed to the keys being pressed. give you the characters being input, as opposed to the keys being pressed.
GLFW 3 has key tokens for all keys on a standard 105 key keyboard, so instead of GLFW 3 has key tokens for all keys on a standard 105 key keyboard, so instead of
having to remember whether to check for `'a'` or `'A'`, you now check for having to remember whether to check for `a` or `A`, you now check for
`GLFW_KEY_A`. @ref GLFW_KEY_A.
@subsection moving_joystick Joystick function changes @subsection moving_joystick Joystick function changes

View File

@ -27,6 +27,14 @@ are still available.
For more information see @ref cursor_standard. For more information see @ref cursor_standard.
@subsubsection mouse_passthrough_34 Mouse event passthrough
GLFW now provides the [GLFW_MOUSE_PASSTHROUGH](@ref GLFW_MOUSE_PASSTHROUGH_hint)
window hint for making a window transparent to mouse input, lettings events pass
to whatever window is behind it. This can also be changed after window
creation with the matching [window attribute](@ref GLFW_MOUSE_PASSTHROUGH_attrib).
@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
@ -47,6 +55,21 @@ applications.
@subsection caveats_34 Caveats for version 3.4 @subsection caveats_34 Caveats for version 3.4
@subsubsection joysticks_34 Joystick support is initialized on demand
The joystick part of GLFW is now initialized when first used, primarily to work
around faulty Windows drivers that cause DirectInput to take up to several
seconds to enumerate devices.
This change will usually not be observable. However, if your application waits
for events without having first called any joystick function or created any
visible windows, the wait may never unblock as GLFW may not yet have subscribed
to joystick related OS events.
To work around this, call any joystick function before waiting for events, for
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 sub-project
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
@ -74,6 +97,13 @@ GLFW no longer depends on the CoreVideo framework on macOS and it no longer
needs to be specified during compilation or linking. needs to be specified during compilation or linking.
@subsubsection caveat_fbtransparency_34 Framebuffer transparency requires DWM transparency
GLFW no longer supports framebuffer transparency enabled via @ref
GLFW_TRANSPARENT_FRAMEBUFFER on Windows 7 if DWM transparency is off
(the Transparency setting under Personalization > Window Color).
@subsection deprecations_34 Deprecations in version 3.4 @subsection deprecations_34 Deprecations in version 3.4
@subsection removals_34 Removals in 3.4 @subsection removals_34 Removals in 3.4
@ -97,6 +127,7 @@ then GLFW will fail to initialize.
- @ref GLFW_RESIZE_NWSE_CURSOR - @ref GLFW_RESIZE_NWSE_CURSOR
- @ref GLFW_RESIZE_NESW_CURSOR - @ref GLFW_RESIZE_NESW_CURSOR
- @ref GLFW_RESIZE_ALL_CURSOR - @ref GLFW_RESIZE_ALL_CURSOR
- @ref GLFW_MOUSE_PASSTHROUGH
- @ref GLFW_NOT_ALLOWED_CURSOR - @ref GLFW_NOT_ALLOWED_CURSOR
- @ref GLFW_CURSOR_UNAVAILABLE - @ref GLFW_CURSOR_UNAVAILABLE
- @ref GLFW_WIN32_KEYBOARD_MENU - @ref GLFW_WIN32_KEYBOARD_MENU

View File

@ -234,13 +234,6 @@ alpha channel will be used to combine the framebuffer with the background. This
does not affect window decorations. Possible values are `GLFW_TRUE` and does not affect window decorations. Possible values are `GLFW_TRUE` and
`GLFW_FALSE`. `GLFW_FALSE`.
@par
@win32 GLFW sets a color key for the window to work around repainting issues
with a transparent framebuffer. The chosen color value is RGB 255,0,255
(magenta). This will make pixels with that exact color fully transparent
regardless of their alpha values. If this is a problem, make these pixels any
other color before buffer swap.
@anchor GLFW_FOCUS_ON_SHOW_hint @anchor GLFW_FOCUS_ON_SHOW_hint
__GLFW_FOCUS_ON_SHOW__ specifies whether the window will be given input __GLFW_FOCUS_ON_SHOW__ specifies whether the window will be given input
focus when @ref glfwShowWindow is called. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. focus when @ref glfwShowWindow is called. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
@ -255,6 +248,13 @@ This hint only has an effect on platforms where screen coordinates and pixels
always map 1:1 such as Windows and X11. On platforms like macOS the resolution always map 1:1 such as Windows and X11. On platforms like macOS the resolution
of the framebuffer is changed independently of the window size. of the framebuffer is changed independently of the window size.
@anchor GLFW_MOUSE_PASSTHROUGH_hint
__GLFW_MOUSE_PASSTHROUGH__ specifies whether the window is transparent to mouse
input, letting any mouse events pass through to whatever window is behind it.
This is only supported for undecorated windows. Decorated windows with this
enabled will behave differently between platforms. Possible values are
`GLFW_TRUE` and `GLFW_FALSE`.
@subsubsection window_hints_fb Framebuffer related hints @subsubsection window_hints_fb Framebuffer related hints
@ -416,6 +416,10 @@ Debug contexts for OpenGL and OpenGL ES are described in detail by the
[GL_KHR_debug](https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_debug.txt) [GL_KHR_debug](https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_debug.txt)
extension. extension.
@par
This is the new name, introduced in GLFW 3.4. The older
`GLFW_OPENGL_DEBUG_CONTEXT` name is also available for compatibility.
@anchor GLFW_OPENGL_PROFILE_hint @anchor GLFW_OPENGL_PROFILE_hint
__GLFW_OPENGL_PROFILE__ specifies which OpenGL profile to create the context __GLFW_OPENGL_PROFILE__ specifies which OpenGL profile to create the context
for. Possible values are one of `GLFW_OPENGL_CORE_PROFILE` or for. Possible values are one of `GLFW_OPENGL_CORE_PROFILE` or
@ -523,6 +527,7 @@ GLFW_CENTER_CURSOR | `GLFW_TRUE` | `GLFW_TRUE` or `GL
GLFW_TRANSPARENT_FRAMEBUFFER | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_TRANSPARENT_FRAMEBUFFER | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
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_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`
@ -1223,7 +1228,11 @@ If the system does not support whole window transparency, this function always
returns one. returns one.
GLFW comes with a test program that lets you control whole window transparency GLFW comes with a test program that lets you control whole window transparency
at run-time called `opacity`. at run-time called `window`.
If you want to use either of these transparency methods to display a temporary
overlay like for example a notification, the @ref GLFW_FLOATING and @ref
GLFW_MOUSE_PASSTHROUGH window hints and attributes may be useful.
@subsection window_attribs Window attributes @subsection window_attribs Window attributes
@ -1313,6 +1322,15 @@ focus when @ref glfwShowWindow is called. This can be set before creation
with the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint or with the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint or
after with @ref glfwSetWindowAttrib. after with @ref glfwSetWindowAttrib.
@anchor GLFW_MOUSE_PASSTHROUGH_attrib
__GLFW_MOUSE_PASSTHROUGH__ specifies whether the window is transparent to mouse
input, letting any mouse events pass through to whatever window is behind it.
This can be set before creation with the
[GLFW_MOUSE_PASSTHROUGH](@ref GLFW_MOUSE_PASSTHROUGH_hint) window hint or after
with @ref glfwSetWindowAttrib. This is only supported for undecorated windows.
Decorated windows with this enabled will behave differently between platforms.
@subsubsection window_attribs_ctx Context related attributes @subsubsection window_attribs_ctx Context related attributes
@anchor GLFW_CLIENT_API_attrib @anchor GLFW_CLIENT_API_attrib
@ -1344,6 +1362,10 @@ OpenGL forward-compatible one, or `GLFW_FALSE` otherwise.
__GLFW_CONTEXT_DEBUG__ is `GLFW_TRUE` if the window's context is in debug __GLFW_CONTEXT_DEBUG__ is `GLFW_TRUE` if the window's context is in debug
mode, or `GLFW_FALSE` otherwise. mode, or `GLFW_FALSE` otherwise.
@par
This is the new name, introduced in GLFW 3.4. The older
`GLFW_OPENGL_DEBUG_CONTEXT` name is also available for compatibility.
@anchor GLFW_OPENGL_PROFILE_attrib @anchor GLFW_OPENGL_PROFILE_attrib
__GLFW_OPENGL_PROFILE__ indicates the OpenGL profile used by the context. This __GLFW_OPENGL_PROFILE__ indicates the OpenGL profile used by the context. This
is `GLFW_OPENGL_CORE_PROFILE` or `GLFW_OPENGL_COMPAT_PROFILE` if the context is `GLFW_OPENGL_CORE_PROFILE` or `GLFW_OPENGL_COMPAT_PROFILE` if the context

View File

@ -33,6 +33,7 @@ add_executable(sharing WIN32 MACOSX_BUNDLE sharing.c ${ICON} ${GLAD_GL})
add_executable(splitview WIN32 MACOSX_BUNDLE splitview.c ${ICON} ${GLAD_GL}) add_executable(splitview WIN32 MACOSX_BUNDLE splitview.c ${ICON} ${GLAD_GL})
add_executable(triangle-opengl WIN32 MACOSX_BUNDLE triangle-opengl.c ${ICON} ${GLAD_GL}) add_executable(triangle-opengl WIN32 MACOSX_BUNDLE triangle-opengl.c ${ICON} ${GLAD_GL})
add_executable(wave WIN32 MACOSX_BUNDLE wave.c ${ICON} ${GLAD_GL}) add_executable(wave WIN32 MACOSX_BUNDLE wave.c ${ICON} ${GLAD_GL})
add_executable(windows WIN32 MACOSX_BUNDLE windows.c ${ICON} ${GLAD_GL})
target_link_libraries(particles Threads::Threads) target_link_libraries(particles Threads::Threads)
if (RT_LIBRARY) if (RT_LIBRARY)
@ -40,7 +41,7 @@ if (RT_LIBRARY)
endif() endif()
set(GUI_ONLY_BINARIES boing gears heightmap particles sharing splitview set(GUI_ONLY_BINARIES boing gears heightmap particles sharing splitview
triangle-opengl wave) triangle-opengl wave windows)
set(CONSOLE_BINARIES offscreen) set(CONSOLE_BINARIES offscreen)
set_target_properties(${GUI_ONLY_BINARIES} ${CONSOLE_BINARIES} PROPERTIES set_target_properties(${GUI_ONLY_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
@ -67,6 +68,7 @@ if (APPLE)
set_target_properties(triangle-opengl PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "OpenGL Triangle") set_target_properties(triangle-opengl PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "OpenGL Triangle")
set_target_properties(splitview PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "SplitView") set_target_properties(splitview PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "SplitView")
set_target_properties(wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave") set_target_properties(wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave")
set_target_properties(windows PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Windows")
set_source_files_properties(glfw.icns PROPERTIES set_source_files_properties(glfw.icns PROPERTIES
MACOSX_PACKAGE_LOCATION "Resources") MACOSX_PACKAGE_LOCATION "Resources")

View File

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// Simple multi-window test // Simple multi-window example
// Copyright (c) Camilla Löwy <elmindreda@glfw.org> // Copyright (c) Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
@ -22,10 +22,6 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
//
// This test creates four windows and clears each in a different color
//
//========================================================================
#include <glad/gl.h> #include <glad/gl.h>
#define GLFW_INCLUDE_NONE #define GLFW_INCLUDE_NONE
@ -34,109 +30,60 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
static GLFWwindow* windows[4];
static const char* titles[] =
{
"Red",
"Green",
"Blue",
"Yellow"
};
static const struct
{
float r, g, b;
} colors[] =
{
{ 0.95f, 0.32f, 0.11f },
{ 0.50f, 0.80f, 0.16f },
{ 0.f, 0.68f, 0.94f },
{ 0.98f, 0.74f, 0.04f }
};
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void arrange_windows(void)
{
int xbase, ybase;
glfwGetWindowPos(windows[0], &xbase, &ybase);
for (int i = 0; i < 4; i++)
{
int left, top, right, bottom;
glfwGetWindowFrameSize(windows[i], &left, &top, &right, &bottom);
glfwSetWindowPos(windows[i],
xbase + (i & 1) * (200 + left + right),
ybase + (i >> 1) * (200 + top + bottom));
}
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action != GLFW_PRESS)
return;
switch (key)
{
case GLFW_KEY_SPACE:
{
int xpos, ypos;
glfwGetWindowPos(window, &xpos, &ypos);
glfwSetWindowPos(window, xpos, ypos);
break;
}
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
case GLFW_KEY_D:
{
for (int i = 0; i < 4; i++)
{
const int decorated = glfwGetWindowAttrib(windows[i], GLFW_DECORATED);
glfwSetWindowAttrib(windows[i], GLFW_DECORATED, !decorated);
}
arrange_windows();
break;
}
}
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
glfwSetErrorCallback(error_callback); int xpos, ypos, height;
const char* description;
GLFWwindow* windows[4];
if (!glfwInit()) if (!glfwInit())
{
glfwGetError(&description);
printf("Error: %s\n", description);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
glfwGetMonitorWorkarea(glfwGetPrimaryMonitor(), &xpos, &ypos, NULL, &height);
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
const int size = height / 5;
const struct
{
float r, g, b;
} colors[] =
{
{ 0.95f, 0.32f, 0.11f },
{ 0.50f, 0.80f, 0.16f },
{ 0.f, 0.68f, 0.94f },
{ 0.98f, 0.74f, 0.04f }
};
if (i > 0) if (i > 0)
glfwWindowHint(GLFW_FOCUS_ON_SHOW, GLFW_FALSE); glfwWindowHint(GLFW_FOCUS_ON_SHOW, GLFW_FALSE);
windows[i] = glfwCreateWindow(200, 200, titles[i], NULL, NULL); windows[i] = glfwCreateWindow(size, size, "Multi-Window Example", NULL, NULL);
if (!windows[i]) if (!windows[i])
{ {
glfwGetError(&description);
printf("Error: %s\n", description);
glfwTerminate(); glfwTerminate();
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
glfwSetKeyCallback(windows[i], key_callback); glfwSetWindowPos(windows[i],
xpos + size * (1 + (i & 1)),
ypos + size * (1 + (i >> 1)));
glfwSetInputMode(windows[i], GLFW_STICKY_KEYS, GLFW_TRUE);
glfwMakeContextCurrent(windows[i]); glfwMakeContextCurrent(windows[i]);
gladLoadGL(glfwGetProcAddress); gladLoadGL(glfwGetProcAddress);
glClearColor(colors[i].r, colors[i].g, colors[i].b, 1.f); glClearColor(colors[i].r, colors[i].g, colors[i].b, 1.f);
} }
arrange_windows();
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
glfwShowWindow(windows[i]); glfwShowWindow(windows[i]);
@ -148,7 +95,8 @@ int main(int argc, char** argv)
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(windows[i]); glfwSwapBuffers(windows[i]);
if (glfwWindowShouldClose(windows[i])) if (glfwWindowShouldClose(windows[i]) ||
glfwGetKey(windows[i], GLFW_KEY_ESCAPE))
{ {
glfwTerminate(); glfwTerminate();
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);

View File

@ -895,6 +895,13 @@ extern "C" {
*/ */
#define GLFW_FOCUS_ON_SHOW 0x0002000C #define GLFW_FOCUS_ON_SHOW 0x0002000C
/*! @brief Mouse input transparency window hint and attribute
*
* Mouse input transparency [window hint](@ref GLFW_MOUSE_PASSTHROUGH_hint) or
* [window attribute](@ref GLFW_MOUSE_PASSTHROUGH_attrib).
*/
#define GLFW_MOUSE_PASSTHROUGH 0x0002000D
/*! @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).
@ -3668,6 +3675,7 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
* [GLFW_FLOATING](@ref GLFW_FLOATING_attrib), * [GLFW_FLOATING](@ref GLFW_FLOATING_attrib),
* [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and * [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and
* [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib). * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib).
* [GLFW_MOUSE_PASSTHROUGH](@ref GLFW_MOUSE_PASSTHROUGH_attrib)
* *
* Some of these attributes are ignored for full screen windows. The new * Some of these attributes are ignored for full screen windows. The new
* value will take effect if the window is later made windowed. * value will take effect if the window is later made windowed.

View File

@ -551,7 +551,6 @@ int _glfwPlatformInit(void)
return GLFW_FALSE; return GLFW_FALSE;
_glfwInitTimerNS(); _glfwInitTimerNS();
_glfwInitJoysticksNS();
_glfwPollMonitorsNS(); _glfwPollMonitorsNS();
@ -605,7 +604,6 @@ void _glfwPlatformTerminate(void)
free(_glfw.ns.clipboardString); free(_glfw.ns.clipboardString);
_glfwTerminateNSGL(); _glfwTerminateNSGL();
_glfwTerminateJoysticksNS();
} // autoreleasepool } // autoreleasepool
} }

View File

@ -44,7 +44,3 @@ typedef struct _GLFWjoystickNS
CFMutableArrayRef hats; CFMutableArrayRef hats;
} _GLFWjoystickNS; } _GLFWjoystickNS;
void _glfwInitJoysticksNS(void);
void _glfwTerminateJoysticksNS(void);

View File

@ -304,12 +304,10 @@ static void removeCallback(void* context,
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Initialize joystick interface GLFWbool _glfwPlatformInitJoysticks(void)
//
void _glfwInitJoysticksNS(void)
{ {
CFMutableArrayRef matching; CFMutableArrayRef matching;
const long usages[] = const long usages[] =
@ -328,7 +326,7 @@ void _glfwInitJoysticksNS(void)
if (!matching) if (!matching)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create array"); _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create array");
return; return GLFW_FALSE;
} }
for (size_t i = 0; i < sizeof(usages) / sizeof(long); i++) for (size_t i = 0; i < sizeof(usages) / sizeof(long); i++)
@ -383,26 +381,24 @@ void _glfwInitJoysticksNS(void)
// Execute the run loop once in order to register any initially-attached // Execute the run loop once in order to register any initially-attached
// joysticks // joysticks
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false); CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false);
return GLFW_TRUE;
} }
// Close all opened joystick handles void _glfwPlatformTerminateJoysticks(void)
//
void _glfwTerminateJoysticksNS(void)
{ {
int jid; int jid;
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
closeJoystick(_glfw.joysticks + jid); closeJoystick(_glfw.joysticks + jid);
CFRelease(_glfw.ns.hidManager); if (_glfw.ns.hidManager)
_glfw.ns.hidManager = NULL; {
CFRelease(_glfw.ns.hidManager);
_glfw.ns.hidManager = NULL;
}
} }
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
{ {
if (mode & _GLFW_POLL_AXES) if (mode & _GLFW_POLL_AXES)

View File

@ -277,14 +277,20 @@ static double getFallbackRefreshRate(CGDirectDisplayID displayID)
CFSTR("IOFBCurrentPixelCount"), CFSTR("IOFBCurrentPixelCount"),
kCFAllocatorDefault, kCFAllocatorDefault,
kNilOptions); kNilOptions);
if (!clockRef || !countRef)
break;
uint32_t clock = 0, count = 0; uint32_t clock = 0, count = 0;
CFNumberGetValue(clockRef, kCFNumberIntType, &clock);
CFNumberGetValue(countRef, kCFNumberIntType, &count); if (clockRef)
CFRelease(clockRef); {
CFRelease(countRef); CFNumberGetValue(clockRef, kCFNumberIntType, &clock);
CFRelease(clockRef);
}
if (countRef)
{
CFNumberGetValue(countRef, kCFNumberIntType, &count);
CFRelease(countRef);
}
if (clock > 0 && count > 0) if (clock > 0 && count > 0)
refreshRate = clock / (double) count; refreshRate = clock / (double) count;

View File

@ -1371,6 +1371,13 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
} // autoreleasepool } // autoreleasepool
} }
void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled)
{
@autoreleasepool {
[window->ns.object setIgnoresMouseEvents:enabled];
}
}
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
{ {
@autoreleasepool { @autoreleasepool {

View File

@ -91,6 +91,7 @@ static void terminate(void)
_glfw.mappingCount = 0; _glfw.mappingCount = 0;
_glfwTerminateVulkan(); _glfwTerminateVulkan();
_glfwPlatformTerminateJoysticks();
_glfwPlatformTerminate(); _glfwPlatformTerminate();
_glfw.initialized = GLFW_FALSE; _glfw.initialized = GLFW_FALSE;

View File

@ -43,6 +43,22 @@
#define _GLFW_JOYSTICK_BUTTON 2 #define _GLFW_JOYSTICK_BUTTON 2
#define _GLFW_JOYSTICK_HATBIT 3 #define _GLFW_JOYSTICK_HATBIT 3
// Initializes the platform joystick API if it has not been already
//
static GLFWbool initJoysticks(void)
{
if (!_glfw.joysticksInitialized)
{
if (!_glfwPlatformInitJoysticks())
{
_glfwPlatformTerminateJoysticks();
return GLFW_FALSE;
}
}
return _glfw.joysticksInitialized = GLFW_TRUE;
}
// Finds a mapping based on joystick GUID // Finds a mapping based on joystick GUID
// //
static _GLFWmapping* findMapping(const char* guid) static _GLFWmapping* findMapping(const char* guid)
@ -929,6 +945,9 @@ GLFWAPI int glfwJoystickPresent(int jid)
return GLFW_FALSE; return GLFW_FALSE;
} }
if (!initJoysticks())
return GLFW_FALSE;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->present)
return GLFW_FALSE; return GLFW_FALSE;
@ -954,6 +973,9 @@ GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
return NULL; return NULL;
} }
if (!initJoysticks())
return NULL;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->present)
return NULL; return NULL;
@ -983,6 +1005,9 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
return NULL; return NULL;
} }
if (!initJoysticks())
return NULL;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->present)
return NULL; return NULL;
@ -1016,6 +1041,9 @@ GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
return NULL; return NULL;
} }
if (!initJoysticks())
return NULL;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->present)
return NULL; return NULL;
@ -1042,6 +1070,9 @@ GLFWAPI const char* glfwGetJoystickName(int jid)
return NULL; return NULL;
} }
if (!initJoysticks())
return NULL;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->present)
return NULL; return NULL;
@ -1067,6 +1098,9 @@ GLFWAPI const char* glfwGetJoystickGUID(int jid)
return NULL; return NULL;
} }
if (!initJoysticks())
return NULL;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->present)
return NULL; return NULL;
@ -1112,6 +1146,10 @@ GLFWAPI void* glfwGetJoystickUserPointer(int jid)
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun) GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (!initJoysticks())
return NULL;
_GLFW_SWAP_POINTERS(_glfw.callbacks.joystick, cbfun); _GLFW_SWAP_POINTERS(_glfw.callbacks.joystick, cbfun);
return cbfun; return cbfun;
} }
@ -1191,6 +1229,9 @@ GLFWAPI int glfwJoystickIsGamepad(int jid)
return GLFW_FALSE; return GLFW_FALSE;
} }
if (!initJoysticks())
return GLFW_FALSE;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->present)
return GLFW_FALSE; return GLFW_FALSE;
@ -1216,6 +1257,9 @@ GLFWAPI const char* glfwGetGamepadName(int jid)
return NULL; return NULL;
} }
if (!initJoysticks())
return NULL;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->present)
return NULL; return NULL;
@ -1248,6 +1292,9 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
return GLFW_FALSE; return GLFW_FALSE;
} }
if (!initJoysticks())
return GLFW_FALSE;
js = _glfw.joysticks + jid; js = _glfw.joysticks + jid;
if (!js->present) if (!js->present)
return GLFW_FALSE; return GLFW_FALSE;

View File

@ -273,6 +273,7 @@ struct _GLFWwndconfig
GLFWbool maximized; GLFWbool maximized;
GLFWbool centerCursor; GLFWbool centerCursor;
GLFWbool focusOnShow; GLFWbool focusOnShow;
GLFWbool mousePassthrough;
GLFWbool scaleToMonitor; GLFWbool scaleToMonitor;
struct { struct {
GLFWbool retina; GLFWbool retina;
@ -401,6 +402,7 @@ struct _GLFWwindow
GLFWbool autoIconify; GLFWbool autoIconify;
GLFWbool floating; GLFWbool floating;
GLFWbool focusOnShow; GLFWbool focusOnShow;
GLFWbool mousePassthrough;
GLFWbool shouldClose; GLFWbool shouldClose;
void* userPointer; void* userPointer;
GLFWvidmode videoMode; GLFWvidmode videoMode;
@ -558,6 +560,7 @@ struct _GLFWlibrary
_GLFWmonitor** monitors; _GLFWmonitor** monitors;
int monitorCount; int monitorCount;
GLFWbool joysticksInitialized;
_GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1]; _GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1];
_GLFWmapping* mappings; _GLFWmapping* mappings;
int mappingCount; int mappingCount;
@ -652,6 +655,8 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
void _glfwPlatformSetClipboardString(const char* string); void _glfwPlatformSetClipboardString(const char* string);
const char* _glfwPlatformGetClipboardString(void); const char* _glfwPlatformGetClipboardString(void);
GLFWbool _glfwPlatformInitJoysticks(void);
void _glfwPlatformTerminateJoysticks(void);
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode); int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode);
void _glfwPlatformUpdateGamepadGUID(char* guid); void _glfwPlatformUpdateGamepadGUID(char* guid);
@ -700,6 +705,7 @@ float _glfwPlatformGetWindowOpacity(_GLFWwindow* window);
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled);
void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled);
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity); void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity);
void _glfwPlatformPollEvents(void); void _glfwPlatformPollEvents(void);

View File

@ -264,9 +264,50 @@ static int compareJoysticks(const void* fp, const void* sp)
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Initialize joystick interface void _glfwDetectJoystickConnectionLinux(void)
// {
GLFWbool _glfwInitJoysticksLinux(void) if (_glfw.linjs.inotify <= 0)
return;
ssize_t offset = 0;
char buffer[16384];
const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer));
while (size > offset)
{
regmatch_t match;
const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
offset += sizeof(struct inotify_event) + e->len;
if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) != 0)
continue;
char path[PATH_MAX];
snprintf(path, sizeof(path), "/dev/input/%s", e->name);
if (e->mask & (IN_CREATE | IN_ATTRIB))
openJoystickDevice(path);
else if (e->mask & IN_DELETE)
{
for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
{
closeJoystick(_glfw.joysticks + jid);
break;
}
}
}
}
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
GLFWbool _glfwPlatformInitJoysticks(void)
{ {
const char* dirname = "/dev/input"; const char* dirname = "/dev/input";
@ -320,9 +361,7 @@ GLFWbool _glfwInitJoysticksLinux(void)
return GLFW_TRUE; return GLFW_TRUE;
} }
// Close all opened joystick handles void _glfwPlatformTerminateJoysticks(void)
//
void _glfwTerminateJoysticksLinux(void)
{ {
int jid; int jid;
@ -333,60 +372,16 @@ void _glfwTerminateJoysticksLinux(void)
closeJoystick(js); closeJoystick(js);
} }
regfree(&_glfw.linjs.regex);
if (_glfw.linjs.inotify > 0) if (_glfw.linjs.inotify > 0)
{ {
if (_glfw.linjs.watch > 0) if (_glfw.linjs.watch > 0)
inotify_rm_watch(_glfw.linjs.inotify, _glfw.linjs.watch); inotify_rm_watch(_glfw.linjs.inotify, _glfw.linjs.watch);
close(_glfw.linjs.inotify); close(_glfw.linjs.inotify);
regfree(&_glfw.linjs.regex);
} }
} }
void _glfwDetectJoystickConnectionLinux(void)
{
if (_glfw.linjs.inotify <= 0)
return;
ssize_t offset = 0;
char buffer[16384];
const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer));
while (size > offset)
{
regmatch_t match;
const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
offset += sizeof(struct inotify_event) + e->len;
if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) != 0)
continue;
char path[PATH_MAX];
snprintf(path, sizeof(path), "/dev/input/%s", e->name);
if (e->mask & (IN_CREATE | IN_ATTRIB))
openJoystickDevice(path);
else if (e->mask & IN_DELETE)
{
for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
{
closeJoystick(_glfw.joysticks + jid);
break;
}
}
}
}
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
{ {
// Read all queued events (non-blocking) // Read all queued events (non-blocking)

View File

@ -55,8 +55,5 @@ typedef struct _GLFWlibraryLinux
GLFWbool dropped; GLFWbool dropped;
} _GLFWlibraryLinux; } _GLFWlibraryLinux;
GLFWbool _glfwInitJoysticksLinux(void);
void _glfwTerminateJoysticksLinux(void);
void _glfwDetectJoystickConnectionLinux(void); void _glfwDetectJoystickConnectionLinux(void);

View File

@ -33,6 +33,15 @@
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
GLFWbool _glfwPlatformInitJoysticks(void)
{
return GLFW_TRUE;
}
void _glfwPlatformTerminateJoysticks(void)
{
}
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
{ {
return GLFW_FALSE; return GLFW_FALSE;

View File

@ -72,6 +72,10 @@ void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{ {
if (xpos)
*xpos = 0;
if (ypos)
*ypos = 0;
} }
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
@ -90,9 +94,9 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
const GLFWvidmode mode = getVideoMode(); const GLFWvidmode mode = getVideoMode();
if (xpos) if (xpos)
*xpos = 10; *xpos = 0;
if (ypos) if (ypos)
ypos = 0; *ypos = 10;
if (width) if (width)
*width = mode.width; *width = mode.width;
if (height) if (height)

View File

@ -269,10 +269,25 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
{ {
if (window->null.decorated && !window->monitor) if (window->null.decorated && !window->monitor)
{ {
*left = 1; if (left)
*top = 10; *left = 1;
*right = 1; if (top)
*bottom = 1; *top = 10;
if (right)
*right = 1;
if (bottom)
*bottom = 1;
}
else
{
if (left)
*left = 0;
if (top)
*top = 0;
if (right)
*right = 0;
if (bottom)
*bottom = 0;
} }
} }
@ -362,6 +377,10 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
window->null.floating = enabled; window->null.floating = enabled;
} }
void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled)
{
}
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
{ {
return window->null.opacity; return window->null.opacity;

View File

@ -143,6 +143,8 @@ static GLFWbool loadLibraries(void)
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush"); GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
_glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow) _glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow)
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow"); GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");
_glfw.win32.dwmapi.GetColorizationColor = (PFN_DwmGetColorizationColor)
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmGetColorizationColor");
} }
_glfw.win32.shcore.instance = LoadLibraryA("shcore.dll"); _glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
@ -580,7 +582,6 @@ int _glfwPlatformInit(void)
return GLFW_FALSE; return GLFW_FALSE;
_glfwInitTimerWin32(); _glfwInitTimerWin32();
_glfwInitJoysticksWin32();
_glfwPollMonitorsWin32(); _glfwPollMonitorsWin32();
return GLFW_TRUE; return GLFW_TRUE;
@ -607,8 +608,6 @@ void _glfwPlatformTerminate(void)
_glfwTerminateWGL(); _glfwTerminateWGL();
_glfwTerminateEGL(); _glfwTerminateEGL();
_glfwTerminateJoysticksWin32();
freeLibraries(); freeLibraries();
} }

View File

@ -491,39 +491,6 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Initialize joystick interface
//
void _glfwInitJoysticksWin32(void)
{
if (_glfw.win32.dinput8.instance)
{
if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
DIRECTINPUT_VERSION,
&IID_IDirectInput8W,
(void**) &_glfw.win32.dinput8.api,
NULL)))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to create interface");
}
}
_glfwDetectJoystickConnectionWin32();
}
// Close all opened joystick handles
//
void _glfwTerminateJoysticksWin32(void)
{
int jid;
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
closeJoystick(_glfw.joysticks + jid);
if (_glfw.win32.dinput8.api)
IDirectInput8_Release(_glfw.win32.dinput8.api);
}
// Checks for new joysticks after DBT_DEVICEARRIVAL // Checks for new joysticks after DBT_DEVICEARRIVAL
// //
void _glfwDetectJoystickConnectionWin32(void) void _glfwDetectJoystickConnectionWin32(void)
@ -603,6 +570,37 @@ void _glfwDetectJoystickDisconnectionWin32(void)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
GLFWbool _glfwPlatformInitJoysticks(void)
{
if (_glfw.win32.dinput8.instance)
{
if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
DIRECTINPUT_VERSION,
&IID_IDirectInput8W,
(void**) &_glfw.win32.dinput8.api,
NULL)))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to create interface");
return GLFW_FALSE;
}
}
_glfwDetectJoystickConnectionWin32();
return GLFW_TRUE;
}
void _glfwPlatformTerminateJoysticks(void)
{
int jid;
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
closeJoystick(_glfw.joysticks + jid);
if (_glfw.win32.dinput8.api)
IDirectInput8_Release(_glfw.win32.dinput8.api);
}
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
{ {
if (js->win32.device) if (js->win32.device)

View File

@ -48,9 +48,6 @@ typedef struct _GLFWjoystickWin32
GUID guid; GUID guid;
} _GLFWjoystickWin32; } _GLFWjoystickWin32;
void _glfwInitJoysticksWin32(void);
void _glfwTerminateJoysticksWin32(void);
void _glfwDetectJoystickConnectionWin32(void); void _glfwDetectJoystickConnectionWin32(void);
void _glfwDetectJoystickDisconnectionWin32(void); void _glfwDetectJoystickDisconnectionWin32(void);

View File

@ -77,6 +77,9 @@
#ifndef WM_DWMCOMPOSITIONCHANGED #ifndef WM_DWMCOMPOSITIONCHANGED
#define WM_DWMCOMPOSITIONCHANGED 0x031E #define WM_DWMCOMPOSITIONCHANGED 0x031E
#endif #endif
#ifndef WM_DWMCOLORIZATIONCOLORCHANGED
#define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320
#endif
#ifndef WM_COPYGLOBALDATA #ifndef WM_COPYGLOBALDATA
#define WM_COPYGLOBALDATA 0x0049 #define WM_COPYGLOBALDATA 0x0049
#endif #endif
@ -244,9 +247,11 @@ typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UIN
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*); typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID); typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*); typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*);
typedef HRESULT (WINAPI * PFN_DwmGetColorizationColor)(DWORD*,BOOL*);
#define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled #define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled
#define DwmFlush _glfw.win32.dwmapi.Flush #define DwmFlush _glfw.win32.dwmapi.Flush
#define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow #define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow
#define DwmGetColorizationColor _glfw.win32.dwmapi.GetColorizationColor
// shcore.dll function pointer typedefs // shcore.dll function pointer typedefs
typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
@ -368,6 +373,7 @@ typedef struct _GLFWlibraryWin32
PFN_DwmIsCompositionEnabled IsCompositionEnabled; PFN_DwmIsCompositionEnabled IsCompositionEnabled;
PFN_DwmFlush Flush; PFN_DwmFlush Flush;
PFN_DwmEnableBlurBehindWindow EnableBlurBehindWindow; PFN_DwmEnableBlurBehindWindow EnableBlurBehindWindow;
PFN_DwmGetColorizationColor GetColorizationColor;
} dwmapi; } dwmapi;
struct { struct {

View File

@ -377,12 +377,17 @@ static void updateWindowStyles(const _GLFWwindow* window)
// //
static void updateFramebufferTransparency(const _GLFWwindow* window) static void updateFramebufferTransparency(const _GLFWwindow* window)
{ {
BOOL enabled; BOOL composition, opaque;
DWORD color;
if (!IsWindowsVistaOrGreater()) if (!IsWindowsVistaOrGreater())
return; return;
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled) if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition)
return;
if (IsWindows8OrGreater() ||
(SUCCEEDED(DwmGetColorizationColor(&color, &opaque)) && !opaque))
{ {
HRGN region = CreateRectRgn(0, 0, -1, -1); HRGN region = CreateRectRgn(0, 0, -1, -1);
DWM_BLURBEHIND bb = {0}; DWM_BLURBEHIND bb = {0};
@ -390,37 +395,18 @@ static void updateFramebufferTransparency(const _GLFWwindow* window)
bb.hRgnBlur = region; bb.hRgnBlur = region;
bb.fEnable = TRUE; bb.fEnable = TRUE;
if (SUCCEEDED(DwmEnableBlurBehindWindow(window->win32.handle, &bb))) DwmEnableBlurBehindWindow(window->win32.handle, &bb);
{
// Decorated windows don't repaint the transparent background
// leaving a trail behind animations
// HACK: Making the window layered with a transparency color key
// seems to fix this. Normally, when specifying
// a transparency color key to be used when composing the
// layered window, all pixels painted by the window in this
// color will be transparent. That doesn't seem to be the
// case anymore, at least when used with blur behind window
// plus negative region.
LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
exStyle |= WS_EX_LAYERED;
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
// Using a color key not equal to black to fix the trailing
// issue. When set to black, something is making the hit test
// not resize with the window frame.
SetLayeredWindowAttributes(window->win32.handle,
RGB(255, 0, 255), 255, LWA_COLORKEY);
}
DeleteObject(region); DeleteObject(region);
} }
else else
{ {
LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE); // HACK: Disable framebuffer transparency on Windows 7 when the
exStyle &= ~WS_EX_LAYERED; // colorization color is opaque, because otherwise the window
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle); // contents is blended additively with the previous frame instead
RedrawWindow(window->win32.handle, NULL, NULL, // of replacing it
RDW_ERASE | RDW_INVALIDATE | RDW_FRAME); DWM_BLURBEHIND bb = {0};
bb.dwFlags = DWM_BB_ENABLE;
DwmEnableBlurBehindWindow(window->win32.handle, &bb);
} }
} }
@ -526,6 +512,9 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_DEVICECHANGE: case WM_DEVICECHANGE:
{ {
if (!_glfw.joysticksInitialized)
break;
if (wParam == DBT_DEVICEARRIVAL) if (wParam == DBT_DEVICEARRIVAL)
{ {
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam; DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
@ -1101,6 +1090,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
} }
case WM_DWMCOMPOSITIONCHANGED: case WM_DWMCOMPOSITIONCHANGED:
case WM_DWMCOLORIZATIONCOLORCHANGED:
{ {
if (window->win32.transparent) if (window->win32.transparent)
updateFramebufferTransparency(window); updateFramebufferTransparency(window);
@ -1826,7 +1816,8 @@ int _glfwPlatformWindowHovered(_GLFWwindow* window)
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{ {
BOOL enabled; BOOL composition, opaque;
DWORD color;
if (!window->win32.transparent) if (!window->win32.transparent)
return GLFW_FALSE; return GLFW_FALSE;
@ -1834,7 +1825,20 @@ int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
if (!IsWindowsVistaOrGreater()) if (!IsWindowsVistaOrGreater())
return GLFW_FALSE; return GLFW_FALSE;
return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled; if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition)
return GLFW_FALSE;
if (!IsWindows8OrGreater())
{
// HACK: Disable framebuffer transparency on Windows 7 when the
// colorization color is opaque, because otherwise the window
// contents is blended additively with the previous frame instead
// of replacing it
if (FAILED(DwmGetColorizationColor(&color, &opaque)) || opaque)
return GLFW_FALSE;
}
return GLFW_TRUE;
} }
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled) void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
@ -1854,6 +1858,36 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
} }
void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled)
{
COLORREF key = 0;
BYTE alpha = 0;
DWORD flags = 0;
DWORD exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
if (exStyle & WS_EX_LAYERED)
GetLayeredWindowAttributes(window->win32.handle, &key, &alpha, &flags);
if (enabled)
exStyle |= (WS_EX_TRANSPARENT | WS_EX_LAYERED);
else
{
exStyle &= ~WS_EX_TRANSPARENT;
// NOTE: Window opacity also needs the layered window style so do not
// remove it if the window is alpha blended
if (exStyle & WS_EX_LAYERED)
{
if (!(flags & LWA_ALPHA))
exStyle &= ~WS_EX_LAYERED;
}
}
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
if (enabled)
SetLayeredWindowAttributes(window->win32.handle, key, alpha, flags);
}
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
{ {
BYTE alpha; BYTE alpha;
@ -1871,19 +1905,22 @@ float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
{ {
if (opacity < 1.f) LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
if (opacity < 1.f || (exStyle & WS_EX_TRANSPARENT))
{ {
const BYTE alpha = (BYTE) (255 * opacity); const BYTE alpha = (BYTE) (255 * opacity);
DWORD style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE); exStyle |= WS_EX_LAYERED;
style |= WS_EX_LAYERED; SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style);
SetLayeredWindowAttributes(window->win32.handle, 0, alpha, LWA_ALPHA); SetLayeredWindowAttributes(window->win32.handle, 0, alpha, LWA_ALPHA);
} }
else if (exStyle & WS_EX_TRANSPARENT)
{
SetLayeredWindowAttributes(window->win32.handle, 0, 0, 0);
}
else else
{ {
DWORD style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE); exStyle &= ~WS_EX_LAYERED;
style &= ~WS_EX_LAYERED; SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style);
} }
} }

View File

@ -197,13 +197,14 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
window->videoMode.blueBits = fbconfig.blueBits; window->videoMode.blueBits = fbconfig.blueBits;
window->videoMode.refreshRate = _glfw.hints.refreshRate; window->videoMode.refreshRate = _glfw.hints.refreshRate;
window->monitor = (_GLFWmonitor*) monitor; window->monitor = (_GLFWmonitor*) monitor;
window->resizable = wndconfig.resizable; window->resizable = wndconfig.resizable;
window->decorated = wndconfig.decorated; window->decorated = wndconfig.decorated;
window->autoIconify = wndconfig.autoIconify; window->autoIconify = wndconfig.autoIconify;
window->floating = wndconfig.floating; window->floating = wndconfig.floating;
window->focusOnShow = wndconfig.focusOnShow; window->focusOnShow = wndconfig.focusOnShow;
window->cursorMode = GLFW_CURSOR_NORMAL; window->mousePassthrough = wndconfig.mousePassthrough;
window->cursorMode = GLFW_CURSOR_NORMAL;
window->minwidth = GLFW_DONT_CARE; window->minwidth = GLFW_DONT_CARE;
window->minheight = GLFW_DONT_CARE; window->minheight = GLFW_DONT_CARE;
@ -228,6 +229,9 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
} }
} }
if (wndconfig.mousePassthrough)
_glfwPlatformSetWindowMousePassthrough(window, GLFW_TRUE);
if (window->monitor) if (window->monitor)
{ {
if (wndconfig.centerCursor) if (wndconfig.centerCursor)
@ -378,6 +382,9 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_FOCUS_ON_SHOW: case GLFW_FOCUS_ON_SHOW:
_glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE;
return; return;
case GLFW_MOUSE_PASSTHROUGH:
_glfw.hints.window.mousePassthrough = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_CLIENT_API: case GLFW_CLIENT_API:
_glfw.hints.context.client = value; _glfw.hints.context.client = value;
return; return;
@ -822,6 +829,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
return _glfwPlatformWindowHovered(window); return _glfwPlatformWindowHovered(window);
case GLFW_FOCUS_ON_SHOW: case GLFW_FOCUS_ON_SHOW:
return window->focusOnShow; return window->focusOnShow;
case GLFW_MOUSE_PASSTHROUGH:
return window->mousePassthrough;
case GLFW_TRANSPARENT_FRAMEBUFFER: case GLFW_TRANSPARENT_FRAMEBUFFER:
return _glfwPlatformFramebufferTransparent(window); return _glfwPlatformFramebufferTransparent(window);
case GLFW_RESIZABLE: case GLFW_RESIZABLE:
@ -900,6 +909,14 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
} }
else if (attrib == GLFW_FOCUS_ON_SHOW) else if (attrib == GLFW_FOCUS_ON_SHOW)
window->focusOnShow = value; window->focusOnShow = value;
else if (attrib == GLFW_MOUSE_PASSTHROUGH)
{
if (window->mousePassthrough == value)
return;
window->mousePassthrough = value;
_glfwPlatformSetWindowMousePassthrough(window, value);
}
else else
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib); _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
} }
@ -1102,3 +1119,4 @@ GLFWAPI void glfwPostEmptyEvent(void)
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_glfwPlatformPostEmptyEvent(); _glfwPlatformPostEmptyEvent();
} }

View File

@ -341,9 +341,9 @@ static void pointerHandleAxis(void* data,
axis == WL_POINTER_AXIS_VERTICAL_SCROLL); axis == WL_POINTER_AXIS_VERTICAL_SCROLL);
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
x = wl_fixed_to_double(value) * scrollFactor; x = -wl_fixed_to_double(value) * scrollFactor;
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
y = wl_fixed_to_double(value) * scrollFactor; y = -wl_fixed_to_double(value) * scrollFactor;
_glfwInputScroll(window, x, y); _glfwInputScroll(window, x, y);
} }
@ -1146,11 +1146,6 @@ int _glfwPlatformInit(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);
#ifdef __linux__
if (!_glfwInitJoysticksLinux())
return GLFW_FALSE;
#endif
_glfwInitTimerPOSIX(); _glfwInitTimerPOSIX();
_glfw.wl.timerfd = -1; _glfw.wl.timerfd = -1;
@ -1213,9 +1208,6 @@ int _glfwPlatformInit(void)
void _glfwPlatformTerminate(void) void _glfwPlatformTerminate(void)
{ {
#ifdef __linux__
_glfwTerminateJoysticksLinux();
#endif
_glfwTerminateEGL(); _glfwTerminateEGL();
if (_glfw.wl.egl.handle) if (_glfw.wl.egl.handle)
{ {

View File

@ -955,8 +955,10 @@ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window,
int* width, int* height) int* width, int* height)
{ {
_glfwPlatformGetWindowSize(window, width, height); _glfwPlatformGetWindowSize(window, width, height);
*width *= window->wl.scale; if (width)
*height *= window->wl.scale; *width *= window->wl.scale;
if (height)
*height *= window->wl.scale;
} }
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
@ -1127,6 +1129,19 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
"Wayland: Window attribute setting not implemented yet"); "Wayland: Window attribute setting not implemented yet");
} }
void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled)
{
if (enabled)
{
struct wl_region* region = wl_compositor_create_region(_glfw.wl.compositor);
wl_surface_set_input_region(window->wl.surface, region);
wl_region_destroy(region);
}
else
wl_surface_set_input_region(window->wl.surface, 0);
wl_surface_commit(window->wl.surface);
}
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
{ {
return 1.f; return 1.f;

View File

@ -851,6 +851,35 @@ static GLFWbool initExtensions(void)
} }
} }
#if defined(__CYGWIN__)
_glfw.x11.xshape.handle = _glfw_dlopen("libXext-6.so");
#else
_glfw.x11.xshape.handle = _glfw_dlopen("libXext.so.6");
#endif
if (_glfw.x11.xshape.handle)
{
_glfw.x11.xshape.QueryExtension = (PFN_XShapeQueryExtension)
_glfw_dlsym(_glfw.x11.xshape.handle, "XShapeQueryExtension");
_glfw.x11.xshape.ShapeCombineRegion = (PFN_XShapeCombineRegion)
_glfw_dlsym(_glfw.x11.xshape.handle, "XShapeCombineRegion");
_glfw.x11.xshape.QueryVersion = (PFN_XShapeQueryVersion)
_glfw_dlsym(_glfw.x11.xshape.handle, "XShapeQueryVersion");
_glfw.x11.xshape.ShapeCombineMask = (PFN_XShapeCombineMask)
_glfw_dlsym(_glfw.x11.xshape.handle, "XShapeCombineMask");
if (XShapeQueryExtension(_glfw.x11.display,
&_glfw.x11.xshape.errorBase,
&_glfw.x11.xshape.eventBase))
{
if (XShapeQueryVersion(_glfw.x11.display,
&_glfw.x11.xshape.major,
&_glfw.x11.xshape.minor))
{
_glfw.x11.xshape.available = GLFW_TRUE;
}
}
}
// Update the key code LUT // Update the key code LUT
// FIXME: We should listen to XkbMapNotify events to track changes to // FIXME: We should listen to XkbMapNotify events to track changes to
// the keyboard mapping. // the keyboard mapping.
@ -1122,6 +1151,8 @@ int _glfwPlatformInit(void)
_glfw_dlsym(_glfw.x11.xlib.handle, "XCreateFontCursor"); _glfw_dlsym(_glfw.x11.xlib.handle, "XCreateFontCursor");
_glfw.x11.xlib.CreateIC = (PFN_XCreateIC) _glfw.x11.xlib.CreateIC = (PFN_XCreateIC)
_glfw_dlsym(_glfw.x11.xlib.handle, "XCreateIC"); _glfw_dlsym(_glfw.x11.xlib.handle, "XCreateIC");
_glfw.x11.xlib.CreateRegion = (PFN_XCreateRegion)
_glfw_dlsym(_glfw.x11.xlib.handle, "XCreateRegion");
_glfw.x11.xlib.CreateWindow = (PFN_XCreateWindow) _glfw.x11.xlib.CreateWindow = (PFN_XCreateWindow)
_glfw_dlsym(_glfw.x11.xlib.handle, "XCreateWindow"); _glfw_dlsym(_glfw.x11.xlib.handle, "XCreateWindow");
_glfw.x11.xlib.DefineCursor = (PFN_XDefineCursor) _glfw.x11.xlib.DefineCursor = (PFN_XDefineCursor)
@ -1132,6 +1163,8 @@ int _glfwPlatformInit(void)
_glfw_dlsym(_glfw.x11.xlib.handle, "XDeleteProperty"); _glfw_dlsym(_glfw.x11.xlib.handle, "XDeleteProperty");
_glfw.x11.xlib.DestroyIC = (PFN_XDestroyIC) _glfw.x11.xlib.DestroyIC = (PFN_XDestroyIC)
_glfw_dlsym(_glfw.x11.xlib.handle, "XDestroyIC"); _glfw_dlsym(_glfw.x11.xlib.handle, "XDestroyIC");
_glfw.x11.xlib.DestroyRegion = (PFN_XDestroyRegion)
_glfw_dlsym(_glfw.x11.xlib.handle, "XDestroyRegion");
_glfw.x11.xlib.DestroyWindow = (PFN_XDestroyWindow) _glfw.x11.xlib.DestroyWindow = (PFN_XDestroyWindow)
_glfw_dlsym(_glfw.x11.xlib.handle, "XDestroyWindow"); _glfw_dlsym(_glfw.x11.xlib.handle, "XDestroyWindow");
_glfw.x11.xlib.DisplayKeycodes = (PFN_XDisplayKeycodes) _glfw.x11.xlib.DisplayKeycodes = (PFN_XDisplayKeycodes)
@ -1344,11 +1377,6 @@ int _glfwPlatformInit(void)
NULL); NULL);
} }
#if defined(__linux__)
if (!_glfwInitJoysticksLinux())
return GLFW_FALSE;
#endif
_glfwInitTimerPOSIX(); _glfwInitTimerPOSIX();
_glfwPollMonitorsX11(); _glfwPollMonitorsX11();
@ -1442,10 +1470,6 @@ void _glfwPlatformTerminate(void)
_glfwTerminateEGL(); _glfwTerminateEGL();
_glfwTerminateGLX(); _glfwTerminateGLX();
#if defined(__linux__)
_glfwTerminateJoysticksLinux();
#endif
if (_glfw.x11.xlib.handle) if (_glfw.x11.xlib.handle)
{ {
_glfw_dlclose(_glfw.x11.xlib.handle); _glfw_dlclose(_glfw.x11.xlib.handle);

View File

@ -48,6 +48,9 @@
// The XInput extension provides raw mouse motion input // The XInput extension provides raw mouse motion input
#include <X11/extensions/XInput2.h> #include <X11/extensions/XInput2.h>
// The Shape extension provides custom window shapes
#include <X11/extensions/shape.h>
typedef XClassHint* (* PFN_XAllocClassHint)(void); typedef XClassHint* (* PFN_XAllocClassHint)(void);
typedef XSizeHints* (* PFN_XAllocSizeHints)(void); typedef XSizeHints* (* PFN_XAllocSizeHints)(void);
typedef XWMHints* (* PFN_XAllocWMHints)(void); typedef XWMHints* (* PFN_XAllocWMHints)(void);
@ -61,11 +64,13 @@ typedef int (* PFN_XConvertSelection)(Display*,Atom,Atom,Atom,Window,Time);
typedef Colormap (* PFN_XCreateColormap)(Display*,Window,Visual*,int); typedef Colormap (* PFN_XCreateColormap)(Display*,Window,Visual*,int);
typedef Cursor (* PFN_XCreateFontCursor)(Display*,unsigned int); typedef Cursor (* PFN_XCreateFontCursor)(Display*,unsigned int);
typedef XIC (* PFN_XCreateIC)(XIM,...); typedef XIC (* PFN_XCreateIC)(XIM,...);
typedef Region (* PFN_XCreateRegion)(void);
typedef Window (* PFN_XCreateWindow)(Display*,Window,int,int,unsigned int,unsigned int,unsigned int,int,unsigned int,Visual*,unsigned long,XSetWindowAttributes*); typedef Window (* PFN_XCreateWindow)(Display*,Window,int,int,unsigned int,unsigned int,unsigned int,int,unsigned int,Visual*,unsigned long,XSetWindowAttributes*);
typedef int (* PFN_XDefineCursor)(Display*,Window,Cursor); typedef int (* PFN_XDefineCursor)(Display*,Window,Cursor);
typedef int (* PFN_XDeleteContext)(Display*,XID,XContext); typedef int (* PFN_XDeleteContext)(Display*,XID,XContext);
typedef int (* PFN_XDeleteProperty)(Display*,Window,Atom); typedef int (* PFN_XDeleteProperty)(Display*,Window,Atom);
typedef void (* PFN_XDestroyIC)(XIC); typedef void (* PFN_XDestroyIC)(XIC);
typedef int (* PFN_XDestroyRegion)(Region);
typedef int (* PFN_XDestroyWindow)(Display*,Window); typedef int (* PFN_XDestroyWindow)(Display*,Window);
typedef int (* PFN_XDisplayKeycodes)(Display*,int*,int*); typedef int (* PFN_XDisplayKeycodes)(Display*,int*,int*);
typedef int (* PFN_XEventsQueued)(Display*,int); typedef int (* PFN_XEventsQueued)(Display*,int);
@ -161,11 +166,13 @@ typedef void (* PFN_Xutf8SetWMProperties)(Display*,Window,const char*,const char
#define XCreateColormap _glfw.x11.xlib.CreateColormap #define XCreateColormap _glfw.x11.xlib.CreateColormap
#define XCreateFontCursor _glfw.x11.xlib.CreateFontCursor #define XCreateFontCursor _glfw.x11.xlib.CreateFontCursor
#define XCreateIC _glfw.x11.xlib.CreateIC #define XCreateIC _glfw.x11.xlib.CreateIC
#define XCreateRegion _glfw.x11.xlib.CreateRegion
#define XCreateWindow _glfw.x11.xlib.CreateWindow #define XCreateWindow _glfw.x11.xlib.CreateWindow
#define XDefineCursor _glfw.x11.xlib.DefineCursor #define XDefineCursor _glfw.x11.xlib.DefineCursor
#define XDeleteContext _glfw.x11.xlib.DeleteContext #define XDeleteContext _glfw.x11.xlib.DeleteContext
#define XDeleteProperty _glfw.x11.xlib.DeleteProperty #define XDeleteProperty _glfw.x11.xlib.DeleteProperty
#define XDestroyIC _glfw.x11.xlib.DestroyIC #define XDestroyIC _glfw.x11.xlib.DestroyIC
#define XDestroyRegion _glfw.x11.xlib.DestroyRegion
#define XDestroyWindow _glfw.x11.xlib.DestroyWindow #define XDestroyWindow _glfw.x11.xlib.DestroyWindow
#define XDisplayKeycodes _glfw.x11.xlib.DisplayKeycodes #define XDisplayKeycodes _glfw.x11.xlib.DisplayKeycodes
#define XEventsQueued _glfw.x11.xlib.EventsQueued #define XEventsQueued _glfw.x11.xlib.EventsQueued
@ -331,6 +338,16 @@ typedef XRenderPictFormat* (* PFN_XRenderFindVisualFormat)(Display*,Visual const
#define XRenderQueryVersion _glfw.x11.xrender.QueryVersion #define XRenderQueryVersion _glfw.x11.xrender.QueryVersion
#define XRenderFindVisualFormat _glfw.x11.xrender.FindVisualFormat #define XRenderFindVisualFormat _glfw.x11.xrender.FindVisualFormat
typedef Bool (* PFN_XShapeQueryExtension)(Display*,int*,int*);
typedef Status (* PFN_XShapeQueryVersion)(Display*dpy,int*,int*);
typedef void (* PFN_XShapeCombineRegion)(Display*,Window,int,int,int,Region,int);
typedef void (* PFN_XShapeCombineMask)(Display*,Window,int,int,int,Pixmap,int);
#define XShapeQueryExtension _glfw.x11.xshape.QueryExtension
#define XShapeQueryVersion _glfw.x11.xshape.QueryVersion
#define XShapeCombineRegion _glfw.x11.xshape.ShapeCombineRegion
#define XShapeCombineMask _glfw.x11.xshape.ShapeCombineMask
typedef VkFlags VkXlibSurfaceCreateFlagsKHR; typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
typedef VkFlags VkXcbSurfaceCreateFlagsKHR; typedef VkFlags VkXcbSurfaceCreateFlagsKHR;
@ -515,11 +532,13 @@ typedef struct _GLFWlibraryX11
PFN_XCreateColormap CreateColormap; PFN_XCreateColormap CreateColormap;
PFN_XCreateFontCursor CreateFontCursor; PFN_XCreateFontCursor CreateFontCursor;
PFN_XCreateIC CreateIC; PFN_XCreateIC CreateIC;
PFN_XCreateRegion CreateRegion;
PFN_XCreateWindow CreateWindow; PFN_XCreateWindow CreateWindow;
PFN_XDefineCursor DefineCursor; PFN_XDefineCursor DefineCursor;
PFN_XDeleteContext DeleteContext; PFN_XDeleteContext DeleteContext;
PFN_XDeleteProperty DeleteProperty; PFN_XDeleteProperty DeleteProperty;
PFN_XDestroyIC DestroyIC; PFN_XDestroyIC DestroyIC;
PFN_XDestroyRegion DestroyRegion;
PFN_XDestroyWindow DestroyWindow; PFN_XDestroyWindow DestroyWindow;
PFN_XDisplayKeycodes DisplayKeycodes; PFN_XDisplayKeycodes DisplayKeycodes;
PFN_XEventsQueued EventsQueued; PFN_XEventsQueued EventsQueued;
@ -720,6 +739,19 @@ typedef struct _GLFWlibraryX11
PFN_XRenderFindVisualFormat FindVisualFormat; PFN_XRenderFindVisualFormat FindVisualFormat;
} xrender; } xrender;
struct {
GLFWbool available;
void* handle;
int major;
int minor;
int eventBase;
int errorBase;
PFN_XShapeQueryExtension QueryExtension;
PFN_XShapeCombineRegion ShapeCombineRegion;
PFN_XShapeQueryVersion QueryVersion;
PFN_XShapeCombineMask ShapeCombineMask;
} xshape;
} _GLFWlibraryX11; } _GLFWlibraryX11;
// X11-specific per-monitor data // X11-specific per-monitor data

View File

@ -2702,6 +2702,25 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
XFlush(_glfw.x11.display); XFlush(_glfw.x11.display);
} }
void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled)
{
if (!_glfw.x11.xshape.available)
return;
if (enabled)
{
Region region = XCreateRegion();
XShapeCombineRegion(_glfw.x11.display, window->x11.handle,
ShapeInput, 0, 0, region, ShapeSet);
XDestroyRegion(region);
}
else
{
XShapeCombineMask(_glfw.x11.display, window->x11.handle,
ShapeInput, 0, 0, None, ShapeSet);
}
}
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
{ {
float opacity = 1.f; float opacity = 1.f;
@ -2757,7 +2776,8 @@ void _glfwPlatformPollEvents(void)
_GLFWwindow* window; _GLFWwindow* window;
#if defined(__linux__) #if defined(__linux__)
_glfwDetectJoystickConnectionLinux(); if (_glfw.joysticksInitialized)
_glfwDetectJoystickConnectionLinux();
#endif #endif
XPending(_glfw.x11.display); XPending(_glfw.x11.display);

View File

@ -35,13 +35,12 @@ add_executable(gamma WIN32 MACOSX_BUNDLE gamma.c ${GLAD_GL})
add_executable(icon WIN32 MACOSX_BUNDLE icon.c ${GLAD_GL}) add_executable(icon WIN32 MACOSX_BUNDLE icon.c ${GLAD_GL})
add_executable(inputlag WIN32 MACOSX_BUNDLE inputlag.c ${GETOPT} ${GLAD_GL}) add_executable(inputlag WIN32 MACOSX_BUNDLE inputlag.c ${GETOPT} ${GLAD_GL})
add_executable(joysticks WIN32 MACOSX_BUNDLE joysticks.c ${GLAD_GL}) add_executable(joysticks WIN32 MACOSX_BUNDLE joysticks.c ${GLAD_GL})
add_executable(opacity WIN32 MACOSX_BUNDLE opacity.c ${GLAD_GL})
add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c ${GLAD_GL}) add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c ${GLAD_GL})
add_executable(threads WIN32 MACOSX_BUNDLE threads.c ${TINYCTHREAD} ${GLAD_GL}) add_executable(threads WIN32 MACOSX_BUNDLE threads.c ${TINYCTHREAD} ${GLAD_GL})
add_executable(timeout WIN32 MACOSX_BUNDLE timeout.c ${GLAD_GL}) add_executable(timeout WIN32 MACOSX_BUNDLE timeout.c ${GLAD_GL})
add_executable(title WIN32 MACOSX_BUNDLE title.c ${GLAD_GL}) add_executable(title WIN32 MACOSX_BUNDLE title.c ${GLAD_GL})
add_executable(triangle-vulkan WIN32 triangle-vulkan.c ${GLAD_VULKAN}) add_executable(triangle-vulkan WIN32 triangle-vulkan.c ${GLAD_VULKAN})
add_executable(windows WIN32 MACOSX_BUNDLE windows.c ${GLAD_GL}) add_executable(window WIN32 MACOSX_BUNDLE window.c ${GLAD_GL})
target_link_libraries(empty Threads::Threads) target_link_libraries(empty Threads::Threads)
target_link_libraries(threads Threads::Threads) target_link_libraries(threads Threads::Threads)
@ -50,8 +49,8 @@ if (RT_LIBRARY)
target_link_libraries(threads "${RT_LIBRARY}") target_link_libraries(threads "${RT_LIBRARY}")
endif() endif()
set(GUI_ONLY_BINARIES empty gamma icon inputlag joysticks opacity tearing set(GUI_ONLY_BINARIES empty gamma icon inputlag joysticks tearing threads
threads timeout title triangle-vulkan windows) timeout title triangle-vulkan window)
set(CONSOLE_BINARIES clipboard events msaa glfwinfo iconify monitors reopen set(CONSOLE_BINARIES clipboard events msaa glfwinfo iconify monitors reopen
cursor usercontext) cursor usercontext)
@ -70,12 +69,11 @@ if (APPLE)
set_target_properties(gamma PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gamma") set_target_properties(gamma PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gamma")
set_target_properties(inputlag PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Input Lag") set_target_properties(inputlag PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Input Lag")
set_target_properties(joysticks PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Joysticks") set_target_properties(joysticks PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Joysticks")
set_target_properties(opacity PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Opacity")
set_target_properties(tearing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Tearing") set_target_properties(tearing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Tearing")
set_target_properties(threads PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Threads") set_target_properties(threads PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Threads")
set_target_properties(timeout PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Timeout") set_target_properties(timeout PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Timeout")
set_target_properties(title PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Title") set_target_properties(title PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Title")
set_target_properties(windows PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Windows") set_target_properties(window PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Window")
set_target_properties(${GUI_ONLY_BINARIES} PROPERTIES set_target_properties(${GUI_ONLY_BINARIES} PROPERTIES
MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION}

View File

@ -1,109 +0,0 @@
//========================================================================
// Window opacity test program
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#define NK_IMPLEMENTATION
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_STANDARD_VARARGS
#include <nuklear.h>
#define NK_GLFW_GL2_IMPLEMENTATION
#include <nuklear_glfw_gl2.h>
#include <stdio.h>
#include <stdlib.h>
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
int main(int argc, char** argv)
{
GLFWwindow* window;
struct nk_context* nk;
struct nk_font_atlas* atlas;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
glfwWindowHint(GLFW_WIN32_KEYBOARD_MENU, GLFW_TRUE);
window = glfwCreateWindow(400, 400, "Opacity", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(1);
nk = nk_glfw3_init(window, NK_GLFW3_INSTALL_CALLBACKS);
nk_glfw3_font_stash_begin(&atlas);
nk_glfw3_font_stash_end();
while (!glfwWindowShouldClose(window))
{
int width, height;
struct nk_rect area;
glfwGetWindowSize(window, &width, &height);
area = nk_rect(0.f, 0.f, (float) width, (float) height);
glClear(GL_COLOR_BUFFER_BIT);
nk_glfw3_new_frame();
if (nk_begin(nk, "", area, 0))
{
float opacity = glfwGetWindowOpacity(window);
nk_layout_row_dynamic(nk, 30, 2);
if (nk_slider_float(nk, 0.f, &opacity, 1.f, 0.001f))
glfwSetWindowOpacity(window, opacity);
nk_labelf(nk, NK_TEXT_LEFT, "%0.3f", opacity);
}
nk_end(nk);
nk_glfw3_render(NK_ANTI_ALIASING_ON);
glfwSwapBuffers(window);
glfwWaitEventsTimeout(1.0);
}
nk_glfw3_shutdown();
glfwTerminate();
exit(EXIT_SUCCESS);
}

417
tests/window.c Normal file
View File

@ -0,0 +1,417 @@
//========================================================================
// Window properties test
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <stdarg.h>
#define NK_IMPLEMENTATION
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_BUTTON_TRIGGER_ON_RELEASE
#include <nuklear.h>
#define NK_GLFW_GL2_IMPLEMENTATION
#include <nuklear_glfw_gl2.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(int argc, char** argv)
{
int windowed_x, windowed_y, windowed_width, windowed_height;
int last_xpos = INT_MIN, last_ypos = INT_MIN;
int last_width = INT_MIN, last_height = INT_MIN;
int limit_aspect_ratio = false, aspect_numer = 1, aspect_denom = 1;
int limit_min_size = false, min_width = 400, min_height = 400;
int limit_max_size = false, max_width = 400, max_height = 400;
char width_buffer[10] = "", height_buffer[10] = "";
char xpos_buffer[10] = "", ypos_buffer[10] = "";
char numer_buffer[10] = "", denom_buffer[10] = "";
char min_width_buffer[10] = "", min_height_buffer[10] = "";
char max_width_buffer[10] = "", max_height_buffer[10] = "";
int may_close = true;
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
glfwWindowHint(GLFW_WIN32_KEYBOARD_MENU, GLFW_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
GLFWwindow* window = glfwCreateWindow(600, 600, "Window Features", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(0);
bool position_supported = true;
glfwGetError(NULL);
glfwGetWindowPos(window, &last_xpos, &last_ypos);
sprintf(xpos_buffer, "%i", last_xpos);
sprintf(ypos_buffer, "%i", last_ypos);
if (glfwGetError(NULL) == GLFW_FEATURE_UNAVAILABLE)
position_supported = false;
glfwGetWindowSize(window, &last_width, &last_height);
sprintf(width_buffer, "%i", last_width);
sprintf(height_buffer, "%i", last_height);
sprintf(numer_buffer, "%i", aspect_numer);
sprintf(denom_buffer, "%i", aspect_denom);
sprintf(min_width_buffer, "%i", min_width);
sprintf(min_height_buffer, "%i", min_height);
sprintf(max_width_buffer, "%i", max_width);
sprintf(max_height_buffer, "%i", max_height);
struct nk_context* nk = nk_glfw3_init(window, NK_GLFW3_INSTALL_CALLBACKS);
struct nk_font_atlas* atlas;
nk_glfw3_font_stash_begin(&atlas);
nk_glfw3_font_stash_end();
while (!(may_close && glfwWindowShouldClose(window)))
{
int width, height;
glfwGetWindowSize(window, &width, &height);
struct nk_rect area = nk_rect(0.f, 0.f, (float) width, (float) height);
nk_window_set_bounds(nk, "main", area);
nk_glfw3_new_frame();
if (nk_begin(nk, "main", area, 0))
{
nk_layout_row_dynamic(nk, 30, 4);
if (nk_button_label(nk, "Toggle Fullscreen"))
{
if (glfwGetWindowMonitor(window))
{
glfwSetWindowMonitor(window, NULL,
windowed_x, windowed_y,
windowed_width, windowed_height, 0);
}
else
{
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwGetWindowPos(window, &windowed_x, &windowed_y);
glfwGetWindowSize(window, &windowed_width, &windowed_height);
glfwSetWindowMonitor(window, monitor,
0, 0, mode->width, mode->height,
mode->refreshRate);
}
}
if (nk_button_label(nk, "Maximize"))
glfwMaximizeWindow(window);
if (nk_button_label(nk, "Iconify"))
glfwIconifyWindow(window);
if (nk_button_label(nk, "Restore"))
glfwRestoreWindow(window);
nk_layout_row_dynamic(nk, 30, 1);
if (glfwGetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH))
{
nk_label(nk, "Press H to disable mouse passthrough", NK_TEXT_CENTERED);
if (glfwGetKey(window, GLFW_KEY_H))
glfwSetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH, false);
}
nk_label(nk, "Press Enter in a text field to set value", NK_TEXT_CENTERED);
nk_flags events;
const nk_flags flags = NK_EDIT_FIELD |
NK_EDIT_SIG_ENTER |
NK_EDIT_GOTO_END_ON_ACTIVATE;
if (position_supported)
{
int xpos, ypos;
glfwGetWindowPos(window, &xpos, &ypos);
nk_layout_row_dynamic(nk, 30, 3);
nk_label(nk, "Position", NK_TEXT_LEFT);
events = nk_edit_string_zero_terminated(nk, flags, xpos_buffer,
sizeof(xpos_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
xpos = atoi(xpos_buffer);
glfwSetWindowPos(window, xpos, ypos);
}
else if (xpos != last_xpos || (events & NK_EDIT_DEACTIVATED))
sprintf(xpos_buffer, "%i", xpos);
events = nk_edit_string_zero_terminated(nk, flags, ypos_buffer,
sizeof(ypos_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
ypos = atoi(ypos_buffer);
glfwSetWindowPos(window, xpos, ypos);
}
else if (ypos != last_ypos || (events & NK_EDIT_DEACTIVATED))
sprintf(ypos_buffer, "%i", ypos);
last_xpos = xpos;
last_ypos = ypos;
}
else
nk_label(nk, "Position not supported", NK_TEXT_LEFT);
nk_layout_row_dynamic(nk, 30, 3);
nk_label(nk, "Size", NK_TEXT_LEFT);
events = nk_edit_string_zero_terminated(nk, flags, width_buffer,
sizeof(width_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
width = atoi(width_buffer);
glfwSetWindowSize(window, width, height);
}
else if (width != last_width || (events & NK_EDIT_DEACTIVATED))
sprintf(width_buffer, "%i", width);
events = nk_edit_string_zero_terminated(nk, flags, height_buffer,
sizeof(height_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
height = atoi(height_buffer);
glfwSetWindowSize(window, width, height);
}
else if (height != last_height || (events & NK_EDIT_DEACTIVATED))
sprintf(height_buffer, "%i", height);
last_width = width;
last_height = height;
bool update_ratio_limit = false;
if (nk_checkbox_label(nk, "Aspect Ratio", &limit_aspect_ratio))
update_ratio_limit = true;
events = nk_edit_string_zero_terminated(nk, flags, numer_buffer,
sizeof(numer_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
aspect_numer = abs(atoi(numer_buffer));
update_ratio_limit = true;
}
else if (events & NK_EDIT_DEACTIVATED)
sprintf(numer_buffer, "%i", aspect_numer);
events = nk_edit_string_zero_terminated(nk, flags, denom_buffer,
sizeof(denom_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
aspect_denom = abs(atoi(denom_buffer));
update_ratio_limit = true;
}
else if (events & NK_EDIT_DEACTIVATED)
sprintf(denom_buffer, "%i", aspect_denom);
if (update_ratio_limit)
{
if (limit_aspect_ratio)
glfwSetWindowAspectRatio(window, aspect_numer, aspect_denom);
else
glfwSetWindowAspectRatio(window, GLFW_DONT_CARE, GLFW_DONT_CARE);
}
bool update_size_limit = false;
if (nk_checkbox_label(nk, "Minimum Size", &limit_min_size))
update_size_limit = true;
events = nk_edit_string_zero_terminated(nk, flags, min_width_buffer,
sizeof(min_width_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
min_width = abs(atoi(min_width_buffer));
update_size_limit = true;
}
else if (events & NK_EDIT_DEACTIVATED)
sprintf(min_width_buffer, "%i", min_width);
events = nk_edit_string_zero_terminated(nk, flags, min_height_buffer,
sizeof(min_height_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
min_height = abs(atoi(min_height_buffer));
update_size_limit = true;
}
else if (events & NK_EDIT_DEACTIVATED)
sprintf(min_height_buffer, "%i", min_height);
if (nk_checkbox_label(nk, "Maximum Size", &limit_max_size))
update_size_limit = true;
events = nk_edit_string_zero_terminated(nk, flags, max_width_buffer,
sizeof(max_width_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
max_width = abs(atoi(max_width_buffer));
update_size_limit = true;
}
else if (events & NK_EDIT_DEACTIVATED)
sprintf(max_width_buffer, "%i", max_width);
events = nk_edit_string_zero_terminated(nk, flags, max_height_buffer,
sizeof(max_height_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
max_height = abs(atoi(max_height_buffer));
update_size_limit = true;
}
else if (events & NK_EDIT_DEACTIVATED)
sprintf(max_height_buffer, "%i", max_height);
if (update_size_limit)
{
glfwSetWindowSizeLimits(window,
limit_min_size ? min_width : GLFW_DONT_CARE,
limit_min_size ? min_height : GLFW_DONT_CARE,
limit_max_size ? max_width : GLFW_DONT_CARE,
limit_max_size ? max_height : GLFW_DONT_CARE);
}
int fb_width, fb_height;
glfwGetFramebufferSize(window, &fb_width, &fb_height);
nk_label(nk, "Framebuffer Size", NK_TEXT_LEFT);
nk_labelf(nk, NK_TEXT_LEFT, "%i", fb_width);
nk_labelf(nk, NK_TEXT_LEFT, "%i", fb_height);
float xscale, yscale;
glfwGetWindowContentScale(window, &xscale, &yscale);
nk_label(nk, "Content Scale", NK_TEXT_LEFT);
nk_labelf(nk, NK_TEXT_LEFT, "%f", xscale);
nk_labelf(nk, NK_TEXT_LEFT, "%f", yscale);
nk_layout_row_begin(nk, NK_DYNAMIC, 30, 5);
int frame_left, frame_top, frame_right, frame_bottom;
glfwGetWindowFrameSize(window, &frame_left, &frame_top, &frame_right, &frame_bottom);
nk_layout_row_push(nk, 1.f / 3.f);
nk_label(nk, "Frame Size:", NK_TEXT_LEFT);
nk_layout_row_push(nk, 1.f / 6.f);
nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_left);
nk_layout_row_push(nk, 1.f / 6.f);
nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_top);
nk_layout_row_push(nk, 1.f / 6.f);
nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_right);
nk_layout_row_push(nk, 1.f / 6.f);
nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_bottom);
nk_layout_row_end(nk);
nk_layout_row_begin(nk, NK_DYNAMIC, 30, 2);
float opacity = glfwGetWindowOpacity(window);
nk_layout_row_push(nk, 1.f / 3.f);
nk_labelf(nk, NK_TEXT_LEFT, "Opacity: %0.3f", opacity);
nk_layout_row_push(nk, 2.f / 3.f);
if (nk_slider_float(nk, 0.f, &opacity, 1.f, 0.001f))
glfwSetWindowOpacity(window, opacity);
nk_layout_row_end(nk);
nk_layout_row_begin(nk, NK_DYNAMIC, 30, 2);
int should_close = glfwWindowShouldClose(window);
nk_layout_row_push(nk, 1.f / 3.f);
if (nk_checkbox_label(nk, "Should Close", &should_close))
glfwSetWindowShouldClose(window, should_close);
nk_layout_row_push(nk, 2.f / 3.f);
nk_checkbox_label(nk, "May Close", &may_close);
nk_layout_row_end(nk);
nk_layout_row_dynamic(nk, 30, 1);
nk_label(nk, "Attributes", NK_TEXT_CENTERED);
nk_layout_row_dynamic(nk, 30, width > 200 ? width / 200 : 1);
int decorated = glfwGetWindowAttrib(window, GLFW_DECORATED);
if (nk_checkbox_label(nk, "Decorated", &decorated))
glfwSetWindowAttrib(window, GLFW_DECORATED, decorated);
int resizable = glfwGetWindowAttrib(window, GLFW_RESIZABLE);
if (nk_checkbox_label(nk, "Resizable", &resizable))
glfwSetWindowAttrib(window, GLFW_RESIZABLE, resizable);
int floating = glfwGetWindowAttrib(window, GLFW_FLOATING);
if (nk_checkbox_label(nk, "Floating", &floating))
glfwSetWindowAttrib(window, GLFW_FLOATING, floating);
int passthrough = glfwGetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH);
if (nk_checkbox_label(nk, "Mouse Passthrough", &passthrough))
glfwSetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH, passthrough);
int auto_iconify = glfwGetWindowAttrib(window, GLFW_AUTO_ICONIFY);
if (nk_checkbox_label(nk, "Auto Iconify", &auto_iconify))
glfwSetWindowAttrib(window, GLFW_AUTO_ICONIFY, auto_iconify);
nk_value_bool(nk, "Focused", glfwGetWindowAttrib(window, GLFW_FOCUSED));
nk_value_bool(nk, "Hovered", glfwGetWindowAttrib(window, GLFW_HOVERED));
nk_value_bool(nk, "Visible", glfwGetWindowAttrib(window, GLFW_VISIBLE));
nk_value_bool(nk, "Iconified", glfwGetWindowAttrib(window, GLFW_ICONIFIED));
nk_value_bool(nk, "Maximized", glfwGetWindowAttrib(window, GLFW_MAXIMIZED));
}
nk_end(nk);
glClear(GL_COLOR_BUFFER_BIT);
nk_glfw3_render(NK_ANTI_ALIASING_ON);
glfwSwapBuffers(window);
glfwWaitEvents();
}
nk_glfw3_shutdown();
glfwTerminate();
exit(EXIT_SUCCESS);
}