Browse Source

Fixed bug 4018 - Implement SDL_GetWindowBordersSize() under Windows/Win32/WinAPI

Ismael Ferreras Morezuelas (Swyter)

As a new year gift I have implemented the Windows version of SDL_GetWindowBordersSize(). I needed it for auto-selecting a cozy window size for the game I'm currently working on and noticed that it only worked under X11, so I thought it could be a good excuse to contribute back more stuff. The Mercurial patch is attached as a .diff file. Let me know what you think.

Happy 2018 to all the SDL2 devs and users!

--

PS: Keep in mind that Windows 10 includes the 8px invisible grip borders as part of the frame. There's a way of detecting if Aero/DWM is being used and ask only for the visible rect, but I believe that GetWindowRect() is doing that for a reason and working as intended, so I haven't changed it. (See [2])


References:
[1]: http://www.firststeps.ru/mfc/winapi/r.php?72
[2]: https://stackoverflow.com/a/34143777/674685
[3]: https://stackoverflow.com/a/431548/674685
[4]: https://wiki.libsdl.org/SDL_GetWindowBordersSize
Sam Lantinga 7 years ago
parent
commit
7c60bec493

+ 1 - 0
src/video/windows/SDL_windowsvideo.c

@@ -143,6 +143,7 @@ WIN_CreateDevice(int devindex)
     device->SetWindowIcon = WIN_SetWindowIcon;
     device->SetWindowPosition = WIN_SetWindowPosition;
     device->SetWindowSize = WIN_SetWindowSize;
+    device->GetWindowBordersSize = WIN_GetWindowBordersSize;
     device->SetWindowOpacity = WIN_SetWindowOpacity;
     device->ShowWindow = WIN_ShowWindow;
     device->HideWindow = WIN_HideWindow;

+ 43 - 0
src/video/windows/SDL_windowswindow.c

@@ -479,6 +479,49 @@ WIN_SetWindowSize(_THIS, SDL_Window * window)
     WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOACTIVATE);
 }
 
+int
+WIN_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right)
+{
+    HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
+    RECT rcClient, rcWindow;
+    POINT ptDiff;
+
+    /* rcClient stores the size of the inner window, while rcWindow stores the outer size relative to the top-left
+     * screen position; so the top/left values of rcClient are always {0,0} and bottom/right are {height,width} */
+    GetClientRect(hwnd, &rcClient);
+    GetWindowRect(hwnd, &rcWindow);
+
+    /* convert the top/left values to make them relative to
+     * the window; they will end up being slightly negative */
+    ptDiff.y = rcWindow.top;
+    ptDiff.x = rcWindow.left;
+
+    ScreenToClient(hwnd, &ptDiff);
+
+    rcWindow.top  = ptDiff.y;
+    rcWindow.left = ptDiff.x;
+
+    /* convert the bottom/right values to make them relative to the window,
+     * these will be slightly bigger than the inner width/height */
+    ptDiff.y = rcWindow.bottom;
+    ptDiff.x = rcWindow.right;
+
+    ScreenToClient(hwnd, &ptDiff);
+
+    rcWindow.bottom = ptDiff.y;
+    rcWindow.right  = ptDiff.x;
+
+    /* Now that both the inner and outer rects use the same coordinate system we can substract them to get the border size.
+     * Keep in mind that the top/left coordinates of rcWindow are negative because the border lies slightly before {0,0},
+     * so switch them around because SDL2 wants them in positive. */
+    *top    = rcClient.top    - rcWindow.top;
+    *left   = rcClient.left   - rcWindow.left;
+    *bottom = rcWindow.bottom - rcClient.bottom;
+    *right  = rcWindow.right  - rcClient.right;
+
+    return 0;
+}
+
 void
 WIN_ShowWindow(_THIS, SDL_Window * window)
 {

+ 1 - 0
src/video/windows/SDL_windowswindow.h

@@ -58,6 +58,7 @@ extern void WIN_SetWindowTitle(_THIS, SDL_Window * window);
 extern void WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon);
 extern void WIN_SetWindowPosition(_THIS, SDL_Window * window);
 extern void WIN_SetWindowSize(_THIS, SDL_Window * window);
+extern int WIN_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right);
 extern int WIN_SetWindowOpacity(_THIS, SDL_Window * window, float opacity);
 extern void WIN_ShowWindow(_THIS, SDL_Window * window);
 extern void WIN_HideWindow(_THIS, SDL_Window * window);