-rw-r--r-- qtools/focus/focus.py
1 """ 2 This plugin exports four functions - up, down, left and right - that when called will 3 move window focus to the first window in that general direction. Focussing is based 4 entirely on position and geometry, so is independent of screens, layouts and whether 5 windows are floating or tiled. It can also move focus to and from empty screens. 6 7 Example usage: 8 9 import qtools.focus 10 keys.extend([EzKey(k, v) for k, v in { 11 'M-k': lazy.function(qtools.focus.up) 12 'M-j': lazy.function(qtools.focus.down) 13 'M-h': lazy.function(qtools.focus.left) 14 'M-l': lazy.function(qtools.focus.right) 15 }.items()]) 16 17 """ 18 19 20 from libqtile.config import Screen 21 from xcffib.xproto import StackMode 22 23 24 def up(qtile): 25 _focus_window(qtile, -1, 'y') 26 27 28 def down(qtile): 29 _focus_window(qtile, 1, 'y') 30 31 32 def left(qtile): 33 _focus_window(qtile, -1, 'x') 34 35 36 def right(qtile): 37 _focus_window(qtile, 1, 'x') 38 39 40 def _focus_window(qtile, dir, axis): 41 win = None 42 win_wide = None 43 dist = 10000 44 dist_wide = 10000 45 cur = qtile.current_window 46 if not cur: 47 cur = qtile.current_screen 48 49 if axis == 'x': 50 dim = 'width' 51 band_axis = 'y' 52 band_dim = 'height' 53 cur_pos = cur.x 54 band_min = cur.y 55 band_max = cur.y + cur.height 56 else: 57 dim = 'height' 58 band_axis = 'x' 59 band_dim = 'width' 60 band_min = cur.x 61 cur_pos = cur.y 62 band_max = cur.x + cur.width 63 64 cur_pos += getattr(cur, dim) / 2 65 66 windows = [w for g in qtile.groups if g.screen for w in g.windows] 67 windows.extend([s for s in qtile.screens if not s.group.windows]) 68 69 if cur in windows: 70 windows.remove(cur) 71 72 for w in windows: 73 if isinstance(w, Screen) or not w.minimized: 74 pos = getattr(w, axis) + getattr(w, dim) / 2 75 gap = dir * (pos - cur_pos) 76 if gap > 5: 77 band_pos = getattr(w, band_axis) + getattr(w, band_dim) / 2 78 if band_min < band_pos < band_max: 79 if gap < dist: 80 dist = gap 81 win = w 82 else: 83 if gap < dist_wide: 84 dist_wide = gap 85 win_wide = w 86 87 if not win: 88 win = win_wide 89 if win: 90 qtile.focus_screen(win.group.screen.index) 91 win.group.focus(win, True) 92 if not isinstance(win, Screen): 93 win.window.configure(stackmode=StackMode.Above) 94 win.focus(False) 95