B

The uwm Window Manager

If you are running Release 3 of X (or an earlier release), the standard window manager is uwm, the universal window manager. uwm allows you to perform all of the basic window manipulation functions, such as:

•   Sizing and positioning client windows on the screen interactively.

•   Creating additional xterm terminal windows.

•   Refreshing your screen.

•   Moving windows around the screen.

•   Changing the size of windows.

•   Lowering windows (sending them to the back of others).

•   Raising windows (bringing them to the front of others).

•   Converting windows to icons and icons to windows.

•   Removing windows.

The uwm window manipulation functions can be invoked in three ways:

•   Using the WindowOps menu.

•   By combinations of keyboard keys and pointer buttons.

•   Automatically, when a client is started (to allow you to size and place the client window on the screen).

The window manager also has a second menu, the Preferences menu, that allows you to set various keyboard and pointer preferences.

Be aware also that you can customize nearly every feature of uwm by modifying a window manager startup file called .uwmrc, kept in your home directory. You can change the keystroke and pointer button combinations used to invoke window manager functions, modify the default uwm menus, create new menus, etc.

The first half of this appendix discusses the default window manipulation functions provided by uwm. The second half discusses how to customize the window manager to suit your needs. First, however. let’s take a look at starting uwm.

Starting the Window Manager

You start uwm from the command line by typing:

% uwm &

in an xterm window. If xdm (the display manager) is starting X on your system, the uwm window manager is probably started automatically when you log on. (See the discussions of xdm in Chapter 2, Getting Started, and Appendix A, System Management.) When uwm is started, nothing visible will happen, but your terminal will beep once to indicate that uwm is running on the current screen.

Note also that you can run xterm or other X clients without running a window manager. uwm allows you to size and place client windows on the screen, but you can also use command line options to do this. However, there is no way to change the size or location of windows on the screen without a window manager.

The WindowOps Menu

The uwm WindowOps menu gives you access to many of the most frequently used window manipulation functions. In the standard version of uwm shipped by MIT, you bring up this menu by moving the pointer to the root window and holding down the middle pointer button. The WindowOps menu and the menu pointer appear as shown in Figure B-1.

Note that the last two items, KillWindow and Exit, appear on the menu as of Release 3. If you are running Release 2, your menu will not include these items. (However, the items that appear on both Release 2 and Release 3 menus are identical in functionality; our discussions of these common menu items apply to either release.)

Another Release 3 feature is that the “hand” pointer is used to indicate the window to be acted upon (resized, refreshed, etc.). In Release 2, this function was performed by the “target circle” pointer. The figures in this appendix depict Release 3 pointers, but the Release 2 and 3 pointers function in the same way.

images

Figure B-1. WindowOps menu

The following pages explain the functions of the uwm WindowOps menu. Remember that all of the window manager functions are customizable. Items can be added to or deleted from this menu (and the Preferences menu) by modifying the .uwmrc window manager startup file. as described in the section “Customizing uwm” later in this appendix. This appendix describes the window manager as it is shipped with the standard release of the X Window System from the MIT X Consortium.

To bring up the WindowOps menu, move the pointer to the root window and hold down the middle button on the pointer. To select a menu item, continue to hold down the middle button and move the pointer to the desired menu item. A horizontal band, or highlighting bar, follows the pointer. When you’ve highlighted the desired menu item, release the button. The selected function will be executed. Note that you must keep the pointer within the menu as you drag down to make a choice, or the menu will disappear and you’ll have to start over.

Some of the functions on the menus can be invoked simply by pressing a combination of pointer buttons and keyboard keys. We discuss these “keyboard shortcuts” as appropriate when discussing each menu function, and summarize them in Table B-1 later in this appendix. These shortcuts all make use of the “Meta” modifier key. See Chapter 11, Setup Clients, for a discussion of how to determine which key on your keyboard serves as the Meta key. (For the Sun-3 keyboard, for example, Meta is either of the keys labeled “Left” or “Right.”)

Creating New Terminal Windows

You can create new xterm terminal windows from the WindowOps menu. To create a terminal window:

1. Bring up the WindowOps menu.

2. Select New Window with the menu pointer and release the pointer button. An upper-left comer cursor appears on your screen. This comer cursor tracks pointer movement. You now have three options:

Making a Default-Size Window. Move the comer cursor to the position desired for the upper-left comer of the window and click the left pointer button. A default-size (80 × 24) window appears on your screen as shown in Figure B-2.

images

Figure B-2. A default-size xterm window

Making a Custom-Size Window. Move the comer cursor to the desired position for the upper-left comer of the new window. Press and hold down the middle pointer button. Notice that the upper-left comer cursor is now fixed at that position and that a lower-right comer cursor appears.

While holding down the middle button, move the comer cursor to the desired position for the lower-right comer of the window. The window size, as you change it, appears in the upper-left corner of your screen. Release the button. A window of the width and height you specified with the pointer appears. See Figure B-3.

images

Figure B-3. A custom-size xterm window

Making a Maximum-Height Window. Move the comer to the desired position and click the right button. A default-width by maximum-height (to the bottom of the screen) window appears. See Figure B-4.

Refreshing the Screen

Refreshing your screen means redrawing its contents. This is useful if system messages from outside the X window system appear on the screen, overlaying its contents. To refresh your screen:

1. Bring up the WindowOps menu.

2. Select RefreshScreen with the menu pointer. The screen redraws itself. You can use the xrefresh client to achieve the same effect. Simply type xrefresh at the prompt in any xterm window.

images

Figure B-4. A maximum-height xterm window

Redrawing a Window

The Redraw menu item redraws (or refreshes) an individual window. To redraw a window:

1. Bring up the WindowOps menu.

2. Select Redraw with the menu pointer. The pointer changes to the hand pointer.

3. Move the hand pointer to the window you want to redraw.

4. Click the left or middle button to redraw the window.

Moving Windows and Icons

The Move menu item moves a window or icon to a new location. When you use this function, an outline, not the entire window or icon, tracks the pointer movement to the new location. See Figure B-5. To move a window:

1. Bring up the WindowOps menu.

2. Select Move with the menu pointer. The pointer changes to the hand pointer.

3. Move the hand pointer to the desired window or icon. Hold down the middle button. The pointer changes to the cross pointer and a window outline appears. This outline tracks the pointer movement.

4. Move the cross pointer with the window outline to the desired location on your screen.

5. Release the middle button. The window will move to the new location.

images

Figure B-5. Moving windows or icons

You can also move a window or icon simply by moving the pointer to the window or icon you want to move, then pressing the right pointer button while holding down the Meta key. The pointer at first changes to a small image of an icon. You can now let go of the Meta key. Then, as you drag the pointer while holding down the button, the pointer changes to a cross, while the window or icon changes to outline form. Drag the outline to the new location, and let go of the right button. The window will be redrawn in the new location.

Resizing Windows

The Resize menu item resizes an existing window. See Figure B-6. To resize a window:

1. Bring up the WindowOps menu.

2. Select Resize with the menu pointer. The pointer changes to the hand pointer.

3. Move the hand pointer to the window you want to resize. Place it near the border you want to move. The opposite border remains in its current position.

4. Hold down the middle button. The pointer changes to the cross pointer.

5. Move the window’s border to obtain the desired window size. As you resize the window, a digital readout appears opposite the pointer showing the window size in pixels. (For the xterm client, size is in characters and lines.) Release the middle button.

images

Figure B-6. Resizing a window

You can also resize a window without using the menu. Move the pointer so that it is within the window you want to resize, placing the pointer near the window border you want ’to change. With one hand, press and hold down the Meta key on the keyboard. With the other hand, press and hold down the middle pointer button. The pointer starts as an icon pointer, but as you drag the pointer, it changes to a cross and a window outline appears. Move the pointer to resize the window. When the window is the proper size, release the middle button and the Meta key.

Resizing an xterm window will not change the dimensions of the text currently in the window. (If you make the window smaller, for instance, some of the text may be obscured.) However, if the operating system supports terminal resizing capabilities (for example, the SIGWINCH signal in systems derived from BSD 4.3), xterm will use these facilities to notify programs running in the window whenever it is resized. As you continue to work, perhaps starting an editing session, the program will use the entire window. If you resize during an editing session, the text editing program may not know about the new size, and may operate incorrectly. Simply quitting out of the editor and starting another session should solve this problem.

If your resized xterm window does not seem to know its new size, you may be working with an operating system that does not support terminal resizing capabilities. Refer to the discussion of the resize client in Chapter 4, The xterm Terminal Emulator, (and to the resize reference page in Part Three of this guide) for alternative solutions.

Shuffling the Window Stack: Raise, Lower, CircUp, CircDown

Under the X Window System, windows can overlap each other. When windows overlap, one or more windows may be fully or partially hidden behind other windows (see Figure B-7). You can think of these windows as being stacked on top of each other much the way papers are stacked on a desk. uwm can control the stacking order of the windows. Stacking functions include: raising a window to the top of the stack, making all of it visible; lowering a window to the bottom of the stack (possibly obscuring it by other windows); circulating the bottom window to the top and lowering every other window one level; or circulating the top window to the bottom and raising every other window one level.

images

Figure B-7. One xterm window overlapping another

Raising Windows (bringing In front of others)

The Raise menu item places a window at the top of a window stack. See Figure B-8. To bring a window to the front:

1. Bring up the WindowOps menu.

2. Select Raise with the menu pointer. The pointer changes to the hand pointer.

3. Move the hand pointer to the desired window.

4. Click the left or middle button. The window is raised to the top of the stack.

images

Figure B-8. Raising a window

Lowering Windows (sending behind others)

The Lower menu item places a window at the bottom of a window stack. To place a window at the bottom:

1. Bring up the WindowOps menu.

2. Select Lower with the menu pointer. The pointer changes to the hand pointer.

3. Move the hand pointer to the appropriate window.

4. Click the left or middle button. The desired window is placed behind all windows except the root window.

Circulating Windows

The CircUp and CircDown menu items circulate the windows in a stack. CircUp raises the bottom window to the top and lowers every other one by one level. CircDown lowers the top window to the bottom and raises every other window by one level. CircUp and CircDown only affect overlapping windows.

To circulate the windows in a stack:

1. Bring up the WindowOps menu.

2. Select CircUp or CircDown.

Note that both CircUp and CircDown circulate every window stack if there is more than one stack of windows on the screen.

Here’s how to change the stacking order using keyboard shortcuts:

•   To raise a window, move the pointer so that the cursor is within the window you want to raise. With your other hand, hold down the Meta key on the keyboard. Then click the right pointer button. The window is raised.

•   To lower a window, move the pointer so that the cursor is within the window you want to lower. With your other hand, hold down the Meta key on the keyboard. Then click the left pointer button. The window is lowered.

•   To circulate all windows, you can use any of the above key and pointer button combinations with the pointer in the root window. However, you do not place the cursor within any particular window (e.g., leave the cursor in the root window). The windows cycle through the stack, raising the bottom window to the top and lowering every other window one level.

Displaying Windows as Icons

If you want to make more space available on your screen, you can convert a window into an icon. An icon is a small symbol that represents the window. You also can convert the icon back into a window.

There are three menu items on the default WindowOps menu used to iconify and deiconify: AutoIconify, LowerIconify, and NewIconify. All three iconify a window or deiconify an icon. In addition, LowerIconify and NewIconify interactively move the icon or window to a new location. See Figure B-9 and Figure B-10.

To convert a window to an icon or an icon to a window:

1. Bring up the WindowOps menu.

2. Select NewIconify with the menu pointer. The pointer changes to the hand pointer.

3. Move the hand pointer to the desired window or icon.

images

Figure B-9. The login window is about to become an icon

4. Hold down the left button and move the pointer to the desired location. The window or icon tracks the pointer to the new location.

5. Release the left button. The window is converted to an icon or the icon to a window in the new location.

While the pointer rests in the icon, you can edit the icon name by typing in the appropriate name or characters. Use the Delete key to delete unwanted characters.

NewIconify can also be used to display an icon as its original window. Follow the same procedure as to iconify a window, but start with an icon, and turn it into a window.

To iconify or deiconify a window using keyboard shortcuts, move the pointer so that the cursor is within the window you want to iconify. With one hand, press and hold down the Meta key on the keyboard. With the other hand, press and hold the left pointer button and drag the window. The window converts to an icon-sized outline. Drag the outline to the desired position, and then release the pointer button and the Meta key. The full icon appears in the specified position.

To bring back the window (deiconify it), move the pointer so that the cursor is within the icon. Then hold down the Meta key and click the middle pointer button. The window appears back in its original position. Or hold down the Meta key and use the left pointer button while dragging the window outline to a new location, just as you did to iconify the window in the first place.

images

Figure B-10. The login window is about to be deiconified

Changing Keyboard Focus

Normally, keyboard input goes to whichever window the pointer is currently in. The Focus option causes keyboard input to go only to a selected window (the focus window) regardless of the position of the pointer.

Focusing can be useful if you are working in one window for an extended period of time, and want to move the pointer out of the way. It also prevents the annoying situation in which you inadvertently knock the pointer out of the window while typing. (This can be very important for touch typists who look infrequently at the screen while typing!)

To choose a focus window:

1. Bring up the WindowOps menu.

2. Select Focus with the menu pointer. The pointer changes to the hand pointer.

3. Move the hand pointer to the window you want to choose as the focus window.

4. Click the middle button to choose the window.

The focus window becomes highlighted with a dark border.

In order to take the focus away from the selected window (and reactivate “pointer focus”), you must give the focus back to the root window. To do this, select Focus again, and click anywhere on the root window. The keyboard focus will once again follow the pointer into any window.

Freezing and UnFreezing the Server

The X server normally responds to requests from clients in a first-come first-served order. There are times when you want one client (such as the window manager) to get priority treatment. For example, if there are many active X clients, or if you are running X across a slow network, you may find that uwm responds sluggishly while performing tasks such as moving or resizing a window. If you select Freeze, the window manager “grabs the server,” so that no other clients have access. All events and requests to display to the screen by other clients are queued, or “saved up,” and will be performed when the server is unfrozen.

To freeze the server:

1. Bring up the WindowOps menu.

2. Select Freeze with the menu pointer.

Since only the window manager has access to the server, window manager operations will go much more quickly. When you are finished moving or resizing windows (or whatever it was you wanted the window manager to do more quickly), select Unfreeze to resume normal operation.

Restarting the Window Manager

The Restart menu item restarts the window manager. This may occasionally become necessary if the window manager functions improperly. To stop and restart the window manager:

1. Bring up the WindowOps menu.

2. Select Restart with the menu pointer.

You may also want to restart the window manager if you edit your .uwmrc configuration file to change the functionality of uwm. For more information, see the section “Customizing uwm” later in this appendix.

Note that when the window manager is stopped, all icons revert to windows. This happens because the window manager is what allows windows to be iconified. When the window manager is restarted, you can iconify the windows again.

Removing a Window

The KillWindow menu item terminates a client window. Like other methods of ‘killing’ a program (such as the xkill client), the KillWindow menu item can adversely affect underlying processes.

Most windows can be removed in ways that do not harm relevant processes. For example, you can generally remove an xterm window by typing the same command you use to log off the system. KillWindow is intended to be used primarily after more conventional methods to remove a window have failed.

To remove a stubborn window:

1. Bring up the WindowOps menu.

2. Select KillWindow with the menu pointer. The pointer changes to the hand pointer.

3. Move the hand pointer into the window you want to terminate.

4. Click any pointer button.

The window is removed.

Refer to the section on xkill in Chapter 7, Other Clients, for a more complete discussion of the hazards of killing a client and a summary of alternatives.

Exiting the Window Manager

The Exit menu item stops the window manager. You may want to stop uwm in order to start another window manager. To stop uwm:

1. Bring up the WindowOps menu.

2. Select Exit with the menu pointer.

The window manager is stopped. All icons revert to windows.

Button Control of Window Manager Functions

Table B-1 summarizes the keyboard shortcuts for window management functions. The first column lists the desired function; the second, the required location for the pointer; and the third, the button-key combination. In this column, “click” means to press and immediately release the specified pointer button; “down” means to press and hold the pointer button, and “drag” means to move the pointer while holding down the pointer button. In all cases, you can let go of the keyboard key as soon as you have pressed the appropriate pointer button.

Note that these key “bindings” can be changed in your .uwmrc file as described later in this appendix. The combinations described in Table B-1 work for the default.uwmrc file.

Table B-1. Keyboard Shortcuts for Window Manager Functions

images

Using uwm to Place Other Clients

As described in Chapter 2, Getting Started, you can start another client simply by typing its name at the command line prompt in an xterm window. Some clients have a default size and/or location. A preferred size and location can also be specified in your .Xresources file, as described in Chapter 9, Setting Resources.

When you start a client, you can also use the -geometry command line option described in Chapter 8, Command Line Options, to size and locate the window, overriding any defaults that the client has.

If none of these geometry specifications has been provided, uwm steps in and requires you to interactively size and locate the windows. You have already seen the process of interactively sizing and positioning a window in Chapter 2, when we discussed how to start a second xterm or an xclock window.

First, the pointer turns into a comer shape and the name of the client appears in the upper-left comer of the screen followed by the digital size readout 0x0.

To place the default-size client, move the pointer to the desired upper-left comer position for the new client. Click the left pointer button.

To both size and place the client, move the pointer to the desired upper-left comer position; press and hold down the middle pointer button. The pointer changes to a lower-right comer shape. Move the pointer to the desired window size. Release the pointer button.

The Preferences Menu

The Preferences menu is generally included in the version of uwm provided with most systems. The Preferences menu lists options for setting bell volume, keyclick volume, whether or not the Caps Lock key works, and the pointer tracking speed.* See Figure B-11.

images

Figure B-11. Preferences menu

Without customizing the window manager, the only way to display the Preferences menu is to first display the WindowOps menu by an alternative method. Instead of placing the pointer on the root window and holding down the middle pointer button, place the pointer anywhere on the screen, hold down both the Shift and Meta keys, and press the middle pointer button. (See Chapter 11, Setup Clients, for a discussion of how to determine which key on your keyboard serves as the Meta key.) The WindowOps menu is displayed.

You can let go of the Shift and Meta keys, but keep holding down the middle pointer button. Then drag the pointer off the right or left side of the WindowOps menu and the Preferences menu will be displayed.

Menus displayed in this way are called slip off menus and are discussed in greater detail in the section “Customizing uwm.” This section also describes how to set up the window manager to display the Preferences menu more easily.

To make selections on the Preferences menu, bring up the menu and select a setting with the menu pointer. There is no visible change to the menu, but the new setting is made. Note that another button or combination might be used to display the Prefences menu at your site. If you cannot access the Preferences menu, this menu is included in the sample .uwmrc file at the end of this appendix.

Customizing uwm

As we’ve seen, uwm allows you to manipulate windows in a variety of ways. In addition, you can modify every function of the uwm window manager. The function itself will remain the same (for example, you will still move a window by holding down a key and pointer button simultaneously and dragging the pointer), but the keys and/or menu items used to invoke the function may be completely different.

The flexibility of uwm allows you to redesign the WindowOps and Preferences menus by reordering, adding and removing items, and changing key/button combinations, and to create entirely new menus. The operation of the window manager, as distributed, is controlled by a text file called default.uwmrc, which is generally installed in the directory /usr/lib/X11/uwm. You can customize uwm by editing a copy of this file, called .uwmrc, in your home directory. By customizing this file, you can:

•   Define your own uwm menus.

•   Bind functions to keyboard key/pointer button combinations.

•   Issue command strings to the shell.

The .uwmrc file has three parts:

•   A variables section, which contains various settings, such as the font with which menus should be displayed, the volume of the keyboard bell, and so on.

•   A key bindings section, which defines the keys, pointer buttons, and key and pointer button combinations that will be used to invoke each window manager function (including the display of menus).

•   A menus section, which defines the contents of the menus.

As users gain experience with the window manager, each can create a file called .uwmrc in his or her home directory. This file can extend default.uwmrc, resetting variables, changing a key binding or adding a menu item—or it can replace it completely, changing the way the window manager operates. As one of its creators remarked, this flexibility makes uwm “the bane of trade show demonstrators and the joy of experienced users.”*

Rather than abstractly explaining the syntax of these various sections in a .uwmrc file, let’s plunge right in, by looking at the default.uwmrc file from the MIT X11 distribution. This is shown in Example B-1. (Note that if you are using a commercial version of X, this file may be significantly different However, in that case, you most likely have a user’s guide specific to your system-perhaps even a customized version of this one!)

Example B-1. The default.uwmrc file from the MIT distribution

images

images

If you wish to change the operation of the window manager, you shouldn’t change the default.uwmrc file. Instead, copy it to your home directory, under the name .uwmrc, and make changes to that copy. Or else, if you are planning only small changes, you can create a .uwmrc file from scratch. Settings in default.uwmrc and your own local .uwmrc file are cumulative (unless you explicitly override default.uwmrc as explained in the next section), so all you need to enter in your .uwmrc are values you wish to change.

Setting .uwmrc Variables

The first section of the file sets global variables. Some variables are Boolean—that is, their presence or absence “toggles” some attribute of the window manager—while others have the form:

variable=value

where value is either a number or a text string.

An example of a Boolean variable is autoselect, which, if present, causes the pointer to automatically appear in the first menu item whenever a menu is invoked. Note however that there are inconsistencies in the way uwm specifies Boolean variables. Some, like reset-variables, take effect if present; they must be deleted from the file or commented out by placing a sharp sign(#) at the start of the line if you don’t want them to take effect. Others, such as normali (which makes sure that icons aren’t placed partially offscreen when created), have an opposite toggle (nonormali), which must be used if you want the opposite effect. If two corresponding on/off toggles are both mistakenly placed in a file, whichever is specified later in the file takes effect.

An example of a text string variable is:

menufont=fixed

which names the font that should be used in all menus. (See Appendix E, Release 3 and 4 Standard Fonts, for lists and illustrations of fonts in the standard X11 distribution.)

An example of a numeric variable is:

volume=4

which sets the volume of the keyboard bell on a scale ranging from 0 to 7.

The available variables are described in detail on the uwm reference page in Part Three of this guide, so we won’t go into detail on each of them here. Three variables that are worthy of note, though, are resetvariables, resetbindings, and resetmenus. You may recall that settings in your local .uwmrc file are cumulative with those in the default.uwmrc file. That is, you need define only changed or added variable values, function bindings or menus if you are happy with the basic operations set forth in default.uwmrc. If, however, you want to start with a clean slate, you should use one or more of the three reset variables which reset, respectively, the three sections of the .uwmrc file. If specified, these variables should always head the list of variables.

One additional note of syntax that is not obvious from the default.uwmrc example shown above: variable definitions need not be written on separate lines; instead, they can be separated by a semicolon and space. For example:

resetvariables; resetbindings; resetmenus

Button/Key Bindings

The second section of the .uwmrc file specifies which combination of keys and buttons (and in which context) will be used to invoke each predefined uwm function. Let’s see how this works, by looking at the first two lines of the function binding section of default.uwmrc.

# FUNCTION     KEYS CONTEXT       MOUSE BUTTON     ACTIONS
f.newiconify=  meta :windowlicon: delta left

The first line we’ve shown is just a comment line, which labels each of the fields in the line below. The first field is separated from the others by an equals sign; subsequent fields are separated by colons. In default.uwmrc, fields are separated by tabs for clarity, making the colons (falsely) appear to be delimiters only for the context field; they could instead follow each other without intervening whitespace.

Let’s talk about each of the fields in turn.

Function Names

The first field in a key binding contains the name of a function, followed by an equals sign.

uwm has a number of predefined functions. Each of these functions has a name beginning with “f.”. The meaning of most of these functions should be fairly obvious to you from the name, if not from your experience using the window manager. For example, f. resize is used to resize a window, f. move to move a window, or f. iconify to change a window to an icon.

Others are less obvious. The function shown in the example, f. newiconify, is used to turn a window into an icon, or an icon into a window, and then to move it to a new location. Notice the function f. beep, which appears coupled with a set of empty quotes rather than a menu selection. This line in the .uwmrc creates a blank line on the WindowOps menu, to isolate the KillWindow and Exit selections from the others. If you select the blank line, the keyboard beeps.

Each of the functions is described in detail on the reference page for uwm in Part Three of this guide.

Keys

The second field lists keys, if any, which must be held down while invoking the specified function. uwm recognizes a small number of keys (discussed more fully in Chapter 11, Setup Clients), the most common of which are shift, control, lock and meta. These names must be entered in the .uwmrc file in lower case, and can be abbreviated s, c, l, and m.

If two keys must be held down at once, the names should be separated by a vertical bar (|). For example, c | s would mean that the Control and Shift keys should be pressed simultaneously. It is not permissible to bind a function to three keys at once. If the field is left blank, no key needs to be pressed while invoking the function.

Control, Shift and Lock should be familiar to most users. But what is a “Meta” key? There isn’t a key by that name on many keyboards—instead, Meta is a user-definable Control key that can be mapped to an actual key on the physical keyboard using the xmodmap client as described in Chapter 11. Most implementations of X will include a mapped Meta key. Type xmodmap without any arguments to display the map. The default.uwmrc specifies the Meta key in many keyboard bindings. On workstations without a special key corresponding to Meta, you will have to use xmodmap to find out or change the definition of Meta to something reasonable.

Meta could be mapped to the Control key, although this could potentially lead to conflicts with applications that want to use the Control key. In particular, certain functions of xedit will operate strangely or not at all if Meta is mapped to Control.

If you want to map the Meta key, it is best to choose a keyboard key that’s within easy reach and is not used frequently for other applications (perhaps an Alt or Funct key). Left- or right-handedness could also be a factor in choosing a Meta key.

The developers of uwm warn against binding functions to the Shift key alone, since they say certain applications use it as a Control key. If you use it in uwm, it will perform both functions simultaneously, which is likely to be confusing. For the same reason, you should not bind functions to buttons without modifier keys, except in the context of the root window.

Context

The third field defines the context—the location the pointer must be in before the function can be invoked. This field may be blank, or may contain one or more of: window, icon, or root Multiple context specifications should be separated by vertical bars.

If the context is blank, it means that the pointer can be anywhere. If root is specified, it means that the pointer must be in the root (background) window. and not in any other window or icon. If the context is window or icon, the pointer must be in a window or icon for the function to be invoked.

The context field makes perfect sense if you consider our sample function binding:

f.newiconify= meta :window|icon: delta left

f. newiconify turns a window into an icon, or an icon into a window, and then moves it to a new location. The pointer must be in a window or an icon for the function to be used.

Mouse Buttons

The fourth field defines the state of the pointer buttons used to invoke the function.

uwm is designed to be used with a three-button pointer, and keeps separate track of when the button is pressed and when it is released. It can also tell when the pointer is moved.

Accordingly, a button specification has two parts:

•   The name of a button: left, middle or right. These must be in lower case, and can be abbreviated l, m and r.

•   The state of the button: down, up (just released), or delta (held down while the pointer is moving). The distance in pixels the pointer must be moved in order to trigger the delta state is set by the delta variable, and is set to 5 in default.uwmrc. The actual translation of pixels to distance will vary from system to system, and you will probably want to experiment to find a value that you are comfortable with. The context for the delta state is the context at the point the button was first pressed, not its position at the time it has moved a delta number of pixels.

The button name and state can be specified in either order.

Going back to our sample function binding:

f.newiconify= meta :window|icon: delta left

you can now understand that the f. newiconify function is invoked by moving the pointer to either a window or an icon, pressing the Meta key and the left pointer button, and dragging the pointer in any direction.

All of the other function definitions should be equally readable to you. Go back for a moment and review the bindings shown in the default.uwmrc file in Example B-1.

You’ll notice that it is possible to bind the same function to more than one set of keys, buttons and/or contexts. For example, the WindowOps menu can be invoked anywhere by pressing the Meta and Shift keys together with the middle button on the pointer. But when the pointer is in the root window, the WindowOps menu can be invoked by pressing only the middle button on the pointer. The reason for this becomes obvious if you realize that when the pointer is on a window or an icon, the middle pointer button alone might have some other meaning to the application running in that window. In order to avoid conflict with other applications, uwm uses the more complex key/button combination. But when the pointer is in the root window, there is no possibility of conflict, and it can take a more forgiving approach.

Action

The fifth field, labeled “Action,” is typically used only for the f. menu function, which allows you to invoke menus. The fifth field specifies the name of a menu, whose contents are defined in the third section of the .uwmrc file. If the menu name contains quotes, special characters, parentheses, tabs, or blanks, it must be enclosed in double quotes. For consistency, you may want to always quote menu names. For example:

f.menu=               :root:    middle down: "WindowOps"
f.menu =      m|s     ::        middle down: "WindowOps"
f.menu =      m|s     ::        middle down: "Preferences"

Defining Menus

The third section of a .uwmrc file contains menu definitions. These definitions have the format:

menu = menu_name {
item_name : action
            .
            .
            .
}

The menu name must exactly match a name specified with the f .menu function.

Each item on the menu is given a label (item_name), which will appear on the menu. This is followed by a colon and the action to be performed. The action may be one of uwm’s functions, or if prefixed by a ! character, it can be a system command to be executed, as if in an xterm window. As shown in Example B-2, the WindowOps menu defined in default.uwmrc shows both types of action.

Example B-2. The WindowOps menu

menu = "WindowOps" {
New Window:     !"xterm&"
RefreshScreen:  f.refresh
Redraw:         f.redraw
Move:           f.move
Resize:         f.resize
Lower:          f.lower
Raise:          f.raise
CircUp:         f.circleup
CircDown:       f.circledown
AutoIconify:    f.iconify
LowerIconify:   f.newiconify
NewIconify:     f.newiconify
Focus:          f.focus
Freeze:         f.pause
UnFreeze:       f.continue
Restart:        f.restart
" ":            f.beep
KillWindow:     f. kill
" ":            f.beep
Exit:           f.exit
}

New Window is accomplished by running another instance of xterm. The other functions are accomplished simply by invoking one of uwm’s predefined functions.

The Preferences menu shown in Example B-3 simply invokes xset with a number of different options:

Example B-3. The Preferences menu

menu =  "Preferences" {
Bell Loud:    !"xset b 7&"
Bell Normal:  !"xset b 3&"
Bell Off:     !"xset b off&"
Click Loud:   !"xset c 8&"
Click Soft:   !"xset c on&"
Click Off:    !"xset c off&"
Lock On:      !"xset led on&"
Lock Off:     !"xset led off&"
Mouse Fast:   !"xset m 4 2&"
Mouse Normal: !"xset m 2 5&"
Mouse Slow:   !"xset m 1 1&"
}

Submenus

Frankly, we consider the menus defined by the default.uwmrc file to be rather awkward and far from complete. Among other things, the WindowOps menu has too many infrequently-used functions mixed right in with those you need all the time.

For the moment, let’s assume that we want to leave the variable definitions and function key bindings alone, but want to redefine the menus. We might create a local .uwmrc file that contained a menu definition like the one shown in Example B-4.

Example B-4. Window operations divided into two menus

resetmenus
menu = "WindowOps" {
Move:                        f.move
Resize:                      f.resize
Raise:                       f.raise
Lower:                       f.lower
(De) Iconify:                f.iconify
New window:                  !"xterm -sb&"
Refresh screen:              f.refresh
Restart window manager:      f.restart
" ":                         f.beep
KillWindow:                  f.kill
" ":                         f.beep
More Window Operations:      f.menu:"More Window Operations"
}
menu = "More Window Operations" {
(De)Iconify and move:        f.newiconify
Circulate windows up:        f.circleup
Circulate windows down:      f.circledown
Focus keyboard on window:    f.focus
Freeze server:               f.pause
Unfreeze server:             f.continue
" ":                         f.beep
Exit:                        f.exit
}

We’ve consolidated the three original menu items to iconify and deiconify into two, called (De)Iconify and (De)Iconify and Move. The latter corresponds to the NewIconify choice on the standard uwm menu.

To get from one menu to another, we simply define f.menu as the action for one item on the menu. No key, button or context is defined, so we go right to the next menu when selecting that item.

Slip off menus

In Example B-4, there was no keyboard binding for the More Window Operations menu. That menu could only be invoked by selecting it from the WindowOps menu. Another way to divide the window into two would be to give both the same key/button/context binding, as shown in Example B-5.

Example B-5. Window operations as two pull-right menus

resetbindings
# Note that if you resetbindings, you must recreate all desired
# operations.  If you are doing this kind of thing, you'd best copy
# the entire default.uwmrc to your home .uwmrc and edit it
f.menu =        :root:    middle down  : "WindowOps"
f.menu=         :root:    middle down  : "More Window Operations"
f.menu =  m|s   ::        middle down  : "WindowOps"
f.menu =  m|s   ::        middle down  : "More Window Operations"

If two menus have the same context and buttons, you can cause the second (or third, if more than two are defined) to appear simply by selecting nothing from the first, and, while continuing to hold down the specified pointer button (you can let go of the key), sliding the pointer off the menu to the right or left. The first menu will be replaced by the second.

Slip off menus may be awkward to control. If the labels of menu items are short, the menu can be too narrow, and hence difficult to use: you spend much more time sliding off menus unintentionally than you do selecting items. You can either train yourself to make pointer movements exactly perpendicular, or you can add horizontal menu padding as suggested in the revamp of uwm at the end of this appendix.

Executing System Commands from a Menu

We mentioned above that it is possible to specify a system command as a menu action simply by placing an exclamation point in front of the string to be executed. As we saw, the menus defined in default.uwmrc use this mechanism to create a new xterm window.

It is easy to cook up a menu that contains a miscellany of useful commands, as shown in Example B-6.

Example B-6. A Useful Commands menu

f.menu=         :root:     middle down          "Useful Commands"
             .
             .
             .
menu = "Useful Commands" {
Analog clock:               !"xclock –geometry 162x162−10+10&"
Digital clock:              !"xclock –digital –geometry 162x37−10+174&"
Edit File:                  !"xterm –e vi"
Calculator:                 !"xcalc –geometry 126x230−180+10&"
Mailbox:                    !"xbiff –geometry 65x65−353+10&"
Display keyboard mappings:  !"xmodmap&"
}

As you can quickly see, you can run any window-based programs directly, but you need to run other programs using xterms -e option (discussed in Chapter 4, The xterm Terminal Emulator). You are limited only by your imagination in what commands you might want to put on a menu. Each command runs in its own window, but that isn’t necessarily the case, as we’ll see in a moment.

Cut Buffer Strings

Another useful feature of uwms menus is that you can define the action for a menu item to be the insertion of a string into the server’s cut buffer. As discussed in Chapter 4, The xterm Terminal Emulator, you can use this cut buffer to cut and paste text between certain client windows. (See Chapter 4 for a more complete discussion of cut buffers.) You can also use the cut buffer from within uwm to define strings that will be placed in the cut buffer, ready for pasting into a window.

This feature is useful for specifying command strings that you want to have executed in an existing xterm window.

A string prefixed with a vertical bar will be loaded into the cut buffer with no trailing newline. This means that you can paste the string into a window and keep typing to add to the command line.

A string prefixed with a caret will be terminated with a newline, which means that if it is a command, and you paste it at the shell prompt in an xterm window, it will be executed immediately.

For example, we could add the following lines to our “Useful Commands” menu, as shown in Example B-7.

Example B-7. Useful commands using cut buffer strings

menu = "Useful Commands" {
     .
     .
     .
Check disk space: ^"df"
Remote login:     |"rlogin"
}

The last item on the menu uses | instead of ^, so that when the string is pasted into an xterm window, you can type in the name of the system to connect to. (If you tended to connect to a number of different systems on a regular basis, you could also just create a submenu with the names of various systems as menu items, and execute the correct command to log in to each system from there.)

Of course, cut buffer strings are not just useful for pasting in commands at the shell prompt. You could also associate editing macros or frequently-used text with menu items for use with a text editor.

Unfortunately, as of Release 3, there is a serious limitation to pasting strings from a uwm menu, related to the discussion of cut buffers versus text “selections” in Chapter 4. The window manager uses a cut buffer only; most Release 3 clients, notably xterm, use selections. With the default keyboard translations (Chapter 9), the contents of a selection are pasted before the contents of a cut buffer. Thus, if you’ve been copying and pasting text from an xterm window, the PRIMARY (default) selection probably contains text. If you then choose the Check disk space item from the uwm menu, that menu item is stored in the cut buffer, but does not replace the PRIMARY selection. When you go to paste Check disk space into an xterm window, you get the text from the PRIMARY selection instead (previously cut from an xterm window).

To solve this problem, you can use the xcutsel client to copy the text from the cut buffer into the selection. In an xterm window, type:

% xcutael &

and then position the xcutsel window using the pointer. When you are having trouble pasting text yanked from a window manager menu because of a previous text selection, click on the Copy 0 to Primary command button in the xcutsel window. This command copies text in the cut buffer (specifically CUT_BUFFER “0”) to the PRIMARY selection. You should then be able to paste the text yanked from the uwm menu successfully.

Note that if the PRIMARY selection is currently empty, the text in the cut buffer will be pasted instead, and this problem will not occur. For more information on the xcutsel client, see Chapter 4, The xterm Terminal Emulator, and the xcutsel reference page in Part Three of this guide.

Color Menus

So far, we’ve assumed that all menus are black and white. But you can also create color menus. You can even assign different colors to the menu title, the highlighting bar (the horizontal band that follows the pointer within the menu and shows which item is selected) and the individual selections on the menu.

Colors are added to menus using the following syntax:

menu = "menu name" (title_fg:title_bg:highlight_fg: highlight_bg) {
"item name": (item_fg:item_bg):  "action"
     .
     .
     .
}

Up to four different colors can be defined for the overall menu:

title_fg The foreground color of the menu title (i.e., the color of the lettering).
title_bg The background color of the menu title.
highlight_fg The foreground color of the highlighting bar (i.e., the color of the lettering within the bar).
highlight_bg The background color of the highlighting bar.

Two colors can be defined for each menu item:

item_fg The foreground color of the item (i.e., the color of the lettering).
item_bg The background color of the item.

Colors can be specified either with color names or hex strings. as described in Chapter 8, Command Line Options.

Here’s a color menu that works well on a Sun-3 workstation. Keep in mind that the colors in the color database may look different on different servers.

menu = "WindowOps" (darkslategrey:plum:darkslategrey:plum) {
  Move:                    (slateblue:lightblue) :f.move
  Resize:                  (slateblue:lightblue) :f.resize
  Raise:                   (slateblue:lightblue) :f.raise
  Lower:                   (slateblue:lightblue) :f.lower
  (De)Iconify:             (slateblue:lightblue) :f.iconify
  New window:              (slateblue:lightblue) :!"xterm&"
  Refresh screen:          (slateblue:lightblue) :f.refresh
  Restart window manager:  (slateblue:lightblue) :f.restart
}

The total number of colors that can be allocated by the window manager for its own use is specified by the maxcolors variable. If you try to use more than maxcolors colors, the additional colors will default to the colors of the root window. This can also happen if the server runs out of free colormap entries.

Some releases of uwm include a color menu bug. If all menu item in the file are specified in color, all menus default to black and white. One quick fix is to leave the final item on the final menu in the file in black and white. More recent versions of uwm have corrected the problem.

A Complete Revamp of uwm

Using the various techniques described in this appendix, we’ve modified the default.uwmrc file to create an interface we think is more helpful to the average user.

Our modified .uwmrc file, hown in Example B-8. sets up four slip off menus, each with a lightly different focus. In effect, we’ve split the original WindowOps menu into two, called windowOps and More Window Operations, renaming and modifying many of the selection, adding a few of our own and putting the less frequently used on the second menu. The, third menu offers some Useful Commands to place other clients, including xclock and xcalc, and to execute system commands, such as df and rlogin. The final menu is a slightly modified Preferences menu, which sets different keyclick volume, leds, and pointer speeds than the default.

You can test our .uwmrc (following) or just use it as a touchstone to create your own.

Example B-8. Modified .uwmrc file

images

images

images

__________

*The pointer tracking speed controls how much the pointer moves on the screen when you move the pointer. Experiment with each setting and see which you are most comfortable with.

*Joel Gancarz, “UWM: A User Interface for X Windows,” in USENIX Conference Proceedings, Summer 1986, p. 431.

Get X Window System User's Guide for X11 R3 and R4 of the X Window System now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.