mirror of
https://github.com/glfw/glfw.git
synced 2024-11-25 22:14:34 +00:00
Merge branch '3.3-stable' into new-cursors-on-3.3-stable
This commit is contained in:
commit
74a1ae065a
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@ -96,8 +96,8 @@ jobs:
|
|||||||
- name: Build shared library
|
- name: Build shared library
|
||||||
run: cmake --build build-shared --parallel
|
run: cmake --build build-shared --parallel
|
||||||
|
|
||||||
build-windows-win32-vs2019:
|
build-windows-win32-vs2022:
|
||||||
name: Win32 (Windows, VS2019)
|
name: Win32 (Windows, VS2022)
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
env:
|
env:
|
||||||
CFLAGS: /WX
|
CFLAGS: /WX
|
||||||
@ -105,12 +105,12 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Configure static library
|
- name: Configure static library
|
||||||
run: cmake -S . -B build-static -G "Visual Studio 16 2019"
|
run: cmake -S . -B build-static -G "Visual Studio 17 2022"
|
||||||
- name: Build static library
|
- name: Build static library
|
||||||
run: cmake --build build-static --parallel
|
run: cmake --build build-static --parallel
|
||||||
|
|
||||||
- name: Configure shared library
|
- name: Configure shared library
|
||||||
run: cmake -S . -B build-shared -G "Visual Studio 16 2019" -D BUILD_SHARED_LIBS=ON
|
run: cmake -S . -B build-shared -G "Visual Studio 17 2022" -D BUILD_SHARED_LIBS=ON
|
||||||
- name: Build shared library
|
- name: Build shared library
|
||||||
run: cmake --build build-shared --parallel
|
run: cmake --build build-shared --parallel
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ video tutorials.
|
|||||||
- David Carlier
|
- David Carlier
|
||||||
- Arturo Castro
|
- Arturo Castro
|
||||||
- Chi-kwan Chan
|
- Chi-kwan Chan
|
||||||
|
- TheChocolateOre
|
||||||
- Joseph Chua
|
- Joseph Chua
|
||||||
- Ian Clarkson
|
- Ian Clarkson
|
||||||
- Michał Cichoń
|
- Michał Cichoń
|
||||||
@ -81,6 +82,7 @@ video tutorials.
|
|||||||
- Paul Holden
|
- Paul Holden
|
||||||
- Warren Hu
|
- Warren Hu
|
||||||
- Charles Huber
|
- Charles Huber
|
||||||
|
- illustris
|
||||||
- InKryption
|
- InKryption
|
||||||
- IntellectualKitty
|
- IntellectualKitty
|
||||||
- Aaron Jacobs
|
- Aaron Jacobs
|
||||||
@ -179,12 +181,15 @@ video tutorials.
|
|||||||
- Ali Sherief
|
- Ali Sherief
|
||||||
- Yoshiki Shibukawa
|
- Yoshiki Shibukawa
|
||||||
- Dmitri Shuralyov
|
- Dmitri Shuralyov
|
||||||
|
- Joao da Silva
|
||||||
- Daniel Sieger
|
- Daniel Sieger
|
||||||
- Daniel Skorupski
|
- Daniel Skorupski
|
||||||
|
- Slemmie
|
||||||
- Bradley Smith
|
- Bradley Smith
|
||||||
- Cliff Smolinsky
|
- Cliff Smolinsky
|
||||||
- Patrick Snape
|
- Patrick Snape
|
||||||
- Erlend Sogge Heggen
|
- Erlend Sogge Heggen
|
||||||
|
- Olivier Sohn
|
||||||
- Julian Squires
|
- Julian Squires
|
||||||
- Johannes Stein
|
- Johannes Stein
|
||||||
- Pontus Stenetorp
|
- Pontus Stenetorp
|
||||||
|
15
README.md
15
README.md
@ -123,8 +123,21 @@ information on what to include when reporting a bug.
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
- [Win32] Bugfix: A window created maximized and undecorated would cover the whole
|
||||||
|
monitor (#1806)
|
||||||
|
- [Win32] Bugfix: The default restored window position was lost when creating a maximized
|
||||||
|
window
|
||||||
|
- [Win32] Bugfix: `glfwMaximizeWindow` would make a hidden window visible
|
||||||
- [Cocoa] Bugfix: `kUTTypeURL` was deprecated in macOS 12.0 (#2003)
|
- [Cocoa] Bugfix: `kUTTypeURL` was deprecated in macOS 12.0 (#2003)
|
||||||
- [X11] Bugfix: Dynamic loading on OpenBSD failed due to soname differences
|
- [X11] Bugfix: Dynamic loading on OpenBSD failed due to soname differences
|
||||||
|
- [X11] Bugfix: Waiting for events would fail if file descriptor was too large
|
||||||
|
(#2024)
|
||||||
|
- [X11] Bugfix: Joystick events could lead to busy-waiting (#1872)
|
||||||
|
- [X11] Bugfix: `glfwWaitEvents*` did not continue for joystick events
|
||||||
|
- [X11] Bugfix: `glfwPostEmptyEvent` could be ignored due to race condition
|
||||||
|
(#379,#1281,#1285,#2033)
|
||||||
|
- [X11] Bugfix: Dynamic loading on NetBSD failed due to soname differences
|
||||||
|
- [X11] Bugfix: Left shift of int constant relied on undefined behavior (#1951)
|
||||||
- [Wayland] Added support for key names via xkbcommon
|
- [Wayland] Added support for key names via xkbcommon
|
||||||
- [Wayland] Bugfix: Key repeat could lead to a race condition (#1710)
|
- [Wayland] Bugfix: Key repeat could lead to a race condition (#1710)
|
||||||
- [Wayland] Bugfix: Activating a window would emit two input focus events
|
- [Wayland] Bugfix: Activating a window would emit two input focus events
|
||||||
@ -135,6 +148,8 @@ information on what to include when reporting a bug.
|
|||||||
- [Wayland] Bugfix: Full screen window creation did not ignore `GLFW_VISIBLE`
|
- [Wayland] Bugfix: Full screen window creation did not ignore `GLFW_VISIBLE`
|
||||||
- [Wayland] Bugfix: Some keys were reported as wrong key or `GLFW_KEY_UNKNOWN`
|
- [Wayland] Bugfix: Some keys were reported as wrong key or `GLFW_KEY_UNKNOWN`
|
||||||
- [Wayland] Bugfix: Text input did not repeat along with key repeat
|
- [Wayland] Bugfix: Text input did not repeat along with key repeat
|
||||||
|
- [Wayland] Bugfix: `glfwPostEmptyEvent` sometimes had no effect (#1520,#1521)
|
||||||
|
- [GLX] Bugfix: Context creation failed if GLX 1.4 was not exported by GLX library
|
||||||
|
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
|
@ -68,8 +68,10 @@ install the `xorgproto` package.
|
|||||||
pkg install xorgproto
|
pkg install xorgproto
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
On Cygwin the `xorgproto` package in the Devel section of the GUI installer will
|
On Cygwin the `libXcursor-devel`, `libXi-devel`, `libXinerama-devel`,
|
||||||
install the headers and other development related files for all of X11.
|
`libXrandr-devel` and `libXrender-devel` packages in the Libs section of the GUI
|
||||||
|
installer will install all the headers and other development related files GLFW
|
||||||
|
requires for X11.
|
||||||
|
|
||||||
Once you have the required depdendencies, move on to @ref compile_generate.
|
Once you have the required depdendencies, move on to @ref compile_generate.
|
||||||
|
|
||||||
|
@ -821,7 +821,7 @@ The second value is always the human-readable name of the gamepad.
|
|||||||
All subsequent values are in the form `<field>:<value>` and describe the layout
|
All subsequent values are in the form `<field>:<value>` and describe the layout
|
||||||
of the mapping. These fields may not all be present and may occur in any order.
|
of the mapping. These fields may not all be present and may occur in any order.
|
||||||
|
|
||||||
The button fields are `a`, `b`, `c`, `d`, `back`, `start`, `guide`, `dpup`,
|
The button fields are `a`, `b`, `x`, `y`, `back`, `start`, `guide`, `dpup`,
|
||||||
`dpright`, `dpdown`, `dpleft`, `leftshoulder`, `rightshoulder`, `leftstick` and
|
`dpright`, `dpdown`, `dpleft`, `leftshoulder`, `rightshoulder`, `leftstick` and
|
||||||
`rightstick`.
|
`rightstick`.
|
||||||
|
|
||||||
|
@ -306,6 +306,12 @@ GLFW_TRANSPARENT_FRAMEBUFFER on Windows 7 if DWM transparency is off
|
|||||||
(the Transparency setting under Personalization > Window Color).
|
(the Transparency setting under Personalization > Window Color).
|
||||||
|
|
||||||
|
|
||||||
|
@subsubsection emptyevents_33 Empty events on X11 no longer roundtrip to server
|
||||||
|
|
||||||
|
Starting with GLFW 3.3.7, events posted with @ref glfwPostEmptyEvent now use a separate
|
||||||
|
unnamed pipe instead of sending an X11 client event to the helper window.
|
||||||
|
|
||||||
|
|
||||||
@subsection deprecations_33 Deprecations in version 3.3
|
@subsection deprecations_33 Deprecations in version 3.3
|
||||||
|
|
||||||
@subsubsection charmods_callback_33 Character with modifiers callback
|
@subsubsection charmods_callback_33 Character with modifiers callback
|
||||||
|
@ -320,7 +320,7 @@ GLFWbool _glfwInitEGL(void)
|
|||||||
"libEGL.dylib",
|
"libEGL.dylib",
|
||||||
#elif defined(__CYGWIN__)
|
#elif defined(__CYGWIN__)
|
||||||
"libEGL-1.so",
|
"libEGL-1.so",
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
"libEGL.so",
|
"libEGL.so",
|
||||||
#else
|
#else
|
||||||
"libEGL.so.1",
|
"libEGL.so.1",
|
||||||
@ -643,7 +643,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
"libGLES_CM.dll",
|
"libGLES_CM.dll",
|
||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
"libGLESv1_CM.dylib",
|
"libGLESv1_CM.dylib",
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
"libGLESv1_CM.so",
|
"libGLESv1_CM.so",
|
||||||
#else
|
#else
|
||||||
"libGLESv1_CM.so.1",
|
"libGLESv1_CM.so.1",
|
||||||
@ -662,7 +662,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
"libGLESv2.dylib",
|
"libGLESv2.dylib",
|
||||||
#elif defined(__CYGWIN__)
|
#elif defined(__CYGWIN__)
|
||||||
"libGLESv2-2.so",
|
"libGLESv2-2.so",
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
"libGLESv2.so",
|
"libGLESv2.so",
|
||||||
#else
|
#else
|
||||||
"libGLESv2.so.2",
|
"libGLESv2.so.2",
|
||||||
@ -675,7 +675,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
_GLFW_OPENGL_LIBRARY,
|
_GLFW_OPENGL_LIBRARY,
|
||||||
#elif defined(_GLFW_WIN32)
|
#elif defined(_GLFW_WIN32)
|
||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
"libGL.so",
|
"libGL.so",
|
||||||
#else
|
#else
|
||||||
"libGL.so.1",
|
"libGL.so.1",
|
||||||
|
@ -260,7 +260,7 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
_GLFW_GLX_LIBRARY,
|
_GLFW_GLX_LIBRARY,
|
||||||
#elif defined(__CYGWIN__)
|
#elif defined(__CYGWIN__)
|
||||||
"libGL-1.so",
|
"libGL-1.so",
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
"libGL.so",
|
"libGL.so",
|
||||||
#else
|
#else
|
||||||
"libGL.so.1",
|
"libGL.so.1",
|
||||||
@ -309,10 +309,6 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
_glfw_dlsym(_glfw.glx.handle, "glXCreateWindow");
|
_glfw_dlsym(_glfw.glx.handle, "glXCreateWindow");
|
||||||
_glfw.glx.DestroyWindow =
|
_glfw.glx.DestroyWindow =
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXDestroyWindow");
|
_glfw_dlsym(_glfw.glx.handle, "glXDestroyWindow");
|
||||||
_glfw.glx.GetProcAddress =
|
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXGetProcAddress");
|
|
||||||
_glfw.glx.GetProcAddressARB =
|
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
|
|
||||||
_glfw.glx.GetVisualFromFBConfig =
|
_glfw.glx.GetVisualFromFBConfig =
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
|
_glfw_dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
|
||||||
|
|
||||||
@ -328,8 +324,6 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
!_glfw.glx.CreateNewContext ||
|
!_glfw.glx.CreateNewContext ||
|
||||||
!_glfw.glx.CreateWindow ||
|
!_glfw.glx.CreateWindow ||
|
||||||
!_glfw.glx.DestroyWindow ||
|
!_glfw.glx.DestroyWindow ||
|
||||||
!_glfw.glx.GetProcAddress ||
|
|
||||||
!_glfw.glx.GetProcAddressARB ||
|
|
||||||
!_glfw.glx.GetVisualFromFBConfig)
|
!_glfw.glx.GetVisualFromFBConfig)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
@ -337,6 +331,12 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: Unlike GLX 1.3 entry points these are not required to be present
|
||||||
|
_glfw.glx.GetProcAddress = (PFNGLXGETPROCADDRESSPROC)
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXGetProcAddress");
|
||||||
|
_glfw.glx.GetProcAddressARB = (PFNGLXGETPROCADDRESSPROC)
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
|
||||||
|
|
||||||
if (!glXQueryExtension(_glfw.x11.display,
|
if (!glXQueryExtension(_glfw.x11.display,
|
||||||
&_glfw.glx.errorBase,
|
&_glfw.glx.errorBase,
|
||||||
&_glfw.glx.eventBase))
|
&_glfw.glx.eventBase))
|
||||||
|
@ -124,7 +124,7 @@ GLFWbool _glfwInitOSMesa(void)
|
|||||||
"libOSMesa.8.dylib",
|
"libOSMesa.8.dylib",
|
||||||
#elif defined(__CYGWIN__)
|
#elif defined(__CYGWIN__)
|
||||||
"libOSMesa-8.so",
|
"libOSMesa-8.so",
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
"libOSMesa.so",
|
"libOSMesa.so",
|
||||||
#else
|
#else
|
||||||
"libOSMesa.so.8",
|
"libOSMesa.so.8",
|
||||||
|
@ -59,7 +59,7 @@ GLFWbool _glfwInitVulkan(int mode)
|
|||||||
_glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
|
_glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
|
||||||
if (!_glfw.vk.handle)
|
if (!_glfw.vk.handle)
|
||||||
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS();
|
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS();
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
_glfw.vk.handle = _glfw_dlopen("libvulkan.so");
|
_glfw.vk.handle = _glfw_dlopen("libvulkan.so");
|
||||||
#else
|
#else
|
||||||
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
|
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
|
||||||
|
@ -92,6 +92,8 @@ static GLFWbool loadLibraries(void)
|
|||||||
GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow");
|
GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow");
|
||||||
_glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)
|
_glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)
|
||||||
GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");
|
GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");
|
||||||
|
_glfw.win32.user32.GetSystemMetricsForDpi_ = (PFN_GetSystemMetricsForDpi)
|
||||||
|
GetProcAddress(_glfw.win32.user32.instance, "GetSystemMetricsForDpi");
|
||||||
|
|
||||||
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
|
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
|
||||||
if (_glfw.win32.dinput8.instance)
|
if (_glfw.win32.dinput8.instance)
|
||||||
@ -484,7 +486,7 @@ void _glfwUpdateKeyNamesWin32(void)
|
|||||||
vk = vks[key - GLFW_KEY_KP_0];
|
vk = vks[key - GLFW_KEY_KP_0];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK);
|
vk = MapVirtualKeyW(scancode, MAPVK_VSC_TO_VK);
|
||||||
|
|
||||||
length = ToUnicode(vk, scancode, state,
|
length = ToUnicode(vk, scancode, state,
|
||||||
chars, sizeof(chars) / sizeof(WCHAR),
|
chars, sizeof(chars) / sizeof(WCHAR),
|
||||||
@ -507,7 +509,8 @@ void _glfwUpdateKeyNamesWin32(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replacement for IsWindowsVersionOrGreater as MinGW lacks versionhelpers.h
|
// Replacement for IsWindowsVersionOrGreater, as we cannot rely on the
|
||||||
|
// application having a correct embedded manifest
|
||||||
//
|
//
|
||||||
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp)
|
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp)
|
||||||
{
|
{
|
||||||
|
@ -497,7 +497,7 @@ void _glfwInitJoysticksWin32(void)
|
|||||||
{
|
{
|
||||||
if (_glfw.win32.dinput8.instance)
|
if (_glfw.win32.dinput8.instance)
|
||||||
{
|
{
|
||||||
if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
|
if (FAILED(DirectInput8Create(GetModuleHandleW(NULL),
|
||||||
DIRECTINPUT_VERSION,
|
DIRECTINPUT_VERSION,
|
||||||
&IID_IDirectInput8W,
|
&IID_IDirectInput8W,
|
||||||
(void**) &_glfw.win32.dinput8.api,
|
(void**) &_glfw.win32.dinput8.api,
|
||||||
|
@ -382,7 +382,7 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
|
|||||||
int* width, int* height)
|
int* width, int* height)
|
||||||
{
|
{
|
||||||
MONITORINFO mi = { sizeof(mi) };
|
MONITORINFO mi = { sizeof(mi) };
|
||||||
GetMonitorInfo(monitor->win32.handle, &mi);
|
GetMonitorInfoW(monitor->win32.handle, &mi);
|
||||||
|
|
||||||
if (xpos)
|
if (xpos)
|
||||||
*xpos = mi.rcWork.left;
|
*xpos = mi.rcWork.left;
|
||||||
|
@ -162,7 +162,9 @@ typedef enum
|
|||||||
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE) -4)
|
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE) -4)
|
||||||
#endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/
|
#endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/
|
||||||
|
|
||||||
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
|
// Replacement for versionhelpers.h macros, as we cannot rely on the
|
||||||
|
// application having a correct embedded manifest
|
||||||
|
//
|
||||||
#define IsWindowsXPOrGreater() \
|
#define IsWindowsXPOrGreater() \
|
||||||
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINXP), \
|
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINXP), \
|
||||||
LOBYTE(_WIN32_WINNT_WINXP), 0)
|
LOBYTE(_WIN32_WINNT_WINXP), 0)
|
||||||
@ -235,12 +237,14 @@ typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND);
|
|||||||
typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE);
|
typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE);
|
||||||
typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
|
typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
|
||||||
typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
|
typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
|
||||||
|
typedef int (WINAPI * PFN_GetSystemMetricsForDpi)(int,UINT);
|
||||||
#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
|
#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
|
||||||
#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
|
#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
|
||||||
#define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
|
#define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
|
||||||
#define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_
|
#define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_
|
||||||
#define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_
|
#define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_
|
||||||
#define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_
|
#define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_
|
||||||
|
#define GetSystemMetricsForDpi _glfw.win32.user32.GetSystemMetricsForDpi_
|
||||||
|
|
||||||
// dwmapi.dll function pointer typedefs
|
// dwmapi.dll function pointer typedefs
|
||||||
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
||||||
@ -366,6 +370,7 @@ typedef struct _GLFWlibraryWin32
|
|||||||
PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
|
PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
|
||||||
PFN_GetDpiForWindow GetDpiForWindow_;
|
PFN_GetDpiForWindow GetDpiForWindow_;
|
||||||
PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi_;
|
PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi_;
|
||||||
|
PFN_GetSystemMetricsForDpi GetSystemMetricsForDpi_;
|
||||||
} user32;
|
} user32;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -435,7 +435,7 @@ static int getKeyMods(void)
|
|||||||
static void fitToMonitor(_GLFWwindow* window)
|
static void fitToMonitor(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
MONITORINFO mi = { sizeof(mi) };
|
MONITORINFO mi = { sizeof(mi) };
|
||||||
GetMonitorInfo(window->monitor->win32.handle, &mi);
|
GetMonitorInfoW(window->monitor->win32.handle, &mi);
|
||||||
SetWindowPos(window->win32.handle, HWND_TOPMOST,
|
SetWindowPos(window->win32.handle, HWND_TOPMOST,
|
||||||
mi.rcMonitor.left,
|
mi.rcMonitor.left,
|
||||||
mi.rcMonitor.top,
|
mi.rcMonitor.top,
|
||||||
@ -456,8 +456,8 @@ static void acquireMonitor(_GLFWwindow* window)
|
|||||||
// the OpenGL ICD switches to page flipping
|
// the OpenGL ICD switches to page flipping
|
||||||
if (IsWindowsXPOrGreater())
|
if (IsWindowsXPOrGreater())
|
||||||
{
|
{
|
||||||
SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
|
SystemParametersInfoW(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
|
||||||
SystemParametersInfo(SPI_SETMOUSETRAILS, 0, 0, 0);
|
SystemParametersInfoW(SPI_SETMOUSETRAILS, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,13 +482,66 @@ static void releaseMonitor(_GLFWwindow* window)
|
|||||||
|
|
||||||
// HACK: Restore mouse trail length saved in acquireMonitor
|
// HACK: Restore mouse trail length saved in acquireMonitor
|
||||||
if (IsWindowsXPOrGreater())
|
if (IsWindowsXPOrGreater())
|
||||||
SystemParametersInfo(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
|
SystemParametersInfoW(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwInputMonitorWindow(window->monitor, NULL);
|
_glfwInputMonitorWindow(window->monitor, NULL);
|
||||||
_glfwRestoreVideoModeWin32(window->monitor);
|
_glfwRestoreVideoModeWin32(window->monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Manually maximize the window, for when SW_MAXIMIZE cannot be used
|
||||||
|
//
|
||||||
|
static void maximizeWindowManually(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
RECT rect;
|
||||||
|
DWORD style;
|
||||||
|
MONITORINFO mi = { sizeof(mi) };
|
||||||
|
|
||||||
|
GetMonitorInfoW(MonitorFromWindow(window->win32.handle,
|
||||||
|
MONITOR_DEFAULTTONEAREST), &mi);
|
||||||
|
|
||||||
|
rect = mi.rcWork;
|
||||||
|
|
||||||
|
if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
if (rect.right - rect.left > window->maxwidth)
|
||||||
|
rect.right = rect.left + window->maxwidth;
|
||||||
|
if (rect.bottom - rect.top > window->maxheight)
|
||||||
|
rect.bottom = rect.top + window->maxheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
style = GetWindowLongW(window->win32.handle, GWL_STYLE);
|
||||||
|
style |= WS_MAXIMIZE;
|
||||||
|
SetWindowLongW(window->win32.handle, GWL_STYLE, style);
|
||||||
|
|
||||||
|
if (window->decorated)
|
||||||
|
{
|
||||||
|
const DWORD exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
|
||||||
|
|
||||||
|
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
|
||||||
|
{
|
||||||
|
const UINT dpi = GetDpiForWindow(window->win32.handle);
|
||||||
|
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
|
||||||
|
OffsetRect(&rect, 0, GetSystemMetricsForDpi(SM_CYCAPTION, dpi));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
|
||||||
|
OffsetRect(&rect, 0, GetSystemMetrics(SM_CYCAPTION));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rect.bottom > mi.rcWork.bottom)
|
||||||
|
rect.bottom = mi.rcWork.bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWindowPos(window->win32.handle, HWND_TOP,
|
||||||
|
rect.left,
|
||||||
|
rect.top,
|
||||||
|
rect.right - rect.left,
|
||||||
|
rect.bottom - rect.top,
|
||||||
|
SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
// Window callback function (handles window messages)
|
// Window callback function (handles window messages)
|
||||||
//
|
//
|
||||||
static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||||
@ -1067,7 +1120,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
|
|
||||||
ZeroMemory(&mi, sizeof(mi));
|
ZeroMemory(&mi, sizeof(mi));
|
||||||
mi.cbSize = sizeof(mi);
|
mi.cbSize = sizeof(mi);
|
||||||
GetMonitorInfo(mh, &mi);
|
GetMonitorInfoW(mh, &mi);
|
||||||
|
|
||||||
mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left;
|
mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left;
|
||||||
mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top;
|
mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top;
|
||||||
@ -1285,18 +1338,22 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||||||
|
|
||||||
window->win32.scaleToMonitor = wndconfig->scaleToMonitor;
|
window->win32.scaleToMonitor = wndconfig->scaleToMonitor;
|
||||||
|
|
||||||
// Adjust window rect to account for DPI scaling of the window frame and
|
|
||||||
// (if enabled) DPI scaling of the content area
|
|
||||||
// This cannot be done until we know what monitor the window was placed on
|
|
||||||
if (!window->monitor)
|
if (!window->monitor)
|
||||||
{
|
{
|
||||||
RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
|
RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
|
||||||
WINDOWPLACEMENT wp = { sizeof(wp) };
|
WINDOWPLACEMENT wp = { sizeof(wp) };
|
||||||
|
const HMONITOR mh = MonitorFromWindow(window->win32.handle,
|
||||||
|
MONITOR_DEFAULTTONEAREST);
|
||||||
|
|
||||||
|
// Adjust window rect to account for DPI scaling of the window frame and
|
||||||
|
// (if enabled) DPI scaling of the content area
|
||||||
|
// This cannot be done until we know what monitor the window was placed on
|
||||||
|
// Only update the restored window rect as the window may be maximized
|
||||||
|
|
||||||
if (wndconfig->scaleToMonitor)
|
if (wndconfig->scaleToMonitor)
|
||||||
{
|
{
|
||||||
float xscale, yscale;
|
float xscale, yscale;
|
||||||
_glfwPlatformGetWindowContentScale(window, &xscale, &yscale);
|
_glfwGetMonitorContentScaleWin32(mh, &xscale, &yscale);
|
||||||
|
|
||||||
if (xscale > 0.f && yscale > 0.f)
|
if (xscale > 0.f && yscale > 0.f)
|
||||||
{
|
{
|
||||||
@ -1305,9 +1362,6 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientToScreen(window->win32.handle, (POINT*) &rect.left);
|
|
||||||
ClientToScreen(window->win32.handle, (POINT*) &rect.right);
|
|
||||||
|
|
||||||
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
|
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
|
||||||
{
|
{
|
||||||
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
|
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
|
||||||
@ -1316,11 +1370,30 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||||||
else
|
else
|
||||||
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
|
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
|
||||||
|
|
||||||
// Only update the restored window rect as the window may be maximized
|
|
||||||
GetWindowPlacement(window->win32.handle, &wp);
|
GetWindowPlacement(window->win32.handle, &wp);
|
||||||
|
OffsetRect(&rect,
|
||||||
|
wp.rcNormalPosition.left - rect.left,
|
||||||
|
wp.rcNormalPosition.top - rect.top);
|
||||||
|
|
||||||
wp.rcNormalPosition = rect;
|
wp.rcNormalPosition = rect;
|
||||||
wp.showCmd = SW_HIDE;
|
wp.showCmd = SW_HIDE;
|
||||||
SetWindowPlacement(window->win32.handle, &wp);
|
SetWindowPlacement(window->win32.handle, &wp);
|
||||||
|
|
||||||
|
// Adjust rect of maximized undecorated window, because by default Windows will
|
||||||
|
// make such a window cover the whole monitor instead of its workarea
|
||||||
|
|
||||||
|
if (wndconfig->maximized && !wndconfig->decorated)
|
||||||
|
{
|
||||||
|
MONITORINFO mi = { sizeof(mi) };
|
||||||
|
GetMonitorInfoW(mh, &mi);
|
||||||
|
|
||||||
|
SetWindowPos(window->win32.handle, HWND_TOP,
|
||||||
|
mi.rcWork.left,
|
||||||
|
mi.rcWork.top,
|
||||||
|
mi.rcWork.right - mi.rcWork.left,
|
||||||
|
mi.rcWork.bottom - mi.rcWork.top,
|
||||||
|
SWP_NOACTIVATE | SWP_NOZORDER);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DragAcceptFiles(window->win32.handle, TRUE);
|
DragAcceptFiles(window->win32.handle, TRUE);
|
||||||
@ -1491,8 +1564,8 @@ void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
|||||||
smallIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICONSM);
|
smallIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICONSM);
|
||||||
}
|
}
|
||||||
|
|
||||||
SendMessage(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon);
|
SendMessageW(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon);
|
||||||
SendMessage(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon);
|
SendMessageW(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon);
|
||||||
|
|
||||||
if (window->win32.bigIcon)
|
if (window->win32.bigIcon)
|
||||||
DestroyIcon(window->win32.bigIcon);
|
DestroyIcon(window->win32.bigIcon);
|
||||||
@ -1672,7 +1745,10 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
ShowWindow(window->win32.handle, SW_MAXIMIZE);
|
if (IsWindowVisible(window->win32.handle))
|
||||||
|
ShowWindow(window->win32.handle, SW_MAXIMIZE);
|
||||||
|
else
|
||||||
|
maximizeWindowManually(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||||
@ -1759,7 +1835,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
|||||||
|
|
||||||
acquireMonitor(window);
|
acquireMonitor(window);
|
||||||
|
|
||||||
GetMonitorInfo(window->monitor->win32.handle, &mi);
|
GetMonitorInfoW(window->monitor->win32.handle, &mi);
|
||||||
SetWindowPos(window->win32.handle, HWND_TOPMOST,
|
SetWindowPos(window->win32.handle, HWND_TOPMOST,
|
||||||
mi.rcMonitor.left,
|
mi.rcMonitor.left,
|
||||||
mi.rcMonitor.top,
|
mi.rcMonitor.top,
|
||||||
@ -2023,7 +2099,7 @@ void _glfwPlatformWaitEventsTimeout(double timeout)
|
|||||||
|
|
||||||
void _glfwPlatformPostEmptyEvent(void)
|
void _glfwPlatformPostEmptyEvent(void)
|
||||||
{
|
{
|
||||||
PostMessage(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0);
|
PostMessageW(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||||
@ -2278,7 +2354,7 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
|||||||
|
|
||||||
memset(&sci, 0, sizeof(sci));
|
memset(&sci, 0, sizeof(sci));
|
||||||
sci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
sci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
||||||
sci.hinstance = GetModuleHandle(NULL);
|
sci.hinstance = GetModuleHandleW(NULL);
|
||||||
sci.hwnd = window->win32.handle;
|
sci.hwnd = window->win32.handle;
|
||||||
|
|
||||||
err = vkCreateWin32SurfaceKHR(instance, &sci, allocator, surface);
|
err = vkCreateWin32SurfaceKHR(instance, &sci, allocator, surface);
|
||||||
|
@ -1195,14 +1195,15 @@ int _glfwPlatformInit(void)
|
|||||||
wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager,
|
wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager,
|
||||||
_glfw.wl.seat);
|
_glfw.wl.seat);
|
||||||
wl_data_device_add_listener(_glfw.wl.dataDevice, &dataDeviceListener, NULL);
|
wl_data_device_add_listener(_glfw.wl.dataDevice, &dataDeviceListener, NULL);
|
||||||
_glfw.wl.clipboardString = malloc(4096);
|
|
||||||
|
_glfw.wl.clipboardSize = 4096;
|
||||||
|
_glfw.wl.clipboardString = calloc(_glfw.wl.clipboardSize, 1);
|
||||||
if (!_glfw.wl.clipboardString)
|
if (!_glfw.wl.clipboardString)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_OUT_OF_MEMORY,
|
||||||
"Wayland: Unable to allocate clipboard memory");
|
"Wayland: Unable to allocate clipboard memory");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
_glfw.wl.clipboardSize = 4096;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
@ -1293,10 +1294,8 @@ void _glfwPlatformTerminate(void)
|
|||||||
if (_glfw.wl.cursorTimerfd >= 0)
|
if (_glfw.wl.cursorTimerfd >= 0)
|
||||||
close(_glfw.wl.cursorTimerfd);
|
close(_glfw.wl.cursorTimerfd);
|
||||||
|
|
||||||
if (_glfw.wl.clipboardString)
|
free(_glfw.wl.clipboardString);
|
||||||
free(_glfw.wl.clipboardString);
|
free(_glfw.wl.clipboardSendString);
|
||||||
if (_glfw.wl.clipboardSendString)
|
|
||||||
free(_glfw.wl.clipboardSendString);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
|
153
src/wl_window.c
153
src/wl_window.c
@ -39,7 +39,8 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/timerfd.h>
|
#include <sys/timerfd.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
static void shellSurfaceHandlePing(void* data,
|
static void shellSurfaceHandlePing(void* data,
|
||||||
struct wl_shell_surface* shellSurface,
|
struct wl_shell_surface* shellSurface,
|
||||||
@ -248,6 +249,53 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait for data to arrive on any of the specified file descriptors
|
||||||
|
//
|
||||||
|
static GLFWbool waitForData(struct pollfd* fds, nfds_t count, double* timeout)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (timeout)
|
||||||
|
{
|
||||||
|
const uint64_t base = _glfwPlatformGetTimerValue();
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__)
|
||||||
|
const time_t seconds = (time_t) *timeout;
|
||||||
|
const long nanoseconds = (long) ((*timeout - seconds) * 1e9);
|
||||||
|
const struct timespec ts = { seconds, nanoseconds };
|
||||||
|
const int result = ppoll(fds, count, &ts, NULL);
|
||||||
|
#elif defined(__NetBSD__)
|
||||||
|
const time_t seconds = (time_t) *timeout;
|
||||||
|
const long nanoseconds = (long) ((*timeout - seconds) * 1e9);
|
||||||
|
const struct timespec ts = { seconds, nanoseconds };
|
||||||
|
const int result = pollts(fds, count, &ts, NULL);
|
||||||
|
#else
|
||||||
|
const int milliseconds = (int) (*timeout * 1e3);
|
||||||
|
const int result = poll(fds, count, milliseconds);
|
||||||
|
#endif
|
||||||
|
const int error = errno; // clock_gettime may overwrite our error
|
||||||
|
|
||||||
|
*timeout -= (_glfwPlatformGetTimerValue() - base) /
|
||||||
|
(double) _glfwPlatformGetTimerFrequency();
|
||||||
|
|
||||||
|
if (result > 0)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
else if (result == -1 && error != EINTR && error != EAGAIN)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
else if (*timeout <= 0.0)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const int result = poll(fds, count, -1);
|
||||||
|
if (result > 0)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
else if (result == -1 && errno != EINTR && errno != EAGAIN)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void createDecoration(_GLFWdecorationWayland* decoration,
|
static void createDecoration(_GLFWdecorationWayland* decoration,
|
||||||
struct wl_surface* parent,
|
struct wl_surface* parent,
|
||||||
struct wl_buffer* buffer, GLFWbool opaque,
|
struct wl_buffer* buffer, GLFWbool opaque,
|
||||||
@ -404,27 +452,25 @@ static void resizeWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
static void checkScaleChange(_GLFWwindow* window)
|
static void checkScaleChange(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
int scale = 1;
|
|
||||||
int i;
|
|
||||||
int monitorScale;
|
|
||||||
|
|
||||||
// Check if we will be able to set the buffer scale or not.
|
// Check if we will be able to set the buffer scale or not.
|
||||||
if (_glfw.wl.compositorVersion < 3)
|
if (_glfw.wl.compositorVersion < 3)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Get the scale factor from the highest scale monitor.
|
// Get the scale factor from the highest scale monitor.
|
||||||
for (i = 0; i < window->wl.monitorsCount; ++i)
|
int maxScale = 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < window->wl.monitorsCount; i++)
|
||||||
{
|
{
|
||||||
monitorScale = window->wl.monitors[i]->wl.scale;
|
const int scale = window->wl.monitors[i]->wl.scale;
|
||||||
if (scale < monitorScale)
|
if (maxScale < scale)
|
||||||
scale = monitorScale;
|
maxScale = scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only change the framebuffer size if the scale changed.
|
// Only change the framebuffer size if the scale changed.
|
||||||
if (scale != window->wl.scale)
|
if (window->wl.scale != maxScale)
|
||||||
{
|
{
|
||||||
window->wl.scale = scale;
|
window->wl.scale = maxScale;
|
||||||
wl_surface_set_buffer_scale(window->wl.surface, scale);
|
wl_surface_set_buffer_scale(window->wl.surface, maxScale);
|
||||||
resizeWindow(window);
|
resizeWindow(window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -833,8 +879,28 @@ static void incrementCursorImage(_GLFWwindow* window)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleEvents(int timeout)
|
static GLFWbool flushDisplay(void)
|
||||||
{
|
{
|
||||||
|
while (wl_display_flush(_glfw.wl.display) == -1)
|
||||||
|
{
|
||||||
|
if (errno != EAGAIN)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
struct pollfd fd = { wl_display_get_fd(_glfw.wl.display), POLLOUT };
|
||||||
|
|
||||||
|
while (poll(&fd, 1, -1) == -1)
|
||||||
|
{
|
||||||
|
if (errno != EINTR && errno != EAGAIN)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleEvents(double* timeout)
|
||||||
|
{
|
||||||
|
GLFWbool event = GLFW_FALSE;
|
||||||
struct pollfd fds[] =
|
struct pollfd fds[] =
|
||||||
{
|
{
|
||||||
{ wl_display_get_fd(_glfw.wl.display), POLLIN },
|
{ wl_display_get_fd(_glfw.wl.display), POLLIN },
|
||||||
@ -842,30 +908,38 @@ static void handleEvents(int timeout)
|
|||||||
{ _glfw.wl.cursorTimerfd, POLLIN },
|
{ _glfw.wl.cursorTimerfd, POLLIN },
|
||||||
};
|
};
|
||||||
|
|
||||||
while (wl_display_prepare_read(_glfw.wl.display) != 0)
|
while (!event)
|
||||||
wl_display_dispatch_pending(_glfw.wl.display);
|
|
||||||
|
|
||||||
// If an error other than EAGAIN happens, we have likely been disconnected
|
|
||||||
// from the Wayland session; try to handle that the best we can.
|
|
||||||
if (wl_display_flush(_glfw.wl.display) < 0 && errno != EAGAIN)
|
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfw.windowListHead;
|
while (wl_display_prepare_read(_glfw.wl.display) != 0)
|
||||||
while (window)
|
wl_display_dispatch_pending(_glfw.wl.display);
|
||||||
|
|
||||||
|
// If an error other than EAGAIN happens, we have likely been disconnected
|
||||||
|
// from the Wayland session; try to handle that the best we can.
|
||||||
|
if (!flushDisplay())
|
||||||
{
|
{
|
||||||
_glfwInputWindowCloseRequest(window);
|
wl_display_cancel_read(_glfw.wl.display);
|
||||||
window = window->next;
|
|
||||||
|
_GLFWwindow* window = _glfw.windowListHead;
|
||||||
|
while (window)
|
||||||
|
{
|
||||||
|
_glfwInputWindowCloseRequest(window);
|
||||||
|
window = window->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_display_cancel_read(_glfw.wl.display);
|
if (!waitForData(fds, 3, timeout))
|
||||||
return;
|
{
|
||||||
}
|
wl_display_cancel_read(_glfw.wl.display);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (poll(fds, 3, timeout) > 0)
|
|
||||||
{
|
|
||||||
if (fds[0].revents & POLLIN)
|
if (fds[0].revents & POLLIN)
|
||||||
{
|
{
|
||||||
wl_display_read_events(_glfw.wl.display);
|
wl_display_read_events(_glfw.wl.display);
|
||||||
wl_display_dispatch_pending(_glfw.wl.display);
|
if (wl_display_dispatch_pending(_glfw.wl.display) > 0)
|
||||||
|
event = GLFW_TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
wl_display_cancel_read(_glfw.wl.display);
|
wl_display_cancel_read(_glfw.wl.display);
|
||||||
@ -886,6 +960,8 @@ static void handleEvents(int timeout)
|
|||||||
_glfwInputTextWayland(_glfw.wl.keyboardFocus,
|
_glfwInputTextWayland(_glfw.wl.keyboardFocus,
|
||||||
_glfw.wl.keyboardLastScancode);
|
_glfw.wl.keyboardLastScancode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event = GLFW_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -894,11 +970,12 @@ static void handleEvents(int timeout)
|
|||||||
uint64_t repeats;
|
uint64_t repeats;
|
||||||
|
|
||||||
if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8)
|
if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8)
|
||||||
|
{
|
||||||
incrementCursorImage(_glfw.wl.pointerFocus);
|
incrementCursorImage(_glfw.wl.pointerFocus);
|
||||||
|
event = GLFW_TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
wl_display_cancel_read(_glfw.wl.display);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@ -1288,22 +1365,24 @@ GLFWbool _glfwPlatformRawMouseMotionSupported(void)
|
|||||||
|
|
||||||
void _glfwPlatformPollEvents(void)
|
void _glfwPlatformPollEvents(void)
|
||||||
{
|
{
|
||||||
handleEvents(0);
|
double timeout = 0.0;
|
||||||
|
handleEvents(&timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformWaitEvents(void)
|
void _glfwPlatformWaitEvents(void)
|
||||||
{
|
{
|
||||||
handleEvents(-1);
|
handleEvents(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformWaitEventsTimeout(double timeout)
|
void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||||
{
|
{
|
||||||
handleEvents((int) (timeout * 1e3));
|
handleEvents(&timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformPostEmptyEvent(void)
|
void _glfwPlatformPostEmptyEvent(void)
|
||||||
{
|
{
|
||||||
wl_display_sync(_glfw.wl.display);
|
wl_display_sync(_glfw.wl.display);
|
||||||
|
flushDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||||
@ -1793,7 +1872,7 @@ static GLFWbool growClipboardString(void)
|
|||||||
clipboard = realloc(clipboard, _glfw.wl.clipboardSize * 2);
|
clipboard = realloc(clipboard, _glfw.wl.clipboardSize * 2);
|
||||||
if (!clipboard)
|
if (!clipboard)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_OUT_OF_MEMORY,
|
||||||
"Wayland: Impossible to grow clipboard string");
|
"Wayland: Impossible to grow clipboard string");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
@ -1828,9 +1907,9 @@ const char* _glfwPlatformGetClipboardString(void)
|
|||||||
close(fds[1]);
|
close(fds[1]);
|
||||||
|
|
||||||
// XXX: this is a huge hack, this function shouldn’t be synchronous!
|
// XXX: this is a huge hack, this function shouldn’t be synchronous!
|
||||||
handleEvents(-1);
|
handleEvents(NULL);
|
||||||
|
|
||||||
while (1)
|
for (;;)
|
||||||
{
|
{
|
||||||
// Grow the clipboard if we need to paste something bigger, there is no
|
// Grow the clipboard if we need to paste something bigger, there is no
|
||||||
// shrink operation yet.
|
// shrink operation yet.
|
||||||
|
@ -36,6 +36,9 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
// Translate the X11 KeySyms for a key to a GLFW key code
|
// Translate the X11 KeySyms for a key to a GLFW key code
|
||||||
@ -568,7 +571,7 @@ static void detectEWMH(void)
|
|||||||
//
|
//
|
||||||
static GLFWbool initExtensions(void)
|
static GLFWbool initExtensions(void)
|
||||||
{
|
{
|
||||||
#if defined(__OpenBSD__)
|
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
_glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so");
|
_glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so");
|
||||||
#else
|
#else
|
||||||
_glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1");
|
_glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1");
|
||||||
@ -592,7 +595,7 @@ static GLFWbool initExtensions(void)
|
|||||||
|
|
||||||
#if defined(__CYGWIN__)
|
#if defined(__CYGWIN__)
|
||||||
_glfw.x11.xi.handle = _glfw_dlopen("libXi-6.so");
|
_glfw.x11.xi.handle = _glfw_dlopen("libXi-6.so");
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
_glfw.x11.xi.handle = _glfw_dlopen("libXi.so");
|
_glfw.x11.xi.handle = _glfw_dlopen("libXi.so");
|
||||||
#else
|
#else
|
||||||
_glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6");
|
_glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6");
|
||||||
@ -624,7 +627,7 @@ static GLFWbool initExtensions(void)
|
|||||||
|
|
||||||
#if defined(__CYGWIN__)
|
#if defined(__CYGWIN__)
|
||||||
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr-2.so");
|
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr-2.so");
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so");
|
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so");
|
||||||
#else
|
#else
|
||||||
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2");
|
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2");
|
||||||
@ -718,7 +721,7 @@ static GLFWbool initExtensions(void)
|
|||||||
|
|
||||||
#if defined(__CYGWIN__)
|
#if defined(__CYGWIN__)
|
||||||
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor-1.so");
|
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor-1.so");
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so");
|
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so");
|
||||||
#else
|
#else
|
||||||
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1");
|
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1");
|
||||||
@ -741,7 +744,7 @@ static GLFWbool initExtensions(void)
|
|||||||
|
|
||||||
#if defined(__CYGWIN__)
|
#if defined(__CYGWIN__)
|
||||||
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama-1.so");
|
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama-1.so");
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so");
|
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so");
|
||||||
#else
|
#else
|
||||||
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1");
|
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1");
|
||||||
@ -794,7 +797,7 @@ static GLFWbool initExtensions(void)
|
|||||||
|
|
||||||
#if defined(__CYGWIN__)
|
#if defined(__CYGWIN__)
|
||||||
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb-1.so");
|
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb-1.so");
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so");
|
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so");
|
||||||
#else
|
#else
|
||||||
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1");
|
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1");
|
||||||
@ -807,7 +810,7 @@ static GLFWbool initExtensions(void)
|
|||||||
|
|
||||||
#if defined(__CYGWIN__)
|
#if defined(__CYGWIN__)
|
||||||
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender-1.so");
|
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender-1.so");
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so");
|
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so");
|
||||||
#else
|
#else
|
||||||
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1");
|
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1");
|
||||||
@ -974,6 +977,37 @@ static Window createHelperWindow(void)
|
|||||||
CWEventMask, &wa);
|
CWEventMask, &wa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the pipe for empty events without assumuing the OS has pipe2(2)
|
||||||
|
//
|
||||||
|
static GLFWbool createEmptyEventPipe(void)
|
||||||
|
{
|
||||||
|
if (pipe(_glfw.x11.emptyEventPipe) != 0)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"X11: Failed to create empty event pipe: %s",
|
||||||
|
strerror(errno));
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
const int sf = fcntl(_glfw.x11.emptyEventPipe[i], F_GETFL, 0);
|
||||||
|
const int df = fcntl(_glfw.x11.emptyEventPipe[i], F_GETFD, 0);
|
||||||
|
|
||||||
|
if (sf == -1 || df == -1 ||
|
||||||
|
fcntl(_glfw.x11.emptyEventPipe[i], F_SETFL, sf | O_NONBLOCK) == -1 ||
|
||||||
|
fcntl(_glfw.x11.emptyEventPipe[i], F_SETFD, df | FD_CLOEXEC) == -1)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"X11: Failed to set flags for empty event pipe: %s",
|
||||||
|
strerror(errno));
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
// X error handler
|
// X error handler
|
||||||
//
|
//
|
||||||
static int errorHandler(Display *display, XErrorEvent* event)
|
static int errorHandler(Display *display, XErrorEvent* event)
|
||||||
@ -1095,6 +1129,9 @@ int _glfwPlatformInit(void)
|
|||||||
|
|
||||||
getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY);
|
getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY);
|
||||||
|
|
||||||
|
if (!createEmptyEventPipe())
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
if (!initExtensions())
|
if (!initExtensions())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
@ -1212,6 +1249,12 @@ void _glfwPlatformTerminate(void)
|
|||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
_glfwTerminateJoysticksLinux();
|
_glfwTerminateJoysticksLinux();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (_glfw.x11.emptyEventPipe[0] || _glfw.x11.emptyEventPipe[1])
|
||||||
|
{
|
||||||
|
close(_glfw.x11.emptyEventPipe[0]);
|
||||||
|
close(_glfw.x11.emptyEventPipe[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
|
@ -244,6 +244,7 @@ typedef struct _GLFWlibraryX11
|
|||||||
double restoreCursorPosX, restoreCursorPosY;
|
double restoreCursorPosX, restoreCursorPosY;
|
||||||
// The window whose disabled cursor mode is active
|
// The window whose disabled cursor mode is active
|
||||||
_GLFWwindow* disabledCursorWindow;
|
_GLFWwindow* disabledCursorWindow;
|
||||||
|
int emptyEventPipe[2];
|
||||||
|
|
||||||
// Window manager atoms
|
// Window manager atoms
|
||||||
Atom NET_SUPPORTED;
|
Atom NET_SUPPORTED;
|
||||||
|
173
src/x11_window.c
173
src/x11_window.c
@ -27,12 +27,16 @@
|
|||||||
// It is fine to use C99 in this file because it will not be built with VS
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#include <X11/cursorfont.h>
|
#include <X11/cursorfont.h>
|
||||||
#include <X11/Xmd.h>
|
#include <X11/Xmd.h>
|
||||||
|
|
||||||
#include <sys/select.h>
|
#include <poll.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -56,50 +60,126 @@
|
|||||||
|
|
||||||
#define _GLFW_XDND_VERSION 5
|
#define _GLFW_XDND_VERSION 5
|
||||||
|
|
||||||
|
// Wait for data to arrive on any of the specified file descriptors
|
||||||
// Wait for data to arrive using select
|
|
||||||
// This avoids blocking other threads via the per-display Xlib lock that also
|
|
||||||
// covers GLX functions
|
|
||||||
//
|
//
|
||||||
static GLFWbool waitForEvent(double* timeout)
|
static GLFWbool waitForData(struct pollfd* fds, nfds_t count, double* timeout)
|
||||||
{
|
{
|
||||||
fd_set fds;
|
|
||||||
const int fd = ConnectionNumber(_glfw.x11.display);
|
|
||||||
int count = fd + 1;
|
|
||||||
|
|
||||||
#if defined(__linux__)
|
|
||||||
if (_glfw.linjs.inotify > fd)
|
|
||||||
count = _glfw.linjs.inotify + 1;
|
|
||||||
#endif
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
FD_ZERO(&fds);
|
|
||||||
FD_SET(fd, &fds);
|
|
||||||
#if defined(__linux__)
|
|
||||||
if (_glfw.linjs.inotify > 0)
|
|
||||||
FD_SET(_glfw.linjs.inotify, &fds);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (timeout)
|
if (timeout)
|
||||||
{
|
{
|
||||||
const long seconds = (long) *timeout;
|
|
||||||
const long microseconds = (long) ((*timeout - seconds) * 1e6);
|
|
||||||
struct timeval tv = { seconds, microseconds };
|
|
||||||
const uint64_t base = _glfwPlatformGetTimerValue();
|
const uint64_t base = _glfwPlatformGetTimerValue();
|
||||||
|
|
||||||
const int result = select(count, &fds, NULL, NULL, &tv);
|
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__)
|
||||||
const int error = errno;
|
const time_t seconds = (time_t) *timeout;
|
||||||
|
const long nanoseconds = (long) ((*timeout - seconds) * 1e9);
|
||||||
|
const struct timespec ts = { seconds, nanoseconds };
|
||||||
|
const int result = ppoll(fds, count, &ts, NULL);
|
||||||
|
#elif defined(__NetBSD__)
|
||||||
|
const time_t seconds = (time_t) *timeout;
|
||||||
|
const long nanoseconds = (long) ((*timeout - seconds) * 1e9);
|
||||||
|
const struct timespec ts = { seconds, nanoseconds };
|
||||||
|
const int result = pollts(fds, count, &ts, NULL);
|
||||||
|
#else
|
||||||
|
const int milliseconds = (int) (*timeout * 1e3);
|
||||||
|
const int result = poll(fds, count, milliseconds);
|
||||||
|
#endif
|
||||||
|
const int error = errno; // clock_gettime may overwrite our error
|
||||||
|
|
||||||
*timeout -= (_glfwPlatformGetTimerValue() - base) /
|
*timeout -= (_glfwPlatformGetTimerValue() - base) /
|
||||||
(double) _glfwPlatformGetTimerFrequency();
|
(double) _glfwPlatformGetTimerFrequency();
|
||||||
|
|
||||||
if (result > 0)
|
if (result > 0)
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
if ((result == -1 && error == EINTR) || *timeout <= 0.0)
|
else if (result == -1 && error != EINTR && error != EAGAIN)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
else if (*timeout <= 0.0)
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
else if (select(count, &fds, NULL, NULL, NULL) != -1 || errno != EINTR)
|
else
|
||||||
return GLFW_TRUE;
|
{
|
||||||
|
const int result = poll(fds, count, -1);
|
||||||
|
if (result > 0)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
else if (result == -1 && errno != EINTR && errno != EAGAIN)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for event data to arrive on the X11 display socket
|
||||||
|
// This avoids blocking other threads via the per-display Xlib lock that also
|
||||||
|
// covers GLX functions
|
||||||
|
//
|
||||||
|
static GLFWbool waitForX11Event(double* timeout)
|
||||||
|
{
|
||||||
|
struct pollfd fd = { ConnectionNumber(_glfw.x11.display), POLLIN };
|
||||||
|
|
||||||
|
while (!XPending(_glfw.x11.display))
|
||||||
|
{
|
||||||
|
if (!waitForData(&fd, 1, timeout))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for event data to arrive on any event file descriptor
|
||||||
|
// This avoids blocking other threads via the per-display Xlib lock that also
|
||||||
|
// covers GLX functions
|
||||||
|
//
|
||||||
|
static GLFWbool waitForAnyEvent(double* timeout)
|
||||||
|
{
|
||||||
|
nfds_t count = 2;
|
||||||
|
struct pollfd fds[3] =
|
||||||
|
{
|
||||||
|
{ ConnectionNumber(_glfw.x11.display), POLLIN },
|
||||||
|
{ _glfw.x11.emptyEventPipe[0], POLLIN }
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
if (_glfw.linjs.inotify > 0)
|
||||||
|
fds[count++] = (struct pollfd) { _glfw.linjs.inotify, POLLIN };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (!XPending(_glfw.x11.display))
|
||||||
|
{
|
||||||
|
if (!waitForData(fds, count, timeout))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
for (int i = 1; i < count; i++)
|
||||||
|
{
|
||||||
|
if (fds[i].revents & POLLIN)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes a byte to the empty event pipe
|
||||||
|
//
|
||||||
|
static void writeEmptyEvent(void)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
const char byte = 0;
|
||||||
|
const int result = write(_glfw.x11.emptyEventPipe[1], &byte, 1);
|
||||||
|
if (result == 1 || (result == -1 && errno != EINTR))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drains available data from the empty event pipe
|
||||||
|
//
|
||||||
|
static void drainEmptyEvents(void)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
char dummy[64];
|
||||||
|
const int result = read(_glfw.x11.emptyEventPipe[0], dummy, sizeof(dummy));
|
||||||
|
if (result == -1 && errno != EINTR)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +196,7 @@ static GLFWbool waitForVisibilityNotify(_GLFWwindow* window)
|
|||||||
VisibilityNotify,
|
VisibilityNotify,
|
||||||
&dummy))
|
&dummy))
|
||||||
{
|
{
|
||||||
if (!waitForEvent(&timeout))
|
if (!waitForX11Event(&timeout))
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -971,7 +1051,7 @@ static const char* getSelectionString(Atom selection)
|
|||||||
SelectionNotify,
|
SelectionNotify,
|
||||||
¬ification))
|
¬ification))
|
||||||
{
|
{
|
||||||
waitForEvent(NULL);
|
waitForX11Event(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notification.xselection.property == None)
|
if (notification.xselection.property == None)
|
||||||
@ -1007,7 +1087,7 @@ static const char* getSelectionString(Atom selection)
|
|||||||
isSelPropNewValueNotify,
|
isSelPropNewValueNotify,
|
||||||
(XPointer) ¬ification))
|
(XPointer) ¬ification))
|
||||||
{
|
{
|
||||||
waitForEvent(NULL);
|
waitForX11Event(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
XFree(data);
|
XFree(data);
|
||||||
@ -1252,7 +1332,7 @@ static void processEvent(XEvent *event)
|
|||||||
// (the server never sends a timestamp of zero)
|
// (the server never sends a timestamp of zero)
|
||||||
// NOTE: Timestamp difference is compared to handle wrap-around
|
// NOTE: Timestamp difference is compared to handle wrap-around
|
||||||
Time diff = event->xkey.time - window->x11.keyPressTimes[keycode];
|
Time diff = event->xkey.time - window->x11.keyPressTimes[keycode];
|
||||||
if (diff == event->xkey.time || (diff > 0 && diff < (1 << 31)))
|
if (diff == event->xkey.time || (diff > 0 && diff < ((Time)1 << 31)))
|
||||||
{
|
{
|
||||||
if (keycode)
|
if (keycode)
|
||||||
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
|
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
|
||||||
@ -1938,7 +2018,7 @@ void _glfwPushSelectionToManagerX11(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForEvent(NULL);
|
waitForX11Event(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2256,7 +2336,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
|||||||
isFrameExtentsEvent,
|
isFrameExtentsEvent,
|
||||||
(XPointer) window))
|
(XPointer) window))
|
||||||
{
|
{
|
||||||
if (!waitForEvent(&timeout))
|
if (!waitForX11Event(&timeout))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue");
|
"X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue");
|
||||||
@ -2748,7 +2828,7 @@ GLFWbool _glfwPlatformRawMouseMotionSupported(void)
|
|||||||
|
|
||||||
void _glfwPlatformPollEvents(void)
|
void _glfwPlatformPollEvents(void)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window;
|
drainEmptyEvents();
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
_glfwDetectJoystickConnectionLinux();
|
_glfwDetectJoystickConnectionLinux();
|
||||||
@ -2762,7 +2842,7 @@ void _glfwPlatformPollEvents(void)
|
|||||||
processEvent(&event);
|
processEvent(&event);
|
||||||
}
|
}
|
||||||
|
|
||||||
window = _glfw.x11.disabledCursorWindow;
|
_GLFWwindow* window = _glfw.x11.disabledCursorWindow;
|
||||||
if (window)
|
if (window)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
@ -2782,32 +2862,19 @@ void _glfwPlatformPollEvents(void)
|
|||||||
|
|
||||||
void _glfwPlatformWaitEvents(void)
|
void _glfwPlatformWaitEvents(void)
|
||||||
{
|
{
|
||||||
while (!XPending(_glfw.x11.display))
|
waitForAnyEvent(NULL);
|
||||||
waitForEvent(NULL);
|
|
||||||
|
|
||||||
_glfwPlatformPollEvents();
|
_glfwPlatformPollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformWaitEventsTimeout(double timeout)
|
void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||||
{
|
{
|
||||||
while (!XPending(_glfw.x11.display))
|
waitForAnyEvent(&timeout);
|
||||||
{
|
|
||||||
if (!waitForEvent(&timeout))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwPlatformPollEvents();
|
_glfwPlatformPollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformPostEmptyEvent(void)
|
void _glfwPlatformPostEmptyEvent(void)
|
||||||
{
|
{
|
||||||
XEvent event = { ClientMessage };
|
writeEmptyEvent();
|
||||||
event.xclient.window = _glfw.x11.helperWindowHandle;
|
|
||||||
event.xclient.format = 32; // Data is 32-bit longs
|
|
||||||
event.xclient.message_type = _glfw.x11.NULL_;
|
|
||||||
|
|
||||||
XSendEvent(_glfw.x11.display, _glfw.x11.helperWindowHandle, False, 0, &event);
|
|
||||||
XFlush(_glfw.x11.display);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||||
|
Loading…
Reference in New Issue
Block a user