Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

no way to compute actual window size or bounds (including decorations and OS-imposed minimums) #1471

Closed
SDLBugzilla opened this issue Feb 10, 2021 · 0 comments

Comments

@SDLBugzilla
Copy link
Collaborator

This bug report was migrated from our old Bugzilla tracker.

These attachments are available in the static archive:

Reported in version: 2.0.3
Reported for operating system, platform: Windows 7, x86_64

Comments on the original bug report:

On 2014-05-09 20:21:53 +0000, Adam M. wrote:

It would be very helpful if there was a way to compute the actual size of a window given the size of a drawing area. Currently, sizing and positioning an SDL_Window actually sizes and positions the drawing area within the window, so the actual window is larger and offset within the desktop. I'm fine with that, but if I want to place a window at 0,0 for instance, or to create two windows and stack them one above the other, there's apparently no way to do it.

Also, and I'm not sure how related this is, there appear to be OS-imposed minimums on the size of a window. For instance, it's not possible to create a normal window with a 100x100 drawing area on my machine. The actual drawing area becomes 116x100, and this is OS-imposed minimum is not reflected by SDL_GetWindowMinimumSize.

I would suggest a function like the following (pick a better name if you like):

SDL_GetDecoratedWindowArea(int drawWidth, int drawHeight, WindowFlags flags, int *windowWidth, int *windowHeight, Rect *decoratedDrawArea)

INPUT:
drawWidth/Height - The size of the SDL_Window drawing area on the desktop screen (i.e. the same dimensions used with SDL_Get/SetWindowSize).
flags - The flags that would be used to create the window.

OUTPUT:
windowWidth/Height - The actual size of the OS window on the desktop.
decoratedDrawArea - The position of the drawing area relative to the top-left corner of the OS window, and its size taking into account any OS-imposed minimums.

On 2014-06-25 09:11:07 +0000, Sam Lantinga wrote:

Yes, this would be very helpful. I believe it's easy to do on Windows and Mac OS X, but I'm not sure the info is available on Linux with the various desktop window managers available.

Patches welcome!

On 2014-08-18 04:36:30 +0000, Adam M. wrote:

Unfortunately, I'm not familiar with how to do that on GNU/Linux either. :-|

On 2014-11-19 15:12:56 +0000, Ben Swick wrote:

Created attachment 1934
Patch to add display working area API

On 2014-11-19 15:30:31 +0000, Ben Swick wrote:

I've attached a patch that adds an API function to get the available space on a display excluding taskbars and docks. I've implemented it on Windows and Linux.

It should be easy to finish the Mac OS X implementation using the screen's visibleFrame property, but I do not have a Mac system to compile or test on.

The Linux implementation is not always correct with multiple monitors. It uses the _NET_WORKAREA property and window managers do not always send useful values. I'm running Linux Mint 17 Cinnamon with two monitors and I get a rectangle consisting of most of the virtual desktop. The implementation intersects the _NET_WORKAREA rectangle with the display bounds to deal with this.

If no work area is calculated the function returns an error flag and the user will probably just have to fall back to how they do things now.

It looks like there is a way on Mac OS X to get the window decorations using NSWindow contentRectForFrameRect. I haven't determined if there is a way on Linux and Windows yet.

On 2015-02-19 06:32:14 +0000, Ryan C. Gordon wrote:

Marking a large number of bugs with the "triage-2.0.4" keyword at once. Sorry
if you got a lot of email from this. This is to help me sort through some bugs
in regards to a 2.0.4 release. We may or may not fix this bug for 2.0.4,
though!

On 2015-04-07 04:57:57 +0000, Ryan C. Gordon wrote:

(sorry if you get a lot of copies of this email, I'm marking several bugs at once)

Marking bugs for the (mostly) final 2.0.4 TODO list. This means we're hoping to resolve this bug before 2.0.4 ships if possible. In a perfect world, the open bug count with the target-2.0.4 keyword is zero when we ship.

(Note that closing a bug report as WONTFIX, INVALID or WORKSFORME might still happen.)

--ryan.

On 2015-04-09 00:11:38 +0000, wrote:

I am not sure it is a good idea idea to expose such functionality to an application. I have tried to implement both usable display area and window border sizes before cross-platform and it does not work.

Two use-cases I can currently see are:

  1. For positioning a window relative to another window.

SDL should provide a child/parent window API for this.

  1. For sizing a windowed application inside the desktop area.

Applications could probably use SDL_GetWindowMaximumSize or another function such as SDL_GL_GetDawableMaximumSize. This should be based on fitting the drawable inside the display area taking into account docks and everything else (if it does not currently do this already).

Ideally games really should move away from using the old methodology which deal in hardcoded fixed resolutions. They should just have a quality sliders and aspect ratios instead as they should be doing for SDL_WINDOW_FULLSCREEN_DESKTOP. Obviously a bit of an over simplification, but something to think about.

Placing a window at 0,0 seems not a valid use case. Ideally non child windows should not need to be placed in exact co-ordinates as it is not cross-platform. Just use SDL_WINDOW_POS_CENTERED/UNDEFINED(_DISPLAY). Why would you want to place the drawable area at actual display co-ordinates 0,0? It may not even be possible and if it was you would prevent moving the window and occlude the menubar/dock.

Everything an application does should really be agnostic of what is going on outside of the drawable area of the window. Also you cannot really expect developers to handle failure cases correctly, they will QA test with the non failure case only.

Docks do not have to span the entire width of a display (meaning a window sized small enough code fit next to the dock) and could be at the top or bottom, and could pop-in or pop-out forcing the window to move.

Window decorations may not be rectangular or may hide/show/resize based on mouse over, etc.

On 2015-04-09 05:28:50 +0000, Ryan C. Gordon wrote:

Hmm, I just built something almost identical that's sitting in my experimental repo:

https://hg.icculus.org/icculus/SDL-gui-backend/rev/a3eb0df213bd

(and the next few commits after that implement it for Windows, X11, Mac OS X, iOS.)

So I guess we're making progress towards this one way or another. :)

--ryan.

On 2015-04-10 06:06:29 +0000, wrote:

Obviously this helps as a quick porting drop in for SPI_GETWORKAREA.

Some new window flags might be useful:

SDL_WINDOW_FIT_TO_DISPLAY window maximum size will be set to fit inside the usable display bounds.
SDL_WINDOW_CLAMP_TO_DISPLAY window will be resized to always fit inside the usable display bounds.

If SDL_WINDOW_CLAMP_TO_DISPLAY is set the the window will either be moved or resized if it tries to call SetWindowSize to larger than the usable display bounds taking into account its current location.

Just an idea.

I believe this is also relevant to https://bugzilla.libsdl.org/show_bug.cgi?id=2652 on some level.

On 2015-04-10 22:12:27 +0000, Adam M. wrote:

x414e54@linux.com said "I am not sure it is a good idea idea to expose such functionality... games really should move away from using the old methodology which deal in hardcoded fixed resolutions... Placing a window at 0,0 seems not a valid use case."

I suppose that depends on whether you think SDL should only be used for games or whether it should be a general, cross-platform library for getting input, drawing output, etc. I personally have used SDL (1.3) for developing complex non-game applications.

Anyway, I might not even mind if all fixed-resolution features were removed from SDL. But given that they exist, it seems like a deficiency to be unable to make full use of them.

On 2015-04-11 03:33:51 +0000, wrote:

(In reply to Adam M. from comment # 10)

x414e54@linux.com said "I am not sure it is a good idea idea to expose such
functionality... games really should move away from using the old
methodology which deal in hardcoded fixed resolutions... Placing a window at
0,0 seems not a valid use case."

I suppose that depends on whether you think SDL should only be used for
games or whether it should be a general, cross-platform library for getting
input, drawing output, etc. I personally have used SDL (1.3) for developing
complex non-game applications.

Anyway, I might not even mind if all fixed-resolution features were removed
from SDL. But given that they exist, it seems like a deficiency to be unable
to make full use of them.

Apologies for incoming wall of text:

I am currently helping out with the UE4Editor on Wayland and have used SDL to partially implement a drop in Win32 API before. Both of these are GUI cases rather than single window games.

Wayland and Mir do not support positioning of the root window or getting the window position back. This is for various reasons such as windows can be rotated an arbitrary amount.

If you are working with a tool-kit you do not care where the root window is placed just that it is visible on the screen. You may care where child windows are placed in the case of menus, etc. Which is why SDL should have some kind of child or menu window support. Most GUI based use cases the user would be able to resize the root window (except games) so you really do not to care if SDL resizes it to fit it on the display for you. Video applications you may care about the aspect ratio of the resize.

When you tell SDL 0,0 you just mean top-left of the screen you do not mean place it under/over the menu/taskbar. It is largely irrelevant if you tell SDL 0,0 and either SDL or the OS places it at 0,10. In most cases (except Mir and Wayland) you would get a movement event back and the application knows it new location. SDL should be dealing with the origin of the window as if it was border-less.

If you are trying to-do something where you are moving the window based on the mouse pointer and need global mouse co-ordinates... do not do it... because you can end up with this https://www.youtube.com/watch?v=PTu7-hBwZ1o - to move a top level window based on the mouse position use the SDL_SetHitTest function or for tabs SDL should have drag and drop like Firefox uses.

I do appreciate your comments on the above.

On 2015-05-29 17:38:20 +0000, Ryan C. Gordon wrote:

This is going in after 2.0.4 ships, so I'm removing the target-2.0.4 keyword.

--ryan.

On 2015-06-04 20:37:58 +0000, Adam M. wrote:

If you are working with a tool-kit you do not care where the root window is
placed just that it is visible on the screen. You may care where child
windows are placed in the case of menus, etc. Which is why SDL should have
some kind of child or menu window support.
For my part, I don't disagree with this, although SDL doesn't currently seem to have any notion of a child window.

I guess I'm mostly concerned about two things:

  1. When you specify a window's location, you're actually specifying the location of the drawing surface / client area, which means that the window decorations such as the title bar and control buttons might end up off the screen. (Placing a window at 0,0 puts the title bar and left edge off the screen.) /If/ window positioning is supported by SDL (which it is), then it seems reasonable to be able to avoid putting the window in weird places that hide expected UI controls.

  2. You can't predict the size of the drawing area before creating a window. You can ask for a 100x100 drawing area and get back a 116x100 drawing area because of some OS-imposed minimum (which isn't but should be reported by SDL_GetWindowMinimumSize).

I would support having SDL handle window positioning entirely automatically, like x414e54 suggests should be the case.

But currently you need to use window positioning in order to deal with multiple displays, so if you want to put a window on display # 2, you need to set its position, and if you don't want some parts of the window to end up offscreen, you need a way to consider window decoration.

Anyway, those are my concerns. I'm not very attached to the proposed function signature I posted in the original comment. If somebody wants to solve the problem in a different/better way, that'd be fine with me. :-)

On 2015-06-17 03:46:29 +0000, wrote:

(In reply to Adam M. from comment # 13)

  1. When you specify a window's location, you're actually specifying the
    location of the drawing surface / client area, which means that the window
    decorations such as the title bar and control buttons might end up off the
    screen. (Placing a window at 0,0 puts the title bar and left edge off the
    screen.) /If/ window positioning is supported by SDL (which it is), then it
    seems reasonable to be able to avoid putting the window in weird places that
    hide expected UI controls.

Well most operating systems do this for you. SDL does not need (and should not need) to do anything.

As far as I know you cannot place a window over or under the system menu bar at least on Gnome 3 and OSX?
If it does then either it is a bug in the Window Manager or some user setting.

Do you actually have an example of this occurring?

If this really does occur then SDL should just calculate the correct position internally such that when an application requests 0,0 it will make sure to place it correctly and not over or under the menu bar.
That is part of the SDL abstraction. The application should not need to do this manually itself as there are plenty of old applications that will request 0, 0 and be placed over/under the menu bar.

  1. You can't predict the size of the drawing area before creating a window.
    You can ask for a 100x100 drawing area and get back a 116x100 drawing area
    because of some OS-imposed minimum (which isn't but should be reported by
    SDL_GetWindowMinimumSize).

I think this should be a separate bug so it does not get confused with the SDL_GetDecoratedWindowArea issue.

On 2015-06-17 11:09:49 +0000, Adam M. wrote:

As far as I know you cannot place a window over or under the system menu bar
at least on Gnome 3 and OSX? ... Do you actually have an example of this
occurring?
Yes, if you ask SDL to place a window at 0,0 in Windows (7), the drawing surface will be placed at 0,0 and the left and upper window decorations (e.g. title bar, system menu, and minimize, maximize, and close controls) will be off the screen.

Well most operating systems do this for you. SDL does not need (and should
not need) to do anything.
I would support this approach, but then SDL may need to report the size of the display differently. Currently a display has a particular rectangular area in virtual screen coordinates, and that represents the region in which you can place a drawing surface. If the drawing surface has decorations around it, and those decorations are to be automatically taken into account by SDL, then the available area for placing SDL windows should be shrunk accordingly so that all legal positions within the display area give reasonable results.

But then, the size of the decorations depends on the flags you give to SDL... for instance, it depends on whether you specify the SDL_WINDOW_BORDERLESS flag. So the area in which you can reasonably place a bordless window is different from the area in which you can place a normal window. Do you have any proposals for that?

I suppose SDL doing everything automatically as long as it's consistent. One possibility is to remove support for window placement entirely, and only allow you to specify which display the window should be on. But I think people would object...

  1. You can't predict the size of the drawing area before creating a window.
    I think this should be a separate bug so it does not get confused with the
    SDL_GetDecoratedWindowArea issue.
    I agree.

On 2015-06-17 11:11:28 +0000, Adam M. wrote:

s/suppose/support

On 2015-06-17 13:27:06 +0000, wrote:

(In reply to Adam M. from comment # 15)

As far as I know you cannot place a window over or under the system menu bar
at least on Gnome 3 and OSX? ... Do you actually have an example of this
occurring?
Yes, if you ask SDL to place a window at 0,0 in Windows (7), the drawing
surface will be placed at 0,0 and the left and upper window decorations
(e.g. title bar, system menu, and minimize, maximize, and close controls)
will be off the screen.

This seems like a bug with the Windows code.

But then, the size of the decorations depends on the flags you give to
SDL... for instance, it depends on whether you specify the
SDL_WINDOW_BORDERLESS flag. So the area in which you can reasonably place a
bordless window is different from the area in which you can place a normal
window. Do you have any proposals for that?

I suggested earlier something like a new flag:

SDL_WINDOW_FIT_TO_DISPLAY window maximum size will be set to fit inside the usable display bounds.

But this is starting to sound like you want a maximized window.

I suppose SDL doing everything automatically as long as it's consistent. One
possibility is to remove support for window placement entirely, and only
allow you to specify which display the window should be on. But I think
people would object...

Taking some newer protocols such as Mir or Wayland, do not support window placement for various reasons.

On 2015-06-18 02:11:45 +0000, Adam M. wrote:

I suggested earlier something like a new flag:

SDL_WINDOW_FIT_TO_DISPLAY window maximum size will be set to fit inside the
usable display bounds.

But this is starting to sound like you want a maximized window.
I'm referring to normal windows. (Position and size are automatic for maximized windows.)

If SDL supports window positioning, which it does, then it needs to have a way for you to know the valid range of positions (i.e. the available area). Currently you can try to use SDL_GetDisplayBounds. This reports the actual display size as reported by the OS. But SDL_Window coordinates seem to be for the drawing surface only and not the OS window. This means there are two coordinate systems. The SDL display coordinates are in actual pixels on screen, but the SDL_Window coordinates may be translated to account for window decoration. For instance, placing a 200x200 SDL_Window in the area 0,0 to 200,200 might actually create a 208x228 OS window from -4,-24 to 204,204.

My original proposal was effectively a function to help translate between these two coordinate systems. Another possibility is to have only a single coordinate system in which window decoration is always handled automatically by SDL, obviating the need for a translation function. This seems to be what you're getting at, although I'm not sure you thought about how it would affect functions like SDL_GetDisplayBounds. This latter possibility is also complicated by the SDL_WINDOW_BORDERLESS flag, since it changes the size of the window decorations.

Let's say the user has a single 1024x768 display. So I guess my questions about your proposal are:

  1. What does SDL_GetDisplayBounds return and what do the numbers represent? (Currently 0,0 and 1024x768, representing the resolution of the display and position in multi-screen space.)
  2. Does SDL_CreateWindow use the same coordinate system? (Currently no.)
  3. Can you call SDL_CreateWindow with any rectangle within the display bounds and get a window that's not clipped? (Currently no.)
  4. Is # 3 true if you use the SDL_WINDOW_BORDERLESS flag? (Currently yes.)
  5. If so, can you create a borderless window that fills all the available width or height without being clipped? (Currently, you can position it at 0,0 and use either a width of displayWidth or a height of displayHeight.)

It does seem cleaner to just get rid of window positioning entirely.

On 2015-06-18 03:02:20 +0000, wrote:

  1. Can you call SDL_CreateWindow with any rectangle within the display
    bounds and get a window that's not clipped? (Currently no.)

You will never be able todo this because you cannot know the position and size of a window until AFTER you create it.

However you know the position and size of a window after you create it so you can always size it to be inside the display bounds or the user can just move it or resize it.

  1. If so, can you create a borderless window that fills all the available
    width or height without being clipped? (Currently, you can position it at
    0,0 and use either a width of displayWidth or a height of displayHeight.)

How is this not a maximized window?

On 2015-06-18 11:51:31 +0000, Adam M. wrote:

You will never be able todo this because you cannot know the position and
size of a window until AFTER you create it.
Well, that was the purpose of my proposed function: to give the size before you create it.

However you know the position and size of a window after you create it
As far as I know, you actually don't. There's no way to get the position and size of a window in SDL that I can see. You can only get the position and size of the drawing surface in a kind of virtual coordinate system that is different from the real coordinate system on screen (and therefore different from the coordinate system used by SDL_GetDisplayBounds).

  1. If so, can you create a borderless window that fills all the available
    width or height without being clipped?
    How is this not a maximized window?
    Because I wrote "or" rather than "and". :-P Anyway, I wasn't proposing it as an important use case, only as a way to understand how your proposal would deal with the two coordinate systems that SDL currently uses.

On 2015-06-18 22:50:30 +0000, wrote:

(In reply to Adam M. from comment # 20)

You will never be able todo this because you cannot know the position and
size of a window until AFTER you create it.
Well, that was the purpose of my proposed function: to give the size before
you create it.

Yes but my point is even SDL cannot know the position and size of a window before it is created.
Two windows created with the same parameters may end up in two completely different positions or sizes.

The Window Manager is free to place the window anywhere it wants and at any size.
It will do its best to accommodate the requested size and position, but in a sense the WM is king and you just have to make do with what you get given.

Think about a tiling window manager for example, you get allocated a division of the screen. If there are no windows you will be allocated the fullscreen, if there is already one window you will be allocated half the screen and so on.

However you know the position and size of a window after you create it
As far as I know, you actually don't. There's no way to get the position and
size of a window in SDL that I can see. You can only get the position and
size of the drawing surface in a kind of virtual coordinate system that is
different from the real coordinate system on screen (and therefore different
from the coordinate system used by SDL_GetDisplayBounds).

SDL provides you with the absolute position of the client (drawable and event receiving) area of the window in screen space. Just because the origin of the window does not take into account the frame, does not mean it is a different co-ordinate system.

If it did not then the mouse co-ordinates would always be offset by the size of the title bar.
The mouse co-ordinate 0,0 is the top left of the client area of the current focus window.

On 2015-06-19 00:39:48 +0000, Adam M. wrote:

Just because the origin of the window does not take into account the
frame, does not mean it is a different co-ordinate system.
Well, whatever you want to call it. I'm not sure what, if anything, you're proposing the SDL developers actually do.

I'm proposing that if SDL is going to continue supporting window positioning, then there should be a way to position windows so that the window frame doesn't end up partially offscreen.

On 2015-06-19 00:53:46 +0000, wrote:

(In reply to Adam M. from comment # 22)

Just because the origin of the window does not take into account the
frame, does not mean it is a different co-ordinate system.
Well, whatever you want to call it. I'm not sure what, if anything, you're
proposing the SDL developers actually do.

I'm proposing that if SDL is going to continue supporting window
positioning, then there should be a way to position windows so that the
window frame doesn't end up partially offscreen.

A resizable window will always fit on screen. No matter what size you pick or location it will always be on screen and not clipped. If it does not then there is a bug in the SDL code or your window manager.

If you use SDL_WINDOW_MAXIMIZED then it will always fit on the screen and non clipped. If it does not then there is a bug in the SDL code or your window manager.

If your application can only support one window size (e.g. all your assets are hard coded and you did not implement scaling), I am not sure what you would expect?

There are going to be some systems where the window will be too large and some where it will be too small.

On 2017-08-14 13:57:00 +0000, Sam Lantinga wrote:

This is implemented in the API as SDL_GetDisplayUsableBounds()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant