Vista auto-fullscreen-detection disabling aero?

I’m working on OpenGL based game on windows. If I make the window with the OpenGL context cover the whole screen, it seems that Vista automatically flags the app as being ‘full screen’, and disables aero to boost performance. I don’t even have to call ChangeDisplaySettings(…, CDS_FULLSCREEN) - It is entirely automatic!

Now, the problem is, what if I don’t want it do that? I would like to control myself whether aero is disabled (or not disabled, as the case may be). Enabling or disabling aero is a fairly disruptive event, taking up to 10 seconds to complete and flashing the screen several times. And this happens every time the user alt-tabs to/from our game.

Frankly, I don’t understand why Microsoft would do this. If an application wants fullscreen mode, it can specify that by calling ChangeDisplaySettings with CDS_FULLSCREEN. That’s how it worked on XP so everyone is doing it already anyway.

I have noticed that some other apps that do hardware accelerated 3D, specifically VLC and Media Player Classic, CAN toggle between windowed and fullscreen without causing aero to get toggled. I don’t know if they use OpenGL though.

So, my question is, does anyone know anything about this automatic fullscreen thing in Vista, and how to control it? I apologise in advance if my google-fu is weak, but I just couldn’t find anything related to this at all. Not in the documentation or on the net in general.

Windows define “fullscreen” as a WS_POPUP, SW_MAXIMIZE, topmost window. This is the same as XP, only XP doesn’t have Aero so the transition is less jarring. (Don’t believe me? Try using ‘print screen’ on an application with those styles).

CDS_FULLSCREEN is completely orthogonal to that - this is merely a hint to restore the original display settings when the application exits. CDS_FULLSCREEN does not in any way affect whether an application is considered fullscreen or not (you can ChangeDisplaySettings(CDS_FULLSCREEN) and keep your application windowed just fine).

So how can you create a maximized, borderless window that doesn’t trigger the “fullscreen” effect? To the best of my knowledge, you can only do this by not using SW_MAXIMIZE on the window. Instead, make it fixed size and resize it so that it covers the whole monitor (or working area, if you wish to keep the taskbar intact). Annoying, but this seems to be a very common workaround that (I can confirm) works fine. The only issue is that you need to respond to display change events, if you don’t wish your application to look broken.

If you manage to find a better solution, please post it!

VLC on windows and Media Player Classic do not use GL by default.
For vlc you can force it somewhere on the advanced settings, that way you can check if vlc is affected too.

Thank you both for the replies. That’s interesting - and good to know - about CDS_FULLSCREEN being orthogonal to windows considering the app to be fullscreen.

I’ve done some further investigation. VLC under OpenGL does not experience the problem.

Stephen A is correct about it being related to the window flags, but my tests indicate it also has to do with OpenGL. If I use the same combination of flags that causes the problem, but just BitBlt a bitmap instead of using OpenGL, then aero does not get disabled.

According to my experiments, the condition appears to be something like this:

disableAero = usingOpenGL && (windowRect == screenRect) && ((flags & WS_POPUP) || isTopMost)

SW_MAXIMIZE (and/or WS_MAXIMIZE) do not appear to be related.

(Shouldn’t this stuff be documented somewhere???)

I was able to mostly get the desired behavior by removing WS_POPUP and not making the window topmost. I was also able to regain most of the speed lost by not disabling aero by rendering to the front buffer and using glFlush instead of SwapBuffers.

However, making the window “not topmost” creates another problem: The taskbar isn’t always hidden anymore! Sometimes it is, sometimes it isn’t - I’m not really sure what the condition is, but it looks really silly to have it visible in-game.

Any ideas how I can simultaneously not disable aero, and ensure the taskbar is hidden?

I’ve always assumed that the window needed to be maximized for the fullscreen mode to be enabled, but you say it only needs windowRect == screenRect? Interesting!

Since VLC is open source, I’d suggest digging into its source to see what exactly is going on when it goes fullscreen. Another pssibility is to use a tool that can display the styles of a specific window (I think sysinternals releases such a tools for free) - this should show the exact combination you need to use.

As far as I know fullscreen mode is enabled only for OpenGL or D3D applications. Among other things, it causes the secondary monitors (if any) to go black and causes print screen to capture black rectangles.

Finally, I would suggest against drawing to the frontbuffer, both for obvious reasons (flicker) and less obvious reasons (it doesn’t cooperate well with compositors and may cause Aero to be disabled on some systems).

Sorry, no idea about the taskbar.

Correct me if I’m wrong, but I think rendering to the front buffer is fine for “non fullscreen” apps, because in windowed mode the OpenGL frontbuffer acts like a backbuffer. When you call glFlush, the frontbuffer gets copied into the compositing surface, and then it becomes visible.

Windowed applications that use frontbuffer rendering without ever calling glFlush or glFinish (as they should) are likely to appear completely black, because the rendering will sit forever in the offscreen frontbuffer. Not even switching the DWM off is likely to fix these, given that the offscreen frontbuffer is a requirement of the driver model itself.


Actually, I tested this with fullscreen too and it seems fine (no flicker). I also noticed that aero does not get disabled unless SwapBuffers is called.

So the condition can be modified to

disableAero = usingSwapBuffers && (windowRect == screenRect) && ((flags & WS_POPUP) || isTopMost)

This means that I can use popup and topmost as long as I don’t use swapbuffers. I think that solves all my problems.

Yikes, using only front buffer seem … so disturbing.

You basically just hope that the compositer will display your frame at the right moment. Normally this moment is when swapbuffers is called, but without it, how do you mark your frame as complete ?

Fine if it is fine for you, just be warned that this sounds very fragile.

>> Enabling or disabling aero is a fairly disruptive event, taking up to 10 seconds to complete and flashing the screen several times.

That sounds a wee bit high. Shouldn’t take more than a second or thereabouts. A call to SetWindowLongPtr + SetWindowPos should do the trick.

Tests indicate that it works on ATI and nVidia but not Intel integrated graphics. So you are correct, it does not work in general. Unfortunately :frowning:

This is a bit of a non sequitur, I think perhaps you didn’t understand the topic?

Let’s recap:

  1. I was looking for a way to have my app not disable aero while fullscreen.

  2. We discovered (at least part of) the condition under which aero is diabled:

disableAero = usingSwapBuffers && (windowRect == screenRect) && ((flags & WS_POPUP) || isTopMost)

  1. This leads to two methods to avoid disabling aero while fullscreen:

either (don’t use SwapBuffers), or (remove WS_POPUP and make the window not topmost).

The former just isn’t usable (doesn’t work on intel integrated graphics) and the latter has an unfortunate issue: If the window is not topmost, then the taskbar can cover up part of the app which isn’t acceptable for fullscreen.

So I still don’t have a complete solution.

Did you look at VLC source to check how this problem is solved ?

another alternative is to completely disable aero when your application runs using DwmEnableComposition.

-fullscreen exclusive mode- is a performance optimization, so different vendors will have different ways to handle it…

The problem with disabling Aero for me is that vsync seems to stop working (on Nvidia cards atleast), so I need it to stay enabled.

I have never seen Aero get disabled when using regular double buffering / SwapBuffers on a fullscreen (WS_POPUP, topmost) window. Tested on Intel, Nvidia and Ati cards, it works fine.

Problems start arising when you draw to the front buffer - this simply won’t work reliably in a composited environment.

I can confirm your observation regarding vsync on NVIDIA HW. VSync works well when using WinXP or Vista/7 with aero enabled. When I disable aero the vsync does not work anymore. I also tested wglSwapIntervalEXT. There was no improvement. I am using double buffered OpenGL window.

Maybe it has something to do with refresh rate. My app refreshes the window at about 1/2 of screen refresh rate. Maybe there is some “smart” optimization to disable Vsync when you are late.

NVIDIA, any suggestions?

Most problem is that those performance optimizations are NOT controlled by Windows itself. Someone give GPU drivers to do that and now we have uncontrolled behaviour…

I found that AMD/ATi add this ‘Aero off’ in Catalyst for Windows 7 not long time ago. I tested last year drivers and ‘auto Aero off’ not appear with them, but with ~this year~ drivers it happens.

Sure for heavy games it is very useful to get more performance, but for light-weight applications like my image-viewer/movie-player it is very ANNOYING.

I tried to play with dwmapi, but while no functions to lock Aero state - them not too useful…

If someone found the solution - please tell!

Has anyone used PFD_SUPPORT_COMPOSITION = $00008000
for the dwFlags component of when using ChoosePixelFormat.
I use the following dwFlag options:

I tried PFD_SUPPORT_COMPOSITION, but I noticed NO difference in behaviour on both, ATI and Nvidia.
It may be, because WGL_ARB_pixel_format (which is probably the preferred method today) has no equivalent for PFD_SUPPORT_COMPOSITION anyway…

Better leave PFD_DRAW_TO_BITMAP and PFD_GENERIC_ACCELERATED away - you certainly don’t want the MS software GL ICD kick in :wink:

How do I switch a window between normal and fullscreen?

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.