Initial Glass support

written 13 Aug 2008
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

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.