]> Dogcows Code - chaz/openbox/blobdiff - scripts/focus.py
allow a callback to determine if a window should be history-placed
[chaz/openbox] / scripts / focus.py
index 74bcae74fdf4bb7a1d590766249bdb09cc40f260..f1097aa51426c69f952c080123d7b02bcf09c1e0 100644 (file)
@@ -5,11 +5,18 @@
 ###########################################################################
 ###         Options that affect the behavior of the focus module.       ###
 ###                                                                     ###
-# raise the window also when it is focused                              ###
+# cycle_raise - raise the window also when it is focused                ###
 cycle_raise = 1                                                         ###
-# raise as you cycle in stacked mode                                    ###
+# avoid_skip_taskbar - Don't focus windows which have requested to not  ###
+###                    be displayed in taskbars. You will still be able ###
+###                    to focus the windows, but not through cycling,   ###
+###                    and they won't be focused as a fallback if       ###
+###                    'fallback' is enabled.                           ###
+avoid_skip_taskbar = 1                                                  ###
+# stacked_cycle_raise - raise as you cycle in stacked mode              ###
 stacked_cycle_raise = 0                                                 ###
-# show a pop-up list of windows while cycling                           ###
+# stacked_cycle_popup_list - show a pop-up list of windows while        ###
+###                          cycling                                    ###
 stacked_cycle_popup_list = 1                                            ###
 # send focus somewhere when nothing is left with the focus, if possible ###
 fallback = 0                                                            ###
@@ -40,6 +47,13 @@ _clients = []
 # maintaint he current focused window
 _doing_stacked = 0
 
+def _focusable(client, desktop):
+    if not (avoid_skip_taskbar and client.skipTaskbar()) and \
+       (client.desktop() == desktop or client.desktop() == 0xffffffff) and \
+       client.normal() and (client.canFocus() or client.focusNotify()):
+        return 1
+    return 0
+
 def _new_win(data):
     global _clients
     global _doing_stacked
@@ -48,7 +62,7 @@ def _new_win(data):
     if _doing_stacked:
         _clients.insert(_clients.index(_cyc_w), data.client.window())
         _create_popup_list(data)
-        _hilite_popup_list()
+        _hilite_popup_list(data)
     else:
         if not len(_clients):
             _clients.append(data.client.window())
@@ -84,15 +98,17 @@ def _focused(data):
             _clients.insert(0, win)
         else: # if we are cycling, then update our pointer
             _cyc_w = data.client.window()
-            _hilite_popup_list()
+            _hilite_popup_list(data)
     elif fallback: 
         # pass around 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()):
+            if client and _focusable(client, desktop) and client.focus():
                 break
+        if _doing_stacked:
+            _cyc_w = 0
+            _hilite_popup_list(data)
 
 _cyc_mask = 0
 _cyc_key = 0
@@ -118,8 +134,8 @@ def _do_stacked_cycle(data, forward):
     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 client and _focusable(client, desktop) and client.focus():
             if stacked_cycle_raise:
                 ob.openbox.screen(data.screen).raiseWindow(client)
             return
@@ -132,27 +148,38 @@ def _focus_stacked_ungrab(data):
     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
+            _destroy_popup_list()
+            ob.kungrab()
+            ob.mungrab()
             _doing_stacked = 0;
             if cycle_raise:
                 client = ob.openbox.findClient(_cyc_w)
                 if client:
                     ob.openbox.screen(data.screen).raiseWindow(client)
-            _destroy_popup_list()
 
 _list_widget = 0
 _list_labels = []
 _list_windows = []
 
-def _hilite_popup_list():
-    global _cyc_w
+def _hilite_popup_list(data):
+    global _cyc_w, _doing_stacked
     global _list_widget, _list_labels, _list_windows
+    found = 0
+
+    if not _list_widget and _doing_stacked:
+        _create_popup_list(data)
+    
     if _list_widget:
         i = 0
         for w in _list_windows:
-            if w == _cyc_w: _list_labels[i].focus()
-            else: _list_labels[i].unfocus()
+            if w == _cyc_w:
+                _list_labels[i].focus()
+                found = 1
+            else:
+                _list_labels[i].unfocus()
             i += 1
+    if not found:
+        _create_popup_list(data)
 
 def _destroy_popup_list():
     global _list_widget, _list_labels, _list_windows
@@ -162,6 +189,7 @@ def _destroy_popup_list():
         _list_widget = 0
     
 def _create_popup_list(data):
+    global avoid_skip_taskbar
     global _list_widget, _list_labels, _list_windows, _clients
 
     if _list_widget:
@@ -178,26 +206,24 @@ def _create_popup_list(data):
     font = style.labelFont()
     height = font.height()
     longest = 0
+    desktop = ob.openbox.screen(data.screen).desktop()
     for c in _clients:
         client = ob.openbox.findClient(c)
-        desktop = ob.openbox.screen(data.screen).desktop()
-        if client and (client.desktop() == desktop and \
-                       client.normal()):
+        if client and _focusable(client, desktop):
             t = client.title()
             if len(t) > 50: # limit the length of titles
                 t = t[:24] + "..." + t[-24:]
             titles.append(t)
             _list_windows.append(c)
-            l = font.measureString(t) + 10 # add margin
+            l = font.measureString(t)
             if l > longest: longest = l
-    if len(titles):
+    if len(titles) > 1:
         for t in titles:
             w = otk.FocusLabel(_list_widget)
-            w.resize(longest, height)
+            w.fitSize(longest, height)
             w.setText(t)
             w.unfocus()
             _list_labels.append(w)
-        _list_labels[0].focus()
         _list_widget.update()
         area = otk.display.screenInfo(data.screen).rect()
         _list_widget.move(area.x() + (area.width() -
@@ -206,7 +232,7 @@ def _create_popup_list(data):
                                       _list_widget.height()) / 2)
         _list_widget.show(1)
     else:
-        _list_widget = 0 #nothing to list
+        _destroy_popup_list() # nothing (or only 1) to list
 
 def focus_next_stacked(data, forward=1):
     """Focus the next (or previous, with forward=0) window in a stacked
@@ -232,6 +258,10 @@ def focus_next_stacked(data, forward=1):
             _create_popup_list(data)
 
         ob.kgrab(data.screen, _focus_stacked_ungrab)
+        # the pointer grab causes pointer events during the keyboard grab to
+        # go away, which means we don't get enter notifies when the popup
+        # disappears, screwing up the focus
+        ob.mgrab(data.screen)
         focus_next_stacked(data, forward) # start with the first press
 
 def focus_prev_stacked(data):
@@ -241,6 +271,8 @@ def focus_prev_stacked(data):
 def focus_next(data, num=1, forward=1):
     """Focus the next (or previous, with forward=0) window in a linear
        order."""
+    global avoid_skip_taskbar
+
     screen = ob.openbox.screen(data.screen)
     count = screen.clientCount()
 
@@ -265,12 +297,10 @@ def focus_next(data, num=1, forward=1):
             else: target = count - 1
 
     t = target
-    curdesk = screen.desktop()
+    desktop = screen.desktop()
     while 1:
         client = screen.client(t)
-        if client.normal() and \
-               (client.desktop() == curdesk or client.desktop() == 0xffffffff)\
-               and client.focus():
+        if client and _focusable(client, desktop) and client.focus():
             if cycle_raise:
                 screen.raiseWindow(client)
             return
This page took 0.028695 seconds and 4 git commands to generate.