14.4 A Closer Look at the X Window System
In contrast with Wayland-based systems, the X Window System (http://www.x.org/) has historically been very large, with the base distribution including the X server, client support libraries, and clients. Due to the emergence of desktop environments such as GNOME and KDE, the role of X has changed over time, with the focus now more on the core server that manages rendering and input devices, as well as a simplified client library.
The X server is easy to identify on your system. It’s called X or Xorg. Check for it in a process listing; you’ll usually see it running with a number of options like this:
Xorg -core :0 -seat seat0 -auth /var/run/lightdm/root/:0 -nolisten tcp vt7
-novtswitch
The :0 shown here is called the X display, an identifier representing one or more monitors that you access with a common keyboard and/or mouse. Usually, the display just corresponds to the single monitor attached to your computer, but you can put multiple monitors under the same display. For processes running under an X session, the DISPLAY environment variable is set to the display identifier.
Displays can be further subdivided into screens, such as :0.0 and :0.1, but this is quite rare because X extensions like RandR can combine multiple monitors into one larger virtual screen.
On Linux, an X server runs on a virtual terminal. In this example, the vt7 argument shows that it’s been told to run on /dev/tty7 (normally, the p. 355 server starts on the first virtual terminal available). You can run more than one X server at a time on Linux by running them on separate virtual terminals, with each server having a unique display identifier. You can switch between the servers with the CTRL-ALT-FN keys or the chvt command.
14.4.1 Display Managers
You normally wouldn’t start the X server on the command line, because starting the server doesn’t define any clients that are supposed to run on it. If you start the server by itself, you’ll just get a blank screen. Instead, the most common way to start an X server is with a display manager, a program that starts the server and puts a login box on the screen. When you log in, the display manager starts a set of clients, such as a window manager and file manager, so that you can start to use the machine.
Many different display managers are available, such as gdm (for GNOME) and kdm (for KDE). The lightdm in the argument list for the preceding X server invocation is a cross-platform display manager meant to be able to start GNOME or KDE sessions.
If you insist on starting an X session from a virtual console instead of using a display manager, you can run the startx or xinit command. However, the session you get will likely be a very simple one that looks completely unlike that of a display manager, because the mechanics and startup files are different.
14.4.2 Network Transparency
One feature of X is network transparency. Because clients talk to the server using a protocol, it’s possible to run clients across a network to a server running on a different machine directly over the network, with the X server listening for TCP connections on port 6000. Clients connecting to that port could authenticate and then send windows to the server.
Unfortunately, this method doesn’t normally offer any encryption and is insecure as a result. To close this hole, most distributions now disable the X server’s network listener (with the -nolisten tcp option to the server). However, you can still run X clients from a remote machine with SSH tunneling, as described in Chapter 10, by connecting the X server’s Unix domain socket to a socket on the remote machine.
There is no simple way to run remotely with Wayland, because clients have their own screen memory that the compositor must access directly in order to display. However, many emerging systems, such as RDP (Remote Desktop Protocol), can work in conjunction with the compositor to provide remote functionality.
14.4.3 Ways of Exploring X Clients
Although one doesn’t normally think of working with a graphical user interface from the command line, several utilities allow you to explore the parts of the X Window System. In particular, you can inspect clients as they run.
One of the simplest tools is xwininfo. When run without any arguments, it asks you to click on a window:
$ xwininfo
xwininfo: Please select the window about which you
would like information by clicking the
mouse in that window.
After you click, it prints a list of information about the window, such as its location and size:
xwininfo: Window id: 0x5400024 "xterm"
Absolute upper-left X: 1075
Absolute upper-left Y: 594
--snip--
Notice the window ID here. The X server and window managers use this identifier to keep track of windows. To get a list of all window IDs and clients, use the xlsclients -l command.
14.4.4 X Events
X clients get their input and other information about the state of the server through a system of events. X events work like other asynchronous interprocess communication events, such as udev events and D-Bus events. The X server receives information from a source, such as an input device, and then redistributes that input as an event to any interested X client.
You can experiment with events via the xev command. Running it opens a new window that you can mouse into, click, and type. As you do so, xev generates output describing the X events that it receives from the server. For example, here’s sample output for mouse movement:
$ xev
--snip--
MotionNotify event, serial 36, synthetic NO, window 0x6800001,
root 0xbb, subw 0x0, time 43937883, (47,174), root:(1692,486),
state 0x0, is_hint 0, same_screen YES
MotionNotify event, serial 36, synthetic NO, window 0x6800001,
root 0xbb, subw 0x0, time 43937891, (43,177), root:(1688,489),
state 0x0, is_hint 0, same_screen YES
Notice the coordinates in parentheses. The first pair represents the x- and y-coordinates of the mouse pointer inside the window, and the second (root:) is the location of the pointer on the entire display.
Other low-level events include keypresses and button clicks, but more advanced ones indicate whether the mouse has entered or exited the window, or whether the window has gained or lost focus from the window manager. For example, here are corresponding exit and unfocus events.
LeaveNotify event, serial 36, synthetic NO, window 0x6800001,
root 0xbb, subw 0x0, time 44348653, (55,185), root:(1679,420),
mode NotifyNormal, detail NotifyNonlinear, same_screen YES,
focus YES, state 0
FocusOut event, serial 36, synthetic NO, window 0x6800001,
mode NotifyNormal, detail NotifyNonlinear
One common use of xev is to extract keycodes and key symbols for different keyboards when remapping the keyboard. Here’s the output from pressing the L key; the keycode here is 46:
KeyPress event, serial 32, synthetic NO, window 0x4c00001,
root 0xbb, subw 0x0, time 2084270084, (131,120), root:(197,172),
state 0x0, keycode 46 (keysym 0x6c, l), same_screen YES,
XLookupString gives 1 bytes: (6c) "l"
XmbLookupString gives 1 bytes: (6c) "l"
XFilterEvent returns: False
You can also attach xev to an existing window ID with the -id id option. Replace id with the ID you get from xwininfo (it will be a hexadecimal number starting with 0x).
14.4.5 X Input and Preference Settings
One of the most potentially baffling characteristics of X is that there’s often more than one way to set preferences, and some methods may not work. For example, one common keyboard preference on Linux systems is to remap the CAPS LOCK key to a CTRL key. There are a number of ways to do this, from making small adjustments with the old xmodmap command to providing an entirely new keyboard map with the setxkbmap utility. How do you know which one (if any) to use? It’s a matter of knowing which pieces of the system have responsibility, but determining this can be difficult. Keep in mind that a desktop environment may provide its own settings and overrides. With this said, here are a few pointers on the underlying infrastructure.
Input Devices (General)
The X server uses the X Input Extension to manage input from many different devices. There are two basic types of input device—keyboard and pointer (mouse)—and you can attach as many devices as you like. To handle more than one of the same type of device simultaneously, the X Input Extension creates a virtual core device that funnels device input to the X server.
To see the device configuration on your machine, run the xinput --list command:
$ xinput --list
∣ Virtual core pointer id=2 [master pointer (3)]
∣ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
∣ ↳ Logitech Unifying Device id=8 [slave pointer (2)]
⌊ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
↳ Power Button id=6 [slave keyboard (3)]
↳ Power Button id=7 [slave keyboard (3)]
↳ Cypress USB Keyboard id=9 [slave keyboard (3)]
Each device has an associated ID that you can use with xinput and other commands. In this output, IDs 2 and 3 are the core devices, and IDs 8 and 9 are the real devices. Notice that the power buttons on the machine are also treated as X input devices.
Most X clients listen for input from the core devices, because there’s no reason for them to be concerned about which particular device initiates an event. In fact, most clients know nothing about the X Input Extension. However, a client can use the extension to single out a particular device.
Each device has a set of associated properties. To view the properties, use xinput with the device number:
$ xinput --list-props 8
Device 'Logitech Unifying Device. Wireless PID:4026':
Device Enabled (126): 1
Coordinate Transformation Matrix (128): 1.000000, 0.000000, 0.000000,
0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
Device Accel Profile (256): 0
Device Accel Constant Deceleration (257): 1.000000
Device Accel Adaptive Deceleration (258): 1.000000
Device Accel Velocity Scaling (259): 10.000000
--snip--
You can change a number of properties with the --set-prop option. See the xinput(1) manual page for more information.
Mouse
You can manipulate device-related settings with the xinput command, and many of the most useful options pertain to the mouse (pointer). You can change many settings directly as properties, but it’s usually easier with the specialized --set-ptr-feedback and --set-button-map options to xinput. For example, if you have a three-button mouse at dev on which you’d like to reverse the order of buttons (this is handy for left-handed users), try this:
$ xinput --set-button-map dev 3 2 1
Keyboard
The many different keyboard layouts available internationally present particular difficulties for integration into any windowing system. X has always had an internal keyboard-mapping capability in its core protocol that you can manipulate with the xmodmap command, but any halfway recent system uses XKB (the X keyboard extension) to gain finer control.
XKB is complicated, so much so that many people still use xmodmap when they need to make quick changes. The basic idea behind XKB is that you can define a keyboard map, compile it with the xkbcomp command, and then load and activate that map in the X server with the setxkbmap command. This system has two especially interesting features:
- You can define partial maps to supplement existing maps. This is particularly handy for tasks such as changing your CAPS LOCK key into a CTRL key, and it is used by many graphical keyboard preference utilities in desktop environments.
- You can define individual maps for each attached keyboard.
Desktop Background
The root window of your X server is the background of the display. The old X command xsetroot allows you to set the background color and other characteristics of the root window, but it has no effect on most machines because the root window is never visible. Instead, most desktop environments place a big window in the back of all of your other windows in order to enable features such as “active wallpaper” and desktop file browsing. There are ways to change the background from the command line (for example, with the gsettings command in some GNOME installations), but if you actually want to do this, you probably have too much time on your hands.
xset
Probably the oldest preference command is xset. It’s not used much anymore, but you can run a quick xset q to get the status of a few features. Perhaps the most useful are the screensaver and Display Power Management Signaling (DPMS) settings.