Fixed bug 4018 - Implement SDL_GetWindowBordersSize() under Windows/Win32/WinAPI
authorSam Lantinga <slouken@libsdl.org>
Wed, 03 Jan 2018 10:58:58 -0800
changeset 1181516dbfcc5e455
parent 11814 0d9b386fefb7
child 11816 dea9cf23bad5
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
src/video/windows/SDL_windowsvideo.c
src/video/windows/SDL_windowswindow.c
src/video/windows/SDL_windowswindow.h
     1.1 --- a/src/video/windows/SDL_windowsvideo.c	Wed Jan 03 10:49:26 2018 -0800
     1.2 +++ b/src/video/windows/SDL_windowsvideo.c	Wed Jan 03 10:58:58 2018 -0800
     1.3 @@ -143,6 +143,7 @@
     1.4      device->SetWindowIcon = WIN_SetWindowIcon;
     1.5      device->SetWindowPosition = WIN_SetWindowPosition;
     1.6      device->SetWindowSize = WIN_SetWindowSize;
     1.7 +    device->GetWindowBordersSize = WIN_GetWindowBordersSize;
     1.8      device->SetWindowOpacity = WIN_SetWindowOpacity;
     1.9      device->ShowWindow = WIN_ShowWindow;
    1.10      device->HideWindow = WIN_HideWindow;
     2.1 --- a/src/video/windows/SDL_windowswindow.c	Wed Jan 03 10:49:26 2018 -0800
     2.2 +++ b/src/video/windows/SDL_windowswindow.c	Wed Jan 03 10:58:58 2018 -0800
     2.3 @@ -479,6 +479,49 @@
     2.4      WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOACTIVATE);
     2.5  }
     2.6  
     2.7 +int
     2.8 +WIN_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right)
     2.9 +{
    2.10 +    HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
    2.11 +    RECT rcClient, rcWindow;
    2.12 +    POINT ptDiff;
    2.13 +
    2.14 +    /* rcClient stores the size of the inner window, while rcWindow stores the outer size relative to the top-left
    2.15 +     * screen position; so the top/left values of rcClient are always {0,0} and bottom/right are {height,width} */
    2.16 +    GetClientRect(hwnd, &rcClient);
    2.17 +    GetWindowRect(hwnd, &rcWindow);
    2.18 +
    2.19 +    /* convert the top/left values to make them relative to
    2.20 +     * the window; they will end up being slightly negative */
    2.21 +    ptDiff.y = rcWindow.top;
    2.22 +    ptDiff.x = rcWindow.left;
    2.23 +
    2.24 +    ScreenToClient(hwnd, &ptDiff);
    2.25 +
    2.26 +    rcWindow.top  = ptDiff.y;
    2.27 +    rcWindow.left = ptDiff.x;
    2.28 +
    2.29 +    /* convert the bottom/right values to make them relative to the window,
    2.30 +     * these will be slightly bigger than the inner width/height */
    2.31 +    ptDiff.y = rcWindow.bottom;
    2.32 +    ptDiff.x = rcWindow.right;
    2.33 +
    2.34 +    ScreenToClient(hwnd, &ptDiff);
    2.35 +
    2.36 +    rcWindow.bottom = ptDiff.y;
    2.37 +    rcWindow.right  = ptDiff.x;
    2.38 +
    2.39 +    /* Now that both the inner and outer rects use the same coordinate system we can substract them to get the border size.
    2.40 +     * Keep in mind that the top/left coordinates of rcWindow are negative because the border lies slightly before {0,0},
    2.41 +     * so switch them around because SDL2 wants them in positive. */
    2.42 +    *top    = rcClient.top    - rcWindow.top;
    2.43 +    *left   = rcClient.left   - rcWindow.left;
    2.44 +    *bottom = rcWindow.bottom - rcClient.bottom;
    2.45 +    *right  = rcWindow.right  - rcClient.right;
    2.46 +
    2.47 +    return 0;
    2.48 +}
    2.49 +
    2.50  void
    2.51  WIN_ShowWindow(_THIS, SDL_Window * window)
    2.52  {
     3.1 --- a/src/video/windows/SDL_windowswindow.h	Wed Jan 03 10:49:26 2018 -0800
     3.2 +++ b/src/video/windows/SDL_windowswindow.h	Wed Jan 03 10:58:58 2018 -0800
     3.3 @@ -58,6 +58,7 @@
     3.4  extern void WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon);
     3.5  extern void WIN_SetWindowPosition(_THIS, SDL_Window * window);
     3.6  extern void WIN_SetWindowSize(_THIS, SDL_Window * window);
     3.7 +extern int WIN_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right);
     3.8  extern int WIN_SetWindowOpacity(_THIS, SDL_Window * window, float opacity);
     3.9  extern void WIN_ShowWindow(_THIS, SDL_Window * window);
    3.10  extern void WIN_HideWindow(_THIS, SDL_Window * window);