How to configure X11 in a simple way

3 months ago 8

Preamble

The modern common Linux and as a result also a UNIX desktop is heavily bloated. Even if you install not a full-scale DE like Gnome, but a small WM: i3wm, WindowMaker, XFCE, StumpWM, etc. These window managers are small itself, but when user installs a necessary GUI programs — then a lot of bloat will be installed too: gsettings-daemon, D-Bus daemon, polkitd, console-kit-daemon, etc, etc…

What can I do with all these bloatware? There are two solutions:

  1. Disable unwanted compile-time options and recompile necessary stuff by itself. I already wrote something about this approach here. There is one disadvantage — sometimes you need to edit the source code or port-related files to get rid of strange things, like Krita's Wayland dependency when I'm using it in the pure X11 environment and so on.
  2. Use good, old and mature, well-tested by time programs and solutions. You don't obliged to install a lot of Gnome/KDE-related libraries if you want a simple program with GUI to achieve a simple task, like draw a login window and check user's credentials for the single-user box.

In this post I'll write about the second approach — how to make nice things with simple (for the "modern" world; of course some purist will say that even these things are bloated too) good old programs and ways.

All nice things from desktop environments, like nice effects, nice themes, automatic execution of mail client after click on the proper link, etc — don't need tons of frameworks and libraries from big desktop environments. They are totally acessible with an elegant utilities from a more civilized era.

Actions, described in this blogpost, were (obviously) performed in the FreeBSD 14.3, not in Linux :-) and with X server, not Wayland :-).

Covered topics:

  • How to setup X server to operate with HighDPI display?
  • How to setup keyboard only with a shell and text editor?
  • How to setup different pointing devices, including tricky setup of trackball for left-handed user?
  • Good old XScreenSaver.
  • How to setup nice effects: transparency, shadows and animations — for a small WM (e.g. StumpWM)?
  • How to switch multi-monitor configurations and perform tricky things with xrandr?
  • How to use XDM as a display manager and login screen? It has a very limited set of dependencies, lesser than a "lightweight" LightDM.
  • How to use xdg-utils to open Emacs Dired as a default filemanager, Emacs ComposeMode as a default e-mail composer, etc?
  • How to setup some nice themes without GUI utilities — just by editing text files with any text editor?

High DPI

I have a small 13.3" display with a 2K resolultion in my laptop. As a result, by default I see all GUI element on my screen very small, so I can't see them without unnecessary strain in my eyes (and not only I, of course).

The usual approach to this problem — instruct GUI environment that this screen with a big resolution doesn't have a big diagonal too.

So, I read these articles:

And also a man 5 xorg.conf. Suddenly I found that I don't need to play with tricky environment variables to please every GUI toolkit. All that I need to do — is to specify active area dimensions in millimeters for my monitor in X11 configuration! The neat part — this settings will be applied to the whole system (login window, any WM, etc), not only for logged in user with necessary environment variables.

I got the necessary dimensions in millimeters from a display module datasheet:

Sharp LQ125T1JW02 physical specifications. Width and height of active area 276.48x155.52 mm

Active area dimensions (mm) from Sharp LQ125T1JW02 datasheet

And specified these dimensions in the proper section (file /usr/local/etc/X11/xorg.conf.d/10-intel.conf):

Section "Monitor" Identifier "MainMonitor" Option "Primary" "true" DisplaySize 276.48 155.52 EndSection

The MainMonitor is specified in the Device section as monitor connected to the DP-3 bus:

Section "Device" Identifier "intel" ... Option "Monitor-DP-3" "MainMonitor" Option "Monitor-LVDS-1" "PhantomMonitor" EndSection

And both sections are connected in the Screen section:

Section "Screen" Identifier "MainScreen" Device "intel" Monitor "MainMonitor" EndSection

Also, for applications which are using GTK3, I added this line to the ~/.config/gtk-3.0/settings.ini, because looks like it doesn't respect the X server settings and draws all letters very small:

gtk-font-name=DejaVu Serif Book 16

After X server restart I happily found that almost all GUI applications are displaying correctly! The Emacs, Conky, GIMP, Krita, etc… With one exception — the Librewolf (Firefox). Suddenly it doesn't want to use X settings.

The solution for Librewolf here — the tricky option ui.textScaleFactor in the about:config (the @[email protected]helped me with that). I set it to 170 and Librewolf now scaled properly like any other GUI program in the system.

Keyboard configuration

Previously I used next two commands in my ~/.xinitrc to properly configure keyboard in X:

1: setxkbmap -model "thinkpad" \ 2: -layout us,ru \ 3: -option grp:menu_toggle -option grp_led:caps \ 4: -option compose:ralt \ 5: -option shift:both_capslock_cancel \ 6: -option caps:ctrl_modifier 7: xmodmap -e "keycode 147 = ISO_Next_Group Menu ISO_Next_Group Menu"

The setxkbmap is the main command which does the all necessary magic. It uses the X keyboard extension1 to control the keyboard configuration:

  • keyboard layout
  • indicators actions (NumLock, CapsLock and ScrollLock and also the bell)
  • keyboard parameters like repeat speed and delay
  • behaviour of keyboard modifiers (Ctrl, Alt and so on)
  • manipulation of mouse cursor with keyboard keys
  • etc.

In the code above, I setup the next things:

  1. The keyboard model in the first line. The keyboard model specifies physical layout of keyboard and maps the physical key with the keycode. For example, the Menu key for thinkpad layout is mapped with 147 keycode.

    Usually user uses only one keyboard at a time (if user is not an octopus), so only one keyboard model could be specified with the setxkbmap command. If there are mutliple keyboards, then the X keyboard extension should be configured through the xorg.conf.

    The X server should determine the keyboard type automatically so it is not necessary to specify keyboard model — the server will determine keyboard and process the special keys (like volume control keys or multimedia controls) by itself. But I explicitly specified keyboard model as thinkpad keyboard just for clarity.

  2. The line 2 specifies the used keyboard layouts. Each layout describes how the keycode maps with real symbol.

    For example, on my keyboard (for Russian market) on the key right of Tab key there are the next symbols engraved: q and й. So, to use both sets of symbols — English and Cyrillic — I should use us and ru layouts. Obviously, it is possible to specify more layouts if necessary — just add them with comma as a separator.

    When I press this key on my thinkpad keyboard the keycode 24 will be generated. And for us layout this keycode will generate q letter with 0x71 keysym:

    KeyPress event, serial 36, synthetic NO, window 0x2200001, root 0x26a, subw 0x0, time 71799711, (1351,400), root:(1351,400), state 0x0, keycode 24 (keysym 0x71, q), same_screen YES, XLookupString gives 1 bytes: (71) "q" XmbLookupString gives 1 bytes: (71) "q" XFilterEvent returns: False

    And when I press this key with ru layout, then the same keycode (24) will be generated and letter й will be issued (0xd0 0xb9 keysym):

    KeyPress event, serial 36, synthetic NO, window 0x2200001, root 0x26a, subw 0x0, time 71809991, (1351,400), root:(1351,400), state 0x2000, keycode 24 (keysym 0x6ca, Cyrillic_shorti), same_screen YES, XLookupString gives 2 bytes: (d0 b9) "й" XmbLookupString gives 2 bytes: (d0 b9) "й" XFilterEvent returns: False
  3. On the line 3 I specify which key is used to switch between layouts. I use Menu key for it. But there are a rich set of different keychords to switch layouts: from common Alt+Shift or Ctrl+Shift to exotic Left Ctrl+Left Win. The full list of possible keychords can be viewed in the section OPTIONS subsection Switching to another layout from the man 7 xkeyboard-config.

    Also, on the same line, I use CapsLock LED as an indicator of selected layout. It is turned off when I'm using the us layout and turned on when I'm using the ru layout. List of options for different keyboard LEDs written in the Use keyboard LED to show alternative layout subsection of the same section of manual.

  4. On the line 4 I setup one cool feature of X — the Compose key. I use Right Alt key as a Compose key.

    It was a separate and very valuable key on the old keyboards but since some physical keys were removed because of enshittification "simplification" — it is disappeared. This process still doesn't stopped — the Copilot key was added to nudge Windows users to use integrated LLM, some keys were labelled by manufacturers as "less valuable" and they can be pressed with Fn key (for example, F1-F12 keys on the some laptops) or even removed like Scroll Lock key (it is necessary to scroll lines on the text terminal).

    The Compose key is necessary to type some obscure symbols, which are not accessible the usual way, like the —, °, ⇒, ₽ and other symbols. To type, for example — symbol, I press and release the Compose (aka Right Alt) key and then triple press the - key. Full list of these cool keychords can be viewed in the /usr/local/lib/X11/locale/en_US.UTF-8/Compose file for en_US.UTF-8 locale and in the /usr/local/lib/X11/locale/ru_RU.UTF-8/Compose for ru_RU.UTF-8 locale.

  5. Option on the line 5 allows to enable CapsLock by simultaneous press to the Left Shift and Right Shift keys. CapsLock mode will be disabled if one of the Shift keys will be pressed.

    This tricky configuration was added because on the line 6 I remap CapsLock to the Ctrl key — to avoid "pinky finger problem" while I'm using Emacs. But I'm still need the CapsLock mode, because it is heavily used in the blind typing to enter abbreviations and so on.

On the last line (7) I use xmodmap utility to remap the Menu keycode (147) to the ISO_Next_Group keysym (if no modifiers are pressed). There is a hack necessary for StumpWM — by default it treats the Menu key in the wrong way, so in the Emacs I can't use it to switch between keyboard layouts.

Rewrite configuration for xorg.conf

Keyboard configuration via setxkbmap is good but not good enough. This configuration works only after user's ~/.xinitrc (or ~/.xsession) was launched. While I'm logging in the system via the graphical display manager, or logged as another user, then this configuration will not be applied.

So, it is better to make this configuration system-wide by writing almost the same directives in the xorg.conf. How to do it? This is described in the man 5 xorg.conf, man 4 xkb, also look to the man 7 xkeyboard-config for available options.

The setxkbmap options, listed above, can be rewritten for xorg.conf in the next manner:

/usr/local/etc/X11/xorg.conf.d/23-keyboard.conf

Section "InputClass" Identifier "X220 Keyboard" MatchIsKeyboard "on" Driver "evdev" Option "XkbModel" "thinkpad" Option "XkbLayout" "us,ru" Option "XkbOptions" "grp:menu_toggle,grp_led:caps,compose:ralt,shift:both_capslock_cancel,caps:ctrl_modifier" EndSection

Because there is only one keyboard connected to the laptop all the time, I use simple MatchIsKeyboard "on" to select the every (only one) keyboard, found by X server.

Pointing devices

As visible from next sections, I'm using a lot of pointing devices. Some of them need configuration to conform with my habits. And some are not.

Touchpad

This is the most hateful thing in my laptop. Although, the size of touchpand in the Thinkpad X220 is relatively small, comparing to the modern laptops with A5 size [ sarcasm ] touchpads, it still gets under my hands when I type some text.

The Thinkpad X200 palmrest is the ideal for me — no touchpad, only left and right mouse buttons and the trackpoint!

Thinkpad X200 laptop

Thinkpad X200 laptop

So, I just disabled the touchpad completely with the next configuration for X server:

Section "InputClass" Identifier "X220 Touchpad" MatchIsTouchpad "on" MatchDevicePath "/dev/input/event*" Driver "libinput" Option "Ignore" "true" EndSection

Instead of it I prefer to use the next device:

Trackpoint

The iconinc input device of the all Thinkpads!

It doesn't require configuration in X. If it fits it sits.

In the FreeBSD some setup for trackpoint may be performed in the /etc/sysctl.conf (if kernel module acpi_ibm is loaded):

hw.psm.trackpoint.sensitivity=150 hw.psm.trackpoint.upper_plateau=125

Trackball

I'm using the Logitech Trackman Marble Trackball with my left hand:

Logitech Trackman Marble Trackball

It's configuration for X is tricky enough:

1: Section "InputClass" 2: Identifier "Marble Mouse" 3: MatchProduct "Logitech USB Trackball" 4: Driver "evdev" 5: Option "EmulateWheel" "true" 6: Option "EmulateWheelButton" "9" 7: Option "ButtonMapping" "3 8 1 4 5 6 7 2 9" 8: Option "XAxisMapping" "6 7" 9: EndSection

By default trackball has four buttons: two big buttons operate as left and right mouse buttons and two small buttons operate as forward and backward buttons, e.g. in the browser. There are no scroll wheel or any scroll device and no middle button.

But with information from man 4 evdev it is possible to add both scrolling and a missing middle button by reusing unnecessary for me Forward/Backward buttons.

The evdev driver supports "wheel emulation mode" for pointing devices — if specified button is pressed (see two lines starting from 5 line) and mouse moved when the corresponding vertical/horizontal scrolling events from "mouse wheel" will be generated. This mode may looks hard to use with mouse but for trackball it is doing the right thing — I'm able to press button and scroll anywhere just with the ball.

Then the some magic starts. The line 7 remaps some buttons and axes of the pointing device. Each number corresponds to some button and by default evdev uses buttons in natural order, like: Option "ButtonMapping" "1 2 3 4 5 6 7 8 9". So, to remap some buttons it is necessary just to rearrange these numbers.

I used xev to get some clues about mapping between real buttons and numbers:

xev output after pressing the big left button on the trackball

ButtonPress event, serial 36, synthetic NO, window 0xc00001, root 0x26a, subw 0x0, time 277844392, (1194,439), root:(1194,439), state 0x0, button 1, same_screen YES ButtonRelease event, serial 36, synthetic NO, window 0xc00001, root 0x26a, subw 0x0, time 277844538, (1194,439), root:(1194,439), state 0x100, button 1, same_screen YES

Logitech Marble Trackball buttons' mappings

Logitech Marble Trackball buttons' mappings

Looks like the number 2 is related to the middle mouse button, which is not exists in my device. Also, looks like the numbers from 4 to 7 relates to axes: first two numbers to the Y-axis and the last two to the X-axis, I think. I didn't find any clues in the documentation about it.

So, I change numbers' positions in ButtonMapping option to use trackball with my left hand:

Position in list Original value Remapped value Note
1 1 3 Left button becomes the right mouse button
2 2 8 Use left small button (Backward) as a middle button
3 3 1 Right button becomes the left mouse button
4 4 4 Don’t touch axes
5 5 5  
6 6 6  
7 7 7  
8 8 2 Move non-existent middle button to the unused “Backward” button
9 9 9 Don’t change right small (Forward) button keycode, will use it in “EmulateWheelButton” option

The line 8 is necessary to use horizontal scrolling in some applications: if in Gimp I can use horizontal scrolling without this line, then horizontal scrolling in Librewolf (Firefox) will not work without it.

Mouse

I'm using a black IBM MU29J ball mouse with my right hand.

Black IBM MU29J ball mouse with two buttons

It has two buttons, so I just explicitly specify the necessity of third button emulation in X server (press left and right buttons simultaneously to make the middle button click):

Section "InputClass" Identifier "IBM MU29J Mouse" Driver "libinput" MatchDevicePath "/dev/input/event9" Option "MiddleEmulation" "on" Option "AccelProfile" "flat" Option "AccelSpeed" "1.0" EndSection

I'm using the old libinput driver to be able to tweak acceleration of mouse cursor. Possibly, I can do this with evdev driver, but libinput configuration looks like simpler for me.

Drawing tablet

I'm using the One by Wacom tablet and it doesn't requre any special configuration. Just plug and draw.

Screensaver

Here the good old XScreenSaver exists. It is damn simple:

~ λ ldd /usr/local/bin/xscreensaver /usr/local/bin/xscreensaver: libSM.so.6 => /usr/local/lib/libSM.so.6 (0x25289f1d000) libICE.so.6 => /usr/local/lib/libICE.so.6 (0x2528a90b000) libXi.so.6 => /usr/local/lib/libXi.so.6 (0x2528b61f000) libX11.so.6 => /usr/local/lib/libX11.so.6 (0x2528ba37000) libc.so.7 => /lib/libc.so.7 (0x2528c4ee000) libXext.so.6 => /usr/local/lib/libXext.so.6 (0x2528da6b000) libxcb.so.1 => /usr/local/lib/libxcb.so.1 (0x2528d724000) libthr.so.3 => /lib/libthr.so.3 (0x2528ea36000) libXau.so.6 => /usr/local/lib/libXau.so.6 (0x252904e4000) libXdmcp.so.6 => /usr/local/lib/libXdmcp.so.6 (0x2528f831000) [vdso] (0x25289788000)

With xscreensaver FreeBSD package also the xscreensaver-settings program installed, which helps to configure screensaver:

XScreenSaver settings window with BSOD screensaver demo launched inside it.

XScreenSaver settings GUI

It requires some GTK 3 related libraries, but the xscreensaver itself doesn't depend on these libraries because of security:

The unlock dialog is funny looking, why not use GTK?

The short answer is, for security reasons. The unlock dialog is implemented using raw Xlib because it would be very difficult to implement it using a GUI toolkit and still have XScreenSaver be secure. More technical details can be found on the On Toolkits page.

Source: https://www.jwz.org/xscreensaver/faq.html#toolkits

Today, the only libraries that are actually linked into the xscreensaver daemon are Xlib and dependent libraries; and the few crypto-related libraries needed to determine whether a typed password is, in fact, the right one.

That's why I implemented the unlock dialog using only Xlib: not because I think Xlib is a good way to write user interfaces, but because I think this was the safest way. The amount of code in Xlib is very small, and has been extensively security audited. It is very unlikely that there are crashing bugs lurking in Xlib itself. The same cannot be said for larger, more featureful libraries. So, by making minimal use of Xlib (the dialog box is drawn using only the lowest level text-printing and rectangle-drawing routines) we can keep the code path short and auditable.

Source: https://www.jwz.org/xscreensaver/toolkits.html

Configuration, through the xscreensaver-settings, is damn simple too. Anyway, all settings are written to the ~/.xscreensaver file.

To use screensaver the xscreensaver should be started when the X starts: via the ~/.xinitrc, ~/.xsession or configuration file for WM. In my case, I use this line for StumpWM:

(run-shell-command "xscreensaver --no-splash")

Because xscreensaver will use DPMS and could blank a screen — these commands should not be executed during the X startup:

xset s off xset s noblank xset -dpms

And to increase security, according to the man 1 xscreensaver (see the section SECURITY CONCERNS, subsection MAGIC BACKDOOR KEYSTROKES), there are some options in the X server configuration should be disabled:

  1. Magic Ctrl+Alt+Backspace keystroke. It should be disable because someone could kill your X server for fun. And because if X server was launched manually via startx then the attacker could get access to the your text console.
  2. Also manual recommends to disable some Linux-specific Magic SysRq keys, which is not applicable to FreeBSD. And disable keys to switch between virtual text consoles but I use these keybindings sometimes, so I didn't disable them (anyway, I don't leave any text console unlocked).

According to the man 5 xorg.conf there are these lines should be placed in the X configuration files to disable Ctrl+Alt+Backspace keybinding:

Section "ServerFlags" Option "DontZap" "true" EndSection

Disable screensaver for fullscreen videos

Sadly, there are only two options:

  1. Use systemd — there is some abomination named xscreensaver-systemd exists, which disables the screensaver when multimedia player reports to it about playing video via D-Bus. Obviously, this is not acceptable.
  2. Stop screensaver via xscreensaver-command -exit and start it again via xscreensaver --no-splash.

Because I'm using StumpWM, I automated toggling the state of XScreensaver with the next code:

; XScreensaver automation (let ((xscreensaver-running t)) (defun xscreensaver-toggle () "Toggle XScreensaver state if fullscreen video is playing." (if xscreensaver-running (progn (run-shell-command "xscreensaver-command --exit") (run-shell-command "xset -dpms") (setf xscreensaver-running nil)) (progn (run-shell-command "xscreensaver --no-splash") (run-shell-command "xset +dpms") (setf xscreensaver-running t)))) (defun any-fullscreen-window-p () "Checks is any fullscreen window is displayed." (find t (mapcar (lambda (win) (window-fullscreen win)) (all-windows)))) (run-with-timer 10 10 (lambda () (if (any-fullscreen-window-p) (if xscreensaver-running (xscreensaver-toggle)) (if (not xscreensaver-running) (xscreensaver-toggle))))))

This code is simple enough. Here the xscreensaver-running variable in the let clause which indicates the XScreensaver state. By default XScreensaver is enabled after StumpWM startup. The function xscreensaver-toggle toggles the xscreensaver and DPMS capabilities — turning it on or off. Another function: any-fullscreen-window-p returns t if there is any fullscreen window (like media player window or online player window) in the StumpWM. Or nil if there are no such windows.

And the last S-expression just starts 10-second repetitive timer which disables XScreensaver if there is any fullscreen window and XScreensaver is running. Or enables it otherwise.

Compositor (no, not that thing from Wayland)

Here, the word "compositor" means the "compositing manager"2 — usually these software used to draw nice shadows, make nice 3D effects and so on with the existing WM/DE. The most known compositor is Compiz, which was used to have a nice "3D rotating cube" effect for switching between workspaces, wobbly windows, transparency and so on.

For lightweight WMs there are lightweigh compositors exists. First was xcompmgr, with shadows and transparency for windows on the screen. Then, xcompmgr was forked to the xcompmgr-dana with support of transparent menus and some bugfixes. Then xcompmgr-dana was forked to the Compton, also with some bugfixes and with added windows' dimming, colored shadows and blurring. Then Compton was forked to the Picom because the first became unmaintained.

And now I'm using the Picom to get some niceties in my StumpWM. All nice things may be set right in the one configuration file: ~/.config/picom.conf.

I didn't change main settings a lot, just disable D-Bus support, blurring, setup common shadow and fade settings:

# shadow shadow = true; shadow-radius = 10; shadow-offset-x = -5; shadow-offset-y = -5; # fading fading = true; fade-in-step = 0.05; fade-out-step = 0.05; fade-delta = 7; # background blurring blur-background = false; use-ewmh-active-win = true; crop-shadow-to-monitor = true; dbus = false; unredir-if-possible = true;

The last line here just disables picom effects if it is necessary by rules, or if there is fullscreen window right now on the display, or there are no windows managed by rules at all.

All niceties should be configured by rules — if rule matches a desired window, then the effect, described in rule, will be applied to the window.

Disabling unwanted outputs

By default, my laptop has a 1366x768 display, which was connected via the LVDS interface4 to the motherboard. Of course, after I started to use a new 2K display, connected via the expansion board to the DP-3 output, the old display was disconnected and lying somewhere on the shelf now.

But the laptop's hardware still thinks that some 1366x768 display still connected to the LVDS and the X server still can use it as a working output. So, to completely stop X server from using this output, I explicitly described my LVDS and DP-3 outputs in the videocard section:

Section "Device" Identifier "intel" Driver "modesetting" BusID "PCI:0:2:0" ... Option "Monitor-DP-3" "MainMonitor" Option "Monitor-LVDS-1" "PhantomMonitor" EndSection

Here the outputs is described in the next format: Monintor-OutputName, where the OutputName used right as they printed by xrandr.

Then, in the section for non-existent default monitor, I describe it as disabled and ignored monitor:

Section "Monitor" Identifier "PhantomMonitor" Option "Primary" "false" Option "Disable" "true" Option "Ignore" "true" EndSection

As a result, the LVDS output not available even in the xrandr output:

~ λ xrandr Screen 0: minimum 320 x 200, current 2560 x 1440, maximum 8192 x 8192 DP-3 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 277mm x 155mm 2560x1440 59.95*+ 39.97 VGA-1 disconnected (normal left inverted right x axis y axis) HDMI-1 disconnected (normal left inverted right x axis y axis) DP-1 disconnected (normal left inverted right x axis y axis) HDMI-2 disconnected (normal left inverted right x axis y axis) HDMI-3 disconnected (normal left inverted right x axis y axis) DP-2 disconnected (normal left inverted right x axis y axis)

Juggling with displays

Speaking about xrandr. I tried some GUI applications, like arandr, to switch between various multimonitor configurations — but found that they all are using just a limited subset of xrandr features.

For example, I can't use mixed DPI settings or scale some outputs with arandr, but I can do it with xrandr: https://mas.to/@evgandr/114394277310057344. Yes, the X can do that! The well-known rumors (usually spreaded by Wayland fans) that only Wayland can do such things — looks like a fake.

There are some utilities to configure newly connected display(s) automatically, like autorandr or xlayoutdisplay. But I prefer to issue xrandr commands by my hands, when I attach additional display(s) to my laptop. Because automation not always works the necessary way.

For example, let's play with a big Benq XI2420z 24" monitor with 1920x1080 as a maximal available resoultion. I connected it to my laptop via good old VGA cable. So by default it reports not so much useful resolutions:

~ λ xrandr Screen 0: minimum 320 x 200, current 2560 x 1440, maximum 8192 x 8192 DP-3 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 277mm x 155mm 2560x1440 59.95*+ 39.97 VGA-1 connected (normal left inverted right x axis y axis) 1024x768 60.00 800x600 60.32 56.25 848x480 60.00 640x480 59.94 HDMI-1 disconnected (normal left inverted right x axis y axis) DP-1 disconnected (normal left inverted right x axis y axis) HDMI-2 disconnected (normal left inverted right x axis y axis) HDMI-3 disconnected (normal left inverted right x axis y axis) DP-2 disconnected (normal left inverted right x axis y axis)

I can use the --auto key to let the xrandr use some automation and connect my Benq as the monitor right of my main monitor:

~ λ xrandr --output VGA-1 --right-of DP-3 --auto ~ λ xrandr Screen 0: minimum 320 x 200, current 3584 x 1440, maximum 8192 x 8192 DP-3 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 277mm x 155mm 2560x1440 59.95*+ 39.97 VGA-1 connected 1024x768+2560+0 (normal left inverted right x axis y axis) 0mm x 0mm 1024x768 60.00* 800x600 60.32 56.25 848x480 60.00 640x480 59.94 HDMI-1 disconnected (normal left inverted right x axis y axis) DP-1 disconnected (normal left inverted right x axis y axis) HDMI-2 disconnected (normal left inverted right x axis y axis) HDMI-3 disconnected (normal left inverted right x axis y axis) DP-2 disconnected (normal left inverted right x axis y axis)

And it looks like not so good:

X output on the two displays, one is 2K with 2560x1440 resolution and the other with 1024x768 resolution.

X output for primary display with 2560x1440 resolution and secondary with 1024x768 resolution

No problem! I'll add 1920x1080 resolution by myself!

To calculate the proper modeline for necessary resolution, the cvt utility exists (see man 1 cvt). It accepts the desired resolution (and refresh rate if necessary) and outputs the modeline string, which should be just passed to the xrandr. Then, added modeline could be attached to the desired video output — to the VGA-1 in my case:

~ λ cvt -r 1920 1080 # 1920x1080 59.93 Hz (CVT 2.07M9-R) hsync: 66.59 kHz; pclk: 138.50 MHz Modeline "1920x1080R" 138.50 1920 1968 2000 2080 1080 1083 1088 1111 +hsync -vsync ~ λ xrandr --newmode "1920x1080R" 138.50 1920 1968 2000 2080 1080 1083 1088 1111 +hsync -vsync ~ λ xrandr --addmode VGA-1 1920x1080R ~ λ xrandr Screen 0: minimum 320 x 200, current 3584 x 1440, maximum 8192 x 8192 DP-3 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 277mm x 155mm 2560x1440 59.95*+ 39.97 VGA-1 connected 1024x768+2560+0 (normal left inverted right x axis y axis) 0mm x 0mm 1024x768 60.00* 800x600 60.32 56.25 848x480 60.00 640x480 59.94 1920x1080R 59.93 HDMI-1 disconnected (normal left inverted right x axis y axis) DP-1 disconnected (normal left inverted right x axis y axis) HDMI-2 disconnected (normal left inverted right x axis y axis) HDMI-3 disconnected (normal left inverted right x axis y axis) DP-2 disconnected (normal left inverted right x axis y axis)

And, as a result I can use the newly created modeline to "reconnect" my second monitor with 1920x1080 resolution:

~ λ xrandr --output VGA-1 --right-of DP-3 --mode 1920x1080R

X output on the two displays, one is 2K with 2560x1440 resolution and the other with 1920x1080 resolution.

X output for primary display with 2560x1440 resolution and secondary with 1920x1080 resolution

Resulting output of xrandr:

~ λ xrandr Screen 0: minimum 320 x 200, current 4480 x 1440, maximum 8192 x 8192 DP-3 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 277mm x 155mm 2560x1440 59.95*+ 39.97 VGA-1 connected 1920x1080+2560+0 (normal left inverted right x axis y axis) 0mm x 0mm 1024x768 60.00 800x600 60.32 56.25 848x480 60.00 640x480 59.94 1920x1080R 59.93* HDMI-1 disconnected (normal left inverted right x axis y axis) DP-1 disconnected (normal left inverted right x axis y axis) HDMI-2 disconnected (normal left inverted right x axis y axis) HDMI-3 disconnected (normal left inverted right x axis y axis) DP-2 disconnected (normal left inverted right x axis y axis)

Note, how size of "virtual" framebuffer changed with this operation. When I used 1024x768 resolution it was 3584x1440. And after switching to 1920x1080 resolution for the second monitor it became: 4480x1440.

Looks good, but on this second monitor things looks soo big, comparing with my primary laptop monitor. No problem! I can scale down the output on the second monitor, so more UI elements wil fit in it:

~ λ xrandr --output VGA-1 --right-of DP-3 --mode 1920x1080R --scale 1.9 --filter nearest

Result:

X output on the two displays, one is 2K with 2560x1440 resolution and the other with 1920x1080 resolution (scaled).

X output for primary display with 2560x1440 resolution and secondary with 1920x1080 resolution (scaled)

Now the screen sizes on the both displays are representing a real monitor dimensions (not ideally).

The number after the --scaled option was set after some experiments. Ideally, it should has the some value which allows the GIU element with 2 cm length on the primary screen has the same length on the secondary display. But I just don't need such level of accuracy, so I set this value "by eye".

Note, how size of virtual framebuffer changed again:

~ λ xrandr Screen 0: minimum 320 x 200, current 6208 x 2052, maximum 8192 x 8192 DP-3 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 277mm x 155mm 2560x1440 59.95*+ 39.97 VGA-1 connected 3648x2052+2560+0 (normal left inverted right x axis y axis) 0mm x 0mm 1024x768 60.00 800x600 60.32 56.25 848x480 60.00 640x480 59.94 1920x1080R 59.93* HDMI-1 disconnected (normal left inverted right x axis y axis) DP-1 disconnected (normal left inverted right x axis y axis) HDMI-2 disconnected (normal left inverted right x axis y axis) HDMI-3 disconnected (normal left inverted right x axis y axis) DP-2 disconnected (normal left inverted right x axis y axis)

Here the one problem lies. See the maximum 8192 x 8192 string? If I connect tons of external monitors to my laptop, then I'll be constrained with the 8192x8192 pixels as a size of global framebuffer. So, some big resolutions will become unaccessible, e.g. if I connect two additional 2K/4K monitors and try to use them with my laptop's 2K monitor.

Looks like (according to the little search in the Internet: https://bugs.freedesktop.org/show_bug.cgi?id=102508), the maximal resolution depends on the used graphical drivers or hardware…

Terminal

Usually, I'm using eshell when I need a terminal.

Eshell buffer in the Emacs

Eshell buffer

But sometimes I need the plain old-school terminal. E.g. when I configure some FreeBSD ports — somehow both eshell and /bin/sh in ansi-term didn't behave well with displaying these ncurses interfaces.

So, for this rare curcumstances I'm using plain old xterm. It is configuration is pretty simple — just write necessary X resources lines in the file and source it with xrdb -merge /path/to/file. The list of all available X resources for XTerm available in the man 1 xterm manpage.

So, I apply the next settings with lines from my ~/.Xresources.d/xterm:

  • double buffering
  • use Scroll Lock key to really lock scrolling
  • blinking cursor, displayed as a rectangle
  • just reverse colors for text selection and don't keep selection if some new output is displayed
  • don't cut new line when select some text
  • insert selection to the CLIPBOARD (text could be inserted via the Shift+Insert) not to the PRIMARY (inserted via middle mouse button) buffer.
  • use UTF8
XTerm.buffered: true XTerm.bufferedFPS: 60 XTerm.maximized: true XTerm.sameName: true XTerm.vt100.allowBoldFonts: true XTerm.vt100.allowScrollLock: true XTerm.vt100.alwaysHighlight: true XTerm.vt100.autoWrap: true XTerm.vt100.cursorBar: false XTerm.vt100.cursorBlink: always XTerm.vt100.cutNewLine: false XTerm.vt100.fastScroll: true XTerm.vt100.highlightReverse: true XTerm.vt100.hightlightSelection: true XTerm.vt100.keepSelection: false XTerm.vt100.logInhibit: true XTerm.vt100.loginShell: true XTerm.vt100.maxGraphicSize: 2560x1440 XTerm.vt100.selectToClipboard: true XTerm.vt100.utf8: always XTerm.vt100.wideChars: true

Then, the color settings going on. Here I define only 16 colors from the Solarized Light color theme:

! ! Solarized Light colors: ! ! Background color for Solarized Light: XTerm.vt100.background: #fdf6e3 ! Foreground color for Solarized Light XTerm.vt100.foreground: #1c1c1c ! Black XTerm.vt100.color0: #262626 ! Red XTerm.vt100.color1: #dc322f ! Green XTerm.vt100.color2: #859900 ! Yellow XTerm.vt100.color3: #b58900 ! Blue XTerm.vt100.color4: #268bd2 ! Magenta XTerm.vt100.color5: #d33682 ! Cyan XTerm.vt100.color6: #2aa198 ! White XTerm.vt100.color7: #eee8d5 ! ! Solarized Light bright colors: ! ! Black XTerm.vt100.color8: #002b36 ! Red XTerm.vt100.color9: #cb4b16 ! Green XTerm.vt100.color10: #586e75 ! Yellow XTerm.vt100.color11: #657b83 ! Blue XTerm.vt100.color12: #839496 ! Magenta XTerm.vt100.color13: #6c71c4 ! Cyan XTerm.vt100.color14: #93a1a1 ! White XTerm.vt100.color15: #fdf6e3

Then, finally the lines for font configuration. Here I just using DejaVu Sans Mono font with 8 size:

! ! Fonts: ! XTerm.vt100.faceName: xft:DejaVu Sans Mono:style=Book:antialias=true:autohint=false XTerm.vt100.faceSize: 8 XTerm.vt100.fontWarnings: 2 XTerm.vt100.initialFont: DejaVu Serif XTerm.vt100.renderFont: true

The result looks like this:

XTerm window with fortune and ls output.

XTerm window with `make configure' for editors/emacs FreeBSD port.

Display manager (XDM)

The XDM (X display manager) just exists. It depends only on X11 libraries and XSM (X session manager) which depends only on X11 libraries too.

Goodbye LightDM, you bring too many unwanted dependencies to my system:

~ λ pkg info -d lightdm lightdm-1.32.0_7: libxklavier-5.3_4,1 libxcb-1.17.0 libXdmcp-1.1.5 libX11-1.8.12,1 consolekit2-1.2.6_5 accountsservice-23.13.9_3 libgcrypt-1.11.1 glib-2.84.1_2,2 gettext-runtime-0.23.1 ~ λ pkg info -d accountsservice accountsservice-23.13.9_3: libxslt-1.1.43_1 libxml2-2.14.5 polkit-125_1 consolekit2-1.2.6_5 glib-2.84.1_2,2 gettext-runtime-0.23.1 ~ λ pkg info -d consolekit2 consolekit2-1.2.6_5: libX11-1.8.12,1 libxslt-1.1.43_1 libxml2-2.14.5 polkit-125_1 libdrm-2.4.123,1 libudev-devd-0.6.0 libevdev-1.13.2 glib-2.84.1_2,2 gettext-runtime-0.23.1 dbus-1.16.2_3,1 ~ λ pkg info -d polkit polkit-125_1: expat-2.7.1 duktape-lib-2.7.0 glib-2.84.1_2,2 gettext-runtime-0.23.1 dbus-1.16.2_3,1

The XDM installation was simple:

  1. doas pkg install xdm
  2. Added the line:

    to the /etc/rc.conf.

  3. Issued the next commands:

    chmod ug+x ~/.xinitrc ln -s ~/.xinitrc ~/.xsession
  4. In the ~/.xinitrc the first line should be #!/bin/sh and the last line should execute the desired WM as usual:

    . ~/.profile exec /usr/local/bin/stumpwm

    Also, I instruct X server to read and execute the ~/.profile file, because it has some environment variables valuable for StumpWM (SBCL_HOME and ASDF_DATA_DIR).

Then, I slightly configured XDM to match with my preferences. First, I disabled XConsole startup, which shows kernel messages in my X session — I just opened the /usr/local/etc/X11/xdm/Xsetup_0 file and removed this line from it:

xconsole -geometry 480x130-0-0 -daemon -notify -verbose -fn fixed -exitOnFail

After careful reading of man 8 xdm, I changed some X resources for XDM in the /usr/local/etc/X11/xdm/Xresources file — setup Solarized Light colors in the login window:

xlogin*shdColor: #073642 xlogin*hiColor: #002b36 xlogin*background: #fdf6e3 xlogin*inpColor: #eee8d5 xlogin*greetColor: #268bd2 xlogin*failColor: #dc322f *Foreground: #002b36 *Background: #fdf6e3

Use classic X cursor (a black one):

Xcursor.theme: hicolor

Change a password prompt so input boxes for login and for password now using the same width:

xlogin*namePrompt: \040\040\040\040\040\040\040Login: xlogin*passwdPrompt: \040\040\040\040Password:

Use DejaVu Serif fonts (will work if XDM was compiled with XFT support):

xlogin*greetFace: DejaVu Serif-24:bold:italic xlogin*face: DejaVu Serif-18 xlogin*promptFace: DejaVu Serif-18:bold xlogin*failFace: DejaVu Serif-18:bold

Disallowed root login and passwordless logins, also echo 6 symbol when I type password (for fun):

xlogin*Login*allowRootLogin: false xlogin*Login*allowNullPasswd: false xlogin*Login*echoPasswd: true xlogin*Login*echoPasswdChar: 6

I didn't cover XSM (X Session Manager) setup in this section because I never used this function and don't know how it can be helpful for me — all two programs, which should save the state (Emacs and Librewolf) able to do it with it's internal mechanisms.

Xdg-utils

There are set of utils exists, which used to simplify DE/WM and different programs integration — the xdg-utils. For example, I could open URL with my default browser from Emacs with browse-url-xdg-open command. Or send e-mail with my preferred e-mail client using the xdg-email console command.

It works the next way. First, the type of given object is determined:

~ λ xdg-mime query filetype .emacs.d inode/directory

Then the default application for computed type is called. E.g. in my system the RawTherapee somehow set as a program to open directories:

~ λ xdg-mime query default inode/directory rawtherapee.desktop

So, when I click the button with folder icon in the list of downloaded files in Librewolf — then the RawTherapee will be opened…

Of course, it is possible to setup things in the right way in my minimalistic environment. So different programs will operate with each other and I shouldn't install gigantic DEs to obtain the same level of interoperability.

Emacs Dired as a default file manager

For this topic I should write my own desktop entry to use EmacsClient and Dired to view contents of given catalog.

The local *.desktop files lies in the ~/.local/share/applications/ and I used them as a reference. As a result this ~/.local/share/applications/dired.desktop was created:

[Desktop Entry] Hidden=false Exec=/usr/local/bin/emacsclient -a= -c -s /var/run/drag0n/emacs/main -e '(dired "%f")' Type=Application NoDisplay=false Terminal=false Version=1.0 MimeType=inode/directory; StartupNotify=true StartupWMClass=Emacs DBusActivatable=false Categories=Development;TextEditor; Terminal=false Comment=Open directory Name=Emacs (Dired) GenericName=Dired Icon=emacs

And installed with this command:

~ λ xdg-mime default dired.desktop inode/directory

Note that all MIME type(s), used with xdg-mime command here, should be listed in the MimeType line in the *.desktop file. Different MIME types should be divided with ; symbol.

The result — when I trying to open the directory of downloaded file in Librewolf then the new Emacs frame with Dired buffer with desired directory will be opened:

Emacs Compose as a default mail agent

The /usr/local/share/applications/emacsclient-mail.desktop file already exists in my system, but it doesn't work well with my Emacs setup. So I rewrite it. This is my compose.desktop contents:

[Desktop Entry] Categories=Network;Email; Comment=Compose e-mail in Emacs Exec=/usr/local/bin/emacsclient -a= -c -s /var/run/drag0n/emacs/main -e "(message-mailto (pop server-eval-args-left))" %u Icon=emacs Name=Emacs (Mail, Client) MimeType=x-scheme-handler/mailto; NoDisplay=false Terminal=false Type=Application Keywords=emacsclient; StartupNotify=true StartupWMClass=Emacs DBusActivatable=false

And the command to install it to use with xdg-email:

~ λ xdg-mime default compose.desktop x-scheme-handler/mailto

How it works when I click on the e-mail link in the browser:

nSxiv as a default image viewer

The file /usr/local/share/applications/nsxiv.desktop already exists in my system, so it was necessary to switch all listed MIME types to use nsxiv:

~ λ xdg-mime default nsxiv.desktop image/bmp ~ λ xdg-mime default nsxiv.desktop image/gif ~ λ xdg-mime default nsxiv.desktop image/jpeg ~ λ xdg-mime default nsxiv.desktop image/jpg ~ λ xdg-mime default nsxiv.desktop image/png ~ λ xdg-mime default nsxiv.desktop image/tiff ~ λ xdg-mime default nsxiv.desktop image/x-bmp ~ λ xdg-mime default nsxiv.desktop image/x-portable-anymap ~ λ xdg-mime default nsxiv.desktop image/x-portable-bitmap ~ λ xdg-mime default nsxiv.desktop image/x-portable-graymap ~ λ xdg-mime default nsxiv.desktop image/x-tga ~ λ xdg-mime default nsxiv.desktop image/x-xpixmap ~ λ xdg-mime default nsxiv.desktop image/webp

And that's all.

MPV as a default video/audio player

The same is true for MPV: the file /usr/local/share/applications/mpv.desktop already exists. So I just issued the next command:

~ λ xdg-mime default nsxiv.desktop 'extremely-big-list-of-mime-types-from-mentioned-desktop-file'

Emacs as a default editor for some files

The proper emacsclient.desktop already was installed in my system, with the proper commandline arguments. So I just copy it's contents here:

[Desktop Entry] Hidden=false Exec=/usr/local/bin/emacsclient -a= -c -s /var/run/drag0n/emacs/main Icon=emacs Type=Application NoDisplay=false Version=1.0 MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;x-scheme-handler/org-protocol; StartupNotify=true StartupWMClass=Emacs GenericName[en_US]=Text Editor Comment=Edit text DBusActivatable=false Categories=Development;TextEditor; Terminal=false Name=Emacs (Client) GenericName=Text Editor Icon[en_US]=emacs Name[en_US]=Emacs (Client) Comment[en_US]=Edit text

Emacs PDF-tools as a default PDF viewer

The PDF files have the next MIME:

~ λ xdg-mime query filetype ~/rsync/projects/thinkpad/12AH3_Fuse.pdf application/pdf

And for this MIME type the next pdf-tools.desktop file was created (it opens the given PDF file with find-file, the Emacs will call the PDF Tools by itself):

[Desktop Entry] Hidden=false Exec=/usr/local/bin/emacsclient -a= -c -s /var/run/drag0n/emacs/main -e '(find-file "%f")' Type=Application NoDisplay=false Terminal=false Version=1.0 MimeType=application/pdf; StartupNotify=true StartupWMClass=Emacs DBusActivatable=false Categories=Development;TextEditor; Terminal=false Comment=Open PDF Name=Emacs (PDF Tools) GenericName=PDF Tools Icon=emacs

This command necessary to use Emacs PDF Tools as a default PDF viewer:

~ λ xdg-mime default pdf-tools.desktop application/pdf

Beauty

I'll write about ricing the GUI applications at the end. I'm using the Solarized Light theme almost everywhere5 — it is good enough for my eyes (can't use dark themes without strain in my eyes). So, here I'll describe how to make things nice with small X11 utilities and text editor.

Changing the cursor theme

I'm using the MacOS-inspired cursor from here:

Image with different MacOS cursors, taken from beforementioned link.

To use it system-wide the archive should be extracted to the ~/.icons/macos catalog:

~ λ ls ~/.icons/macos/ cursor.theme cursors index.theme

Then the cursor should be added to the X resources. In my case the ~/.Xresources.d/cursor file was added and it's contents was merged to the X resources database with xrdb utility:

xrdb -merge ~/.Xresources.d/cursor

Or the more nice approach — there is a ~/.Xresources file which contains necessary include statement(s):

#include ".Xresources.d/cursor"

And it is sourced with the next command:

xrdb -I$HOME ~/.Xresources

The contents of the ~/.Xresources/cursor file:

Xcursor.theme: macos Xcursor.size: 32

And after X server restart the MacOS cursor will be used in all GUI applications: which use Qt graphical toolkit, GTK2 or GTK3 toolkit, and the native X applications of course.

But … the Emacs doesn't respect all these settings🙁. Because:

GNU Emacs 30.1 (build 2, amd64-portbld-freebsd14.2, GTK+ Version 3.24.49, cairo version 1.18.2)

And the configuration of GTK+ version 3 resources is full of horrors CSS — while it is ok for me to tweak some CSS for my blog, then doing the same only to use a proper cursor inside Emacs is not ok6:

In GTK+ version 3, GTK+ resources have been replaced by a completely different system. The appearance of GTK+ widgets is now determined by CSS-like style files

The solution I used — recompile Emacs with right options:

Emacs build options from FreeBSD ports. The GTK 3 GUI toolkit is disabled and Athena is enabled.

Athena toolkit is used instead of GTK3

GTK2 theme

I found Solarized Light theme for GTK2 here: https://github.com/rtlewis88/rtl88-Themes/tree/Solarized-Light/Solarized-Light.

Installation is simple enough:

  1. Clone repository
  2. Checkout the Solarized-Light branch
  3. Copy Solarized-Light/ directory to the ~/.themes/
  4. Add or edit the next line in the ~/.gtkrc-2.0:

    gtk-theme-name = "Solarized-Light"
  5. Install gtk-murrine-engine package.

Done!

GTK 2 message box themed with Solarized Light

Themed GTK 2 message box

Also I added the next lines to the ~/.gtkrc-2.0 to remove some annoyances:

gtk-button-images = 0 gtk-menu-images = 0 gtk-cursor-blink = 1 gtk-application-prefer-dark-theme = 0 gtk-key-theme-name = "Emacs" gtk-enable-event-sounds = 0 gtk-enable-input-feedback-sounds = 0

GTK3 theme

Most of the necessary actions already done in the previous section. To enable the same theme for the GTK3 application only the next steps are necessary:

  1. Open the ~/.config/gtk-3.0/settings.ini file
  2. Add or edit the next line:

    gtk-theme-name=Solarized-Light

Done!

GTK 3 message box themed with Solarized Light

Themed GTK 3 message box

Also I added the next lines like in the previous section:

1: gtk-enable-animations=0 2: gtk-application-prefer-dark-theme=false 3: gtk-key-theme-name=Emacs 4: gtk-overlay-scrolling=false 5: gtk-menu-images=0 6: gtk-decoration-layout=menu: 7: gtk-enable-event-sounds=0 8: gtk-enable-input-feedback-sounds=0

On the line 6 the I remove the Client Side Decorations (CSD) from GTK 3 windows — an ugly thing which draws the window header and minimize/maximize/close buttons, so the window decorations from WM become duplicated. This line works with the next lines from ~/.config/gtk-3.0/gtk.css:

.window-frame, .window-frame:backdrop { box-shadow: 0 0 0 black; border-style: none; margin: 0; border-radius: 0; } .titlebar { border-radius: 0; } .window-frame.csd.popup { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.13); } .header-bar { background-image: none; background-color: #ededed; box-shadow: none; } GtkLabel.title { opacity: 0; }

Also I recommend to use this hack for GTK 3 applications to bring back the normal scrolls, not that unbearable abomination invented by people who never used the computer mouse in their life.

I've made some changes in the CSS file to use Solarized Light colors and increase size of scrollbars, so they looks good on my hi-res display. The diff file is here and the result looks like this:

The sample GTK3 application with a big text view and horizontal and vertical scrollbars in Windows 95 style.

Text View⇒Automatic Scrolling application from gtk3-demo

GTK4 theme

Lasciate ogne speranza, voi ch'intrate.

Abandon all hope, ye who enter here.

— Inferno, Dante.

This abomination doesn't respect anything: the X resources, size of display's active area, etc — it is all ignored.

Gajim main window

Gajim main window

So, I don't use any GTK4 applications anymore.

Qt theme

Since GTK2 and GTK3 is successfully configured, I'm able to reuse it look and feel in the Qt applications. There are next steps necessary:

  1. Install qt5-style-plugins and qt5ct packages
  2. Set environment variable QT_QPA_PLATFORMTHEME in the ~/.profile:

    QT_QPA_PLATFORMTHEME="qt5ct" export QT_QPA_PLATFORMTHEME
  3. Relogin
  4. Open qt5ct application
  5. Change the next settings:
    • Style: gtk2
    • Standard dialogs: GTK2. With this setting the file open dialog will look like in other programs.
    • Pallete: Default
    • Also I change fonts to my preferred DejaVu Serif and DejaVu Sans Mono.
  6. Press OK.

QMapShack main window themed with Solarized Light

Styled QMapShack main window

Fonts

I prefer to use DejaVu fonts family, especially DejaVu Serif.

To start using these fonts I installed a dejavu package and added path to installed fonts in the proper part of X server configuration, along with paths to other fonts from my system:

Section "Module" Load "freetype" EndSection Section "Files" FontPath "/usr/local/share/fonts/dejavu/" FontPath "/usr/local/share/fonts/bitstream-vera/" FontPath "/usr/local/share/fonts/inconsolata-ttf/" FontPath "/usr/local/share/fonts/Liberation/" FontPath "/usr/local/share/fonts/webfonts/" FontPath "/usr/local/share/fonts/twemoji-color-font-ttf/" EndSection

Module freetype here is necessary to use TrueType fonts. According to FreeBSD handbook (section 5.6.1. TrueType® Fonts) it is more consistent than other similar modules.

There are some tricks for fonts look&feel available — for applications using the Xft library (most of the applications now, according to the 5.6.3. Anti-Aliased Fonts section in the FreeBSD handbook). Some of them I enabled globally by going to the /usr/local/etc/fonts/conf.d and making some symlinks to desired settings along with removing symlinks to conflicting settings:

ln -s ../conf.avail/10-hinting-none.conf ln -s ../conf.avail/10-unhinted.conf ln -s ../conf.avail/10-sub-pixel-rgb.conf ln -s ../conf.avail/11-lcdfilter-default.conf

Same settings can be enabled per-user by using these Xresources with xrdb:

Xft.rgba: rgb Xft.hinting: 0 Xft.antialias: 1 Xft.hintstyle: hintnone Xft.lcdfilter: lcddefault Xft.autohint: 0

DejaVu font(s) for frameworks were set via gtk-font-name option in the ~/.gtkrc-2.0, and ~/.config/gtk-3.0/settings.ini, and via qt5ct configurator:

~/.gtkrc-2.0

gtk-font-name = "DejaVu Serif Book 10"

~/.config/gtk-3.0/settings.ini

gtk-font-name=DejaVu Serif Book 16

Also, for some applicatons (Emacs and Librewolf) I changed the using fonts via it's own settings.

Icons

I use the "Solarized-Deluxe-iconpack" from the same rtl88-Themes repository where I got the GTK2 and GTK3 themes.

To install them I just copied the ./Solarized-Deluxe-iconpack catalog to the ~/.icons/ with cp -R option to avoid problems with symlinks, followed by the find ~/.icons/Solarized-Deluxe-iconpack/ -type f -exec chmod -v 644 {} \; command because some files from the repo has the wrong 755 mode.

And enabled these icons for GTK 2 in the ~/.gtkrc-2.0:

gtk-icon-theme-name = "Solarized-Deluxe-iconpack"

And for GTK 3 in the ~/.config/gtk-3.0/settings.ini:

gtk-icon-theme-name=Solarized-Deluxe-iconpack

For Qt the icons could be selected via the qt5ct program.

The result in the "Select file" dialog will look like this:

Solarized Light icons in the file dialog

Solarized Light icons in the file dialog

Read Entire Article