My collection of plugins for the Qtile window manager.
git clone https://mcol.xyz/code/qtools
Log | Files | Refs | README

focus.py (2529B)


      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)