]> Dogcows Code - chaz/openbox/blobdiff - scripts/focus.py
include gettext.h from ../src
[chaz/openbox] / scripts / focus.py
index c0d60b1ee7bb06308f05cd65d5ea268e3738a42a..3ea42edc7023a850777cc88abe6033b2f9ce6f4a 100644 (file)
 ###          Functions for helping out with your window focus.          ###
 ###########################################################################
 
-ob_focus_raise = 1
-ob_focus_fallback = 0
-ob_focus_stack = []
-
-def ob_focused(data):
-    global ob_focus_raise
-    global ob_focus_fallback
-    global ob_focus_stack
+###########################################################################
+###         Options that affect the behavior of the focus module.       ###
+###                                                                     ###
+# raise the window also when it is focused                              ###
+cycle_raise = 1                                                         ###
+# raise as you cycle in stacked mode                                    ###
+stacked_cycle_raise = 0                                                 ###
+# send focus somewhere when nothing is left with the focus, if possible ###
+fallback = 0                                                            ###
+###                                                                     ###
+###########################################################################
+
+import ob
+
+# maintain a list of clients, stacked in focus order
+_clients = []
+# maintaint he current focused window
+_doing_stacked = 0
+
+def _new_win(data):
+    global _clients
+    global _doing_stacked
+    global _cyc_w;
+
+    if _doing_stacked:
+        _clients.insert(_clients.index(_cyc_w), data.client.window())
+    else:
+        if not len(_clients):
+            _clients.append(data.client.window())
+        else:
+            _clients.insert(1, data.client.window()) # insert in 2nd slot
+
+def _close_win(data):
+    global _clients
+    global _cyc_w;
+    global _doing_stacked
+
+    if not _doing_stacked:
+        # not in the middle of stacked cycling, so who cares
+        _clients.remove(data.client.window())
+    else:
+        # have to fix the cycling if we remove anything
+        win = data.client.window()
+        if _cyc_w == win:
+            _do_stacked_cycle(data) # cycle off the window first
+        _clients.remove(win)
+
+def _focused(data):
+    global _clients
+    global _doing_stacked
+    global _cyc_w
+    
     if data.client:
-        window = data.client.window()
-        # add/move to front the stack
-        if window in ob_focus_stack:
-            ob_focus_stack.remove(window)
-        ob_focus_stack.insert(0, window)
-    elif ob_focus_fallback:
+        if not _doing_stacked: # only move the window when we're not cycling
+            win = data.client.window()
+            # move it to the top
+            _clients.remove(win)
+            _clients.insert(0, win)
+        else: # if we are cycling, then update our pointer
+            _cyc_w = data.client.window()
+    elif fallback: 
         # pass around focus
-        desktop = openbox.screen(data.screen).desktop()
-        l = len(ob_focus_stack)
-        i = 0
-        while i < l:
-            w = ob_focus_stack[i]
-            client = openbox.findClient(w)
-            if not client: # window is gone, remove it
-                ob_focus_stack.pop(i)
-                l = l - 1
-            elif client.desktop() == desktop and \
-                     client.normal() and client.focus():
+        desktop = ob.openbox.screen(_cyc_screen).desktop()
+        for w in _clients:
+            client = ob.openbox.findClient(w)
+            if client and (client.desktop() == desktop and \
+                           client.normal() and client.focus()):
                 break
-            else:
-                i = i + 1
 
-ebind(EventFocus, ob_focused)
+_cyc_mask = 0
+_cyc_key = 0
+_cyc_w = 0 # last window cycled to
+_cyc_screen = 0
+
+def _do_stacked_cycle(data, forward):
+    global _cyc_w
+    global stacked_cycle_raise
+    global _clients
+
+    clients = _clients[:] # make a copy
+
+    if not forward:
+        clients.reverse()
+
+    try:
+        i = clients.index(_cyc_w) + 1
+    except ValueError:
+        i = 1
+    clients = clients[i:] + clients[:i]
+        
+    desktop = ob.openbox.screen(data.screen).desktop()
+    for w in clients:
+        client = ob.openbox.findClient(w)
+        if client and (client.desktop() == desktop and \
+                       client.normal() and client.focus()):
+            if stacked_cycle_raise:
+                ob.openbox.screen(data.screen).raiseWindow(client)
+            return
+
+def _focus_stacked_ungrab(data):
+    global _cyc_mask;
+    global _cyc_key;
+    global _doing_stacked;
+
+    if data.action == ob.KeyAction.Release:
+        # have all the modifiers this started with been released?
+        if not _cyc_mask & data.state:
+            ob.kungrab() # ungrab ourself
+            _doing_stacked = 0;
+            if cycle_raise:
+                client = ob.openbox.findClient(_cyc_w)
+                if client:
+                    ob.openbox.screen(data.screen).raiseWindow(client)
+
+def focus_next_stacked(data, forward=1):
+    """Focus the next (or previous, with forward=0) window in a stacked
+       order."""
+    global _cyc_mask
+    global _cyc_key
+    global _cyc_w
+    global _cyc_screen
+    global _doing_stacked
+
+    if _doing_stacked:
+        if _cyc_key == data.key:
+            _do_stacked_cycle(data,forward)
+    else:
+        _cyc_mask = data.state
+        _cyc_key = data.key
+        _cyc_w = 0
+        _cyc_screen = data.screen
+        _doing_stacked = 1
+
+        ob.kgrab(data.screen, _focus_stacked_ungrab)
+        focus_next_stacked(data, forward) # start with the first press
+
+def focus_prev_stacked(data):
+    """Focus the previous window in a stacked order."""
+    focus_next_stacked(data, forward=0)
 
 def focus_next(data, num=1, forward=1):
     """Focus the next (or previous, with forward=0) window in a linear
        order."""
-    screen = openbox.screen(data.screen)
+    screen = ob.openbox.screen(data.screen)
     count = screen.clientCount()
 
     if not count: return # no clients
@@ -53,10 +160,11 @@ def focus_next(data, num=1, forward=1):
         for i in r:
             if found:
                 target = i
+                found = 2
                 break
             elif screen.client(i).window() == client_win:
                 found = 1
-        if not found: # wraparound
+        if found == 1: # wraparound
             if forward: target = 0
             else: target = count - 1
 
@@ -67,14 +175,14 @@ def focus_next(data, num=1, forward=1):
         if client.normal() and \
                (client.desktop() == curdesk or client.desktop() == 0xffffffff)\
                and client.focus():
-            if ob_focus_raise:
+            if cycle_raise:
                 screen.raiseWindow(client)
             return
         if forward:
             t += num
             if t >= count: t -= count
         else:
-            t -= 1
+            t -= num
             if t < 0: t += count
         if t == target: return # nothing to focus
 
@@ -83,4 +191,8 @@ def focus_prev(data, num=1):
     focus_next(data, num, forward=0)
 
 
+ob.ebind(ob.EventAction.NewWindow, _new_win)
+ob.ebind(ob.EventAction.CloseWindow, _close_win)
+ob.ebind(ob.EventAction.Focus, _focused)
+
 print "Loaded focus.py"
This page took 0.024564 seconds and 4 git commands to generate.