X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=scripts%2Ffocus.py;h=adba37258fb89ed93a885e010b9165c9abad065e;hb=3409b046a043d8ffabf2e9c33ea037c2e5be15e4;hp=3ea42edc7023a850777cc88abe6033b2f9ce6f4a;hpb=997f94cf8657201ea9d1f2497e4ec4f56342e22f;p=chaz%2Fopenbox diff --git a/scripts/focus.py b/scripts/focus.py index 3ea42edc..adba3725 100644 --- a/scripts/focus.py +++ b/scripts/focus.py @@ -9,11 +9,30 @@ cycle_raise = 1 ### # raise as you cycle in stacked mode ### stacked_cycle_raise = 0 ### +# 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 ### ### ### +### ### +# Provides: ### +# def focus_next_stacked(data, forward=1): ### +# """Focus the next (or previous, with forward=0) window in a stacked ### +# order.""" ### +# def focus_prev_stacked(data): ### +# """Focus the previous window in a stacked order.""" ### +# def focus_next(data, num=1, forward=1): ### +# """Focus the next (or previous, with forward=0) window in a linear ### +# order.""" ### +# def focus_prev(data, num=1): ### +# """Focus the previous window in a linear order.""" ### +### ### +# All of these functions call be used as callbacks for bindings ### +# directly. ### +### ### ########################################################################### +import otk import ob # maintain a list of clients, stacked in focus order @@ -28,6 +47,8 @@ def _new_win(data): if _doing_stacked: _clients.insert(_clients.index(_cyc_w), data.client.window()) + _create_popup_list(data) + _hilite_popup_list(data) else: if not len(_clients): _clients.append(data.client.window()) @@ -46,8 +67,9 @@ def _close_win(data): # 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 + _do_stacked_cycle(data, 1) # cycle off the window first, forward _clients.remove(win) + _create_popup_list(data) def _focused(data): global _clients @@ -62,6 +84,7 @@ def _focused(data): _clients.insert(0, win) else: # if we are cycling, then update our pointer _cyc_w = data.client.window() + _hilite_popup_list(data) elif fallback: # pass around focus desktop = ob.openbox.screen(_cyc_screen).desktop() @@ -70,6 +93,9 @@ def _focused(data): if client and (client.desktop() == desktop and \ client.normal() and client.focus()): break + if _doing_stacked: + _cyc_w = 0 + _hilite_popup_list(data) _cyc_mask = 0 _cyc_key = 0 @@ -109,6 +135,7 @@ 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: + _destroy_popup_list() ob.kungrab() # ungrab ourself _doing_stacked = 0; if cycle_raise: @@ -116,6 +143,85 @@ def _focus_stacked_ungrab(data): if client: ob.openbox.screen(data.screen).raiseWindow(client) +_list_widget = 0 +_list_labels = [] +_list_windows = [] + +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() + 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 + if _list_widget: + _list_windows = [] + _list_labels = [] + _list_widget = 0 + +def _create_popup_list(data): + global _list_widget, _list_labels, _list_windows, _clients + + if _list_widget: + _destroy_popup_list() + + style = ob.openbox.screen(data.screen).style() + _list_widget = otk.Widget(ob.openbox, style, + otk.Widget.Vertical, 0, + style.bevelWidth(), 1) + t = style.titlebarFocusBackground() + _list_widget.setTexture(t) + + titles = [] + font = style.labelFont() + height = font.height() + longest = 0 + for c in _clients: + client = ob.openbox.findClient(c) + desktop = ob.openbox.screen(data.screen).desktop() + if client and ((client.desktop() == desktop or + client.desktop() == 0xffffffff) and \ + client.normal() and (client.canFocus() or + client.focusNotify())): + 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) + if l > longest: longest = l + if len(titles) > 1: + for t in titles: + w = otk.FocusLabel(_list_widget) + w.fitSize(longest, height) + w.setText(t) + w.unfocus() + _list_labels.append(w) + _list_widget.update() + area = otk.display.screenInfo(data.screen).rect() + _list_widget.move(area.x() + (area.width() - + _list_widget.width()) / 2, + area.y() + (area.height() - + _list_widget.height()) / 2) + _list_widget.show(1) + else: + _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 order.""" @@ -135,6 +241,10 @@ def focus_next_stacked(data, forward=1): _cyc_screen = data.screen _doing_stacked = 1 + global stacked_cycle_popup_list + if stacked_cycle_popup_list: + _create_popup_list(data) + ob.kgrab(data.screen, _focus_stacked_ungrab) focus_next_stacked(data, forward) # start with the first press