new/better/cleaner scripting interface
This commit is contained in:
parent
02d6362111
commit
997f94cf86
16 changed files with 349 additions and 641 deletions
|
@ -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:
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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))
|
||||
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))
|
||||
|
||||
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-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"
|
||||
|
|
183
scripts/focus.py
183
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)
|
||||
if _cyc_w == win:
|
||||
_do_stacked_cycle(data) # cycle off the window first
|
||||
_clients.remove(win)
|
||||
|
||||
def ob_focused(data):
|
||||
global ob_clients
|
||||
global ob_doing_stacked
|
||||
global ob_cyc_w
|
||||
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
|
||||
"""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
|
||||
|
||||
kgrab(data.screen, focus_next_stacked_grab)
|
||||
print "GRABBED!"
|
||||
focus_next_stacked_grab(data) # start with the first press
|
||||
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"
|
||||
|
|
|
@ -23,7 +23,7 @@ openbox3_SOURCES= actions.cc client.cc frame.cc openbox.cc screen.cc \
|
|||
openbox_wrap.cc
|
||||
openbox3_LDFLAGS= $(PYTHON_LDFLAGS)
|
||||
|
||||
script_DATA = openbox.py
|
||||
script_DATA = ob.py
|
||||
|
||||
EXTRA_DIST = $(script_DATA)
|
||||
|
||||
|
|
|
@ -88,14 +88,14 @@ void Actions::buttonPressHandler(const XButtonEvent &e)
|
|||
else
|
||||
screen = otk::display->findScreen(e.root)->screen();
|
||||
MouseData data(screen, c, e.time, state, e.button, w->mcontext(),
|
||||
MousePress);
|
||||
MouseAction::Press);
|
||||
openbox->bindings()->fireButton(&data);
|
||||
|
||||
if (_button) return; // won't count toward CLICK events
|
||||
|
||||
_button = e.button;
|
||||
|
||||
if (w->mcontext() == MC_Window) {
|
||||
if (w->mcontext() == MouseContext::Window) {
|
||||
/*
|
||||
Because of how events are grabbed on the client window, we can't get
|
||||
ButtonRelease events, so instead we simply manufacture them here, so that
|
||||
|
@ -143,7 +143,7 @@ void Actions::buttonReleaseHandler(const XButtonEvent &e)
|
|||
else
|
||||
screen = otk::display->findScreen(e.root)->screen();
|
||||
MouseData data(screen, c, e.time, state, e.button, w->mcontext(),
|
||||
MouseClick);
|
||||
MouseAction::Click);
|
||||
openbox->bindings()->fireButton(&data);
|
||||
|
||||
|
||||
|
@ -156,7 +156,7 @@ void Actions::buttonReleaseHandler(const XButtonEvent &e)
|
|||
_release.win == e.window && _release.button == e.button) {
|
||||
|
||||
// run the DOUBLECLICK python hook
|
||||
data.action = MouseDoubleClick;
|
||||
data.action = MouseAction::DoubleClick;
|
||||
openbox->bindings()->fireButton(&data);
|
||||
|
||||
// reset so you cant triple click for 2 doubleclicks
|
||||
|
@ -183,7 +183,7 @@ void Actions::enterHandler(const XCrossingEvent &e)
|
|||
screen = c->screen();
|
||||
else
|
||||
screen = otk::display->findScreen(e.root)->screen();
|
||||
EventData data(screen, c, EventEnterWindow, e.state);
|
||||
EventData data(screen, c, EventAction::EnterWindow, e.state);
|
||||
openbox->bindings()->fireEvent(&data);
|
||||
}
|
||||
|
||||
|
@ -199,14 +199,13 @@ void Actions::leaveHandler(const XCrossingEvent &e)
|
|||
screen = c->screen();
|
||||
else
|
||||
screen = otk::display->findScreen(e.root)->screen();
|
||||
EventData data(screen, c, EventLeaveWindow, e.state);
|
||||
EventData data(screen, c, EventAction::LeaveWindow, e.state);
|
||||
openbox->bindings()->fireEvent(&data);
|
||||
}
|
||||
|
||||
|
||||
void Actions::keyPressHandler(const XKeyEvent &e)
|
||||
{
|
||||
printf("press\n");
|
||||
otk::EventHandler::keyPressHandler(e);
|
||||
|
||||
// kill off the Button1Mask etc, only want the modifiers
|
||||
|
@ -214,13 +213,12 @@ void Actions::keyPressHandler(const XKeyEvent &e)
|
|||
Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
|
||||
openbox->bindings()->
|
||||
fireKey(otk::display->findScreen(e.root)->screen(),
|
||||
state, e.keycode, e.time, EventKeyPress);
|
||||
state, e.keycode, e.time, KeyAction::Press);
|
||||
}
|
||||
|
||||
|
||||
void Actions::keyReleaseHandler(const XKeyEvent &e)
|
||||
{
|
||||
printf("release\n");
|
||||
otk::EventHandler::keyReleaseHandler(e);
|
||||
|
||||
// kill off the Button1Mask etc, only want the modifiers
|
||||
|
@ -248,7 +246,7 @@ void Actions::keyReleaseHandler(const XKeyEvent &e)
|
|||
|
||||
openbox->bindings()->
|
||||
fireKey(otk::display->findScreen(e.root)->screen(),
|
||||
state, e.keycode, e.time, EventKeyRelease);
|
||||
state, e.keycode, e.time, KeyAction::Release);
|
||||
}
|
||||
|
||||
|
||||
|
@ -301,8 +299,9 @@ void Actions::motionHandler(const XMotionEvent &e)
|
|||
screen = c->screen();
|
||||
else
|
||||
screen = otk::display->findScreen(e.root)->screen();
|
||||
MouseData data(screen, c, e.time, state, button, w->mcontext(), MouseMotion,
|
||||
x_root, y_root, _posqueue[0]->pos, _posqueue[0]->clientarea);
|
||||
MouseData data(screen, c, e.time, state, button, w->mcontext(),
|
||||
MouseAction::Motion, x_root, y_root,
|
||||
_posqueue[0]->pos, _posqueue[0]->clientarea);
|
||||
openbox->bindings()->fireButton(&data);
|
||||
}
|
||||
|
||||
|
@ -322,7 +321,7 @@ void Actions::xkbHandler(const XkbEvent &e)
|
|||
screen = c->screen();
|
||||
else
|
||||
screen = openbox->focusedScreen()->number();
|
||||
EventData data(screen, c, EventBell, 0);
|
||||
EventData data(screen, c, EventAction::Bell, 0);
|
||||
openbox->bindings()->fireEvent(&data);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -344,7 +344,9 @@ void Bindings::removeAllKeys()
|
|||
|
||||
void Bindings::grabKeys(bool grab)
|
||||
{
|
||||
for (int i = 0; i < openbox->screenCount(); ++i) {
|
||||
for (int i = 0; i < ScreenCount(**otk::display); ++i) {
|
||||
Screen *sc = openbox->screen(i);
|
||||
if (!sc) continue; // not a managed screen
|
||||
Window root = otk::display->screenInfo(i)->rootWindow();
|
||||
|
||||
KeyBindingTree *p = _curpos->first_child;
|
||||
|
@ -377,18 +379,13 @@ bool Bindings::grabKeyboard(int screen, PyObject *callback)
|
|||
assert(callback);
|
||||
if (_keybgrab_callback) return false; // already grabbed
|
||||
|
||||
int i;
|
||||
for (i = 0; i < openbox->screenCount(); ++i)
|
||||
if (openbox->screen(screen)->number() == screen)
|
||||
break;
|
||||
if (i >= openbox->screenCount())
|
||||
return false; // couldn't find the screen.. it's not managed
|
||||
if (!openbox->screen(screen))
|
||||
return false; // the screen is not managed
|
||||
|
||||
Window root = otk::display->screenInfo(i)->rootWindow();
|
||||
Window root = otk::display->screenInfo(screen)->rootWindow();
|
||||
if (XGrabKeyboard(**otk::display, root, false, GrabModeAsync,
|
||||
GrabModeSync, CurrentTime))
|
||||
GrabModeAsync, CurrentTime))
|
||||
return false;
|
||||
printf("****GRABBED****\n");
|
||||
_keybgrab_callback = callback;
|
||||
return true;
|
||||
}
|
||||
|
@ -400,20 +397,20 @@ void Bindings::ungrabKeyboard()
|
|||
|
||||
_keybgrab_callback = 0;
|
||||
XUngrabKeyboard(**otk::display, CurrentTime);
|
||||
printf("****UNGRABBED****\n");
|
||||
}
|
||||
|
||||
|
||||
void Bindings::fireKey(int screen, unsigned int modifiers, unsigned int key,
|
||||
Time time, KeyAction action)
|
||||
Time time, KeyAction::KA action)
|
||||
{
|
||||
if (_keybgrab_callback) {
|
||||
Client *c = openbox->focusedClient();
|
||||
KeyData data(screen, c, time, modifiers, key, action);
|
||||
python_callback(_keybgrab_callback, &data);
|
||||
} else {
|
||||
}
|
||||
|
||||
// KeyRelease events only occur during keyboard grabs
|
||||
if (action == EventKeyRelease) return;
|
||||
if (action == KeyAction::Release) return;
|
||||
|
||||
if (key == _resetkey.key && modifiers == _resetkey.modifiers) {
|
||||
resetChains(this);
|
||||
|
@ -446,7 +443,6 @@ void Bindings::fireKey(int screen, unsigned int modifiers, unsigned int key,
|
|||
p = p->next_sibling;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Bindings::resetChains(Bindings *self)
|
||||
|
@ -464,10 +460,10 @@ void Bindings::resetChains(Bindings *self)
|
|||
}
|
||||
|
||||
|
||||
bool Bindings::addButton(const std::string &but, MouseContext context,
|
||||
MouseAction action, PyObject *callback)
|
||||
bool Bindings::addButton(const std::string &but, MouseContext::MC context,
|
||||
MouseAction::MA action, PyObject *callback)
|
||||
{
|
||||
assert(context >= 0 && context < NUM_MOUSE_CONTEXT);
|
||||
assert(context >= 0 && context < MouseContext::NUM_MOUSE_CONTEXT);
|
||||
|
||||
Binding b(0,0);
|
||||
if (!translate(but, b, false))
|
||||
|
@ -491,8 +487,9 @@ bool Bindings::addButton(const std::string &but, MouseContext context,
|
|||
bind->binding.modifiers = b.modifiers;
|
||||
_buttons[context].push_back(bind);
|
||||
// grab the button on all clients
|
||||
for (int sn = 0; sn < openbox->screenCount(); ++sn) {
|
||||
for (int sn = 0; sn < ScreenCount(**otk::display); ++sn) {
|
||||
Screen *s = openbox->screen(sn);
|
||||
if (!s) continue; // not managed
|
||||
Client::List::iterator c_it, c_end = s->clients.end();
|
||||
for (c_it = s->clients.begin(); c_it != c_end; ++c_it) {
|
||||
grabButton(true, bind->binding, context, *c_it);
|
||||
|
@ -507,39 +504,40 @@ bool Bindings::addButton(const std::string &but, MouseContext context,
|
|||
|
||||
void Bindings::removeAllButtons()
|
||||
{
|
||||
for (int i = 0; i < NUM_MOUSE_CONTEXT; ++i) {
|
||||
for (int i = 0; i < MouseContext::NUM_MOUSE_CONTEXT; ++i) {
|
||||
ButtonBindingList::iterator it, end = _buttons[i].end();
|
||||
for (it = _buttons[i].begin(); it != end; ++it) {
|
||||
for (int a = 0; a < NUM_MOUSE_ACTION; ++a) {
|
||||
for (int a = 0; a < MouseAction::NUM_MOUSE_ACTION; ++a) {
|
||||
while (!(*it)->callbacks[a].empty()) {
|
||||
Py_XDECREF((*it)->callbacks[a].front());
|
||||
(*it)->callbacks[a].pop_front();
|
||||
}
|
||||
}
|
||||
// ungrab the button on all clients
|
||||
for (int sn = 0; sn < openbox->screenCount(); ++sn) {
|
||||
for (int sn = 0; sn < ScreenCount(**otk::display); ++sn) {
|
||||
Screen *s = openbox->screen(sn);
|
||||
if (!s) continue; // not managed
|
||||
Client::List::iterator c_it, c_end = s->clients.end();
|
||||
for (c_it = s->clients.begin(); c_it != c_end; ++c_it) {
|
||||
grabButton(false, (*it)->binding, (MouseContext)i, *c_it);
|
||||
grabButton(false, (*it)->binding, (MouseContext::MC)i, *c_it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Bindings::grabButton(bool grab, const Binding &b, MouseContext context,
|
||||
Client *client)
|
||||
void Bindings::grabButton(bool grab, const Binding &b,
|
||||
MouseContext::MC context, Client *client)
|
||||
{
|
||||
Window win;
|
||||
int mode = GrabModeAsync;
|
||||
unsigned int mask;
|
||||
switch(context) {
|
||||
case MC_Frame:
|
||||
case MouseContext::Frame:
|
||||
win = client->frame->window();
|
||||
mask = ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
|
||||
break;
|
||||
case MC_Window:
|
||||
case MouseContext::Window:
|
||||
win = client->frame->plate();
|
||||
mode = GrabModeSync; // this is handled in fireButton
|
||||
mask = ButtonPressMask; // can't catch more than this with Sync mode
|
||||
|
@ -559,16 +557,16 @@ void Bindings::grabButton(bool grab, const Binding &b, MouseContext context,
|
|||
|
||||
void Bindings::grabButtons(bool grab, Client *client)
|
||||
{
|
||||
for (int i = 0; i < NUM_MOUSE_CONTEXT; ++i) {
|
||||
for (int i = 0; i < MouseContext::NUM_MOUSE_CONTEXT; ++i) {
|
||||
ButtonBindingList::iterator it, end = _buttons[i].end();
|
||||
for (it = _buttons[i].begin(); it != end; ++it)
|
||||
grabButton(grab, (*it)->binding, (MouseContext)i, client);
|
||||
grabButton(grab, (*it)->binding, (MouseContext::MC)i, client);
|
||||
}
|
||||
}
|
||||
|
||||
void Bindings::fireButton(MouseData *data)
|
||||
{
|
||||
if (data->context == MC_Window) {
|
||||
if (data->context == MouseContext::Window) {
|
||||
// Replay the event, so it goes to the client
|
||||
XAllowEvents(**otk::display, ReplayPointer, data->time);
|
||||
}
|
||||
|
@ -585,13 +583,13 @@ void Bindings::fireButton(MouseData *data)
|
|||
}
|
||||
|
||||
|
||||
bool Bindings::addEvent(EventAction action, PyObject *callback)
|
||||
bool Bindings::addEvent(EventAction::EA action, PyObject *callback)
|
||||
{
|
||||
if (action < 0 || action >= NUM_EVENTS) {
|
||||
if (action < 0 || action >= EventAction::NUM_EVENTS) {
|
||||
return false;
|
||||
}
|
||||
#ifdef XKB
|
||||
if (action == EventBell && _eventlist[action].empty())
|
||||
if (action == EventAction::Bell && _eventlist[action].empty())
|
||||
XkbSelectEvents(**otk::display, XkbUseCoreKbd,
|
||||
XkbBellNotifyMask, XkbBellNotifyMask);
|
||||
#endif // XKB
|
||||
|
@ -600,9 +598,9 @@ bool Bindings::addEvent(EventAction action, PyObject *callback)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Bindings::removeEvent(EventAction action, PyObject *callback)
|
||||
bool Bindings::removeEvent(EventAction::EA action, PyObject *callback)
|
||||
{
|
||||
if (action < 0 || action >= NUM_EVENTS) {
|
||||
if (action < 0 || action >= EventAction::NUM_EVENTS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -613,7 +611,7 @@ bool Bindings::removeEvent(EventAction action, PyObject *callback)
|
|||
Py_XDECREF(*it);
|
||||
_eventlist[action].erase(it);
|
||||
#ifdef XKB
|
||||
if (action == EventBell && _eventlist[action].empty())
|
||||
if (action == EventAction::Bell && _eventlist[action].empty())
|
||||
XkbSelectEvents(**otk::display, XkbUseCoreKbd,
|
||||
XkbBellNotifyMask, 0);
|
||||
#endif // XKB
|
||||
|
@ -624,7 +622,7 @@ bool Bindings::removeEvent(EventAction action, PyObject *callback)
|
|||
|
||||
void Bindings::removeAllEvents()
|
||||
{
|
||||
for (int i = 0; i < NUM_EVENTS; ++i) {
|
||||
for (int i = 0; i < EventAction::NUM_EVENTS; ++i) {
|
||||
while (!_eventlist[i].empty()) {
|
||||
Py_XDECREF(_eventlist[i].front());
|
||||
_eventlist[i].pop_front();
|
||||
|
|
|
@ -51,7 +51,7 @@ typedef struct KeyBindingTree {
|
|||
|
||||
typedef struct ButtonBinding {
|
||||
Binding binding;
|
||||
CallbackList callbacks[NUM_MOUSE_ACTION];
|
||||
CallbackList callbacks[MouseAction::NUM_MOUSE_ACTION];
|
||||
ButtonBinding() : binding(0, 0) {}
|
||||
};
|
||||
|
||||
|
@ -77,12 +77,12 @@ private:
|
|||
static void resetChains(Bindings *self); // the timer's timeout function
|
||||
|
||||
typedef std::list <ButtonBinding*> ButtonBindingList;
|
||||
ButtonBindingList _buttons[NUM_MOUSE_CONTEXT];
|
||||
ButtonBindingList _buttons[MouseContext::NUM_MOUSE_CONTEXT];
|
||||
|
||||
void grabButton(bool grab, const Binding &b, MouseContext context,
|
||||
void grabButton(bool grab, const Binding &b, MouseContext::MC context,
|
||||
Client *client);
|
||||
|
||||
CallbackList _eventlist[NUM_EVENTS];
|
||||
CallbackList _eventlist[EventAction::NUM_EVENTS];
|
||||
|
||||
PyObject *_keybgrab_callback;
|
||||
|
||||
|
@ -114,7 +114,7 @@ public:
|
|||
void removeAllKeys();
|
||||
|
||||
void fireKey(int screen, unsigned int modifiers,unsigned int key, Time time,
|
||||
KeyAction action);
|
||||
KeyAction::KA action);
|
||||
|
||||
void setResetKey(const std::string &key);
|
||||
|
||||
|
@ -123,8 +123,8 @@ public:
|
|||
bool grabKeyboard(int screen, PyObject *callback);
|
||||
void ungrabKeyboard();
|
||||
|
||||
bool addButton(const std::string &but, MouseContext context,
|
||||
MouseAction action, PyObject *callback);
|
||||
bool addButton(const std::string &but, MouseContext::MC context,
|
||||
MouseAction::MA action, PyObject *callback);
|
||||
|
||||
void grabButtons(bool grab, Client *client);
|
||||
|
||||
|
@ -134,10 +134,10 @@ public:
|
|||
void fireButton(MouseData *data);
|
||||
|
||||
//! Bind a callback for an event
|
||||
bool addEvent(EventAction action, PyObject *callback);
|
||||
bool addEvent(EventAction::EA action, PyObject *callback);
|
||||
|
||||
//! Unbind the callback function from an event
|
||||
bool removeEvent(EventAction action, PyObject *callback);
|
||||
bool removeEvent(EventAction::EA action, PyObject *callback);
|
||||
|
||||
//! Remove all callback functions
|
||||
void removeAllEvents();
|
||||
|
|
|
@ -133,7 +133,7 @@ void Client::getDesktop()
|
|||
otk::Property::atoms.cardinal,
|
||||
(long unsigned*)&_desktop)) {
|
||||
#ifdef DEBUG
|
||||
printf("DEBUG: Window requested desktop: %ld\n", _desktop);
|
||||
// printf("Window requested desktop: %ld\n", _desktop);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1181,7 +1181,6 @@ void Client::applyStartupState()
|
|||
// these are in a carefully crafted order..
|
||||
|
||||
if (_iconic) {
|
||||
printf("MAP ICONIC\n");
|
||||
_iconic = false;
|
||||
setDesktop(ICONIC_DESKTOP);
|
||||
}
|
||||
|
@ -1210,7 +1209,7 @@ void Client::applyStartupState()
|
|||
void Client::fireUrgent()
|
||||
{
|
||||
// call the python UrgentWindow callbacks
|
||||
EventData data(_screen, this, EventUrgentWindow, 0);
|
||||
EventData data(_screen, this, EventAction::UrgentWindow, 0);
|
||||
openbox->bindings()->fireEvent(&data);
|
||||
}
|
||||
|
||||
|
|
|
@ -147,24 +147,28 @@ Openbox::Openbox(int argc, char **argv)
|
|||
python_init(argv[0]);
|
||||
|
||||
// load config values
|
||||
python_exec(SCRIPTDIR"/config.py"); // load openbox config values
|
||||
//python_exec(SCRIPTDIR"/config.py"); // load openbox config values
|
||||
// run all of the python scripts
|
||||
python_exec(SCRIPTDIR"/builtins.py"); // builtin callbacks
|
||||
python_exec(SCRIPTDIR"/focus.py"); // focus helpers
|
||||
//python_exec(SCRIPTDIR"/builtins.py"); // builtin callbacks
|
||||
//python_exec(SCRIPTDIR"/focus.py"); // focus helpers
|
||||
// run the user's script or the system defaults if that fails
|
||||
if (!python_exec(_scriptfilepath.c_str()))
|
||||
python_exec(SCRIPTDIR"/defaults.py"); // system default bahaviors
|
||||
|
||||
// initialize all the screens
|
||||
for (int i = 0, max = ScreenCount(**otk::display); i < max; ++i) {
|
||||
Screen *screen;
|
||||
int i = _single ? DefaultScreen(**otk::display) : 0;
|
||||
int max = _single ? i + 1 : ScreenCount(**otk::display);
|
||||
for (; i < max; ++i) {
|
||||
if (_single && i != DefaultScreen(**otk::display)) {
|
||||
_screens.push_back(0);
|
||||
continue;
|
||||
}
|
||||
screen = new Screen(i);
|
||||
if (screen->managed())
|
||||
_screens.push_back(screen);
|
||||
else
|
||||
else {
|
||||
delete screen;
|
||||
_screens.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (_screens.empty()) {
|
||||
|
@ -390,16 +394,9 @@ void Openbox::setFocusedClient(Client *c)
|
|||
}
|
||||
|
||||
// call the python Focus callbacks
|
||||
EventData data(_focused_screen->number(), c, EventFocus, 0);
|
||||
EventData data(_focused_screen->number(), c, EventAction::Focus, 0);
|
||||
_bindings->fireEvent(&data);
|
||||
}
|
||||
|
||||
void Openbox::execute(int screen, const std::string &bin)
|
||||
{
|
||||
if (screen >= ScreenCount(**otk::display))
|
||||
screen = 0;
|
||||
otk::bexec(bin, otk::display->screenInfo(screen)->displayString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -174,19 +174,17 @@ public:
|
|||
//! Returns the Bindings instance for the window manager
|
||||
inline Bindings *bindings() const { return _bindings; }
|
||||
|
||||
//! Returns a managed screen
|
||||
//! Returns a managed screen or a null pointer
|
||||
/*!
|
||||
ALWAYS check the return value for a non-null, as any unmanaged screens
|
||||
will return one. This includes screen(0) if the first managed screen is 1.
|
||||
*/
|
||||
inline Screen *screen(int num) {
|
||||
assert(num >= 0); assert(num < (signed)_screens.size());
|
||||
if (num < 0 || num >= screenCount())
|
||||
return NULL;
|
||||
assert(num >= 0); assert(num < (signed)ScreenCount(**otk::display));
|
||||
if (num >= (signed)_screens.size()) return 0;
|
||||
return _screens[num];
|
||||
}
|
||||
|
||||
//! Returns the number of managed screens
|
||||
inline int screenCount() const {
|
||||
return (signed)_screens.size();
|
||||
}
|
||||
|
||||
//! Returns the mouse cursors used throughout Openbox
|
||||
inline const Cursors &cursors() const { return _cursors; }
|
||||
|
||||
|
@ -231,9 +229,6 @@ public:
|
|||
inline void restart(const std::string &bin = "") {
|
||||
_shutdown = true; _restart = true; _restart_prog = bin;
|
||||
}
|
||||
|
||||
//! Executes a command on a screen
|
||||
void execute(int screen, const std::string &bin);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
|
||||
|
||||
%module openbox
|
||||
%module ob
|
||||
|
||||
%{
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
extern "C" {
|
||||
// The initializer in openbox_wrap.cc
|
||||
extern void init_openbox(void);
|
||||
extern void init_ob(void);
|
||||
}
|
||||
|
||||
namespace ob {
|
||||
|
@ -23,21 +23,20 @@ void python_init(char *argv0)
|
|||
Py_SetProgramName(argv0);
|
||||
Py_Initialize();
|
||||
// initialize the C python module
|
||||
init_openbox();
|
||||
init_ob();
|
||||
// include the openbox directories for python scripts in the sys path
|
||||
PyRun_SimpleString("import sys");
|
||||
PyRun_SimpleString("sys.path.append('" SCRIPTDIR "')");
|
||||
PyRun_SimpleString(const_cast<char*>(("sys.path.append('" +
|
||||
otk::expandTilde("~/.openbox/python") +
|
||||
"')").c_str()));
|
||||
// import the otk and openbox modules into the main namespace
|
||||
PyRun_SimpleString("from openbox import *;");
|
||||
PyRun_SimpleString("sys.path.append('" SCRIPTDIR "')");
|
||||
PyRun_SimpleString("import ob;");
|
||||
// set up convenience global variables
|
||||
PyRun_SimpleString("openbox = Openbox_instance()");
|
||||
PyRun_SimpleString("display = Display_instance()");
|
||||
PyRun_SimpleString("ob.openbox = ob.Openbox_instance()");
|
||||
PyRun_SimpleString("ob.display = ob.Display_instance()");
|
||||
|
||||
// set up access to the python global variables
|
||||
PyObject *obmodule = PyImport_AddModule("__main__");
|
||||
PyObject *obmodule = PyImport_AddModule("config");
|
||||
obdict = PyModule_GetDict(obmodule);
|
||||
}
|
||||
|
||||
|
@ -93,8 +92,8 @@ bool python_get_stringlist(const char *name, std::vector<otk::ustring> *value)
|
|||
// Stuff for calling from Python scripts //
|
||||
// ************************************* //
|
||||
|
||||
PyObject *mbind(const std::string &button, ob::MouseContext context,
|
||||
ob::MouseAction action, PyObject *func)
|
||||
PyObject *mbind(const std::string &button, ob::MouseContext::MC context,
|
||||
ob::MouseAction::MA action, PyObject *func)
|
||||
{
|
||||
if (!PyCallable_Check(func)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Invalid callback function.");
|
||||
|
@ -109,7 +108,7 @@ PyObject *mbind(const std::string &button, ob::MouseContext context,
|
|||
Py_INCREF(Py_None); return Py_None;
|
||||
}
|
||||
|
||||
PyObject *ebind(ob::EventAction action, PyObject *func)
|
||||
PyObject *ebind(ob::EventAction::EA action, PyObject *func)
|
||||
{
|
||||
if (!PyCallable_Check(func)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Invalid callback function.");
|
||||
|
@ -143,7 +142,7 @@ PyObject *kungrab()
|
|||
Py_INCREF(Py_None); return Py_None;
|
||||
}
|
||||
|
||||
PyObject *kbind(PyObject *keylist, ob::KeyContext context, PyObject *func)
|
||||
PyObject *kbind(PyObject *keylist, ob::KeyContext::KC context, PyObject *func)
|
||||
{
|
||||
if (!PyCallable_Check(func)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Invalid callback function.");
|
||||
|
@ -233,4 +232,11 @@ PyObject *send_client_msg(Window target, Atom type, Window about,
|
|||
Py_INCREF(Py_None); return Py_None;
|
||||
}
|
||||
|
||||
void execute(const std::string &bin, int screen)
|
||||
{
|
||||
if (screen >= ScreenCount(**otk::display))
|
||||
screen = 0;
|
||||
otk::bexec(bin, otk::display->screenInfo(screen)->displayString());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
111
src/python.hh
111
src/python.hh
|
@ -24,53 +24,63 @@ namespace ob {
|
|||
|
||||
class Client;
|
||||
|
||||
enum MouseContext {
|
||||
MC_Frame,
|
||||
MC_Titlebar,
|
||||
MC_Handle,
|
||||
MC_Window,
|
||||
MC_MaximizeButton,
|
||||
MC_CloseButton,
|
||||
MC_IconifyButton,
|
||||
MC_AllDesktopsButton,
|
||||
MC_Grip,
|
||||
MC_Root,
|
||||
MC_MenuItem,
|
||||
struct MouseContext {
|
||||
enum MC {
|
||||
Frame,
|
||||
Titlebar,
|
||||
Handle,
|
||||
Window,
|
||||
MaximizeButton,
|
||||
CloseButton,
|
||||
IconifyButton,
|
||||
AllDesktopsButton,
|
||||
Grip,
|
||||
Root,
|
||||
MenuItem,
|
||||
NUM_MOUSE_CONTEXT
|
||||
};
|
||||
};
|
||||
|
||||
enum MouseAction {
|
||||
MousePress,
|
||||
MouseClick,
|
||||
MouseDoubleClick,
|
||||
MouseMotion,
|
||||
struct MouseAction {
|
||||
enum MA {
|
||||
Press,
|
||||
Click,
|
||||
DoubleClick,
|
||||
Motion,
|
||||
NUM_MOUSE_ACTION
|
||||
};
|
||||
};
|
||||
|
||||
enum KeyContext {
|
||||
KC_Menu,
|
||||
KC_All,
|
||||
struct KeyContext {
|
||||
enum KC {
|
||||
Menu,
|
||||
All,
|
||||
NUM_KEY_CONTEXT
|
||||
};
|
||||
};
|
||||
|
||||
enum KeyAction {
|
||||
EventKeyPress,
|
||||
EventKeyRelease,
|
||||
struct KeyAction {
|
||||
enum KA {
|
||||
Press,
|
||||
Release,
|
||||
NUM_KEY_ACTION
|
||||
};
|
||||
};
|
||||
|
||||
enum EventAction {
|
||||
EventEnterWindow,
|
||||
EventLeaveWindow,
|
||||
EventPlaceWindow,
|
||||
EventNewWindow,
|
||||
EventCloseWindow,
|
||||
EventStartup,
|
||||
EventShutdown,
|
||||
EventFocus,
|
||||
EventBell,
|
||||
EventUrgentWindow,
|
||||
struct EventAction {
|
||||
enum EA {
|
||||
EnterWindow,
|
||||
LeaveWindow,
|
||||
PlaceWindow,
|
||||
NewWindow,
|
||||
CloseWindow,
|
||||
Startup,
|
||||
Shutdown,
|
||||
Focus,
|
||||
Bell,
|
||||
UrgentWindow,
|
||||
NUM_EVENTS
|
||||
};
|
||||
};
|
||||
|
||||
class MouseData {
|
||||
|
@ -80,8 +90,8 @@ public:
|
|||
Time time;
|
||||
unsigned int state;
|
||||
unsigned int button;
|
||||
MouseContext context;
|
||||
MouseAction action;
|
||||
MouseContext::MC context;
|
||||
MouseAction::MA action;
|
||||
int xroot;
|
||||
int yroot;
|
||||
int pressx;
|
||||
|
@ -92,9 +102,9 @@ public:
|
|||
int press_clientheight;
|
||||
|
||||
MouseData(int screen, Client *client, Time time, unsigned int state,
|
||||
unsigned int button, MouseContext context, MouseAction action,
|
||||
int xroot, int yroot, const otk::Point &initpos,
|
||||
const otk::Rect &initarea) {
|
||||
unsigned int button, MouseContext::MC context,
|
||||
MouseAction::MA action, int xroot, int yroot,
|
||||
const otk::Point &initpos, const otk::Rect &initarea) {
|
||||
this->screen = screen;
|
||||
this->client = client;
|
||||
this->time = time;
|
||||
|
@ -112,7 +122,8 @@ public:
|
|||
this->press_clientheight = initarea.height();
|
||||
}
|
||||
MouseData(int screen, Client *client, Time time, unsigned int state,
|
||||
unsigned int button, MouseContext context, MouseAction action) {
|
||||
unsigned int button, MouseContext::MC context,
|
||||
MouseAction::MA action) {
|
||||
this->screen = screen;
|
||||
this->client = client;
|
||||
this->time = time;
|
||||
|
@ -136,9 +147,9 @@ public:
|
|||
int screen;
|
||||
Client *client;
|
||||
unsigned int state;
|
||||
EventAction action;
|
||||
EventAction::EA action;
|
||||
|
||||
EventData(int screen, Client *client, EventAction action,
|
||||
EventData(int screen, Client *client, EventAction::EA action,
|
||||
unsigned int state) {
|
||||
this->screen = screen;
|
||||
this->client = client;
|
||||
|
@ -154,10 +165,10 @@ public:
|
|||
Time time;
|
||||
unsigned int state;
|
||||
char *key;
|
||||
KeyAction action;
|
||||
KeyAction::KA action;
|
||||
|
||||
KeyData(int screen, Client *client, Time time, unsigned int state,
|
||||
unsigned int key, KeyAction action) {
|
||||
unsigned int key, KeyAction::KA action) {
|
||||
this->screen = screen;
|
||||
this->client = client;
|
||||
this->time = time;
|
||||
|
@ -187,21 +198,25 @@ void python_callback(PyObject *func, KeyData *data);
|
|||
|
||||
#endif // SWIG
|
||||
|
||||
PyObject *mbind(const std::string &button, ob::MouseContext context,
|
||||
ob::MouseAction action, PyObject *func);
|
||||
PyObject *mbind(const std::string &button, ob::MouseContext::MC context,
|
||||
ob::MouseAction::MA action, PyObject *func);
|
||||
|
||||
PyObject *kbind(PyObject *keylist, ob::KeyContext context, PyObject *func);
|
||||
PyObject *kbind(PyObject *keylist, ob::KeyContext::KC context, PyObject *func);
|
||||
|
||||
PyObject *kgrab(int screen, PyObject *func);
|
||||
PyObject *kungrab();
|
||||
|
||||
PyObject *ebind(ob::EventAction action, PyObject *func);
|
||||
PyObject *ebind(ob::EventAction::EA action, PyObject *func);
|
||||
|
||||
void set_reset_key(const std::string &key);
|
||||
|
||||
PyObject *send_client_msg(Window target, Atom type, Window about,
|
||||
long data, long data1 = 0, long data2 = 0,
|
||||
long data3 = 0, long data4 = 0);
|
||||
|
||||
|
||||
void execute(const std::string &bin, int screen=0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ Screen::Screen(int screen)
|
|||
openbox->registerHandler(_info->rootWindow(), this);
|
||||
|
||||
// call the python Startup callbacks
|
||||
EventData data(_number, 0, EventShutdown, 0);
|
||||
EventData data(_number, 0, EventAction::Shutdown, 0);
|
||||
openbox->bindings()->fireEvent(&data);
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,7 @@ Screen::~Screen()
|
|||
unmanageWindow(clients.front());
|
||||
|
||||
// call the python Shutdown callbacks
|
||||
EventData data(_number, 0, EventShutdown, 0);
|
||||
EventData data(_number, 0, EventAction::Shutdown, 0);
|
||||
openbox->bindings()->fireEvent(&data);
|
||||
|
||||
XDestroyWindow(**otk::display, _focuswindow);
|
||||
|
@ -498,7 +498,7 @@ void Screen::manageWindow(Window window)
|
|||
client->positionRequested())) {
|
||||
// position the window intelligenty .. hopefully :)
|
||||
// call the python PLACEWINDOW binding
|
||||
EventData data(_number, client, EventPlaceWindow, 0);
|
||||
EventData data(_number, client, EventAction::PlaceWindow, 0);
|
||||
openbox->bindings()->fireEvent(&data);
|
||||
}
|
||||
|
||||
|
@ -523,7 +523,7 @@ void Screen::manageWindow(Window window)
|
|||
openbox->bindings()->grabButtons(true, client);
|
||||
|
||||
// call the python NEWWINDOW binding
|
||||
EventData data(_number, client, EventNewWindow, 0);
|
||||
EventData data(_number, client, EventAction::NewWindow, 0);
|
||||
openbox->bindings()->fireEvent(&data);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -538,7 +538,7 @@ void Screen::unmanageWindow(Client *client)
|
|||
Frame *frame = client->frame;
|
||||
|
||||
// call the python CLOSEWINDOW binding
|
||||
EventData data(_number, client, EventCloseWindow, 0);
|
||||
EventData data(_number, client, EventAction::CloseWindow, 0);
|
||||
openbox->bindings()->fireEvent(&data);
|
||||
|
||||
openbox->bindings()->grabButtons(false, client);
|
||||
|
|
|
@ -32,34 +32,34 @@ public:
|
|||
|
||||
inline WidgetType type() const { return _type; }
|
||||
|
||||
inline MouseContext mcontext() const {
|
||||
inline MouseContext::MC mcontext() const {
|
||||
switch (_type) {
|
||||
case Type_Frame:
|
||||
return MC_Frame;
|
||||
return MouseContext::Frame;
|
||||
case Type_Titlebar:
|
||||
return MC_Titlebar;
|
||||
return MouseContext::Titlebar;
|
||||
case Type_Handle:
|
||||
return MC_Handle;
|
||||
return MouseContext::Handle;
|
||||
case Type_Plate:
|
||||
return MC_Window;
|
||||
return MouseContext::Window;
|
||||
case Type_Label:
|
||||
return MC_Titlebar;
|
||||
return MouseContext::Titlebar;
|
||||
case Type_MaximizeButton:
|
||||
return MC_MaximizeButton;
|
||||
return MouseContext::MaximizeButton;
|
||||
case Type_CloseButton:
|
||||
return MC_CloseButton;
|
||||
return MouseContext::CloseButton;
|
||||
case Type_IconifyButton:
|
||||
return MC_IconifyButton;
|
||||
return MouseContext::IconifyButton;
|
||||
case Type_AllDesktopsButton:
|
||||
return MC_AllDesktopsButton;
|
||||
return MouseContext::AllDesktopsButton;
|
||||
case Type_LeftGrip:
|
||||
return MC_Grip;
|
||||
return MouseContext::Grip;
|
||||
case Type_RightGrip:
|
||||
return MC_Grip;
|
||||
return MouseContext::Grip;
|
||||
case Type_Client:
|
||||
return MC_Window;
|
||||
return MouseContext::Window;
|
||||
case Type_Root:
|
||||
return MC_Root;
|
||||
return MouseContext::Root;
|
||||
default:
|
||||
assert(false); // unhandled type
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue