DesktopWidth/Height fail in full-screen (Win32)

Archives Forums/BlitzMax Bug Reports/DesktopWidth/Height fail in full-screen (Win32)

BlitzSupport(Posted 2011) [#1]
[EDIT: Oh, God, apologies, Mark... see 4th post as to why I'm wrong, so far anyway. I think it's worth a read for people, though!]

I think this is something people have just assumed you have to call before going full-screen, but I think it's wrong...

DesktopWidth...

int bbSystemDesktopWidth(){
	return GetDeviceCaps( GetDC( GetDesktopWindow() ),HORZRES );
}


According to the Win32 GetDeviceCaps docs, HORZRES is "Width, in pixels, of the screen". However, that relates to the currently set display mode, not the desktop size. (In fairness, the desktop is resized to the current display mode behind the scenes, but that's invisible to the user if the program cleans up properly, and frankly not much use to us anyway.)

This was made clearer when I experimented in this thread, which should show that this code should be updated to reflect MaxGUI's GadgetWidth (Desktop ()).

This shouldn't cause any problems as far as I can see. It will simply mean that programs get the correct desktop resolution on Windows, regardless of whether it's stored before Graphics or while running in another display mode.

* In full-screen mode -- it's already correct in windowed mode because the display size is the desktop size.

In effect, in full-screen mode it currently just returns the current GraphicsWidth* instead of what it's meant to return.

Another reason I've jumped on this is because it caused me to have to provide a really ugly "InitVirtualGfx" hack in this Code Archives entry!

Last edited 2011

Last edited 2011


GfK(Posted 2011) [#2]
Reported this many months ago and was told it was normal behaviour. :/

[Edit] http://www.blitzbasic.com/Community/posts.php?topic=90148#1024959

Last edited 2011


BlitzSupport(Posted 2011) [#3]
Well, he said he couldn't find a way to get the right display size, but I reckon I've explained it in the linked post. Hopefully what I've posted here can be confirmed by RobA. I mean, like the man said, "I'm just gonna leave it as is for know unless someone has an better ideas"!

Dunno about the Mac, but I think this should actually trump consistent behaviour -- if the Mac can't provide the primary monitor's display size, that's its problem! (But again, no existing code should break anyway; if anything, it should 'fix', to get the correct size!)


BlitzSupport(Posted 2011) [#4]
Oh, cripes, I think Mark was right, actually.

When you think about it, Windows can treat the desktop as if it's the size of combined multiple monitors' current resolutions, which can be independently set, though I'm not even going to go there:

Monitor #1: 640 x 480
Monitor #2: 640 x 480

Windows desktop: 1280 x 480


This is (partially) dependent on whether the graphics drivers have been set to clone the desktop (which would return the 'correct' size of the first display) or to spread across both (or even > 2).

Regardless, any attempt to return the (Windows) desktop size is going to return either a) the combined size of all monitors, or b) the primary monitor's current resolution, depending on driver settings, Windows monitor settings and how you try to retrieve them.

The Windows desktop takes on the resolution of the current display size, whether the driver is treating the display as a single monitor (which may be duplicated) or spreading it across multiple. It's restored when the display is set back to the original display mode (eg. 1920 x 1080 desktop, game opens 640 x 480 screen [at which point desktop is 640 x 480, and may remain that way if game crashes], restores display mode to original 1920 x 1080, on which the desktop resizes again to 1920 x 1080).

Take into account that another OS could treat its monitors and desktop completely differently, and I'm not surprised that so few products take multiple displays into account -- and I'll bet those that do could be easily tripped up.

My suggestion of using MaxGUI's GadgetWidth (Desktop ()), which returns the correct desktop size regardless of whether it's spread across one monitor or multiple, doesn't update when you Alt-Tab out and change the display resolution. In fact, after messing about with this too much, the Nvidia Control Panel kept freezing and eventually I hung the whole desktop! (Had to reboot.)

Still working on this...


BlitzSupport(Posted 2011) [#5]
Nope! My belief, based on past explorations and this evening's experiments, is that the Windows desktop simply adapts to whatever the current physical display resolution is on the monitor (and this is dependent on the fact that the graphics card may be presenting two or more monitor/s as one), and that all you can do is store whatever it is before you change the display size.

I do have one last hope (based on EnumDisplayMonitors/GetMonitorInfo[A] and/or EnumDisplayDevices), but my tests are failing here so far...


GfK(Posted 2011) [#6]
He probably is right - but then DesktopWidth shouldn't be called that if its not reporting the width of the desktop!


Floyd(Posted 2011) [#7]
...the Windows desktop simply adapts to whatever the current physical display resolution...

That's consistent with an aggravation from the distant past, back when 640x480 was a common resolution for full screen games. When one of them crashed the desktop was left in the same resolution. Icons were automatically relocated to fit the screen. I could reset a higher desktop resolution, but that left the icons stuffed into the upper left quadrant.


BlitzSupport(Posted 2011) [#8]
I sort of agree, but I think if the docs were amended to state that you have to call it before a Graphics call, then it would be correct, based on how Windows's desktop appears to work. Unfortunately, I (mostly) believe that the above is true!

I'm fiddling with EnumDisplayDevices, which I should be able to force to the primary display device (monitor) (basing this on the DEVMODE structure used by ChangeDisplaySettings), but again it's crashing its ass off, so I'm going to have another go in (whisper) PB. However, I still think that even if I get it to work, it's going to read whatever the *current* monitor display mode is!

I'm pretty much resigned to having to store the desktop size before opening a display -- I believe this is how Windows works.


GfK(Posted 2011) [#9]
Way I see it, Windows knows what your desktop resolution is. Even if it changes when something goes full screen, it knows how to change it back. So the info has to be in there somewhere.


BlitzSupport(Posted 2011) [#10]
@Floyd: yeah, and this can still happen!

BTW If anyone here runs into this now and then, use DesktopRestore. Install it, right-click on the desktop and choose Save Desktop.

After having your resolution screwed up, and after fixing your resolution, right-click on the desktop and choose Restore Desktop to put your icons back in place. It's great!


BlitzSupport(Posted 2011) [#11]
@Gfk, it would seem logical for that to be the case, but I now believe it to be otherwise -- I believe any reference Windows makes to the desktop size is retrieved the way we've been doing in this post and my referenced post, on the fly; as far as I can see, the graphics driver stores the actual resolution the monitor is set to (in its own proprietary location) and sets things up on reboot, etc, and Windows adapts to that by querying the driver.

It seems that apps have to restore the original desktop size, or have it restored for them by the library they're using, eg. DirectX. I would dearly love to be proved otherwise on all this, by anyone at all, anywhere, but I've explored this almost as far as I possibly can anyway.

Have a look at "Part iii" of this OpenGL tutorial, for example; this is why I'm still looking into ChangeDisplaySettings, as mentioned above, but I'm not holding out much hope.

In fact, ChangeDisplaySettings is in glgraphics.win32.c, under BlitzMax\mod\brl.mod\glgraphics.mod. (Apparently DirectX stores the information itself and restores on exit, but, again, it can do this at the start.) Blitz uses Null/0 to reset the display size on loss of focus, as, according to the docs: "Passing NULL for the lpDevMode parameter and 0 for the dwFlags parameter is the easiest way to return to the default mode after a dynamic mode change."

There's quite an in-depth discussion of this stuff on the OldNewThing, which is a bit of a Windows Obscurity Bible, making reference to the weirdnesses that ChangeDisplaySettings can cause. (And I bet you anything that DirectX calls this.)

Still gonna fiddle with EnumDisplayDevices, but I'm pretty sure all I'll get is whatever the referenced monitor is *currently* set to and that the above is correct, however unbelievable it appears to me or anyone else!

EDIT: For what it's worth, and check out the OldNewThing link, I believe this is left to the running app (excepting possibly for DirectX handling it when it's in control), however poor a decision that would appear to be historically:


Even if it changes when something goes full screen, [Windows] knows how to change it back



Last edited 2011