Hack 79. Make Firefox Match the Desktop
Take away Firefox's distinctive look, so that it appears to be just another desktop soldier. This hack shows how to make Firefox inherit the appearance dictated by the desktop environment, whether that be Windows, Mac OS X, GNOME, or (sometime soon) KDesktop. Instead of looking like itself, Firefox can be made to look like everything else. Fundamentally, that means styling XUL content so that it looks right. There are also issues with portability [Hack #91] . There are several ways to provide desktop uniformity. The ultimate solution is to use the -moz-appearance style property, but let's dispose of the simpler alternatives first. 7.6.1. Building Static SkinsThe simple way to make Firefox look like the desktop is to build a theme that looks exactly like the desktop. Themes are made up of skins, with one skin per package. The easiest way to build such a theme is to start with an existing, quality theme such as the default theme, or a popular and well-maintained theme from the Mozilla Update site (http://update.mozilla.org). Then:
Static themes generally affect XUL content the most. Particularly for Firefox, a large portion of the main window is given over to HTML page display, and that display is resistant to theme changes. This is because a subset of the files in the res folder of the install area is always applied to HTML pages when they are displayed. html.css is the main file that causes these problems. If HTML pages absolutely must look like the desktop, either hack these resource files to conform or supply a desktop theme that uses the CSS2 !important directive to override other rules. A purely static skin is not very flexible. It applies to one and only one desktop, and can't keep up with any user changes. This is especially rigid on Unix/Linux, where a wide range of configuration options are available. If the desktop is locked down, though, it could be enough. 7.6.2. Building Static Skins with Smart ValuesA small improvement to static skins is to use smarter values in the skin's CSS styles. The CSS 2.1 standard provides a number of font names and colors that map directly to "whatever the desktop specifies currently." This means that small changes made by the user to the desktop's appearance are also picked up by Firefox. The fonts that act in this fashionfor example, serifinclude the special -moz-fixed font [Hack #45], as well as others described in section 15.3 of CSS2.1. The colors that act like thisfor example, THReeDDarkShadoware described in section 18.2 of CSS2.1. In addition, Firefox has some custom style properties that also apply desktop information. Although these special values transmit desktop styles accurately, they provide a very low-level solution. A menu designed to follow the default Windows XP desktop style requires this CSS style for its right edge: menupopup { -moz-border-right-colors: ThreeDShadow; } By comparison, a menu designed to follow the Classic (Windows 98) desktop style requires this style for its right edge: menupopup { -moz-border-right-colors: ThreeDDarkShadow ThreeDShadow; } There's no clean way to support both styles at once. One simple but horrid solution is to pack all required CSS rules for all required desktop styles into a sort of Frankenstein skin and then activate portions of the style depending on some flag set in the content. For example, if an XUL <window> tag is marked with an attribute desktop set to win98 or winXP, then that attribute can selectively choose the required styles: window[desktop="win98"] button { color : blue; } window[desktop="winXP"] button { color : red; } When the window starts up, a piece of JavaScript can flip the attribute, depending on the current platform. Alternatively, the script can modify the href argument of an <?xml-stylesheet?> processing instruction (PI). Both approaches are fairly desperate. 7.6.3. Exploiting -moz-appearance and Theme EnginesThe best solution offered by Firefox is the -moz-appearance style. This style is based on a couple of observations:
The -moz-appearance style tells Firefox, "Delegate the painting of this CSS style target to the native theme engine." Firefox works with Windows theme engines from Windows 98 and later, the pluggable Gtk theme engines, and Mac OS X's Carbon Appearance Manager. This technique is not used much in Firefox, although you can find some references in the xul.css file in the chrome. It is used extensively in the Classic style of the Mozilla Application Suite (1.x). Here is an example of the style at work. First, some XUL: <?xml version="1.0"?> <?xml-stylesheet href="chrome://global/skin"?> <?xml-stylesheet href="mozapp.css"?> <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <hbox> <button id="normal" label="No Native Theme"/> <button id="button" label="Native 'button' Theme"/> <button id="tooltip" label="Native 'tooltip' Theme"/> </hbox> </window> Second, some matching CSS: * { border-width :thick } #normal { -moz-appearance : none; } #button { -moz-appearance : button; } #tooltip { -moz-appearance : tooltip; } The first three styles are typical and correct. The last style mistakenly applies the Desktop theme engine's style for tooltips to the XUL <button> tag. Figure 7-5 shows the result (using Linux for a change). Figure 7-5. Natively themed and BlueCurve-themed XUL buttonsThe thick border is applied only to the first button, because that's the only button that Gecko is directly in charge of. Since the desktop theme (BlueCurve, in this case) doesn't specify thick borders, they're not drawn. If the theme is changed to Crux, then the window is restyled, as shown in Figure 7-6, without needing to be restarted. Figure 7-6. Natively themed and Crux-themed XUL buttonsYou would expect the window decorations (the titlebar) to change when a theme changes, but Firefox also supports changes to widgets within the window. To find all the valid values of -moz-appearance, either look in the xul.css file in toolkit.jar in the chrome, or search for kAppearanceKTable in the nsCSSProps.cpp file at http://lxr.mozilla.org. |