Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This adds a plugin for traversing across windows based on their position in global space. By "plugin" this means an importable module that exports functions that can be used as-is (via `lazy.function`) rather than a full config. I've added a table for this to the readme to set the precedent.
- Loading branch information
Showing
2 changed files
with
99 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
""" | ||
This plugin exports four functions - up, down, left and right - that when called will | ||
move window focus to the first window in that general direction. Focussing is based | ||
entirely on position and geometry, so is independent of screens, layouts and whether | ||
windows are floating or tiled. It can also move focus to and from empty screens. | ||
Example usage: | ||
import traverse | ||
keys.extend([ | ||
Key([mod], 'k', lazy.function(traverse.up)), | ||
Key([mod], 'j', lazy.function(traverse.down)), | ||
Key([mod], 'h', lazy.function(traverse.left)), | ||
Key([mod], 'l', lazy.function(traverse.right)), | ||
]) | ||
Qtile versions known to work: 0.16 - 0.18 | ||
""" | ||
|
||
from libqtile.config import Screen | ||
|
||
|
||
def up(qtile): | ||
_focus_window(qtile, -1, 'y') | ||
|
||
|
||
def down(qtile): | ||
_focus_window(qtile, 1, 'y') | ||
|
||
|
||
def left(qtile): | ||
_focus_window(qtile, -1, 'x') | ||
|
||
|
||
def right(qtile): | ||
_focus_window(qtile, 1, 'x') | ||
|
||
|
||
def _focus_window(qtile, dir, axis): | ||
win = None | ||
win_wide = None | ||
dist = 10000 | ||
dist_wide = 10000 | ||
cur = qtile.current_window | ||
if not cur: | ||
cur = qtile.current_screen | ||
|
||
if axis == 'x': | ||
dim = 'width' | ||
band_axis = 'y' | ||
band_dim = 'height' | ||
cur_pos = cur.x | ||
band_min = cur.y | ||
band_max = cur.y + cur.height | ||
else: | ||
dim = 'height' | ||
band_axis = 'x' | ||
band_dim = 'width' | ||
band_min = cur.x | ||
cur_pos = cur.y | ||
band_max = cur.x + cur.width | ||
|
||
cur_pos += getattr(cur, dim) / 2 | ||
|
||
windows = [w for g in qtile.groups if g.screen for w in g.windows] | ||
windows.extend([s for s in qtile.screens if not s.group.windows]) | ||
|
||
if cur in windows: | ||
windows.remove(cur) | ||
|
||
for w in windows: | ||
if isinstance(w, Screen) or not w.minimized: | ||
pos = getattr(w, axis) + getattr(w, dim) / 2 | ||
gap = dir * (pos - cur_pos) | ||
if gap > 5: | ||
band_pos = getattr(w, band_axis) + getattr(w, band_dim) / 2 | ||
if band_min < band_pos < band_max: | ||
if gap < dist: | ||
dist = gap | ||
win = w | ||
else: | ||
if gap < dist_wide: | ||
dist_wide = gap | ||
win_wide = w | ||
|
||
if not win: | ||
win = win_wide | ||
if win: | ||
qtile.focus_screen(win.group.screen.index) | ||
win.group.focus(win, True) | ||
if not isinstance(win, Screen): | ||
win.focus(False) |