Motivation
Differing from Windows and MacOS, Linux is highly customizable for its desktop environment. In the desktop environment, window manager plays a crucial role in controlling the placement and appearance of windows and the interaction when you switch, preview, or hide windows. Unconsciously, these interactions through window manager steal your time especially when you use multiple windows on multiple screens using mouse extensively. Developers prefer to work in this mode. Fortunately, some excellent window managers are developed to alleviate this issue. Awesome is a representative one. However, naively using Awesome on laptop disables my favorite touchpad gestures tool, libinput-gestures. Thus, I decided to write a small tool to mimic window switching shortcuts in Awesome window manager.
As a dynamic window manager, Awesome inherently has some features from both tiling and floating window managers. For me, I prefer its two major features, tilling layout switching and window switching. In this post, I mainly discuss window switching because tilling layout switching is a special feature on tiling mode and it is hard to mimic using floating window manager (i.e., Mutter for GNOME).
Window Switching in Script
Inspired by libinput-gestures, I use wmctrl to interact with the window manager. In following sections, I first introduce how to get windows list and parse previous and next windows to their proper window titles. Then finish the script to support quickly switch to previous, next or target window.
Getting Windows
For wmctrl, windows are represented by window title, id, etc. To get the windows list, the main idea is to use wmctrl -l
.
However, there are many facets to consider when you parse windows list.
1) The active desktop and its windows 2) Retrieving with proper window title to avoid conflicts.
(After a test, we found that wmctrl CANNOT retrieve window with id while switching to it, but it works with title).
Finally, the bash code snippet to get three key windows including currently active, previous and next window title is shown as follow:
#!/bin/bash
WID=`xprop -root | grep _NET_ACTIVE_WINDOW | head -1 | awk '{print $5}'`
WID="${WID:2}"
ACTIVE_WIN=`wmctrl -lx | grep $WID`
ACTIVE_WIN_ID=`echo $ACTIVE_WIN | awk '{print $1}'`
DESK=`echo $ACTIVE_WIN | awk '{print $2}'`
function get_proper_title() {
echo $1 | awk '{print $5" "$6" "$7}' | \
sed -e 's/N\/A//' | \
sed -e 's/[[:space:]]*$//' | sed -e 's/^[[:space:]]//'
}
if [[ $(wmctrl -lx | awk '$2 == '$DESK | grep -B 1 $ACTIVE_WIN_ID | wc -l) == 2 ]]; then
PREV_WIN=`wmctrl -lx | awk '$2 == '$DESK | grep -B 1 $ACTIVE_WIN_ID | head -1`
else
# loop to last window
PREV_WIN=`wmctrl -lx | awk '$2 == '$DESK | tail -1`
fi
PREV_WIN_TITLE=`get_proper_title "$PREV_WIN"`
if [[ $(wmctrl -lx | awk '$2 == '$DESK | grep -A 1 $ACTIVE_WIN_ID | wc -l) == 2 ]]; then
NEXT_WIN=`wmctrl -lx | awk '$2 == '$DESK | grep -A 1 $ACTIVE_WIN_ID | tail -1`
else
# loop to first window
NEXT_WIN=`wmctrl -lx | awk '$2 == '$DESK | head -1`
fi
NEXT_WIN_TITLE=`get_proper_title "$NEXT_WIN"`
Binding and Switching
After getting the target window to switch, we need to open APIs for real actions.
As shown in following code snippet, actions for -p
and -n
are easy to interpret.
For option -t
, it accepts an integer number n to represent the n-th window in current active desktop.
The script is saved as switch-window.sh in a directory which is included in $PATH
.
if [[ $1 == '-p' ]]; then
wmctrl -a "$PREV_WIN_TITLE"
elif [[ $1 == '-n' ]]; then
wmctrl -a "$NEXT_WIN_TITLE"
elif [[ $1 == '-t' ]]; then
TARGET_WIN=`wmctrl -lx | awk '$2 == '$DESK | sed -n $2p`
TARGET_WIN_TITLE=`get_proper_title "$TARGET_WIN"`
wmctrl -a "$TARGET_WIN_TITLE"
fi
For the shortcut binding, I use Awesome-like binding, friendly for Vim users:
Win + j
:wmctrl -n
, switch to next window.Win + k
:wmctrl -p
, switch to previous window.Win + Alt + h
:wmctrl -t 1
, switch to window 1 on current desktopWin + Alt + j
:wmctrl -t 2
, switch to window 2 on current desktopWin + Alt + k
:wmctrl -t 3
, switch to window 3 on current desktopWin + Alt + l
:wmctrl -t 4
, switch to window 4 on current desktop- …
Now, you can jump to any window with one action. No repetitive Alt + Tab
anymore!