1<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-x11">
2 <title>X Window System</title>
3 <para>
4 The X Window System (X11) provides the basis of NixOS’ graphical
5 user interface. It can be enabled as follows:
6 </para>
7 <programlisting language="bash">
8services.xserver.enable = true;
9</programlisting>
10 <para>
11 The X server will automatically detect and use the appropriate video
12 driver from a set of X.org drivers (such as <literal>vesa</literal>
13 and <literal>intel</literal>). You can also specify a driver
14 manually, e.g.
15 </para>
16 <programlisting language="bash">
17services.xserver.videoDrivers = [ "r128" ];
18</programlisting>
19 <para>
20 to enable X.org’s <literal>xf86-video-r128</literal> driver.
21 </para>
22 <para>
23 You also need to enable at least one desktop or window manager.
24 Otherwise, you can only log into a plain undecorated
25 <literal>xterm</literal> window. Thus you should pick one or more of
26 the following lines:
27 </para>
28 <programlisting language="bash">
29services.xserver.desktopManager.plasma5.enable = true;
30services.xserver.desktopManager.xfce.enable = true;
31services.xserver.desktopManager.gnome.enable = true;
32services.xserver.desktopManager.mate.enable = true;
33services.xserver.windowManager.xmonad.enable = true;
34services.xserver.windowManager.twm.enable = true;
35services.xserver.windowManager.icewm.enable = true;
36services.xserver.windowManager.i3.enable = true;
37services.xserver.windowManager.herbstluftwm.enable = true;
38</programlisting>
39 <para>
40 NixOS’s default <emphasis>display manager</emphasis> (the program
41 that provides a graphical login prompt and manages the X server) is
42 LightDM. You can select an alternative one by picking one of the
43 following lines:
44 </para>
45 <programlisting language="bash">
46services.xserver.displayManager.sddm.enable = true;
47services.xserver.displayManager.gdm.enable = true;
48</programlisting>
49 <para>
50 You can set the keyboard layout (and optionally the layout variant):
51 </para>
52 <programlisting language="bash">
53services.xserver.layout = "de";
54services.xserver.xkbVariant = "neo";
55</programlisting>
56 <para>
57 The X server is started automatically at boot time. If you don’t
58 want this to happen, you can set:
59 </para>
60 <programlisting language="bash">
61services.xserver.autorun = false;
62</programlisting>
63 <para>
64 The X server can then be started manually:
65 </para>
66 <programlisting>
67# systemctl start display-manager.service
68</programlisting>
69 <para>
70 On 64-bit systems, if you want OpenGL for 32-bit programs such as in
71 Wine, you should also set the following:
72 </para>
73 <programlisting language="bash">
74hardware.opengl.driSupport32Bit = true;
75</programlisting>
76 <section xml:id="sec-x11-auto-login">
77 <title>Auto-login</title>
78 <para>
79 The x11 login screen can be skipped entirely, automatically
80 logging you into your window manager and desktop environment when
81 you boot your computer.
82 </para>
83 <para>
84 This is especially helpful if you have disk encryption enabled.
85 Since you already have to provide a password to decrypt your disk,
86 entering a second password to login can be redundant.
87 </para>
88 <para>
89 To enable auto-login, you need to define your default window
90 manager and desktop environment. If you wanted no desktop
91 environment and i3 as your your window manager, you'd define:
92 </para>
93 <programlisting language="bash">
94services.xserver.displayManager.defaultSession = "none+i3";
95</programlisting>
96 <para>
97 Every display manager in NixOS supports auto-login, here is an
98 example using lightdm for a user <literal>alice</literal>:
99 </para>
100 <programlisting language="bash">
101services.xserver.displayManager.lightdm.enable = true;
102services.xserver.displayManager.autoLogin.enable = true;
103services.xserver.displayManager.autoLogin.user = "alice";
104</programlisting>
105 </section>
106 <section xml:id="sec-x11--graphics-cards-intel">
107 <title>Intel Graphics drivers</title>
108 <para>
109 There are two choices for Intel Graphics drivers in X.org:
110 <literal>modesetting</literal> (included in the xorg-server
111 itself) and <literal>intel</literal> (provided by the package
112 xf86-video-intel).
113 </para>
114 <para>
115 The default and recommended is <literal>modesetting</literal>. It
116 is a generic driver which uses the kernel
117 <link xlink:href="https://en.wikipedia.org/wiki/Mode_setting">mode
118 setting</link> (KMS) mechanism. It supports Glamor (2D graphics
119 acceleration via OpenGL) and is actively maintained but may
120 perform worse in some cases (like in old chipsets).
121 </para>
122 <para>
123 The second driver, <literal>intel</literal>, is specific to Intel
124 GPUs, but not recommended by most distributions: it lacks several
125 modern features (for example, it doesn't support Glamor) and the
126 package hasn't been officially updated since 2015.
127 </para>
128 <para>
129 The results vary depending on the hardware, so you may have to try
130 both drivers. Use the option
131 <xref linkend="opt-services.xserver.videoDrivers" /> to set one.
132 The recommended configuration for modern systems is:
133 </para>
134 <programlisting language="bash">
135services.xserver.videoDrivers = [ "modesetting" ];
136</programlisting>
137 <para>
138 If you experience screen tearing no matter what, this
139 configuration was reported to resolve the issue:
140 </para>
141 <programlisting language="bash">
142services.xserver.videoDrivers = [ "intel" ];
143services.xserver.deviceSection = ''
144 Option "DRI" "2"
145 Option "TearFree" "true"
146'';
147</programlisting>
148 <para>
149 Note that this will likely downgrade the performance compared to
150 <literal>modesetting</literal> or <literal>intel</literal> with
151 DRI 3 (default).
152 </para>
153 </section>
154 <section xml:id="sec-x11-graphics-cards-nvidia">
155 <title>Proprietary NVIDIA drivers</title>
156 <para>
157 NVIDIA provides a proprietary driver for its graphics cards that
158 has better 3D performance than the X.org drivers. It is not
159 enabled by default because it’s not free software. You can enable
160 it as follows:
161 </para>
162 <programlisting language="bash">
163services.xserver.videoDrivers = [ "nvidia" ];
164</programlisting>
165 <para>
166 Or if you have an older card, you may have to use one of the
167 legacy drivers:
168 </para>
169 <programlisting language="bash">
170services.xserver.videoDrivers = [ "nvidiaLegacy390" ];
171services.xserver.videoDrivers = [ "nvidiaLegacy340" ];
172services.xserver.videoDrivers = [ "nvidiaLegacy304" ];
173</programlisting>
174 <para>
175 You may need to reboot after enabling this driver to prevent a
176 clash with other kernel modules.
177 </para>
178 </section>
179 <section xml:id="sec-x11--graphics-cards-amd">
180 <title>Proprietary AMD drivers</title>
181 <para>
182 AMD provides a proprietary driver for its graphics cards that is
183 not enabled by default because it’s not Free Software, is often
184 broken in nixpkgs and as of this writing doesn't offer more
185 features or performance. If you still want to use it anyway, you
186 need to explicitly set:
187 </para>
188 <programlisting language="bash">
189services.xserver.videoDrivers = [ "amdgpu-pro" ];
190</programlisting>
191 <para>
192 You will need to reboot after enabling this driver to prevent a
193 clash with other kernel modules.
194 </para>
195 </section>
196 <section xml:id="sec-x11-touchpads">
197 <title>Touchpads</title>
198 <para>
199 Support for Synaptics touchpads (found in many laptops such as the
200 Dell Latitude series) can be enabled as follows:
201 </para>
202 <programlisting language="bash">
203services.xserver.libinput.enable = true;
204</programlisting>
205 <para>
206 The driver has many options (see <xref linkend="ch-options" />).
207 For instance, the following disables tap-to-click behavior:
208 </para>
209 <programlisting language="bash">
210services.xserver.libinput.touchpad.tapping = false;
211</programlisting>
212 <para>
213 Note: the use of <literal>services.xserver.synaptics</literal> is
214 deprecated since NixOS 17.09.
215 </para>
216 </section>
217 <section xml:id="sec-x11-gtk-and-qt-themes">
218 <title>GTK/Qt themes</title>
219 <para>
220 GTK themes can be installed either to user profile or system-wide
221 (via <literal>environment.systemPackages</literal>). To make Qt 5
222 applications look similar to GTK ones, you can use the following
223 configuration:
224 </para>
225 <programlisting language="bash">
226qt5.enable = true;
227qt5.platformTheme = "gtk2";
228qt5.style = "gtk2";
229</programlisting>
230 </section>
231 <section xml:id="custom-xkb-layouts">
232 <title>Custom XKB layouts</title>
233 <para>
234 It is possible to install custom
235 <link xlink:href="https://en.wikipedia.org/wiki/X_keyboard_extension">
236 XKB </link> keyboard layouts using the option
237 <literal>services.xserver.extraLayouts</literal>.
238 </para>
239 <para>
240 As a first example, we are going to create a layout based on the
241 basic US layout, with an additional layer to type some greek
242 symbols by pressing the right-alt key.
243 </para>
244 <para>
245 Create a file called <literal>us-greek</literal> with the
246 following content (under a directory called
247 <literal>symbols</literal>; it's an XKB peculiarity that will help
248 with testing):
249 </para>
250 <programlisting language="bash">
251xkb_symbols "us-greek"
252{
253 include "us(basic)" // includes the base US keys
254 include "level3(ralt_switch)" // configures right alt as a third level switch
255
256 key <LatA> { [ a, A, Greek_alpha ] };
257 key <LatB> { [ b, B, Greek_beta ] };
258 key <LatG> { [ g, G, Greek_gamma ] };
259 key <LatD> { [ d, D, Greek_delta ] };
260 key <LatZ> { [ z, Z, Greek_zeta ] };
261};
262</programlisting>
263 <para>
264 A minimal layout specification must include the following:
265 </para>
266 <programlisting language="bash">
267services.xserver.extraLayouts.us-greek = {
268 description = "US layout with alt-gr greek";
269 languages = [ "eng" ];
270 symbolsFile = /yourpath/symbols/us-greek;
271};
272</programlisting>
273 <note>
274 <para>
275 The name (after <literal>extraLayouts.</literal>) should match
276 the one given to the <literal>xkb_symbols</literal> block.
277 </para>
278 </note>
279 <para>
280 Applying this customization requires rebuilding several packages,
281 and a broken XKB file can lead to the X session crashing at login.
282 Therefore, you're strongly advised to <emphasis role="strong">test
283 your layout before applying it</emphasis>:
284 </para>
285 <programlisting>
286$ nix-shell -p xorg.xkbcomp
287$ setxkbmap -I/yourpath us-greek -print | xkbcomp -I/yourpath - $DISPLAY
288</programlisting>
289 <para>
290 You can inspect the predefined XKB files for examples:
291 </para>
292 <programlisting>
293$ echo "$(nix-build --no-out-link '<nixpkgs>' -A xorg.xkeyboardconfig)/etc/X11/xkb/"
294</programlisting>
295 <para>
296 Once the configuration is applied, and you did a logout/login
297 cycle, the layout should be ready to use. You can try it by e.g.
298 running <literal>setxkbmap us-greek</literal> and then type
299 <literal><alt>+a</literal> (it may not get applied in your
300 terminal straight away). To change the default, the usual
301 <literal>services.xserver.layout</literal> option can still be
302 used.
303 </para>
304 <para>
305 A layout can have several other components besides
306 <literal>xkb_symbols</literal>, for example we will define new
307 keycodes for some multimedia key and bind these to some symbol.
308 </para>
309 <para>
310 Use the <emphasis>xev</emphasis> utility from
311 <literal>pkgs.xorg.xev</literal> to find the codes of the keys of
312 interest, then create a <literal>media-key</literal> file to hold
313 the keycodes definitions
314 </para>
315 <programlisting language="bash">
316xkb_keycodes "media"
317{
318 <volUp> = 123;
319 <volDown> = 456;
320}
321</programlisting>
322 <para>
323 Now use the newly define keycodes in <literal>media-sym</literal>:
324 </para>
325 <programlisting language="bash">
326xkb_symbols "media"
327{
328 key.type = "ONE_LEVEL";
329 key <volUp> { [ XF86AudioLowerVolume ] };
330 key <volDown> { [ XF86AudioRaiseVolume ] };
331}
332</programlisting>
333 <para>
334 As before, to install the layout do
335 </para>
336 <programlisting language="bash">
337services.xserver.extraLayouts.media = {
338 description = "Multimedia keys remapping";
339 languages = [ "eng" ];
340 symbolsFile = /path/to/media-key;
341 keycodesFile = /path/to/media-sym;
342};
343</programlisting>
344 <note>
345 <para>
346 The function
347 <literal>pkgs.writeText <filename> <content></literal>
348 can be useful if you prefer to keep the layout definitions
349 inside the NixOS configuration.
350 </para>
351 </note>
352 <para>
353 Unfortunately, the Xorg server does not (currently) support
354 setting a keymap directly but relies instead on XKB rules to
355 select the matching components (keycodes, types, ...) of a layout.
356 This means that components other than symbols won't be loaded by
357 default. As a workaround, you can set the keymap using
358 <literal>setxkbmap</literal> at the start of the session with:
359 </para>
360 <programlisting language="bash">
361services.xserver.displayManager.sessionCommands = "setxkbmap -keycodes media";
362</programlisting>
363 <para>
364 If you are manually starting the X server, you should set the
365 argument <literal>-xkbdir /etc/X11/xkb</literal>, otherwise X
366 won't find your layout files. For example with
367 <literal>xinit</literal> run
368 </para>
369 <programlisting>
370$ xinit -- -xkbdir /etc/X11/xkb
371</programlisting>
372 <para>
373 To learn how to write layouts take a look at the XKB
374 <link xlink:href="https://www.x.org/releases/current/doc/xorg-docs/input/XKB-Enhancing.html#Defining_New_Layouts">documentation
375 </link>. More example layouts can also be found
376 <link xlink:href="https://wiki.archlinux.org/index.php/X_KeyBoard_extension#Basic_examples">here
377 </link>.
378 </para>
379 </section>
380</chapter>