using i3-ipc and a listener script. Tweak it to float only certain windows.
Recently, I have been tweaking the i3 configuration in my machines, seeking to reduce latency and achieve smoother operation. The defaults and conventional setup are fine (no problems), but my intention is to rice the system and do numerous little things which can add latency reveal quirks in an otherwise smooth and fast window manager. Let us look into the issue as it relates to opening some specific applications in floating windows while other applications open in the tabbed or tiled layout.
It is the i3 config file which is used by most people to set the default layout options and any settings which differ for specific applications. For example, my preference is for terminals, web and file browsers, and certain utilities to open floating above the other tiled windows. To open certain windows in floating mode, the config file would have lines like this:
for_window [class="gnome-terminal"] floating enable for_window [class="URxvt] floating enable
Budlabs posted a Youtube video describing a
phenomenon where a visible glitch occurs when a new window is opened or
if the title or class changes. What happens is that i3 begins to make the
changes associated with the new window or changed title, but takes a number
of milliseconds to read all of the the for_window rules in the config file.
Those rules are searched to determine if there is one applicable to the
window being opened or changed. What can be done to eliminate the glitch?
Budlabs crafted a clever solution in which the for_window rules are replaced with a short bit of code in a separate script, using interprocess communication. This means it is necessary to run an i3-ipc process to monitor what i3 is doing and intervene with a command to handle the opening of a new window. The solution is fast, efficient, and smooth. Any of the available ipc listeners may be used to recognize the time when a new window is being opened. Then, I use a Python script similar to what Budlabs uses, but with changes to limit floating mode to specific windows.
Mister Bud used the following code, within a listener script, to find window opening events:
Here is the Python function to actually enable all new windows to float
instead of tile or tab:
def set_floating(i3, event): event.container.command('floating enable')
Being one who prefers to have most windows not float, I set out to find a way to cause the funtion to only enable floating if a new window was in a list given in the script. Here is what works well:
# a hard coded list of windows to float by default FLOATERS = ['Mate-terminal', 'Firefox', 'vlc', 'Caja', 'URxvt', 'UXTerm', 'xterm'] def set_floating(i3, event): for floater in FLOATERS: print(event.container.window_class) if event.container.window_class == floater: event.container.command('floating enable, resize set 1000 700, \ move absolute position center') break
The essential idea is to compare the new window class to names in the list, and if there is a match, then forget about the remainder of the list and get on with floating the window. In fact, float the window, resize it moderately, and center it on the screen.
There are possible ways to make this more efficient or user friendly. One way is to change from a hard coded list to a user editable list kept in the home directory. That could be read on login, for example. For faster execution, these tasks could be accomplished in a binary compiled from Go instead of running in Python. In this instance the latency in question is a matter of milliseconds, but milliseconds add up. If the entire system is crafted with the intention of minimizing delays, it can be beautifully responsive.
Tags: i3, i3wm, floating windows, i3-ipc