The X Window System is wildly configurable. Here's how to make X look and
It’s midnight and you’re staring at your screen once again. What’s staring back at you? A game? A browser window? System status information? Emacs?
Whatever’s on your display, if you’re using Linux, you’re staring at the results of years of development in the form of the X Window System (or just plain “X”). Originally developed for UNIX machines and later ported to Linux, X draws every pixel and processes every mouse click and key press. More significantly, X provides Linux with a substantial and differentiating competitive advantage: you can make Linux “look and feel” any way you want.
Unlike proprietary window systems, X was specifically designed to be customized. Rather than impose a single look and feel on an application or the desktop, the designers of X chose instead to provide infrastructure — protocol, paradigms, and APIs — and left it to others to specify and build different user interfaces. And, indeed, the variety of graphical user interfaces is one of the things that makes Linux fun to use. Unlike proprietary window systems — like Microsoft Windows and MacOS — you can choose the interface that works best for you.
Don’t like GNOME? Try KDE. Love the old NEXTSTEP interface? Try the AFTERSTEP window manager. Want to change the way xclock looks to complement your Amiga desktop? You can. Want to make xterm work like an old VT220. No problem. (You can find a plethora of Linux desktops and X window managers at http://www.xwinman.org.)
Let’s take a look at the facilities and tools that X provides for customizing applications. With a little effort you can take that stock display of yours and turn it into a throaty, 500HP, candy-apple-red street racing machine. Or, perhaps you’d prefer the green metallic-fleck paint job. Hey, it’s your display. Go crazy.
Although many flavors of X exist, we’ll be looking at the most popular version used in Linux systems — XFree86 (http://www.xfree86.org), the open source implementation of X for Intel-based systems.
X is a networked windowing system. Any machine with a display, keyboard, and mouse can be an X server. And every machine in the network can be an X client. The X Protocol, a messaging scheme that transmits commands like “draw a line” and “left mouse button clicked,” connects an X server and its clients.
X’s notion of server and client might seem backwards if you’re used to thinking of a client (like your PC) as “local” and a server as “remote.” But think about the roles a traditional server and client play. A traditional server has resources to share; clients connect to the server and use those resources. That’s exactly the model that X follows, too. The X server has resources — the display, the mouse, and the keyboard (and others, too) — to share. X clients connect to the server to draw windows and get input. The X Protocol handles all the back and forth.
Even if your computer plays the roles of both server and client (which is probably the case if you use Linux on your desktop), the X Protocol still makes everything happen. X applications running on your desktop computer still use the X Protocol to talk to the X server.
You connect to an X server by specifying its hostname or IP address and a display number, usually just 0, separated by a : (A single X server can manage any number of X displays, but on most Linux systems, you’ll only be running one.)
Thus, if your PC is named hulk.linuxmagazine.com, you would connect to the X server on that machine from a remote host with the string hulk.linuxmagazine. com:0. If you’re running an X application locally on your PC, you can still refer to your X server as hulk.linuxmagazine.com:0 or abbreviate it as :0 (:0 is short for localhost:0).
For example, let’s say you’re logged on to the machine spawn.linuxmagazine.com and want to display an X terminal window on hulk.linuxmagazine.com. You can use the command:
% /usr/X11R6/bin/xterm -display hulk.linuxmagazine.com:0
All X applications accept the -display argument, which specifies what X display to connect to. If you don’t want to type -display hulk.linuxmagazine.com:0 all the time, you can set the shell environment variable $DISPLAY instead.
% export DISPLAY=hulk.linuxmagazine.com:0
If $DISPLAY is set, X applications will connect to the display named in that variable. However, the -display command-line option always overrides the value of $DISPLAY (this is true for all X applications; command-line arguments have precedence).
X Resource Classes and Instances
Each widget in an X application also has a class associated with it. A class is a category or type. For example, fruit is a class of produce. An apple is an instance of a fruit — in other words, it falls within the category of fruit. Similarly, each widget belongs to a class, but each widget is an instance of that class.
The distinction between a widget’s class and its instance is important. For example, the following resources have very different effects.
To see the difference, run the following commands.
% echo ‘XClock*Foreground: blue’ | xrdb -load
% xclock &
% echo ‘XClock*foreground: yellow’ | xrdb -load
% xclock &
|Figure One: The difference between Foreground (right) and foreground (left)|
Figure One shows the results.
Surprised? The resource XClock*Foreground refers to the class of all foreground widgets. XClock*foreground refers only to the foreground color of the clock face. Widget classes make it easier to modify many X resources with a single command.
As it turns out, XClock*Foreground is the equivalent of the following X resources:
X applications also belong to classes. There is a difference between XTerm*foreground: darkblue and xterm*foreground: darkblue. The former would apply to all applications in the class XTerm. The latter would only affect the xterm application itself.
Try the following and see what happens.
% echo ‘xterm*foreground: white’ | xrdb -load
% echo ‘xterm*background: black’ | xrdb -load
% % echo ‘XTerm*background: yellow’ | xrdb -load
% xterm &
% xterm -name adam
The command xterm -name adam changes the instance name of xtermto adam instead of the default name xterm. Only the generic resource XTerm*background applies because adam is still an XTerm application.
More X Basics: X Resources
As mentioned above, X was designed to support many different graphic user interfaces. The developers of X, like the developers of UNIX, built the system as a collection of components. Using the X Protocol, developers can create their own user interface toolkits, window managers, and desktops — and many have. Sun Microsystems created an X-based implementation of Open Look; the Open Software Foundation created OSF/Motif; and others have created clever window managers with “virtual” screens, icon docks, and pluggable themes. GNOME and KDE are excellent examples of just how flexible X is.
Certainly, all graphical interfaces allow for variations via preference settings. But X is so customizable that you can change almost everything that appears on the screen — the labels on buttons, the background color of windows, the font in your text editor, even your entire desktop.
If you look around your office at the displays of the folks running Linux, you’ll probably see a wide variety of user interfaces. Every Linux display is likely to have different window decorations, colors, even different window management schemes. Chances are that even the same X application (like xterm) looks and acts differently from one user to the next.
Preferences in X can be expressed in two ways: using command-line options or using X resources. We won’t cover command-line options except to say that they’re best used for exceptions. As we’ll see, X resources are generally the preferred method to set preferences because they’re persistent and pervasive — they can affect all X clients.
Let’s say you want yellow text on a black background in all of your xterm windows. You could type xterm -fg yellow -bg black each time you invoke xterm, or you could run the following commands once and customize all new xterm windows:
% echo ‘XTerm*Foreground: yellow’ | xrdb -merge
% echo ‘XTerm*Background: black’ | xrdb -merge
To see the changes, just run xterm again. Now the foreground is yellow and background is black. Let’s dig a little deeper and find out how and why this happened.
The X Resoucre Manager
If you’ve used Microsoft Windows, you are probably familiar with the Windows registry. Windows itself, and almost all Windows applications, use the registry as the central repository for system and user preferences. When a Windows application launches, it reads the registry and configures itself to match your preferences. (If you use a Macintosh, the System Folder:Preferences folder acts as a repository in MacOS).
Like Windows, X has its own preference database called the X Resource Manager (or XRM). Like the registry, XRM is a central repository that all X applications can read and modify. When an X application launches, it pulls its preferences from XRM and customizes its appearance based on the settings.
You may be wondering “if an X application can run on any machine on the network, where’s the XRM repository stored?” The answer is simple: XRM is part of the X server, where it’s managed as a central resource just like the screen, keyboard, or mouse. Any X client can add to, read, or modify the repository by sending the proper protocol messages to the X server.
If you want to see what preferences are currently stored in XRM, just run the command:
xrdb is a special X client specifically built to read and modify entries in the XRM. We’ll use xrdb a lot in our examples.
X Resource Files
While the X server provides a centralized preferences store, it was not designed to provide persistence. X itself has no notion of a “current user” and therefore no way to differentiate your preferences from another user’s. So, if the X server shuts down or is reset (as it is between X sessions, which we’ll cover later), all current preferences are lost.
To store preferences (also referred to as “resources”) from one session to the next, you need to use an X resource file. X resource files are text files where each line in the file looks something like this:
Each line says, “In the application Client, set the preference named resource to value.” For example, the following resource says, “In the xclock application, set the clock’s hands color to blue” (Capitalization is important; we’ll get to that in a bit).
The default X resource file is $HOME/.Xresources. When X starts, or when you login via the X Display Manager, X initializes the X Resource Manager with the preferences stored in $HOME/.Xresources. Listing One shows a sample $HOME/.Xresources file.
Listing One: A sample $HOME/.Xresources file
!!! .Xresources file !!!
! Comments start with !
! change document font to helvetica
! change link colours
There are a few important rules to remember when editing your X resource file:
- There is a difference between using periods (.) and asterisks (*) as separators. We’ll explain the difference in the “Widgets” section.
- You can add comments in your X resource file by starting a new line with!
- Make sure you put one or more spaces (or tabs) between the colon and the assigned value. And, don’t forget the colon. Although it may not seem significant, it’s essential; if it’s left out, the line will be ignored.
- Client names are usually capitalized (e.g., XTerm or Netscape. If an application name starts with an “X”, the second letter is also capitalized, as in XClock.
- The order of the lines in an X resource file doesn’t matter, as long as there are no conflicts (for example, XClock*hands: red and XClock*hands: blue). If there is a conflict, a warning is usually given, and the setting that appears last in the file is used.
- The Client portion of a resource can be omitted. If it is, the setting applies to all X applications that support the named resource. If you omit the Client portion of the line, the line must begin with a *.
If you edit your $HOME/.Xresources file and want to update the XRM immediately, you can use the command:
% xrdb -merge $HOME/.Xresources
The -merge option adds your preferences to the X Resource Manager. If the XRM already contains some of those preferences, your new settings will overwrite them. Optionally, if you want to completely replace the contents of the XRM, use xrdb -load $HOME/.Xresources. The -load option empties the XRM database and loads it from scratch with your resources.
Whenever you modify the XRM, your new preferences take effect immediately, but typically do not affect X applications that are already running.
From time to time you might see an entry in an X resource file that looks like this:
This syntax is perfectly acceptable. It says, “In all X applications, set the foreground color of everything to black.” In fact, there are many ways to express preferences in an X resource file. You can be very precise and change the background color of a single button in a specific application, or, you can be general and change the color of all text drawn on the screen.
In X, almost every object that’s drawn on the screen — what X refers to as a widget — can be customized. To customize how a widget looks, you simply need to know the widget’s name and the name of the property you want to customize. A widget’s name is like a file path — the name uniquely identifies the widget and reflects its place in the application’s internal structure. Periods (.) are used to separate each step in the widget’s name (like the slash in a Unix file name).
For example, the fully-qualified name of the hands property in the xclock application is XClock.xclock.clock.hands. Here, XClock is the application name; xclock is the main xclock window and the container for all other widgets in the application; clock is the widget that draws the clock face; and hands is the color of the clock hands. To set the xclock hands to red, you’d use this line in your $HOME/.Xresource file.
XClock*hands: red will accomplish the same thing. The * says, “no matter what the widget hierarchy is, set the hands property to red. Similarly, *foreground: black says “No matter what X application, no matter the widget hierarchy, set the foreground property in every widget (if it has such a property) to black.
There is one difference between XTerm.xclock.clock. hands: red and *hands: red: the former is considered more specific than the latter and takes precedence if both resources exist in the XRM.
You should be careful when using * as a shortcut to setting a property. Using XClock*hands: red means that every widget that has a hands property will be colored red. While hands is very specific to xclock, you could cause unexpected color change in all applications if the resource name in very common.
Getting Resource Information
Most X applications have man pages that describe what preferences you can set, including the application-specific widget and property names to use (for example, xterm). Another good source of information on customizing X applications is other people’s X resource files.
An even better method is to modify preferences interactively with editres. editres lets you see the internal widget hierarchy of any X application (provided the application supports the Editres Protocol) and interactively browse and modify properties. Even better, editres lets you see changes instantly. Let’s see how it works.
|Figure Two: The editres application|
For this example, we’ll use xclock. First, launch xclock and then launch editres (both applications should be in /usr/X11R6/bin on most Linux systems). When editres opens, you’ll see a simple menu bar with two menus: Commands and Tree, as in Figure Two . Click the Commands menu, and choose “Get Tree.” Your cursor will change into a crosshairs. Position the crosshairs over the xclock window and click the mouse. Your editres window now displays a tree representation of the widgets in xclock.
If you examine the tree, you’ll see that the topmost xclock widget has a shellext widget (which we’ll ignore) and a clock widget.
Select the clock widget by clicking on it once, then choose “Flash Active Widgets” from the Tree menu. You’ll see your xclock display flash several times to show the correlation between the widget you chose in editres and the actual display widget.
|Figure Three: The properties of the clock widget|
Next, from the Commands menu, choose “Show Resource Box.” A new window will pop up showing all the resources available for the clock widget (see Figure Three, .
You can see the hands property we used earlier. Click on hands in the window. Now, click on the “Enter Resource Value” edit field and type green. Click the Apply button. The hands of your xclock should turn green.
Next, click on foreground and type blue as the resource value. Click Apply. The clock face should turn blue.
Next, try using editres to set background to black, and analog to 0 (analog is a boolean property and 0 means false — the analog clock will disappear and be replaced by date-like output) and then back to 1 (true), causing the analog clock face to reappear.
That’s a lot of work to customize xclock. Clearly you don’t want to do that every time you run the application. And you don’t have to. Simply edit your .Xresources file and add the settings you prefer. A set of useful xclock resources is shown in Figure Four.
Figure Four: xclock resources stored in $HOME/.Xresources
The X Display Manager
Now that we’ve covered some basics, let’s look at how you can customize the X Display Manager, or xdm. xdm provides access control for X displays in the same way that init, getty, and login control access from character terminals: xdm prompts for a login name and password, authenticates the user, and runs an X “session.”
In most cases, an X session starts when your window manager is launched and ends when you quit the window manager — the indication that you’re finished with all of the windows (applications) connected to the display.
When an X session ends, the X server is reset, all active X connections are closed, all windows are closed, all resources in XRM are purged, and all incoming X connections (except from xdm) are refused.
You probably use xdm every day. When you boot your system, Linux determines whether it will present a login screen from a graphical interface (using X) or a character-based terminal. If the graphical interface is chosen, xdm starts up and presents a login window.
Your /etc/inittab file might contain a line like the following. It tells your system to start up xdm when it enters runlevel 5. (The runlevel numbers other than 0, for halt, and 6, for reboot, are arbitrary and vary by distribution, but 5 is usually the runlevel for graphical login.)
A single xdm daemon can provide login and authentication for any number of X displays on your network. Because xdm provides the first interface that many users will see (including yourself), it’s designed to be simple to use and easy to customize according to the needs of a particular site. xdm has many options, most of which have reasonable defaults.
Setup files for xdm are in the /etc/X11/xdm directory (or in some distributions, /usr/X11R6/lib/X11/xdm). The crucial file within this directory is xdm-config, which might look like Figure Five . (To keep things simple, we’ve assumed all displays are local.) xdm-config is an X resource file just like your own $HOME/.Xresources file.
Figure Five: Typical xdm-config file
! $XConsortium: xdm-conf.cpp /main/3 1996/01/15 15:17:26 gildea $
! All displays should use authorization, but we cannot be sure
! X terminals will be configured that way, so by default
! use authorization only for local displays :0, :1, etc.
! The following three resources set up display :0 as the console.
To customize xdm, set the properties of the DisplayManager widget class. For example, errorLogFile, pidFile, and keyFile identify the locations of various configuration files (these particular properties have no graphical representation within the X Display Manager itself). Other resources, such as daemonMode, simply take true/false values; still others can have string or numeric values.
Figure Five shows how to customize xdm for two local X displays. Each display can be configured separately. Display :0 is referred to as _0, and display :1 is referred to as _1. Resource names may consist only of letters, digits, and the underscore character; all other characters are conventionally represented by the underscore (hence, :0 becomes _0). Each display has an authorize resource, which has a true or false value. In this case the value has been set to true for the first two displays, meaning that a login, managed by xdm, will be required.
Each display has other resources associated with it, including setup, startup, and reset. In Figure Five, each display has a different setup file, but they share a common startup file.
Logging in Via xdm
When xdm starts, it obtains the value of the DisplayManager. servers property and scans that file (/etc/X11/xdm/Xservers in Figure Five pg. 26) to determine which X server to start for each display. Typically, that server will be simply be /usr/X11/bin/X, which in turn is a symbolic link to the server executable appropriate to your video card. XFree86, meanwhile, scans the /etc/X11/XF86Config file for basic information about your hardware; typically, this is set up automatically when you install your distribution, using utilities like SuperProbe. (See “Stupid X Tricks,” for more on this.)
Magnifying Your Display
The xmag program lets you magnify any part of the current display. When you execute the
xmag command, your cursor will change shape. Position it at the upper-left corner of the area you want to magnify, then drag with the middle mouse button (or both buttons simultaneously on a two-button mouse) to the lower-right corner.
Changing Screen Resolution
If you want to change the resolution of the entire screen, take a look at the XF86Config file, in particular the part labeled Section “Screen”. (There may be more than one such section.) This shows the permissible screen resolutions for your monitor. A typical section might include:
Device “My Video Card”
Monitor “Dell Super VGA”
Modes “1024×768″ “800×600″ “640×480″
ViewPort 0 0
This indicates that your screen supports 1024×768 pixels, 800×600, or 640×480. To switch between these modes while running, hold down the CTRL and ALT keys and press the + or - key on the keypad to cycle forward or back.
Three Finger Salute
Another CTRL-ALT combination is CTRL-ALT-Backspace, which kills the X server on your current display. If you’re using a GUI runlevel though, all this will do is log you out and present a new login screen. That’s because the respawn directive in the the /etc/inittab file prevents you from killing xdm altogether without rebooting.
Once X is started, xdm does setup work for each display and calls the file specified by the appropriate DisplayManager.*. session resource. While it is entirely permissible to specify a different session file for each display, the example in Figure Five specifies /etc/X11/xdm/Xsession for all displays. An excerpt from a typical Xsession file is shown in Figure Six .
Figure Six: Excerpt from /etc/X11/xdm/Xsession
if [ -f "$sysresources" ]; then
xrdb -merge “$sysresources”
if [ -f "$userresources" ]; then
xrdb -merge “$userresources”
As we’ve seen before, the command xrdb -merge filename will merge the resources specified in filename into the XRM database. The file /etc/X11/xdm/Xresources is merged into the database first, followed by the the user’s personal .Xresources file (note the leading dot) in the user’s home directory.
So, if you’ve created a .Xresources file, here’s where it’s loaded into the X Resource Manager. Since your resources are loaded last, your personal resources override the system-wide resources. You may also notice a .Xdefaults file in your home directory with the same syntax. This file is used by certain window managers, not by the X Display Manager.
Going Beyond X
Once you have a feel for X, there are many things to explore. If you’re looking for more control files to muck around with, try the /usr/share/xmodmap/ directory, which in conjunction with the xmodmap program lets you remap your keyboard and mouse keys.
Or, if your preference is programming, the various toolkits provide you with resources galore. How your Linux desktop looks is completely up to you.
Running one X Display Within Another
If you want to test changes in your X setup without affecting your current X display, you can start up a second X server within your current X display by using the Xnest program. A sample script to launch Xnest is shown below.
This script cobbles together bits and pieces of the standard X initialization sequences and simplifies them. A couple of lines are worth examining.
Line 2 launches a second X server within your current display, offset from your main X display. The & at the end of Line 2 runs Xnest “in the background”; without the &, the script would pause waiting for Xnest to terminate and nothing would appear in the new X display.
The :2 argument on Line 2 names the new display “2″ (remember that your original X display is “0″).
Line 3 exports the new fully qualified display name. For example, if your machine was named “storm.linuxmagazine.com”, line 3 would set the DISPLAY environment variable to storm.linuxmagazine.com:2.
Line 6 grants access to the X server (storm.linuxmagazine. com:2) only to the local host. X offers a number of authentication schemes to protect access to your X server. xhost +LOCAL: is sufficient for the purposes of setting preferences, but you’ll probably want to look into more secure schemes (such as ssh tunneling or VNC) for your primary display.
Use Xnest to experiment. When you’ve found settings that you like, incorpoate them into your $HOME/.Xresourcesfile.
A shell script to run Xnest
2 Xnest :2 -geometry 800×600+300+300 &
3 export DISPLAY=`hostname -f`:2
4 xrdb -display $DISPLAY -load $HOME/.Xresources
5 xsetroot -display $DISPLAY -solid grey
6 /usr/X11R6/bin/xhost +LOCAL:
7 /usr/bin/gnome-session –display=$DISPLAY 2>/dev/null&
J.C. Freed is a regular contributor to
Linux Magazine. He can be reached at email@example.com.