101 lines
2.5 KiB
Python
101 lines
2.5 KiB
Python
|
"""
|
||
|
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 get_window_in_direction(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
|
||
|
|
||
|
return win
|
||
|
|
||
|
|
||
|
def _focus_window(qtile, dir, axis):
|
||
|
win = get_window_in_direction(qtile, dir, axis)
|
||
|
if win:
|
||
|
qtile.focus_screen(win.group.screen.index)
|
||
|
win.group.focus(win, True)
|
||
|
if not isinstance(win, Screen):
|
||
|
win.focus(False)
|