Add glfwSetWindowAttrib

This function allows updating the GLFW_DECORATED, GLFW_RESIZABLE,
GLFW_FLOATING and GLFW_AUTO_ICONIFY attributes for existing windows.

Fixes #537.
This commit is contained in:
Camilla Löwy
2016-09-30 01:52:22 +02:00
parent d92bb41e25
commit 9e56099edd
12 changed files with 354 additions and 54 deletions
+19
View File
@@ -1385,6 +1385,25 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return [window->ns.object isZoomed];
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
{
[window->ns.object setStyleMask:getStyleMask(window)];
}
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
{
[window->ns.object setStyleMask:getStyleMask(window)];
[window->ns.object makeFirstResponder:window->ns.view];
}
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
{
if (enabled)
[window->ns.object setLevel:NSFloatingWindowLevel];
else
[window->ns.object setLevel:NSNormalWindowLevel];
}
void _glfwPlatformPollEvents(void)
{
for (;;)
+15
View File
@@ -757,6 +757,21 @@ int _glfwPlatformWindowVisible(_GLFWwindow* window);
*/
int _glfwPlatformWindowMaximized(_GLFWwindow* window);
/*! @brief Sets whether the window is resizable by the user.
* @ingroup platform
*/
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
/*! @brief Sets whether the window is decorated.
* @ingroup platform
*/
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
/*! @brief Sets whether the window is floating.
* @ingroup platform
*/
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled);
/*! @copydoc glfwPollEvents
* @ingroup platform
*/
+18
View File
@@ -595,6 +595,24 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return mir_surface_get_state(window->mir.surface) == mir_surface_state_maximized;
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformPollEvents(void)
{
EventNode* node = NULL;
+37
View File
@@ -280,6 +280,26 @@ static void updateClipRect(_GLFWwindow* window)
ClipCursor(NULL);
}
// Update native window styles to match attributes
//
static void updateWindowStyles(const _GLFWwindow* window)
{
RECT rect;
DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
style &= ~(WS_OVERLAPPEDWINDOW | WS_POPUP);
style |= getWindowStyle(window);
GetClientRect(window->win32.handle, &rect);
AdjustWindowRectEx(&rect, style, FALSE, getWindowExStyle(window));
ClientToScreen(window->win32.handle, (POINT*) &rect.left);
ClientToScreen(window->win32.handle, (POINT*) &rect.right);
SetWindowLongW(window->win32.handle, GWL_STYLE, style);
SetWindowPos(window->win32.handle, HWND_TOP,
rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER);
}
// Translates a GLFW standard cursor to a resource ID
//
static LPWSTR translateCursorShape(int shape)
@@ -1346,6 +1366,23 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return IsZoomed(window->win32.handle);
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
{
updateWindowStyles(window);
}
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
{
updateWindowStyles(window);
}
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
{
const HWND after = enabled ? HWND_TOPMOST : HWND_NOTOPMOST;
SetWindowPos(window->win32.handle, after, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
}
void _glfwPlatformPollEvents(void)
{
MSG msg;
+48
View File
@@ -704,6 +704,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
return window->decorated;
case GLFW_FLOATING:
return window->floating;
case GLFW_AUTO_ICONIFY:
return window->autoIconify;
case GLFW_CLIENT_API:
return window->context.client;
case GLFW_CONTEXT_CREATION_API:
@@ -732,6 +734,52 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
return 0;
}
GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT();
value = value ? GLFW_TRUE : GLFW_FALSE;
switch (attrib)
{
case GLFW_RESIZABLE:
if (window->resizable != value)
{
window->resizable = value;
if (!window->monitor)
_glfwPlatformSetWindowResizable(window, value);
}
return;
case GLFW_DECORATED:
if (window->decorated != value)
{
window->decorated = value;
if (!window->monitor)
_glfwPlatformSetWindowDecorated(window, value);
}
return;
case GLFW_FLOATING:
if (window->floating != value)
{
window->floating = value;
if (!window->monitor)
_glfwPlatformSetWindowFloating(window, value);
}
return;
case GLFW_AUTO_ICONIFY:
window->autoIconify = value;
return;
}
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute %i", attrib);
}
GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
+21
View File
@@ -634,6 +634,27 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return window->wl.maximized;
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
{
// TODO
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Window attribute setting not implemented yet");
}
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
{
// TODO
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Window attribute setting not implemented yet");
}
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
{
// TODO
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Window attribute setting not implemented yet");
}
void _glfwPlatformPollEvents(void)
{
handleEvents(0);
+102 -20
View File
@@ -520,26 +520,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
}
if (!wndconfig->decorated)
{
struct
{
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long input_mode;
unsigned long status;
} hints;
hints.flags = 2; // Set decorations
hints.decorations = 0; // No decorations
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.MOTIF_WM_HINTS,
_glfw.x11.MOTIF_WM_HINTS, 32,
PropModeReplace,
(unsigned char*) &hints,
sizeof(hints) / sizeof(long));
}
_glfwPlatformSetWindowDecorated(window, GLFW_FALSE);
if (_glfw.x11.NET_WM_STATE && !window->monitor)
{
@@ -2065,6 +2046,107 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return maximized;
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
{
int width, height;
_glfwPlatformGetWindowSize(window, &width, &height);
updateNormalHints(window, width, height);
}
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
{
if (enabled)
{
XDeleteProperty(_glfw.x11.display,
window->x11.handle,
_glfw.x11.MOTIF_WM_HINTS);
}
else
{
struct
{
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long input_mode;
unsigned long status;
} hints;
hints.flags = 2; // Set decorations
hints.decorations = 0; // No decorations
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.MOTIF_WM_HINTS,
_glfw.x11.MOTIF_WM_HINTS, 32,
PropModeReplace,
(unsigned char*) &hints,
sizeof(hints) / sizeof(long));
}
}
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
{
if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_ABOVE)
return;
if (_glfwPlatformWindowVisible(window))
{
const Atom action = enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
sendEventToWM(window,
_glfw.x11.NET_WM_STATE,
action,
_glfw.x11.NET_WM_STATE_ABOVE,
0, 1, 0);
}
else
{
Atom* states;
unsigned long i, count;
count = _glfwGetWindowPropertyX11(window->x11.handle,
_glfw.x11.NET_WM_STATE,
XA_ATOM,
(unsigned char**) &states);
if (enabled)
{
for (i = 0; i < count; i++)
{
if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
break;
}
if (i == count)
{
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeAppend,
(unsigned char*) &_glfw.x11.NET_WM_STATE_ABOVE,
1);
}
}
else
{
for (i = 0; i < count; i++)
{
if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
{
states[i] = states[count - 1];
count--;
}
}
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeReplace, (unsigned char*) &states, count);
}
XFree(states);
}
XFlush(_glfw.x11.display);
}
void _glfwPlatformPollEvents(void)
{
_glfwPollJoystickEvents();