Monochromatic

z3bra, the stripes apart

You are the WM

08 January, 2015

A window manager is a program that runs in the background, and give you keybinds and/or mouse moves to move/resize and arrange your windows on your screen.

Abbreviated "WM", the window manager is an important part of your system, because without it, you'd probably end up with all your windows pop in the bottom left hand-corner of your screen, unable to switch between them.

But guess what...

You don't need it !

It's a fact. A study determined that some rat could be able to determine which language you are speaking. But that's totally unrelated here, I agree.

What is a window manager ?

It's a program ! woah. Thank you Timmy.

A window manager is a program (thank you Timmy) that runs in the background, and wait for X events (I wont talk about wayland here). Those X events can be of any form: key press, window creation/deletion, mouse move, and so on.

The most used events being the keypress events, because the window manager will perform different actions to arrange your windows.

With dcat, we realized that some programs (sxhkd, xbindkeys and others) already handle those events, and could start programs when receiving them. Following the Ô so true Unix way, we decided to create a set of small tools to perform all the task a window manager is supposed to do.

We ended up with wmutils.

Coreutils, for Xorg

wmutils stands for "window manipulation utilities".

This project aims to provide all the tools needed to manage a list of X windows, while keeping each tool as simple as possible, so that they can easily be glued together to create complex behaviors.
Using wmutils, you can list windows, move/resize/teleport them, change their borders, change their visibility, stacking order, ignore them, focus them, and more... Its power reside in its simplicity. As you can chain commands together, you could easily perform some action that other WM can't even do.

For example, here is how you kill all the windows that are not shown on screen (eg, attached to other workspaces):

lsw -u | xargs killw

Put a window in the top-left corner ? pff. easy:

wtp 0 0 $(wattr whi `$pfw`)

bottom-left corner ?

wid=$(pfw)
w=$(wattr w $wid)
h=$(wattr h $wid)
fh=$(wattr h `lsw -r`)

wtp 0 $((fh - h)) $(wattr whi $wid))

You get the idea. As a matter of fact, the following as been done using ONLY* wmutils tools:

gif showing floating
mode gif showing tiling
mode

*only exception is the use of x-move-resize from no-wm, which is planned to be added to wmutils anyway)

Check out the "contrib" repo. There are some nice scripts in there !

Now throw your window manager away, you don't need it anymore. YOU ARE THE WM !

EDIT

I was asked on reddit to explain my wmutils setup. I gave a fairly detailed answer which might also be useful for others, so I figured out I could add it here (original comment here)

I Have both wmutils/core and wmutils/opt installed. I need the latter for wew, an X event watcher.

MANAGING WINDOWS

The central piece of my workflow is sxhkd. This is a software one can use to bind key combos to commands, or scripts. I use it both to start my applications, but also to manage my windows via wmutils tools, and scripts. For instance, here is the entry that let me move windows around the screen using the keyboard (pfw returns the ID of the currently focused window. It's a rather important piece of software!):

# move windows around
super + {left,down,up,right}
      wmv {-20 0, 0 20, 0 -20, 20 0} $(pfw)

# resize windows
super + alt + {left,down,up,right}
      wrs {-20 0, 0 20, 0 -20, 20, 0} $(pfw)

That's for tools that can be bound "directly" via sxhkd. For more complex tasks, I use a few scripts of my own:

vroum

It can take 3 arguments: "next, prev, $wid". "next" will focus the next window on the stack, previous will focus the previously focused window, and every argument starting by 0x will be considered a window ID to be focused directly. It will also change the border of all the inactive windows, and the active window. I use this script to cycle between them:

# cycle through windows
alt {, + shift} + tab
    vroum {next, prev}

groaw

This is my "group" manager (think of it as workspaces on steroid). By default, new windows are not assigned any groups. Without much explaning how each flag works, I just need it to perform 3 tasks:

  1. add the current window to a specific group
  2. toggle visibility state of a specific group
  3. remove current window from all groups

This result in the following entries:

# add window to a group
super + shift + {1,2,3,4,5}
    groaw -d all; \
    groaw -a {1,2,3,4,5}

# toggle groups' visibility
super + {1,2,3,4,5}
    groaw -t {1,2,3,4,5}

# remove window from all groups
super + Backspace
    groaw -d all

focus

A script I'm really proud of! It focus windows besed on their cardinal positions. It takes exactly 4 different arguments:

        north
          ^
          |
 west <---+---> east
          |
          v
        south

It will then focus the nearest window in the given direction (using top/left edge of the window) It's bound like so

# select windows using directions
alt + {left,down,up,right}
      focus {west, south, north, east} $(pfw)

corner

There's nothing special about it. It put the window in the corner passed as argument (Top-Left, Top-Right, Bottom-Left, Bottom-Right, MiDdle)

# move windows to corners
super + {y,u,b,n,g}
    corner {tl, tr, bl, br, md} $(pfw)

fullscreen

Set a window in fullscreen mode (change its size to the size of the monitor, and remove borders. The previous position/size of the window is saved to a file, so when you disable fullscreen mode, or move another window in fullscreen, the window takes its old position back

# set window fullscreen
super + x
    fullscreen $(pfw)

DEALING WITH EVENTS

The above only applies to existing windows. But when a new window gets created, I need to run a few commands against it, to integrate it to my workflow. This is what wew is for. It prints X events to stdout, and the window ID the event applies to. For example:

16:0x000c00ea
19:0x000c00ea

Event number 16 is "window creation", 19 is "mapping request". I have a parser script that will perform different actions depending on the fired event (it's called yawee, I like weird names):

#!/bin/sh

while IFS=: read ev wid; do
    case $ev in
        # window creation: center window on the screen (except docks, menus or similar)
        16) wattr o $wid || corner md $wid ;;

        # mapping requests: just set a special border for docks, menus and
        # similar. Focus other windows
        19) wattr o $wid \
            && chwb -s 2 -c 0x323232 $wid \
            || vroum $wid ;;

        # when a window gets deleted, focus another one
        18) wattr $(pfw) || vroum prev 2>/dev/null;;

        # Focus windows when the mouse cursor enter them
        7) wattr o $wid || vroum $wid ;;
    esac
done

In my $HOME/.xinitrc, it's started as:

wew | yawee &

Pretty straighforward :)

USING THE MOUSE

Nobody's perfect. I use the mouse from time to time to manage my windows. It is sometimes more efficient to get a window out of your way quickly, or resize one approximatively.

For this purpose, I STILL use sxhkd! Baskerville did an amazing job with this software, as it support integer replacement of the mouse coordinate

# move windows with the mouse:
super + !button{1,3}
    {wmv, wrs} -a %i %i $(pfw)

As simple as that!

MISCELLANOUS

For eye candy purpose, I wrote a pulsar script, to make my currently active window standout. It make the window's border "pulse" like in the following video: wall-border.webm. It uses a $HOME/.colors file containing the colors to be used for the gradient. It will then run chwb at a regular interval to change the current window's borders.

That's pretty much it! If you have any question, do not hesitate to ask. Also, sorry for the huge wall of text, I was trying to be as precise as possible.

As a bonus, to congratulate you from reading it all, here is a video from my actual workflow with this setup (writing my latest blogpost: (grab some popcorns, it's 57 minutes long)