Rob Arnold’s Blog

witty tagline

Initial Glass support

Yesterday, I pushed my patch to add glass support to chrome windows for Vista (see bug for some implementation discussion). For those who don’t use Vista on a physical machine (virtual machines don’t support glass): it is a fancy blurring effect rendered using the system’s graphics card. It is part of Vista’s Aero theme but requires some hardware support beyond Vista’s minimum requirements. The changes overall are mostly trivial, but they required lots of little edits over many files.

Example Glass Window

Example Glass Window

How to use it

Start by adding the CSS property -moz-appearance: -moz-win-glass; to your XUL window. For any areas that you want to be glass, be sure to make their backgrounds transparent. This includes the window itself. You can also set the opacity on elements to have them blend with the glass as transparent windows already do. Ok, you’re done.

Well, almost done. The glass effect is possible only when the user has desktop composition enabled, which requires a reasonably modern graphics card. Also, they can toggle it on or off at runtime as with native themes. Oh, and it only seems to work with the Windows Aero theme; Aero Basic users are left behind.

Rather than add some fallback code when glass is disabled, I left the issue to the theme designers. There’s a new system metric selector, windows-compositor, which detects if the glass effect is enabled. Now you can setup your CSS rules like this:

window:-moz-system-metric(windows-compositor) {
  background: transparent;
  -moz-appearance: -moz-win-glass;
}

to add glass to your window’s client area (and presumably other UI changes) when the user enables composition.

Here are some example rules for emulating the fallback used by Media Player and Explorer:

window[active="true"]:-moz-system-metric(windows-default-theme) {
  background-color: #b9d1ea;
}
window:not([active="true"]):-moz-system-metric(windows-default-theme) {
  background-color: #d7e4f2;
}
window:not(:-moz-system-metric(windows-default-theme)) {
  background-color: -moz-Dialog;
}
window:-moz-system-metric(windows-compositor) {
  background: transparent !important;
  -moz-appearance: -moz-win-glass;
}

Note: When bug 431666 lands, you’ll want to use windows-classic instead of windows-default-theme in your selectors.

Gotchas

The Desktop Window Manager (DWM) draws a border around the window’s client area, but our method of enabling glass disables that, so if you want to achieve the same look as Media Player or Explorer, you’ll have to do some fancy border work. I hope to fix this in the future so that it is automatically done in most cases.

Text on glass is hard. It’s sometimes hard to read which is why Windows provides the DrawThemeTextEx function which adds a glow behind the text; this is done by the DWM for the window title of unmaximized windows. DrawThemeTextEx takes characters, not glyphs so we can’t really integrate it into our text rendering code. CSS text-shadow can fake the glow, but it doesn’t work on the XUL widgets you’d want to use for your UI. So for now, don’t count on using text on glass.

Content (the xul browser element specifically) doesn’t render quite properly on glass. The underlying issue seems to be present in Firefox 3 (with transparent windows though) and will probably be fixed when the internal compositor for Gecko is completed. This unfortunately prevents Firefox from adopting IE7’s Vista UI.

Under the hood changes

Previously, windows were either transparent or not, so I added an enum nsTransparencyMode for the three options: opaque, transparent, and glass. Only windows supports the glass option; the other platforms fall back to opaque. A glass nsWindow calls DwmExtendFrameIntoClientArea to tell the DWM to render the entire window as glass. This has a performance impact for large windows since the entire window has the (already expensive) glass shader applied to it, even though we are probably going to be painting most of the window opaquely. I’m looking into ways to detect which areas of the window are glass and tell the DWM to only render those areas. This also solves the aforementioned border problem. We also have to render each window with an alpha channel, so there is a rendering performance hit.

Demos

I have two little demos to show off. The first (and its style sheet) was my testcase which shows opaque, semi transparent and transparent XUL on a glass window. The second uses an animating CSS transform on a green box with text on plain glass window. Since CSS transforms haven’t landed yet, you’ll need do a build yourself with the patch applied.

8 comments

8 Comments so far

  1. Blair McBride August 13th, 2008 7:48 pm

    This is great news! Its things like this that contribute to the OS integration and a standard native feel for a given OS.

    Good work – thanks :)

  2. Lee August 13th, 2008 8:32 pm

    Perhaps for the blur optimisation you could use DwmEnableBlurBehindWindow with hRgn set to the non-transparent bits. The docs are a bit vague on exactly what it does, though; I’m not sure it will perform any better.

    It seems to me it would be a lot more useful to have the full functionality of DwmExtendFrameIntoClientArea available from CSS, rather than just the “sheet of glass” effect which isn’t used very much. It also doesn’t have the same performance implications since it’s usually used much more conservatively.

    At least you didn’t go the colour key route for rendering – text rendered that way tends to look very odd indeed, due to cleartype rendering the text with the (usually magenta-ish) colour key as the background.

    And regarding the colour used for rendering the fallback like WMP: I expected it to be the “favourite colour”-style thing set in the personalisation options. It seems not, though.

    Of course, I know you won’t want to use a hack like this (it definitely won’t work in Windows Standard or Windows Classic), but I can’t resist suggesting it: use DrawThemeBackgroundEx with Theme=AEROWIZARD, Part=AW_TITLEBAR, State=0 or 2. It seems to get the right colour, anyway. :-)

  3. PJ Cabrera August 14th, 2008 1:59 am

    I find it ironic that just as it starts to look likely that the GPU is the next frontier of performance squeezing terrain available, users are already taking up that valuable processing space to render BS eye candy. :-)

  4. PJ Cabrera August 14th, 2008 2:04 am

    No disrespect is meant at the hacker for the feature and at the effort spent getting this to work. Hats off, Rob. I just find it funny/ironic, that’s all.

  5. DigDug August 14th, 2008 7:26 am

    I still can’t figure out why you guys insisted on doing it this way. Seems better to store offsets from the frame in nsNativeThemeWin and then only request glass in the areas (around the edges) where you want transparency. If its requested from a piece of chrome thats not along an edge, then make the whole page glass, or just ignore it. That would take a load off of the DWM, avoid all the transparency in the content area issues, and it follows the recommended usage better too.

    Is there some reason you insisted on drawing the entire window glass?

  6. Rob Arnold August 15th, 2008 9:24 am

    Lee:
    I considered the blur behind method, but the window border doesn’t disappear as you can see here: http://weblogs.asp.net/kennykerr/archive/2006/08/10/Windows-Vista-for-Developers-_1320_-Part-3-_1320_-The-Desktop-Window-Manager.aspx
    It would be nice to have all of DwmExtendFrameIntoClientArea available to CSS, but I couldn’t find a good API that would respond to elements resizing.
    As for the colorization, the Aero Basic doesn’t respect that which caused quite a stir when it was announced.
    As for your hack, I looked through a lot of parts and states and didn’t find one that quite worked as I wanted; there were some redraw issues too.

    PJ: This is more about native OS look and feel than eye candy for the sake of eye candy :)

    DigDug: I considered that, but it still seems like a hack; we may do it nonetheless. The current implementation was mostly to let the UX team and theme designers play with it and see where it would look good in the UI.

  7. [...] XUL добавлены средства для создания прозрачных и полупрозрачных [...]

  8. [...] New selector to create areas of Aero-style “glass” in XUL [...]

Leave a reply