Compare commits

...

3 Commits

Author SHA1 Message Date
Mārtiņš Možeiko
5c6fbe259b
Merge 11d96a4ab4 into 63a7e8b7f8 2025-08-20 21:31:59 +02:00
Camilla Löwy
63a7e8b7f8 Add and update Wayland-specific notes in docs
Fixes #2746
2025-08-20 20:13:07 +02:00
Mārtiņš Možeiko
11d96a4ab4 Win32: Do the event processing during window resize/move 2025-01-30 01:34:18 -08:00
10 changed files with 214 additions and 55 deletions

View File

@ -55,6 +55,7 @@ video tutorials.
- Jason Daly - Jason Daly
- danhambleton - danhambleton
- Jarrod Davis - Jarrod Davis
- decce
- Olivier Delannoy - Olivier Delannoy
- Paul R. Deppe - Paul R. Deppe
- Michael Dickens - Michael Dickens

View File

@ -153,17 +153,31 @@ the `VK_KHR_xlib_surface` extension. Possible values are `GLFW_TRUE` and
`GLFW_FALSE`. This is ignored on other platforms. `GLFW_FALSE`. This is ignored on other platforms.
#### Windows specific init hints {#init_hints_windows}
@anchor GLFW_WIN32_MESSAGES_IN_FIBER_hint
__GLFW_WIN32_MESSAGES_IN_FIBER__ specifies whether to use separate fiber for
processing Windows message, and not the main thread. This allows to unblock
window move and resize operations, and application can do updates and rendering
in its main loop. __Warning__ - setting this hint is not safe for environments
or frameworks where stack inspection is required (for example, moving garbage
collected languages such as Java or C#). Set this with @ref glfwInitHint.
#### Supported and default values {#init_hints_values} #### Supported and default values {#init_hints_values}
Initialization hint | Default value | Supported values Initialization hint | Default value | Supported values
-------------------------------- | ------------------------------- | ---------------- --------------------------------- | ------------------------------- | ----------------
@ref GLFW_PLATFORM | `GLFW_ANY_PLATFORM` | `GLFW_ANY_PLATFORM`, `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` or `GLFW_PLATFORM_NULL`
@ref GLFW_JOYSTICK_HAT_BUTTONS | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` --------------------------------- | ------------------------------- | ----------------
@ref GLFW_ANGLE_PLATFORM_TYPE | `GLFW_ANGLE_PLATFORM_TYPE_NONE` | `GLFW_ANGLE_PLATFORM_TYPE_NONE`, `GLFW_ANGLE_PLATFORM_TYPE_OPENGL`, `GLFW_ANGLE_PLATFORM_TYPE_OPENGLES`, `GLFW_ANGLE_PLATFORM_TYPE_D3D9`, `GLFW_ANGLE_PLATFORM_TYPE_D3D11`, `GLFW_ANGLE_PLATFORM_TYPE_VULKAN` or `GLFW_ANGLE_PLATFORM_TYPE_METAL` @ref GLFW_PLATFORM | `GLFW_ANY_PLATFORM` | `GLFW_ANY_PLATFORM`, `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` or `GLFW_PLATFORM_NULL`
@ref GLFW_COCOA_CHDIR_RESOURCES | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` @ref GLFW_JOYSTICK_HAT_BUTTONS | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_COCOA_MENUBAR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` @ref GLFW_ANGLE_PLATFORM_TYPE | `GLFW_ANGLE_PLATFORM_TYPE_NONE` | `GLFW_ANGLE_PLATFORM_TYPE_NONE`, `GLFW_ANGLE_PLATFORM_TYPE_OPENGL`, `GLFW_ANGLE_PLATFORM_TYPE_OPENGLES`, `GLFW_ANGLE_PLATFORM_TYPE_D3D9`, `GLFW_ANGLE_PLATFORM_TYPE_D3D11`, `GLFW_ANGLE_PLATFORM_TYPE_VULKAN` or `GLFW_ANGLE_PLATFORM_TYPE_METAL`
@ref GLFW_WAYLAND_LIBDECOR | `GLFW_WAYLAND_PREFER_LIBDECOR` | `GLFW_WAYLAND_PREFER_LIBDECOR` or `GLFW_WAYLAND_DISABLE_LIBDECOR` @ref GLFW_COCOA_CHDIR_RESOURCES | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_X11_XCB_VULKAN_SURFACE | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` @ref GLFW_COCOA_MENUBAR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_WAYLAND_LIBDECOR | `GLFW_WAYLAND_PREFER_LIBDECOR` | `GLFW_WAYLAND_PREFER_LIBDECOR` or `GLFW_WAYLAND_DISABLE_LIBDECOR`
@ref GLFW_X11_XCB_VULKAN_SURFACE | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_WIN32_MESSAGES_IN_FIBER | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
### Runtime platform selection {#platform} ### Runtime platform selection {#platform}

View File

@ -255,3 +255,7 @@ hardware gamma correction, which today is typically an approximation of sRGB
gamma. This means that setting a perfectly linear ramp, or gamma 1.0, will gamma. This means that setting a perfectly linear ramp, or gamma 1.0, will
produce the default (usually sRGB-like) behavior. produce the default (usually sRGB-like) behavior.
@note @wayland An application cannot read or modify the monitor gamma ramp. The
@ref glfwGetGammaRamp, @ref glfwSetGammaRamp and @ref glfwSetGamma functions
emit @ref GLFW_FEATURE_UNAVAILABLE.

View File

@ -893,6 +893,12 @@ int xpos, ypos;
glfwGetWindowPos(window, &xpos, &ypos); glfwGetWindowPos(window, &xpos, &ypos);
``` ```
@note @wayland An applications cannot know the positions of its windows or
whether one has been moved. The @ref GLFW_POSITION_X and @ref GLFW_POSITION_Y
window hints are ignored. The @ref glfwGetWindowPos and @ref glfwSetWindowPos
functions emit @ref GLFW_FEATURE_UNAVAILABLE. The window position callback will
not be called.
### Window title {#window_title} ### Window title {#window_title}
@ -1038,6 +1044,12 @@ You can also get the current iconification state with @ref glfwGetWindowAttrib.
int iconified = glfwGetWindowAttrib(window, GLFW_ICONIFIED); int iconified = glfwGetWindowAttrib(window, GLFW_ICONIFIED);
``` ```
@note @wayland An application cannot know if any of its windows have been
iconified or restore one from iconification. The @ref glfwRestoreWindow
function can only restore windows from maximization and the iconify callback
will not be called. The [GLFW_ICONIFIED](@ref GLFW_ICONIFIED_attrib) attribute
will be false. The @ref glfwIconifyWindow function works normally.
### Window maximization {#window_maximize} ### Window maximization {#window_maximize}

View File

@ -1328,6 +1328,11 @@ extern "C" {
* Wayland specific [init hint](@ref GLFW_WAYLAND_LIBDECOR_hint). * Wayland specific [init hint](@ref GLFW_WAYLAND_LIBDECOR_hint).
*/ */
#define GLFW_WAYLAND_LIBDECOR 0x00053001 #define GLFW_WAYLAND_LIBDECOR 0x00053001
/*! @brief Windows specific init hint.
*
* Windows specific [init hint](@ref GLFW_WIN32_MESSAGES_IN_FIBER_hint).
*/
#define GLFW_WIN32_MESSAGES_IN_FIBER 0x00054001
/*! @} */ /*! @} */
/*! @addtogroup init /*! @addtogroup init
@ -1604,6 +1609,10 @@ typedef void (* GLFWerrorfun)(int error_code, const char* description);
* @param[in] ypos The new y-coordinate, in screen coordinates, of the * @param[in] ypos The new y-coordinate, in screen coordinates, of the
* upper-left corner of the content area of the window. * upper-left corner of the content area of the window.
* *
* @remark @win32 On Windows moving or resizing of window will block event
* processing. Workaround for this is @ref GLFW_WIN32_MESSAGES_IN_FIBER init
* hint.
*
* @sa @ref window_pos * @sa @ref window_pos
* @sa @ref glfwSetWindowPosCallback * @sa @ref glfwSetWindowPosCallback
* *
@ -1625,6 +1634,10 @@ typedef void (* GLFWwindowposfun)(GLFWwindow* window, int xpos, int ypos);
* @param[in] width The new width, in screen coordinates, of the window. * @param[in] width The new width, in screen coordinates, of the window.
* @param[in] height The new height, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window.
* *
* @remark @win32 On Windows moving or resizing of window will block event
* processing. Workaround for this is @ref GLFW_WIN32_MESSAGES_IN_FIBER init
* hint.
*
* @sa @ref window_size * @sa @ref window_size
* @sa @ref glfwSetWindowSizeCallback * @sa @ref glfwSetWindowSizeCallback
* *
@ -2915,8 +2928,8 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_INVALID_VALUE, * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_INVALID_VALUE,
* @ref GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * @ref GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland Gamma handling is a privileged protocol, this function * @remark @wayland Monitor gamma is a privileged protocol, so this function
* will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE. * cannot be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
@ -2939,8 +2952,8 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_PLATFORM_ERROR * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_PLATFORM_ERROR
* and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland Gamma handling is a privileged protocol, this function * @remark @wayland Monitor gamma is a privileged protocol, so this function
* will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE while * cannot be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE while
* returning `NULL`. * returning `NULL`.
* *
* @pointer_lifetime The returned structure and its arrays are allocated and * @pointer_lifetime The returned structure and its arrays are allocated and
@ -2983,8 +2996,8 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
* *
* @remark @win32 The gamma ramp size must be 256. * @remark @win32 The gamma ramp size must be 256.
* *
* @remark @wayland Gamma handling is a privileged protocol, this function * @remark @wayland Monitor gamma is a privileged protocol, so this function
* will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE. * cannot be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE.
* *
* @pointer_lifetime The specified gamma ramp is copied before this function * @pointer_lifetime The specified gamma ramp is copied before this function
* returns. * returns.
@ -3430,8 +3443,8 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* i
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland There is no way for an application to retrieve the global * @remark @wayland Window positions are not currently part of any common
* position of its windows. This function will emit @ref * Wayland protocol, so this function cannot be implemented and will emit @ref
* GLFW_FEATURE_UNAVAILABLE. * GLFW_FEATURE_UNAVAILABLE.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -3464,8 +3477,8 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland There is no way for an application to set the global * @remark @wayland Window positions are not currently part of any common
* position of its windows. This function will emit @ref * Wayland protocol, so this function cannot be implemented and will emit @ref
* GLFW_FEATURE_UNAVAILABLE. * GLFW_FEATURE_UNAVAILABLE.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -3807,10 +3820,6 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @wayland Once a window is iconified, @ref glfwRestoreWindow wont
* be able to restore it. This is a design decision of the xdg-shell
* protocol.
*
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
* @sa @ref window_iconify * @sa @ref window_iconify
@ -3838,6 +3847,10 @@ GLFWAPI void glfwIconifyWindow(GLFWwindow* window);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @wayland Restoring a window from maximization is not currently part
* of any common Wayland protocol, so this function can only restore windows
* from maximization.
*
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
* @sa @ref window_iconify * @sa @ref window_iconify
@ -4058,8 +4071,8 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
* affected by any resizing or mode switching, although you may need to update * affected by any resizing or mode switching, although you may need to update
* your viewport if the framebuffer size has changed. * your viewport if the framebuffer size has changed.
* *
* @remark @wayland The desired window position is ignored, as there is no way * @remark @wayland Window positions are not currently part of any common
* for an application to set this property. * Wayland protocol. The window position arguments are ignored.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
@ -4096,8 +4109,9 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int
* errors. However, this function should not fail as long as it is passed * errors. However, this function should not fail as long as it is passed
* valid arguments and the library has been [initialized](@ref intro_init). * valid arguments and the library has been [initialized](@ref intro_init).
* *
* @remark @wayland The Wayland protocol provides no way to check whether a * @remark @wayland Checking whether a window is iconified is not currently
* window is iconfied, so @ref GLFW_ICONIFIED always returns `GLFW_FALSE`. * part of any common Wayland protocol, so the @ref GLFW_ICONIFIED attribute
* cannot be implemented and is always `GLFW_FALSE`.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
@ -4219,8 +4233,8 @@ GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window);
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
* *
* @remark @wayland This callback will never be called, as there is no way for * @remark @wayland This callback will not be called. The Wayland protocol
* an application to know its global position. * provides no way to be notified of when a window is moved.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
@ -4395,6 +4409,10 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwi
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
* *
* @remark @wayland This callback will not be called. The Wayland protocol
* provides no way to be notified of when a window is iconified, and no way to
* check whether a window is currently iconified.
*
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
* @sa @ref window_iconify * @sa @ref window_iconify

View File

@ -66,6 +66,10 @@ static _GLFWinitconfig _glfwInitHints =
{ {
.libdecorMode = GLFW_WAYLAND_PREFER_LIBDECOR .libdecorMode = GLFW_WAYLAND_PREFER_LIBDECOR
}, },
.win32 =
{
.msgInFiber = GLFW_FALSE,
}
}; };
// The allocation function used when no custom allocator is set // The allocation function used when no custom allocator is set
@ -462,6 +466,9 @@ GLFWAPI void glfwInitHint(int hint, int value)
case GLFW_WAYLAND_LIBDECOR: case GLFW_WAYLAND_LIBDECOR:
_glfwInitHints.wl.libdecorMode = value; _glfwInitHints.wl.libdecorMode = value;
return; return;
case GLFW_WIN32_MESSAGES_IN_FIBER:
_glfwInitHints.win32.msgInFiber = value;
return;
} }
_glfwInputError(GLFW_INVALID_ENUM, _glfwInputError(GLFW_INVALID_ENUM,

View File

@ -388,6 +388,9 @@ struct _GLFWinitconfig
struct { struct {
int libdecorMode; int libdecorMode;
} wl; } wl;
struct {
GLFWbool msgInFiber;
} win32;
}; };
// Window configuration // Window configuration

View File

@ -366,7 +366,6 @@ static LRESULT CALLBACK helperWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LP
// //
static GLFWbool createHelperWindow(void) static GLFWbool createHelperWindow(void)
{ {
MSG msg;
WNDCLASSEXW wc = { sizeof(wc) }; WNDCLASSEXW wc = { sizeof(wc) };
wc.style = CS_OWNDC; wc.style = CS_OWNDC;
@ -417,10 +416,18 @@ static GLFWbool createHelperWindow(void)
DEVICE_NOTIFY_WINDOW_HANDLE); DEVICE_NOTIFY_WINDOW_HANDLE);
} }
while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE)) if (_glfw.hints.init.win32.msgInFiber)
{ {
TranslateMessage(&msg); SwitchToFiber(_glfw.win32.messageFiber);
DispatchMessageW(&msg); }
else
{
MSG msg;
while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
} }
return GLFW_TRUE; return GLFW_TRUE;
@ -594,6 +601,45 @@ BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build)
return RtlVerifyVersionInfo(&osvi, mask, cond) == 0; return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
} }
void _glfwPollMessageLoopWin32(void)
{
_GLFWwindow* window;
MSG msg;
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
// NOTE: While GLFW does not itself post WM_QUIT, other processes
// may post it to this one, for example Task Manager
// HACK: Treat WM_QUIT as a close on all windows
window = _glfw.windowListHead;
while (window)
{
_glfwInputWindowCloseRequest(window);
window = window->next;
}
}
else
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
}
// Windows message dispatch fiber
void CALLBACK messageFiberProc(LPVOID lpFiberParameter)
{
(void)lpFiberParameter;
for (;;)
{
_glfwPollMessageLoopWin32();
SwitchToFiber(_glfw.win32.mainFiber);
}
}
GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform) GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform)
{ {
const _GLFWplatform win32 = const _GLFWplatform win32 =
@ -691,6 +737,17 @@ int _glfwInitWin32(void)
else else
SetProcessDPIAware(); SetProcessDPIAware();
if (_glfw.hints.init.win32.msgInFiber)
{
_glfw.win32.mainFiber = ConvertThreadToFiber(NULL);
if (!_glfw.win32.mainFiber)
return GLFW_FALSE;
_glfw.win32.messageFiber = CreateFiber(0, &messageFiberProc, NULL);
if (!_glfw.win32.messageFiber)
return GLFW_FALSE;
}
if (!createHelperWindow()) if (!createHelperWindow())
return GLFW_FALSE; return GLFW_FALSE;
@ -713,6 +770,12 @@ void _glfwTerminateWin32(void)
if (_glfw.win32.mainWindowClass) if (_glfw.win32.mainWindowClass)
UnregisterClassW(MAKEINTATOM(_glfw.win32.mainWindowClass), _glfw.win32.instance); UnregisterClassW(MAKEINTATOM(_glfw.win32.mainWindowClass), _glfw.win32.instance);
if (_glfw.hints.init.win32.msgInFiber)
{
DeleteFiber(_glfw.win32.messageFiber);
ConvertFiberToThread();
}
_glfw_free(_glfw.win32.clipboardString); _glfw_free(_glfw.win32.clipboardString);
_glfw_free(_glfw.win32.rawInput); _glfw_free(_glfw.win32.rawInput);

View File

@ -375,6 +375,11 @@ typedef struct _GLFWwindowWin32
int lastCursorPosX, lastCursorPosY; int lastCursorPosX, lastCursorPosY;
// The last received high surrogate when decoding pairs of UTF-16 messages // The last received high surrogate when decoding pairs of UTF-16 messages
WCHAR highSurrogate; WCHAR highSurrogate;
// If user pressed mouse button on window title bar
UINT ncMouseButton;
LPARAM ncMousePos;
} _GLFWwindowWin32; } _GLFWwindowWin32;
// Win32-specific global data // Win32-specific global data
@ -403,6 +408,9 @@ typedef struct _GLFWlibraryWin32
// The cursor handle to use to hide the cursor (NULL or a transparent cursor) // The cursor handle to use to hide the cursor (NULL or a transparent cursor)
HCURSOR blankCursor; HCURSOR blankCursor;
LPVOID messageFiber;
LPVOID mainFiber;
struct { struct {
HINSTANCE instance; HINSTANCE instance;
PFN_DirectInput8Create Create; PFN_DirectInput8Create Create;
@ -519,6 +527,7 @@ void _glfwSetWindowOpacityWin32(_GLFWwindow* window, float opacity);
void _glfwSetRawMouseMotionWin32(_GLFWwindow *window, GLFWbool enabled); void _glfwSetRawMouseMotionWin32(_GLFWwindow *window, GLFWbool enabled);
GLFWbool _glfwRawMouseMotionSupportedWin32(void); GLFWbool _glfwRawMouseMotionSupportedWin32(void);
void _glfwPollMessageLoopWin32(void);
void _glfwPollEventsWin32(void); void _glfwPollEventsWin32(void);
void _glfwWaitEventsWin32(void); void _glfwWaitEventsWin32(void);
void _glfwWaitEventsTimeoutWin32(double timeout); void _glfwWaitEventsTimeoutWin32(double timeout);

View File

@ -853,11 +853,46 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
return 0; return 0;
} }
case WM_NCLBUTTONDOWN:
{
if (wParam == HTCAPTION)
{
window->win32.ncMouseButton = uMsg;
window->win32.ncMousePos = lParam;
return 0;
}
break;
}
case WM_NCMOUSEMOVE:
{
if (window->win32.ncMouseButton)
{
if (GET_X_LPARAM(window->win32.ncMousePos) != GET_X_LPARAM(lParam) ||
GET_Y_LPARAM(window->win32.ncMousePos) != GET_Y_LPARAM(lParam))
{
DefWindowProcW(hWnd, window->win32.ncMouseButton, HTCAPTION, window->win32.ncMousePos);
window->win32.ncMouseButton = 0;
}
}
break;
}
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
{ {
const int x = GET_X_LPARAM(lParam); const int x = GET_X_LPARAM(lParam);
const int y = GET_Y_LPARAM(lParam); const int y = GET_Y_LPARAM(lParam);
if (window->win32.ncMouseButton)
{
if (GET_X_LPARAM(window->win32.ncMousePos) != x ||
GET_Y_LPARAM(window->win32.ncMousePos) != y)
{
DefWindowProcW(hWnd, window->win32.ncMouseButton, HTCAPTION, window->win32.ncMousePos);
window->win32.ncMouseButton = 0;
}
}
if (!window->win32.cursorTracked) if (!window->win32.cursorTracked)
{ {
TRACKMOUSEEVENT tme; TRACKMOUSEEVENT tme;
@ -998,6 +1033,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
else if (window->cursorMode == GLFW_CURSOR_CAPTURED) else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
releaseCursor(); releaseCursor();
if (_glfw.hints.init.win32.msgInFiber)
SetTimer(hWnd, 1, 1, NULL);
break; break;
} }
@ -1014,6 +1051,15 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
else if (window->cursorMode == GLFW_CURSOR_CAPTURED) else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
captureCursor(window); captureCursor(window);
if (_glfw.hints.init.win32.msgInFiber)
KillTimer(hWnd, 1);
break;
}
case WM_TIMER:
{
if (_glfw.hints.init.win32.msgInFiber && wParam == 1)
SwitchToFiber(_glfw.win32.mainFiber);
break; break;
} }
@ -2088,31 +2134,13 @@ GLFWbool _glfwRawMouseMotionSupportedWin32(void)
void _glfwPollEventsWin32(void) void _glfwPollEventsWin32(void)
{ {
MSG msg;
HWND handle; HWND handle;
_GLFWwindow* window; _GLFWwindow* window;
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) if (_glfw.hints.init.win32.msgInFiber)
{ SwitchToFiber(_glfw.win32.messageFiber);
if (msg.message == WM_QUIT) else
{ _glfwPollMessageLoopWin32();
// NOTE: While GLFW does not itself post WM_QUIT, other processes
// may post it to this one, for example Task Manager
// HACK: Treat WM_QUIT as a close on all windows
window = _glfw.windowListHead;
while (window)
{
_glfwInputWindowCloseRequest(window);
window = window->next;
}
}
else
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
// HACK: Release modifier keys that the system did not emit KEYUP for // HACK: Release modifier keys that the system did not emit KEYUP for
// NOTE: Shift keys on Windows tend to "stick" when both are pressed as // NOTE: Shift keys on Windows tend to "stick" when both are pressed as