Hi all
When using a decorated window in Windows 10, the winkey (GLFW_LEFT_SUPER) would usually dock your window to the desktop. eg. winkey+left will dock your window to the left and prompt the user to select what window to put on the right.
Is there a way to replicate this behaviour with an undecorated window with glfw? I can’t seem to find anything in the documentation.
I guess the docking itself can be done be checking the position and size of the window related to the monitor, but I don’t have any clue on how the prompt the user for a window of an external program.
Windows Snap is an OS feature, and it requires a window with a WS_SIZEBOX
style, which is the same as WS_THICKFRAME
- i.e. you get a thick border with resize controls.
The prompt for which Window to dock is also an OS feature, and it can be turned off in the Multi-tasking control panel by disabling When I snap a window, show what I can snap next to it.
Since these are OS features, GLFW doesn’t handle them itself.
You could emulate snap movement by using glfwSetWindowSize() when the user presses the GLFW_LEFT_SUPER
and an arrow, however GLFW does not have functions for finding and setting other processes window positions.
EDIT: You’ll also need to use glfwGetMonitorWorkarea to get the size of the work area to know what size to use for your window, and glfwSetWindowPos to set the position.
I have found a potentially interesting workaround using the glfw Native Access API.
Essentially we capture the GLFW_KEY_LEFT_SUPER
and set the style to have a resize, then unset it when the key is released. This enables the Windows OS snap features to work.
#define GLFW_EXPOSE_NATIVE_WIN32
#include <GLFW/glfw3native.h>
void KeyCallback( GLFWwindow* window, int key, int scancode, int action, int mods )
{
if( GLFW_KEY_LEFT_SUPER == key )
{
// switch to decorated
HWND hwnd = glfwGetWin32Window(g_pSys->window);
if( action == GLFW_PRESS )
{
LONG style = GetWindowLongA( hwnd, GWL_STYLE );
style = style | WS_SIZEBOX;
SetWindowLongA( hwnd, GWL_STYLE, style );
}
if( action == GLFW_RELEASE )
{
LONG style = GetWindowLongA( hwnd, GWL_STYLE );
style = style & (~WS_SIZEBOX);
SetWindowLongA( hwnd, GWL_STYLE, style );
}
}
}
This can also be done with glfwSetWindowAttrib(g_pSys->window, GLFW_DECORATED, GLFW_TRUE );
but the result isn’t as good as the client area is resized to be smaller than the full monitor height. You could potentially trap the resize and reset the size to what the user probably intended with some extra work.
1 Like
Thanks, this seams to work. is there a way to avoid the temporary border created from the sizebox?
Apparently you can do this by processing the WM_NCCALCSIZE message, but you’d need to modify GLFW or set a new windows proc to do this (and call the GLFW one).