diff options
| author | Dana Jansens <danakj@orodu.net> | 2003-01-25 16:36:55 +0000 |
|---|---|---|
| committer | Dana Jansens <danakj@orodu.net> | 2003-01-25 16:36:55 +0000 |
| commit | 997f94cf8657201ea9d1f2497e4ec4f56342e22f (patch) | |
| tree | 11d43c9fdadb3c23b6903f4d3a794ba40d2e89b6 /scripts | |
| parent | 02d6362111a9e679b0a2f108d396f105243da4b5 (diff) | |
new/better/cleaner scripting interface
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/Makefile.am | 3 | ||||
| -rw-r--r-- | scripts/builtins.py | 332 | ||||
| -rw-r--r-- | scripts/defaults.py | 55 | ||||
| -rw-r--r-- | scripts/focus.py | 187 |
4 files changed, 138 insertions, 439 deletions
diff --git a/scripts/Makefile.am b/scripts/Makefile.am index ee0287a4..95deedad 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -1,6 +1,7 @@ scriptdir = $(libdir)/openbox/python MAINTAINERCLEANFILES = Makefile.in -script_DATA = config.py builtins.py defaults.py focus.py +script_DATA = config.py builtins.py defaults.py focus.py callbacks.py \ + focusmodel.py windowplacement.py behavior.py EXTRA_DIST = $(script_DATA) distclean-local: diff --git a/scripts/builtins.py b/scripts/builtins.py index db545b3d..70518dcc 100644 --- a/scripts/builtins.py +++ b/scripts/builtins.py @@ -1,334 +1,2 @@ -########################################################################### -### Functions that can be used as callbacks for mouse/keyboard bindings ### -########################################################################### - -def state_above(data, add=2): - """Toggles, adds or removes the 'above' state on a window.""" - if not data.client: return - send_client_msg(display.screenInfo(data.screen).rootWindow(), - Property_atoms().net_wm_state, data.client.window(), add, - Property_atoms().net_wm_state_above) - -def state_below(data, add=2): - """Toggles, adds or removes the 'below' state on a window.""" - if not data.client: return - send_client_msg(display.screenInfo(data.screen).rootWindow(), - Property_atoms().net_wm_state, data.client.window(), add, - Property_atoms().net_wm_state_below) - -def state_shaded(data, add=2): - """Toggles, adds or removes the 'shaded' state on a window.""" - if not data.client: return - send_client_msg(display.screenInfo(data.screen).rootWindow(), - Property_atoms().net_wm_state, data.client.window(), add, - Property_atoms().net_wm_state_shaded) - -def iconify(data): - """Iconifies the window on which the event occured""" - if not data.client: return - send_client_msg(display.screenInfo(data.screen).rootWindow(), - Property_atoms().wm_change_state, - data.client.window(), 3) # IconicState - -def restore(data): - """Un-iconifies the window on which the event occured, but does not focus - if. If you want to focus the window too, it is recommended that you - use the activate() function.""" - if not data.client: return - send_client_msg(display.screenInfo(data.screen).rootWindow(), - Property_atoms().wm_change_state, - data.client.window(), 1) # NormalState - -def close(data): - """Closes the window on which the event occured""" - if not data.client: return - send_client_msg(display.screenInfo(data.screen).rootWindow(), - Property_atoms().net_close_window, data.client.window(), 0) - -def focus(data): - """Focuses the window on which the event occured""" - if not data.client: return - # !normal windows dont get focus from window enter events - if data.action == EventEnterWindow and not data.client.normal(): - return - data.client.focus() - -def move(data): - """Moves the window interactively. This should only be used with - MouseMotion events""" - if not data.client: return - - # !normal windows dont get moved - if not data.client.normal(): return - - dx = data.xroot - data.pressx - dy = data.yroot - data.pressy - data.client.move(data.press_clientx + dx, data.press_clienty + dy) - -def resize(data): - """Resizes the window interactively. This should only be used with - MouseMotion events""" - if not data.client: return - - # !normal windows dont get moved - if not data.client.normal(): return - - px = data.pressx - py = data.pressy - dx = data.xroot - px - dy = data.yroot - py - - # pick a corner to anchor - if not (resize_nearest or data.context == MC_Grip): - corner = Client.TopLeft - else: - x = px - data.press_clientx - y = py - data.press_clienty - if y < data.press_clientheight / 2: - if x < data.press_clientwidth / 2: - corner = Client.BottomRight - dx *= -1 - else: - corner = Client.BottomLeft - dy *= -1 - else: - if x < data.press_clientwidth / 2: - corner = Client.TopRight - dx *= -1 - else: - corner = Client.TopLeft - - data.client.resize(corner, - data.press_clientwidth + dx, - data.press_clientheight + dy); - -def restart(data, other = ""): - """Restarts openbox, optionally starting another window manager.""" - openbox.restart(other) - -def raise_win(data): - """Raises the window on which the event occured""" - if not data.client: return - openbox.screen(data.screen).raiseWindow(data.client) - -def lower_win(data): - """Lowers the window on which the event occured""" - if not data.client: return - openbox.screen(data.screen).lowerWindow(data.client) - -def toggle_shade(data): - """Toggles the shade status of the window on which the event occured""" - state_shaded(data) - -def shade(data): - """Shades the window on which the event occured""" - state_shaded(data, 1) - -def unshade(data): - """Unshades the window on which the event occured""" - state_shaded(data, 0) - -def change_desktop(data, num): - """Switches to a specified desktop""" - root = display.screenInfo(data.screen).rootWindow() - send_client_msg(root, Property_atoms().net_current_desktop, root, num) - -def next_desktop(data, no_wrap=0): - """Switches to the next desktop, optionally (by default) cycling around to - the first when going past the last.""" - screen = openbox.screen(data.screen) - d = screen.desktop() - n = screen.numDesktops() - if (d < (n-1)): - d = d + 1 - elif not no_wrap: - d = 0 - change_desktop(data, d) - -def prev_desktop(data, no_wrap=0): - """Switches to the previous desktop, optionally (by default) cycling around - to the last when going past the first.""" - screen = openbox.screen(data.screen) - d = screen.desktop() - n = screen.numDesktops() - if (d > 0): - d = d - 1 - elif not no_wrap: - d = n - 1 - change_desktop(data, d) - -def send_to_desktop(data, num): - """Sends a client to a specified desktop""" - if not data.client: return - send_client_msg(display.screenInfo(data.screen).rootWindow(), - Property_atoms().net_wm_desktop, data.client.window(), num) - -def toggle_all_desktops(data): - """Toggles between sending a client to all desktops and to the current - desktop.""" - if not data.client: return - if not data.client.desktop() == 0xffffffff: - send_to_desktop(data, 0xffffffff) - else: - send_to_desktop(data, openbox.screen(data.screen).desktop()) - -def send_to_all_desktops(data): - """Sends a client to all desktops""" - if not data.client: return - send_to_desktop(data, 0xffffffff) - -def send_to_next_desktop(data, no_wrap=0, follow=1): - """Sends a window to the next desktop, optionally (by default) cycling - around to the first when going past the last. Also optionally moving to - the new desktop after sending the window.""" - if not data.client: return - screen = openbox.screen(data.screen) - d = screen.desktop() - n = screen.numDesktops() - if (d < (n-1)): - d = d + 1 - elif not no_wrap: - d = 0 - send_to_desktop(data, d) - if follow: - change_desktop(data, d) - -def send_to_prev_desktop(data, no_wrap=0, follow=1): - """Sends a window to the previous desktop, optionally (by default) cycling - around to the last when going past the first. Also optionally moving to - the new desktop after sending the window.""" - if not data.client: return - screen = openbox.screen(data.screen) - d = screen.desktop() - n = screen.numDesktops() - if (d > 0): - d = d - 1 - elif not no_wrap: - d = n - 1 - send_to_desktop(data, d) - if follow: - change_desktop(data, d) - -######################################### -### Convenience functions for scripts ### -######################################### - -def execute(bin, screen = 0): - """Executes a command on the specified screen. It is recommended that you - use this call instead of a python system call. If the specified screen - is beyond your range of screens, the default is used instead.""" - openbox.execute(screen, bin) - -def setup_click_focus(click_raise = 1): - """Sets up for focusing windows by clicking on or in the window. - Optionally, clicking on or in a window can raise the window to the - front of its stacking layer.""" - mbind("Left", MC_Titlebar, MousePress, focus) - mbind("Left", MC_Handle, MousePress, focus) - mbind("Left", MC_Grip, MousePress, focus) - mbind("Left", MC_Window, MousePress, focus) - #mbind("A-Left", MC_Frame, MousePress, focus) - if click_raise: - mbind("Left", MC_Titlebar, MousePress, raise_win) - mbind("Left", MC_Handle, MousePress, raise_win) - mbind("Left", MC_Grip, MousePress, raise_win) - mbind("Left", MC_Window, MousePress, raise_win) - -def setup_sloppy_focus(click_focus = 1, click_raise = 0): - """Sets up for focusing windows when the mouse pointer enters them. - Optionally, clicking on or in a window can focus it if your pointer - ends up inside a window without focus. Also, optionally, clicking on or - in a window can raise the window to the front of its stacking layer.""" - ebind(EventEnterWindow, focus) - if click_focus: - setup_click_focus(click_raise) - -def setup_window_clicks(): - """Sets up the default bindings for various mouse buttons for various - contexts. - This includes: - * Alt-left drag anywhere on a window will move it - * Alt-right drag anywhere on a window will resize it - * Left drag on a window's titlebar/handle will move it - * Left drag on a window's handle grips will resize it - * Alt-left press anywhere on a window's will raise it to the front of - its stacking layer. - * Left press on a window's titlebar/handle will raise it to the front - of its stacking layer. - * Alt-middle click anywhere on a window's will lower it to the bottom - of its stacking layer. - * Middle click on a window's titlebar/handle will lower it to the - bottom of its stacking layer. - * Double-left click on a window's titlebar will toggle shading it - """ - mbind("A-Left", MC_Frame, MouseMotion, move) - mbind("Left", MC_Titlebar, MouseMotion, move) - mbind("Left", MC_Handle, MouseMotion, move) - - mbind("A-Right", MC_Frame, MouseMotion, resize) - mbind("Left", MC_Grip, MouseMotion, resize) - - mbind("Left", MC_Titlebar, MousePress, raise_win) - mbind("Left", MC_Handle, MousePress, raise_win) - mbind("A-Left", MC_Frame, MousePress, raise_win) - mbind("A-Middle", MC_Frame, MouseClick, lower_win) - mbind("Middle", MC_Titlebar, MouseClick, lower_win) - mbind("Middle", MC_Handle, MouseClick, lower_win) - - mbind("Left", MC_Titlebar, MouseDoubleClick, toggle_shade) - -def setup_window_buttons(): - """Sets up the default behaviors for the buttons in the window titlebar.""" - mbind("Left", MC_AllDesktopsButton, MouseClick, toggle_all_desktops) - mbind("Left", MC_CloseButton, MouseClick, close) - mbind("Left", MC_IconifyButton, MouseClick, iconify) - -def setup_scroll(): - """Sets up the default behaviors for the mouse scroll wheel. - This includes: - * scrolling on a window titlebar will shade/unshade it - * alt-scrolling anywhere will switch to the next/previous desktop - * control-alt-scrolling on a window will send it to the next/previous - desktop, and switch to the desktop with the window - """ - mbind("Up", MC_Titlebar, MouseClick, shade) - mbind("Down", MC_Titlebar, MouseClick, unshade) - - mbind("A-Up", MC_Frame, MouseClick, next_desktop) - mbind("A-Up", MC_Root, MouseClick, next_desktop) - mbind("A-Down", MC_Frame, MouseClick, prev_desktop) - mbind("A-Down", MC_Root, MouseClick, prev_desktop) - - mbind("C-A-Up", MC_Frame, MouseClick, send_to_next_desktop) - mbind("C-A-Down", MC_Frame, MouseClick, send_to_prev_desktop) - -def setup_fallback_focus(): - """Sets up a focus fallback routine so that when no windows are focused, - the last window to have focus on the desktop will be focused.""" - global ob_focus_fallback # see focus.py - ob_focus_fallback = 1 - -############################################################################ -### Window placement algorithms, choose one of these and ebind it to the ### -### EventPlaceWindow action. ### -############################################################################ - -ob_rand = None -import random -def placewindows_random(data): - if not data.client: return - client_area = data.client.area() - frame_size = data.client.frame.size() - screen_area = openbox.screen(data.screen).area() - width = screen_area.width() - (client_area.width() + - frame_size.left + frame_size.right) - height = screen_area.height() - (client_area.height() + - frame_size.top + frame_size.bottom) - global ob_rand - if not ob_rand: ob_rand = random.Random() - x = ob_rand.randrange(screen_area.x(), width-1) - y = ob_rand.randrange(screen_area.y(), height-1) - data.client.move(x, y) - print "Loaded builtins.py" diff --git a/scripts/defaults.py b/scripts/defaults.py index f7f444d5..6bb776ea 100644 --- a/scripts/defaults.py +++ b/scripts/defaults.py @@ -1,36 +1,43 @@ +import focus # add some default focus handling and cycling functions +import focusmodel # default focus models +import behavior # defines default behaviors for interaction with windows +import callbacks # a lib of functions that can be used as binding callbacks +import windowplacement # use a routine in here to place windows + +# try focus something when nothing is focused +focus.fallback = 1 + # set up the mouse buttons -setup_sloppy_focus() -setup_window_clicks() -setup_window_buttons() -setup_scroll() -# set up focus fallback so im not left with nothing focused all the time -setup_fallback_focus() +focusmodel.setup_sloppy_focus() +behavior.setup_window_clicks() +behavior.setup_window_buttons() +behavior.setup_scroll() # my window placement algorithm -ebind(EventPlaceWindow, placewindows_random) +ob.ebind(ob.EventAction.PlaceWindow, windowplacement.random) # run xterm from root clicks -mbind("Left", MC_Root, MouseClick, lambda(d): execute("xterm")) +ob.mbind("Left", ob.MouseContext.Root, ob.MouseAction.Click, + lambda(d): ob.execute("xterm", d.screen)) -kbind(["A-F4"], KC_All, close) +ob.kbind(["A-F4"], ob.KeyContext.All, callbacks.close) # desktop changing bindings -kbind(["C-1"], KC_All, lambda(d): change_desktop(d, 0)) -kbind(["C-2"], KC_All, lambda(d): change_desktop(d, 1)) -kbind(["C-3"], KC_All, lambda(d): change_desktop(d, 2)) -kbind(["C-4"], KC_All, lambda(d): change_desktop(d, 3)) -kbind(["C-A-Right"], KC_All, lambda(d): next_desktop(d)) -kbind(["C-A-Left"], KC_All, lambda(d): prev_desktop(d)) - -kbind(["C-S-A-Right"], KC_All, lambda(d): send_to_next_desktop(d)) -kbind(["C-S-A-Left"], KC_All, lambda(d): send_to_prev_desktop(d)) +ob.kbind(["C-1"], ob.KeyContext.All, lambda(d): callbacks.change_desktop(d, 0)) +ob.kbind(["C-2"], ob.KeyContext.All, lambda(d): callbacks.change_desktop(d, 1)) +ob.kbind(["C-3"], ob.KeyContext.All, lambda(d): callbacks.change_desktop(d, 2)) +ob.kbind(["C-4"], ob.KeyContext.All, lambda(d): callbacks.change_desktop(d, 3)) +ob.kbind(["C-A-Right"], ob.KeyContext.All, + lambda(d): callbacks.next_desktop(d)) +ob.kbind(["C-A-Left"], ob.KeyContext.All, + lambda(d): callbacks.prev_desktop(d)) + +ob.kbind(["C-S-A-Right"], ob.KeyContext.All, + lambda(d): callbacks.send_to_next_desktop(d)) +ob.kbind(["C-S-A-Left"], ob.KeyContext.All, + lambda(d): callbacks.send_to_prev_desktop(d)) # focus new windows -def focusnew(data): - if not data.client: return - if data.client.normal(): - focus(data) - -ebind(EventNewWindow, focusnew) +ob.ebind(ob.EventAction.NewWindow, callbacks.focus) print "Loaded defaults.py" diff --git a/scripts/focus.py b/scripts/focus.py index 011fcc5b..3ea42edc 100644 --- a/scripts/focus.py +++ b/scripts/focus.py @@ -2,131 +2,150 @@ ### Functions for helping out with your window focus. ### ########################################################################### -# raise the window also when it is focused -ob_focus_raise = 1 -# send focus somewhere when nothing is left with the focus if possible -ob_focus_fallback = 0 +########################################################################### +### 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 -ob_clients = [] +_clients = [] # maintaint he current focused window -ob_doing_stacked = 0 +_doing_stacked = 0 -def ob_new_win(data): - global ob_clients - global ob_doing_stacked - global ob_cyc_w; +def _new_win(data): + global _clients + global _doing_stacked + global _cyc_w; - if ob_doing_stacked: - ob_clients.insert(ob_clients.index(ob_cyc_w), data.client.window()) + if _doing_stacked: + _clients.insert(_clients.index(_cyc_w), data.client.window()) else: - if not len(ob_clients): - ob_clients.append(data.client.window()) + if not len(_clients): + _clients.append(data.client.window()) else: - ob_clients.insert(1, data.client.window()) # insert in 2nd slot + _clients.insert(1, data.client.window()) # insert in 2nd slot -def ob_close_win(data): - global ob_clients - global ob_cyc_w; - global ob_doing_stacked +def _close_win(data): + global _clients + global _cyc_w; + global _doing_stacked - if not ob_doing_stacked: + if not _doing_stacked: # not in the middle of stacked cycling, so who cares - ob_clients.remove(data.client.window()) + _clients.remove(data.client.window()) else: # have to fix the cycling if we remove anything win = data.client.window() - if ob_cyc_w == win: - do_stacked_cycle(data) # cycle off the window first - ob_clients.remove(win) - -def ob_focused(data): - global ob_clients - global ob_doing_stacked - global ob_cyc_w + 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: - if not ob_doing_stacked: # only move the window when we're not cycling + if not _doing_stacked: # only move the window when we're not cycling win = data.client.window() # move it to the top - ob_clients.remove(win) - ob_clients.insert(0, win) + _clients.remove(win) + _clients.insert(0, win) else: # if we are cycling, then update our pointer - ob_cyc_w = data.client.window() - elif ob_focus_fallback: + _cyc_w = data.client.window() + elif fallback: # pass around focus - desktop = openbox.screen(ob_cyc_screen).desktop() - for w in ob_clients: - client = openbox.findClient(w) + 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 -ebind(EventNewWindow, ob_new_win) -ebind(EventCloseWindow, ob_close_win) -ebind(EventFocus, ob_focused) +_cyc_mask = 0 +_cyc_key = 0 +_cyc_w = 0 # last window cycled to +_cyc_screen = 0 -ob_cyc_mask = 0 -ob_cyc_key = 0 -ob_cyc_w = 0 # last window cycled to -ob_cyc_screen = 0 +def _do_stacked_cycle(data, forward): + global _cyc_w + global stacked_cycle_raise + global _clients -def do_stacked_cycle(data): - global ob_cyc_w + clients = _clients[:] # make a copy + + if not forward: + clients.reverse() try: - i = ob_clients.index(ob_cyc_w) + 1 + i = clients.index(_cyc_w) + 1 except ValueError: - i = 0 + i = 1 + clients = clients[i:] + clients[:i] - clients = ob_clients[i:] + ob_clients[:i] + desktop = ob.openbox.screen(data.screen).desktop() for w in clients: - client = openbox.findClient(w) + 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_next_stacked_grab(data): - global ob_cyc_mask; - global ob_cyc_key; - global ob_cyc_w; - global ob_doing_stacked; +def _focus_stacked_ungrab(data): + global _cyc_mask; + global _cyc_key; + global _doing_stacked; - if data.action == EventKeyRelease: + if data.action == ob.KeyAction.Release: # have all the modifiers this started with been released? - if not ob_cyc_mask & data.state: - kungrab() # ungrab ourself - ob_doing_stacked = 0; - print "UNGRABBED!" - else: - if ob_cyc_key == data.key: - # the next window to try focusing in ob_clients[ob_cyc_i] - print "CYCLING!!" - do_stacked_cycle(data) + 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): - global ob_cyc_mask - global ob_cyc_key - global ob_cyc_w - global ob_cyc_screen - global ob_doing_stacked - ob_cyc_mask = data.state - ob_cyc_key = data.key - ob_cyc_w = 0 - ob_cyc_screen = data.screen - ob_doing_stacked = 1 - - kgrab(data.screen, focus_next_stacked_grab) - print "GRABBED!" - focus_next_stacked_grab(data) # start with the first press + """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): - return + """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 @@ -156,7 +175,7 @@ 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: @@ -172,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" |
