eX Cathedra

Welcome to CLIENTHOST

The X Display Manager, or xdm, is the first thing most people see when they prepare to use the X window system. It can be highly customized for ease of use, site or corporate standards, individuality, or any other reason.

Figure 1 - standard xdm greeting
[Login Screen Image]
Ah, the familiar greeting of our old friend, xdm. Welcome home, or to accounting, or to tb.org's help desk, or whatever. xdm always seems to know where it is, without being told. In reality, it is being told -- just not directly by you.

xdm gets its ideas about fashion from the Xresources file. While this is the common name for the file, you can set (or discover) it in the xdm-config file in the xdm/ directory (usually /usr/lib/X11/xdm/), via a resource named (surprise!) resources:

    DisplayManager*resources:       /usr/lib/X11/xdm/Xresources
xdm's Xresources file is processed through xrdb, which uses the C preprocessor. This means you can customize quite heavily based on a number of parameters. You have probably seen two of them if you've ever looked into the Xresources file:
Figure 2 - chooser
[Chooser Screen Image]
These show up in the standard xdm greeting (figure 1) and in the chooser greeting (figure 2).

These greetings are defined by default with the resource lines:

    xlogin*Login.greeting: \
        SERVERHOST (Login to CLIENTHOST)
    Chooser*label.label:    \
       XDMCP Hosts (from CLIENTHOST)
You can, of course, change these. There is a separate greeting used when authorization is not turned on, in case you don't want to give away information unnecessarily, which you can customize to be informative yet generic:
    xlogin*Login.unsecureGreeting:  Welcome to tb.org!
Almost everything about the look and feel of xdm and the chooser is customizable in this file, including colors, fonts, strings, button shape, and geometry. As delivered, it's pretty plain. Standard xdm will never look as slick as, say, a Motif client, because it is based on the Athena widget set. The Athena widgets were only meant as samples, and hence have a very plain, 2-D look. Using the 3D Athena widgets in the Xaw3d library can help some, provided you have the xdm source (available free from the X Consortium, and are willing to rebuild it.

A Little Flavor

The easiest way to customize colors, fonts, or text strings is to just play with the Xresources file, with the xdm(a) man page handy, as in the above examples.

But some things, such as the login box's background pixmap, are not available at all. (You can set the background color, but not the pixmap.) Other things are not settable via resources, but can be changed programatically.

The main thing most people change this way is the background of the whole screen. NEC, for instance, ships xdm preconfigured to display a tiled logo on the screen. You can do this, and more, by modifying the Xsetup file (this may also be Xsetup_N, where N is the display number). For instance, you can set the background with xsetroot to a solid color or bitmap, or you can use your favorite image loading program such as xv to display an image or color pattern. While this can use a lot of memory, you can make sure the background is reset to something less memory-intensive by including a basic xsetroot as part of the user session.

You can do pretty much anything you like in the Xsetup file. Something I have found useful is running an xclock. Most of the users in my environment use a plain xclock, anyway. If this were not the case, I would need to find a way to terminate the xclock when the user's session started, or they would have two clocks running!

Extreme Customization

The Xresources file is processed through xrdb, which means you can customize quite heavily based on a number of parameters. Of the variables xrdb knows about (see the xrdb man page for full details), we are probably most interested in the following: Many people never customize beyond SERVERHOST and CLIENTHOST (which even appear in most default Xresources files). But in a complex, heterogeneous environment, the others can come in extremely handy. For instance, tb.org is an environment with monitors of varying resolution, depth and size. We can use basic colors and patterns for 4-bit monitors, only black & white for mono screens, spiffy colors and patterns for high-end monitors, and pick fonts according to resolution.

For example, first let's customize the font sizes based on screen resolution and size. The resolution here is in pixels per meter, but font resolutions are in pixels per inch. Because the preprocessor only allows integer in arithmetic expressions, we have to multiple the conversion factor (39.36), and hence the resolution, by 100, to get the font resolutions. We will also pick 3 sets of font sizes, based on screen height.

#if (((Y_RESOLUTION * 100) / 3936) < 87)
# define FH 75
#else
# define FH 100
#endif

#if (HEIGHT <= 640)
# define HT1 120
# define HT2 140
# define HT3 160
#elif (HEIGHT <= 768) 
# define HT1 140
# define HT2 160
# define HT3 200
#else
# define HT1 160
# define HT2 200
# define HT3 240
#endif
   :
   :
xlogin.Login.greetFont:      -bitstream-charterbold-i-*--*-200-*-*-*-*-*-*
xlogin.Login.promptFont:     -bitstream-charterbold-r-*--*-160-*-*-*-*-*-*
xlogin*Login.Font:           -bitstream-charter-bold-r-*-*-*-160-*-*-*-*-*-*
xlogin*Login.failFont:       -bitstream-charter-bold-i-*--*-200-*-*-*-*-*-*
xlogin*Command*Font:         -*-lucidatypewriter-bold-r-*-*-*-140-FH-FH-*-*-*-*
*helpPopup*helpDone*font:    -bitstream-courier-bold-r-*--*-140-*-*-*-*-*-*
Chooser*label.font:          -bitstream-courier-bold-i-*--*-160-*-*-*-*-*-*
Chooser*list.font:           -misc-*-bold-r-*--*-120-FH-FH-c-*-*-*
Chooser*Command*font:        -bitstream-courier-bold-r-*--*-160-*-*-*-*-*-*
(I used the bitstream fonts where possible because they seem to be the most prevalent scalable fonts across platforms.)

Now let's pick some colors based on visual type and depth.

#if (PLANES == 1) /* Black & White */
  xlogin*Foreground:              Black
  xlogin*Background:              White
  XConsole*Foreground:            White
  XConsole*Background:            Black
  Chooser*Foreground:             Black
  Chooser*Background:             White
#else /* either color or grayscale */
# if defined(COLOR)
#   if (PLANES >= 8) /* DECENT COLOR OR BETTER */ 
      xlogin*Background:              Bisque
      xlogin*greetColor:              Black
      xlogin*failColor:               Red
      xlogin*promptColor:             Coral
      !
      xlogin*ok*Background:           Green
      xlogin*reset*Background:        Yellow
      xlogin*restart*Background:      Orange
      xlogin*failsafe*Background:     Violet
      xlogin*help*Background:         Cyan
      xlogin*Command*Foreground:      Black
      !
      xlogin*helpPopup*Background:    Yellow
      xlogin*helpPopup*helpDone*Background:   Green
      !
      *Foreground:                    Black
      !
      Chooser*Background:             Coral
      Chooser*Command*Background:     Tomato
      !
      Chooser*helpPopup*Background:   LightSalmon
      Chooser*helpPopup*helpDone*Background:  Tomato
#   else /* CHEAP COLOR */
      xlogin*Background:              Bisque
      xlogin*greetColor:              Black
      xlogin*failColor:               Red
      xlogin*promptColor:             Black
      !
      xlogin*ok*Background:           Green
      xlogin*reset*Background:        Yellow
      xlogin*restart*Background:      Orange
      xlogin*failsafe*Background:     Violet
      xlogin*help*Background:         Cyan
      xlogin*Command*Foreground:      Black
      !
      xlogin*helpPopup*Background:    Yellow
      xlogin*helpPopup*helpDone*Background:   Green
      !
      *Foreground:                    Black
      !
      Chooser*Background:             Blue
      Chooser*Command*Background:     LightBlue
      !
      Chooser*helpPopup*Background:   Yellow
      Chooser*helpPopup*helpDone*Background:  Green
#   endif /* color types */
# else /* GRAYSCALE (assuming 2 bits - could break down more) */
    xlogin*Background:              Gray75
    xlogin*greetColor:              Black
    xlogin*failColor:               Black
    xlogin*promptColor:             Gray50
    !
    *Command*Background:            Gray75
    *Command*Foreground:            Black
    !
    *helpPopup*Background:          Gray75
    *helpPopup*helpDone*Background: Gray50
    !
    *Foreground:                    Black
    !
    Chooser*Background:             Gray75
# endif /* COLOR vs GRAYSCALE */
#endif /* MONO vs other types */
(The extra command buttons and help popups are features of an enhanced xdm program, which will be covered in a future column.)

Some preprocessors will complain about the comments after the #else and #endif statements. This is merely a warning, but if it bothers you, remove the comments.

You should now be able to make xdm look pretty much any way you want it to look in your environment. In the next issue, I will look at changing xdm's background, consider other clients to run, customize the default user session, and introduce a souped-up xdm interface.


Miles O'Neal <meo@schoneal.com> has been working with X since shortly after Version 10 escaped from the labs at MIT. He has over 15 years experience doing almost everything possible within the software industry, including some things he refuses to remember. In his spare time he operates Roadkills-R-Us.