From 7c1932381bf2088927d8a3d8cd4f262d4bf08c85 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Thu, 24 Jan 2013 19:30:31 +0100 Subject: [PATCH] Reintroduced glfwGetWindowPos, glfwSetWindowPos. --- README.md | 3 +- include/GL/glfw3.h | 51 ++++++++++++++++++++++++++------ src/cocoa_window.m | 45 +++++++++++++++++------------ src/internal.h | 13 +++++---- src/win32_window.c | 72 ++++++++++++++++++++++++++-------------------- src/window.c | 55 +++++++++++++++++++++-------------- src/x11_platform.h | 6 ---- src/x11_window.c | 43 +++++++++++++-------------- tests/sharing.c | 14 ++++++--- tests/threads.c | 7 +++-- tests/windows.c | 7 +++-- 11 files changed, 191 insertions(+), 125 deletions(-) diff --git a/README.md b/README.md index a32dcebc..767cfaca 100644 --- a/README.md +++ b/README.md @@ -232,6 +232,7 @@ GLFW. changes in the set of available monitors * Added `GLFWwindow` and updated window-related functions and callbacks to take a window handle + * Added `glfwGetWindowPos` for retrieving the position of a window * Added `glfwDefaultWindowHints` for resetting all window hints to their default values * Added `glfwMakeContextCurrent` for making the context of the specified window @@ -270,8 +271,6 @@ GLFW. `GLES2/gl2.h` instead of `GL/gl.h` * Added `GLFW_VISIBLE` window hint and parameter for controlling and polling window visibility - * Added `GLFW_POSITION_X` and `GLFW_POSITION_Y` window hints and parameter for - controlling and polling window position * Added `windows` simple multi-window test program * Added `sharing` simple OpenGL object sharing test program * Added `modes` video mode enumeration and setting test program diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index e6dc60b2..c3d4cc17 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -487,8 +487,6 @@ extern "C" { #define GLFW_SHOULD_CLOSE 0x00020003 #define GLFW_RESIZABLE 0x00022007 #define GLFW_VISIBLE 0x00022008 -#define GLFW_POSITION_X 0x00022009 -#define GLFW_POSITION_Y 0x0002200A #define GLFW_CONTEXT_REVISION 0x00020004 #define GLFW_RED_BITS 0x00021000 @@ -1038,9 +1036,6 @@ GLFWAPI void glfwDefaultWindowHints(void); * The @ref GLFW_VISIBLE hint specifies whether the window will be initially * visible. This hint is ignored for fullscreen windows. * - * The @ref GLFW_POSITION_X and @ref GLFW_POSITION_Y hints specify the initial - * position of the window. These hints are ignored for fullscreen windows. - * * @note This function may only be called from the main thread. * * @sa glfwDefaultWindowHints @@ -1121,6 +1116,48 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* window); */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Retrieves the position of the client area of the specified window. + * @param[in] window The window to query. + * @param[out] xpos The x-coordinate of the upper-left corner of the client area. + * @param[out] ypos The y-coordinate of the upper-left corner of the client area. + * @ingroup window + * + * @remarks Either or both coordinate parameters may be @c NULL. + * + * @sa glfwSetWindowPos + */ +GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos); + +/*! @brief Sets the position of the client area of the specified window. + * @param[in] window The window to query. + * @param[in] xpos The x-coordinate of the upper-left corner of the client area. + * @param[in] ypos The y-coordinate of the upper-left corner of the client area. + * @ingroup window + * + * @remarks The position is the screen coordinate of the upper-left corner of + * the client area of the window. + * + * @remarks If you wish to set an initial window position you should create + * a hidden window (using @ref glfwWindowHint and @ref GLFW_VISIBLE), set its + * position and then show it. + * + * @note It is very rarely a good idea to move an already visible window, as it + * will confuse and annoy the user. + * + * @note This function may only be called from the main thread. + * + * @note The window manager may put limits on what positions are allowed. + * + * @bug X11: Some window managers ignore the set position of hidden + * (i.e. unmapped) windows, instead placing them where it thinks is + * appropriate once they are shown. + * + * @bug Mac OS X: The screen coordinate system is inverted. + * + * @sa glfwGetWindowPos + */ +GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int x, int y); + /*! @brief Retrieves the size of the client area of the specified window. * @param[in] window The window whose size to retrieve. * @param[out] width The width of the client area. @@ -1226,10 +1263,6 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); * The @ref GLFW_SHOULD_CLOSE property indicates whether the window has been * requested by the user to close. * - * The @ref GLFW_POSITION_X and @ref GLFW_POSITION_Y properties indicate the - * screen position, in pixels, of the upper-left corner of the window's client - * area. - * * @par Context properties * * The @ref GLFW_CLIENT_API property indicates the client API provided by the diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 1687aa06..a01005ea 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -67,26 +67,18 @@ { [window->nsgl.context update]; - NSRect contentRect = - [window->ns.object contentRectForFrameRect:[window->ns.object frame]]; - - _glfwInputWindowSize(window, contentRect.size.width, contentRect.size.height); + int width, height; + _glfwPlatformGetWindowSize(window, &width, &height); + _glfwInputWindowSize(window, width, height); } - (void)windowDidMove:(NSNotification *)notification { [window->nsgl.context update]; - NSRect contentRect = - [window->ns.object contentRectForFrameRect:[window->ns.object frame]]; - - CGPoint mainScreenOrigin = CGDisplayBounds(CGMainDisplayID()).origin; - double mainScreenHeight = CGDisplayBounds(CGMainDisplayID()).size.height; - CGPoint flippedPos = CGPointMake(contentRect.origin.x - mainScreenOrigin.x, - mainScreenHeight - contentRect.origin.y - - mainScreenOrigin.y - window->height); - - _glfwInputWindowPos(window, flippedPos.x, flippedPos.y); + int x, y; + _glfwPlatformGetWindowPos(window, &x, &y); + _glfwInputWindowPos(window, x, y); } - (void)windowDidMiniaturize:(NSNotification *)notification @@ -690,11 +682,8 @@ static GLboolean createWindow(_GLFWwindow* window, styleMask |= NSResizableWindowMask; } - NSRect contentRect = NSMakeRect(wndconfig->positionX, wndconfig->positionY, - wndconfig->width, wndconfig->height); - window->ns.object = [[NSWindow alloc] - initWithContentRect:contentRect + initWithContentRect:NSMakeRect(0, 0, wndconfig->width, wndconfig->height); styleMask:styleMask backing:NSBackingStoreBuffered defer:NO]; @@ -822,9 +811,27 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char *title) [window->ns.object setTitle:[NSString stringWithUTF8String:title]]; } +void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) +{ + const NSRect contentRect = + [window->ns.object contentRectForFrameRect:[window->ns.object frame]]; + + if (xpos) + *xpos = contentRect.origin.x; + if (ypos) + *ypos = contentRect.origin.y; +} + +void _glfwPlatformSetWindowPos(_GLFWwindow* window, int x, int y) +{ + const NSRect frameRect = + [window->ns.object frameRectForContentRect:NSMakeRect(x, y, 0, 0)]; + [window->ns.object setFrameOrigin:frameRect.origin]; +} + void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) { - NSRect contentRect = + const NSRect contentRect = [window->ns.object contentRectForFrameRect:[window->ns.object frame]]; if (width) diff --git a/src/internal.h b/src/internal.h index b80fd74a..f51a0a03 100644 --- a/src/internal.h +++ b/src/internal.h @@ -144,8 +144,6 @@ struct _GLFWhints GLboolean glDebug; int glProfile; int glRobustness; - int positionX; - int positionY; }; @@ -162,8 +160,6 @@ struct _GLFWwndconfig const char* title; GLboolean resizable; GLboolean visible; - int positionX; - int positionY; int clientAPI; int glMajor; int glMinor; @@ -207,7 +203,6 @@ struct _GLFWwindow struct _GLFWwindow* next; // Window settings and state - int positionX, positionY; GLboolean iconified; GLboolean resizable; GLboolean visible; @@ -459,6 +454,14 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window); */ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title); +/*! @ingroup platform + */ +void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos); + +/*! @ingroup platform + */ +void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos); + /*! @ingroup platform */ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height); diff --git a/src/win32_window.c b/src/win32_window.c index 27568a8e..51a9e980 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -715,16 +715,22 @@ static int createWindow(_GLFWwindow* window, const _GLFWfbconfig* fbconfig) { int positionX, positionY, fullWidth, fullHeight; - POINT pos; + POINT cursorPos; WCHAR* wideTitle; - // Set window styles common to all window modes window->win32.dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN; window->win32.dwExStyle = WS_EX_APPWINDOW; - // Add mode-dependent window styles if (window->monitor) + { window->win32.dwStyle |= WS_POPUP; + + positionX = wndconfig->monitor->positionX; + positionY = wndconfig->monitor->positionY; + + fullWidth = wndconfig->width; + fullHeight = wndconfig->height; + } else { window->win32.dwStyle |= WS_OVERLAPPED | WS_CAPTION | @@ -735,28 +741,13 @@ static int createWindow(_GLFWwindow* window, window->win32.dwStyle |= WS_MAXIMIZEBOX | WS_SIZEBOX; window->win32.dwExStyle |= WS_EX_WINDOWEDGE; } - } - // Adjust window size for frame and title bar - getFullWindowSize(window, - wndconfig->width, wndconfig->height, - &fullWidth, &fullHeight); + positionX = CW_USEDEFAULT; + positionY = CW_USEDEFAULT; - if (window->monitor) - { - // Fullscreen windows are always opened in the upper left corner - // regardless of the desktop working area - positionX = wndconfig->monitor->positionX; - positionY = wndconfig->monitor->positionY; - } - else - { - RECT wa; - SystemParametersInfo(SPI_GETWORKAREA, 0, &wa, 0); - - // Adjust window position to working area - positionX = wndconfig->positionX + wa.left; - positionY = wndconfig->positionY + wa.top; + getFullWindowSize(window, + wndconfig->width, wndconfig->height, + &fullWidth, &fullHeight); } wideTitle = _glfwCreateWideStringFromUTF8(wndconfig->title); @@ -772,10 +763,9 @@ static int createWindow(_GLFWwindow* window, wideTitle, window->win32.dwStyle, positionX, positionY, - fullWidth, // Decorated window width - fullHeight, // Decorated window height - NULL, // No parent window - NULL, // No menu + fullWidth, fullHeight, + NULL, // No parent window + NULL, // No window menu GetModuleHandle(NULL), window); // Pass GLFW window to WM_CREATE @@ -788,10 +778,10 @@ static int createWindow(_GLFWwindow* window, } // Initialize cursor position data - GetCursorPos(&pos); - ScreenToClient(window->win32.handle, &pos); - window->win32.oldCursorX = window->cursorPosX = pos.x; - window->win32.oldCursorY = window->cursorPosY = pos.y; + GetCursorPos(&cursorPos); + ScreenToClient(window->win32.handle, &cursorPos); + window->win32.oldCursorX = window->cursorPosX = cursorPos.x; + window->win32.oldCursorY = window->cursorPosY = cursorPos.y; if (!_glfwCreateContext(window, wndconfig, fbconfig)) return GL_FALSE; @@ -917,6 +907,26 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) free(wideTitle); } +void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) +{ + POINT pos = { 0, 0 }; + ClientToScreen(window->win32.handle, &pos); + + if (xpos) + *xpos = pos.x; + if (ypos) + *ypos = pos.y; +} + +void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) +{ + RECT rect = { xpos, ypos, xpos, ypos }; + AdjustWindowRectEx(&rect, window->win32.dwStyle, + FALSE, window->win32.dwExStyle); + SetWindowPos(window->win32.handle, NULL, rect.left, rect.top, 0, 0, + SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE); +} + void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) { RECT area; diff --git a/src/window.c b/src/window.c index e61041c5..a86e241f 100644 --- a/src/window.c +++ b/src/window.c @@ -94,12 +94,6 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLboolean focused) void _glfwInputWindowPos(_GLFWwindow* window, int x, int y) { - if (window->positionX == x && window->positionY == y) - return; - - window->positionX = x; - window->positionY = y; - if (window->callbacks.pos) window->callbacks.pos((GLFWwindow*) window, x, y); } @@ -189,8 +183,6 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, wndconfig.title = title; wndconfig.resizable = _glfw.hints.resizable ? GL_TRUE : GL_FALSE; wndconfig.visible = _glfw.hints.visible ? GL_TRUE : GL_FALSE; - wndconfig.positionX = _glfw.hints.positionX; - wndconfig.positionY = _glfw.hints.positionY; wndconfig.clientAPI = _glfw.hints.clientAPI; wndconfig.glMajor = _glfw.hints.glMajor; wndconfig.glMinor = _glfw.hints.glMinor; @@ -298,10 +290,6 @@ void glfwDefaultWindowHints(void) _glfw.hints.resizable = GL_TRUE; _glfw.hints.visible = GL_TRUE; - // The default window position is the upper left corner of the screen - _glfw.hints.positionX = 0; - _glfw.hints.positionY = 0; - // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil _glfw.hints.redBits = 8; _glfw.hints.greenBits = 8; @@ -362,12 +350,6 @@ GLFWAPI void glfwWindowHint(int target, int hint) case GLFW_VISIBLE: _glfw.hints.visible = hint; break; - case GLFW_POSITION_X: - _glfw.hints.positionX = hint; - break; - case GLFW_POSITION_Y: - _glfw.hints.positionY = hint; - break; case GLFW_SAMPLES: _glfw.hints.samples = hint; break; @@ -455,6 +437,39 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title) _glfwPlatformSetWindowTitle(window, title); } +GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + + if (!_glfwInitialized) + { + _glfwInputError(GLFW_NOT_INITIALIZED, NULL); + return; + } + + _glfwPlatformGetWindowPos(window, xpos, ypos); +} + +GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + + if (!_glfwInitialized) + { + _glfwInputError(GLFW_NOT_INITIALIZED, NULL); + return; + } + + if (window->monitor) + { + _glfwInputError(GLFW_INVALID_VALUE, + "Fullscreen windows cannot be positioned"); + return; + } + + _glfwPlatformSetWindowPos(window, xpos, ypos); +} + GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height) { _GLFWwindow* window = (_GLFWwindow*) handle; @@ -579,10 +594,6 @@ GLFWAPI int glfwGetWindowParam(GLFWwindow* handle, int param) return window->resizable; case GLFW_VISIBLE: return window->visible; - case GLFW_POSITION_X: - return window->positionX; - case GLFW_POSITION_Y: - return window->positionY; case GLFW_CLIENT_API: return window->clientAPI; case GLFW_CONTEXT_VERSION_MAJOR: diff --git a/src/x11_platform.h b/src/x11_platform.h index 4e7e6a25..a50f3fed 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -96,12 +96,6 @@ typedef struct _GLFWwindowX11 GLboolean cursorCentered; // True if cursor was moved since last poll int cursorPosX, cursorPosY; - // Window position hint (commited the first time the window is shown) - GLboolean windowPosSet; // False until the window position has - // been set - int positionX; // The window position to be set the - int positionY; // first time the window is shown - } _GLFWwindowX11; diff --git a/src/x11_window.c b/src/x11_window.c index 2e40460d..e6dafc9d 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -120,7 +120,7 @@ static GLboolean createWindow(_GLFWwindow* window, window->x11.handle = XCreateWindow(_glfw.x11.display, _glfw.x11.root, - wndconfig->positionX, wndconfig->positionY, + 0, 0, wndconfig->width, wndconfig->height, 0, // Border width visual->depth, // Color depth @@ -137,12 +137,6 @@ static GLboolean createWindow(_GLFWwindow* window, _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to create window"); return GL_FALSE; } - - // Request a window position to be set once the window is shown - // (see _glfwPlatformShowWindow) - window->x11.windowPosSet = GL_FALSE; - window->x11.positionX = wndconfig->positionX; - window->x11.positionY = wndconfig->positionY; } if (window->monitor && !_glfw.x11.hasEWMH) @@ -208,13 +202,6 @@ static GLboolean createWindow(_GLFWwindow* window, // Set ICCCM WM_NORMAL_HINTS property (even if no parts are set) { XSizeHints* hints = XAllocSizeHints(); - if (!hints) - { - _glfwInputError(GLFW_OUT_OF_MEMORY, - "X11: Failed to allocate size hints"); - return GL_FALSE; - } - hints->flags = 0; if (wndconfig->monitor) @@ -896,6 +883,25 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) } } +void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) +{ + Window child; + int x, y; + + XTranslateCoordinates(_glfw.x11.display, window->x11.handle, _glfw.x11.root, + 0, 0, &x, &y, &child); + + if (xpos) + *xpos = x; + if (ypos) + *ypos = y; +} + +void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) +{ + XMoveWindow(_glfw.x11.display, window->x11.handle, xpos, ypos); +} + void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) { XWindowAttributes attribs; @@ -967,15 +973,6 @@ void _glfwPlatformShowWindow(_GLFWwindow* window) { XMapRaised(_glfw.x11.display, window->x11.handle); XFlush(_glfw.x11.display); - - // Set the window position the first time the window is shown - // Note: XMoveWindow has no effect before the window has been mapped. - if (!window->x11.windowPosSet) - { - XMoveWindow(_glfw.x11.display, window->x11.handle, - window->x11.positionX, window->x11.positionY); - window->x11.windowPosSet = GL_TRUE; - } } void _glfwPlatformHideWindow(_GLFWwindow* window) diff --git a/tests/sharing.c b/tests/sharing.c index ec981aec..28ec68ec 100644 --- a/tests/sharing.c +++ b/tests/sharing.c @@ -35,6 +35,7 @@ #define WIDTH 400 #define HEIGHT 400 +#define OFFSET 50 static GLFWwindow* windows[2]; static GLboolean closed = GL_FALSE; @@ -60,14 +61,15 @@ static GLFWwindow* open_window(const char* title, GLFWwindow* share, int posX, i { GLFWwindow* window; - glfwWindowHint(GLFW_POSITION_X, posX); - glfwWindowHint(GLFW_POSITION_Y, posY); + glfwWindowHint(GLFW_VISIBLE, GL_FALSE); window = glfwCreateWindow(WIDTH, HEIGHT, title, NULL, share); if (!window) return NULL; glfwMakeContextCurrent(window); glfwSwapInterval(1); + glfwSetWindowPos(window, posX, posY); + glfwShowWindow(window); glfwSetWindowCloseCallback(window, window_close_callback); glfwSetKeyCallback(window, key_callback); @@ -131,6 +133,7 @@ static void draw_quad(GLuint texture) int main(int argc, char** argv) { + int x, y, width; GLuint texture; glfwSetErrorCallback(error_callback); @@ -138,7 +141,7 @@ int main(int argc, char** argv) if (!glfwInit()) exit(EXIT_FAILURE); - windows[0] = open_window("First", NULL, 0, 0); + windows[0] = open_window("First", NULL, OFFSET, OFFSET); if (!windows[0]) { glfwTerminate(); @@ -150,8 +153,11 @@ int main(int argc, char** argv) // It will then be shared with the second context, created below texture = create_texture(); + glfwGetWindowPos(windows[0], &x, &y); + glfwGetWindowSize(windows[0], &width, NULL); + // Put the second window to the right of the first one - windows[1] = open_window("Second", windows[0], WIDTH + 50, 0); + windows[1] = open_window("Second", windows[0], x + width + OFFSET, y); if (!windows[1]) { glfwTerminate(); diff --git a/tests/threads.c b/tests/threads.c index 38b56e2c..51595006 100644 --- a/tests/threads.c +++ b/tests/threads.c @@ -90,10 +90,10 @@ int main(void) if (!glfwInit()) exit(EXIT_FAILURE); + glfwWindowHint(GLFW_VISIBLE, GL_FALSE); + for (i = 0; i < count; i++) { - glfwWindowHint(GLFW_POSITION_X, 200 + 250 * i); - glfwWindowHint(GLFW_POSITION_Y, 200); threads[i].window = glfwCreateWindow(200, 200, threads[i].title, NULL, NULL); @@ -103,6 +103,9 @@ int main(void) exit(EXIT_FAILURE); } + glfwSetWindowPos(threads[i].window, 200 + 250 * i, 200); + glfwShowWindow(threads[i].window); + if (thrd_create(&threads[i].id, thread_main, threads + i) != thrd_success) { diff --git a/tests/windows.c b/tests/windows.c index 63afb3b7..915fbec0 100644 --- a/tests/windows.c +++ b/tests/windows.c @@ -56,10 +56,10 @@ int main(void) if (!glfwInit()) exit(EXIT_FAILURE); + glfwWindowHint(GLFW_VISIBLE, GL_FALSE); + for (i = 0; i < 4; i++) { - glfwWindowHint(GLFW_POSITION_X, 100 + (i & 1) * 300); - glfwWindowHint(GLFW_POSITION_Y, 100 + (i >> 1) * 300); windows[i] = glfwCreateWindow(200, 200, titles[i], NULL, NULL); if (!windows[i]) { @@ -72,6 +72,9 @@ int main(void) (GLclampf) (i >> 1), i ? 0.f : 1.f, 0.f); + + glfwSetWindowPos(windows[i], 100 + (i & 1) * 300, 100 + (i >> 1) * 300); + glfwShowWindow(windows[i]); } while (running)