summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Makefile.am3
-rw-r--r--scripts/builtins.py332
-rw-r--r--scripts/defaults.py55
-rw-r--r--scripts/focus.py187
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"