X11

From Extremely Corporate Wiki
Jump to navigation Jump to search

X11 is a specification for graphical user sessions on Unix-like operating systems. The most common implementation is that of the X.org foundation. You can read more about X11 on Wikipedia.

Instead of a history lesson or technical documentation (which you can find elsewhere), this article is instead a collection of slightly niche things that might otherwise be upsetting to figure out.

Restricting a Pointing Device to a Specific Region

Diagram of Example Monitor Configuration

It is possible with X11 to restrict a pointing device such as a mouse, touch screen, etc. to a specific region of the whole display.

Consider the following setup: A computer with two monitors arranged side by side, each with a resolution of 1920x1080. The resulting X display has a resolution of 3840x1080.

By default, if you plug in a device such as a graphics tablet with stylus, it will be mapped to the entire display region. However, graphics software is likely to only take up one display at a time. Therefore, it is desirable to configure X such that the stylus is mapped to just one of the two displays. Note that the following configuration example is specific to the scenario described, but can be generalized with minimal effort.

First, create an InputClass section in your X configuration:

Section "InputClass"
    Identifier "input region restriction"
    MatchProduct "Pen"
    MatchIsTablet "on"
EndSection

If your device is something other than a graphics tablet stylus, adjust MatchProduct and MatchIsTablet accordingly (see xorg.conf manual).

The input region restriction is described by a 3x3 transformation matrix:

┌         ┐
│ a  b  c │
│ d  e  f │
│ g  h  i │
└         ┘

Every value in the matrix is on the closed interval [0, 1] and represents a coefficient on the total dimensions of the display. a and e specify the width and height of the region to which the pointer will be bound. Given the arrangement of monitors described previously, a single monitor will have half the width of the full display and equal height. Therefore, a = 0.5 and e = 1. c and f represent the x and y offsets of the region. Let's say we want to restrict the stylus to the rightmost monitor. In that case, the x offset would be the entire width of the leftmost monitor (i.e. half the width of the full display) and the y offset would be 0 since the monitors are level with each other. Therefore, c = 0.5 and f = 0. Every other value in the transformation matrix besides a, e, c or f is equal to 0 except for i which is equal to 1.

To set this transformation matrix in the X configuration, the following option is used:

Option "TransformationMatrix" "a b c d e f g h i"

Therefore, the final InputClass section is as follows:

Section "InputClass"
    Identifier "input region restriction"
    MatchProduct "Pen"
    MatchIsTablet "on"
    Option "TransformationMatrix" "0.5 0 0.5 0 0 0 0 0 1"
EndSection

A More Dynamic Solution

Here is a script which will map an input to the monitor of the currently focused window:

#!/bin/bash

INPUT_MATCH="Pen"

while read line; do
    eval `xdotool getwindowfocus getwindowgeometry --shell`
    while read display; do
        display=( $display )
        display_x=`echo ${display[1]} | cut -f2 -d+`
        display_y=`echo ${display[1]} | cut -f3 -d+`
        display_w=`echo ${display[1]} | cut -f1 -dx`
        display_h=`echo ${display[1]} | cut -f1 -d+ | cut -f2 -dx` 

        if (( $X >= $display_x )) && (( $Y >= $display_y )) \
        && (( $X - $display_x <= $display_w )) \
        && (( $Y - $display_y <= $display_h )); then
            screen_dimensions=( `xrandr | grep "Screen" | cut -d " " -f8,10 | sed 's/,//g'` )
            while read input_id; do
                matrix=( 0 0 0 0 0 0 0 0 1 )
                matrix[0]=`bc -l <<< $display_w/${screen_dimensions[0]}`
                matrix[4]=`bc -l <<< $display_h/${screen_dimensions[1]}`
                matrix[2]=`bc -l <<< $display_x/${screen_dimensions[0]}`
                matrix[5]=`bc -l <<< $display_y/${screen_dimensions[1]}`
                xinput --set-prop $input_id --type=float "Coordinate Transformation Matrix" ${matrix[@]} &> /dev/null
            done < <(xinput | grep $INPUT_MATCH | cut -f 2 -d = | cut -f 1) 

            break
        fi
    done < <(xrandr | grep " connected" | sed 's/ primary//' | cut -d " " -f1,3)
done < <(xprop -spy -root _NET_ACTIVE_WINDOW)

Adding More Fonts

Generally, fontconfig is in charge of indexing fonts, but sometimes software still relies on the X logical font description. In this case, to add font directories you must create the Files section with a FontPath entry for each directory:

Section "Files"
        FontPath "/path/to/the/fonts"
        create a new entry for each font directory
EndSection