new swig build system. much better. yay.

This commit is contained in:
Dana Jansens 2003-02-05 15:38:29 +00:00
parent ffea5b5591
commit 7c8c9e998f
21 changed files with 607 additions and 381 deletions

View file

@ -13,6 +13,8 @@ fi
AM_INIT_AUTOMAKE([openbox], [2.90.0cvs])
AC_PATH_PROG([awk_cmd], [awk]) # used by swig.m4
test "$awk_cmd" || AC_MSG_ERROR([awk not found])
AC_PATH_PROG([regex_cmd], [sed])
test "$regex_cmd" || AC_MSG_ERROR([sed not found])
@ -23,6 +25,11 @@ OB_DEBUG
OB_COMPILER_FLAGS
AC_C_BIGENDIAN
SWIG_PROG(1.3.14)
SWIG_ENABLE_CXX
SWIG_MULTI_MODULE_SUPPORT
SWIG_PYTHON
AC_PROG_LN_S
AC_PROG_LIBTOOL
LIBTOOL="$LIBTOOL --silent"
@ -32,8 +39,6 @@ ALL_LINGUAS=""
AM_GNU_GETTEXT_VERSION(0.11.5)
AM_GNU_GETTEXT([external])
PYTHON_DEVEL
AC_CHECK_HEADERS(ctype.h dirent.h fcntl.h libgen.h locale.h nl_types.h process.h signal.h stdarg.h stdint.h stdio.h stdlib.h string.h time.h unistd.h sys/param.h sys/select.h sys/signal.h sys/stat.h sys/time.h sys/types.h sys/wait.h)
AC_HEADER_TIME
# AC_TYPE_SIGNAL
@ -70,6 +75,7 @@ else
fi
AC_MSG_RESULT([Using '$prefix' for installation.])
AC_MSG_RESULT([Using '$CXX' for C++ compiler.])
AC_MSG_RESULT([Building with '$CPPFLAGS' for C++ preprocessor flags.])
AC_MSG_RESULT([Building with '$CXXFLAGS' for C++ compiler flags.])
AC_MSG_RESULT([Building with '$LIBS' for linker flags.])
AC_MSG_RESULT

View file

@ -7,7 +7,7 @@ EXTRA_DIST = README.menu menu.in
all-local: menu
distclean-local:
rm -f *\~ .\#*
$(RM) *\~ .\#*
menu: menu.in
@regex_cmd@ -e "s,@pkgdatadir@,$(pkgdatadir)," @srcdir@/menu.in > menu
@ -17,5 +17,4 @@ install-data-local: menu
$(INSTALL_DATA) menu $(DESTDIR)$(pkgdatadir)
uninstall-am:
rm -f $(DESTDIR)$(pkgdatadir)/menu
$(RM) $(DESTDIR)$(pkgdatadir)/menu

View file

@ -1,13 +1,13 @@
buttonsdir = $(pkgdatadir)/buttons
#buttonsdir = $(pkgdatadir)/buttons
MAINTAINERCLEANFILES = Makefile.in
buttons_DATA =
#buttons_DATA =
#fieron-bullet.xbm fieron-bulletl.xbm fieron-close.xbm \
#fieron-icon.xbm fieron-max.xbm fieron-stick.xbm \
#max.xbm stick.xbm icon.xbm close.xbm
EXTRA_DIST = $(buttons_DATA)
#EXTRA_DIST = $(buttons_DATA)
distclean-local:
rm -f *\~ .\#*
uninstall-am:
rmdir $(buttonsdir)
$(RM) *\~ .\#*
#uninstall-am:
# rmdir -p $(DESTDIR)$(buttonsdir) || true

View file

@ -1,13 +1,13 @@
styledir = $(pkgdatadir)/styles
#styledir = $(pkgdatadir)/styles
MAINTAINERCLEANFILES = Makefile.in
style_DATA =
#style_DATA =
#artwiz bbs bluebox cthulhain deep fieron fieron2 flux frobozz \
#frobust mbdtex miklos nyz nyzclone ob20 operation outcomes paper \
#purplehaaze shade steelblue steelblue2 the_orange trisb twice \
#warp-xp
EXTRA_DIST = $(style_DATA)
#EXTRA_DIST = $(style_DATA)
distclean-local:
rm -f *\~ .\#*
uninstall-am:
rmdir $(styledir)
$(RM) *\~ .\#*
#uninstall-am:
# rmdir -p $(DESTDIR)$(styledir) || true

View file

@ -8,7 +8,7 @@ EXTRA_DIST = openbox.1.in
DEFAULT_MENU=$(pkgdatadir)/menu
distclean-local:
rm -f *\~ .\#*
$(RM) *\~ .\#*
openbox.1: openbox.1.in
@regex_cmd@ -e "s,@defaultmenu@,$(DEFAULT_MENU)," \

90
m4/swig.m4 Normal file
View file

@ -0,0 +1,90 @@
# SWIG_PROG([required-version])
#
# Checks for the SWIG program. If found you can (and should) call SWIG via $(SWIG).
# You can use the optional first argument to check if the version of the available SWIG
# is greater or equal to the value of the argument. It should have the format:
# N[.N[.N]] (N is a number between 0 and 999. Only the first N is mandatory.)
AC_DEFUN([SWIG_PROG],[
AC_REQUIRE([AC_PROG_MAKE_SET])
AC_CHECK_PROG(SWIG,swig,[`which swig`])
if test -z "$SWIG" ; then
AC_MSG_WARN([cannot find 'swig' program])
SWIG=false
elif test -n "$1" ; then
AC_MSG_CHECKING([for SWIG version])
swig_version=`$SWIG -version 2>&1 | \
awk '/^SWIG Version [[0-9]+\.[0-9]+\.[0-9]]+.*$/ { split($[3],a,"[[^.0-9]]"); print a[[1]] }'`
AC_MSG_RESULT([$swig_version])
if test -n "$swig_version" ; then
swig_version=`echo $swig_version | \
awk '{ split($[1],a,"\."); print [a[1]*1000000+a[2]*1000+a[3]] }' 2>/dev/null`
swig_required_version=`echo $1 | \
awk '{ split($[1],a,"\."); print [a[1]*1000000+a[2]*1000+a[3]] }' 2>/dev/null`
if test $swig_required_version -gt $swig_version ; then
AC_MSG_WARN([SWIG version $1 required])
fi
else
AC_MSG_WARN([cannot determine SWIG version])
fi
fi
])
# SWIG_ENABLE_CXX()
#
# Enable swig C++ support. This effects all invocations of $(SWIG).
AC_DEFUN([SWIG_ENABLE_CXX],[
AC_REQUIRE([SWIG_PROG])
AC_REQUIRE([AC_PROG_CXX])
if test "$SWIG" != "false" ; then
SWIG="$SWIG -c++"
fi
])
# SWIG_MULTI_MODULE_SUPPORT()
#
# Enable support for multiple modules. This effects all invocations of $(SWIG).
# You have to link all generated modules against the appropriate SWIG library.
# If you want to build Python modules for example, use the SWIG_PYTHON() macro
# and link the modules against $(SWIG_PYTHON_LIB). The $(SWIG_LDFLAGS) variable
# can be used to help the linker to find this library.
AC_DEFUN([SWIG_MULTI_MODULE_SUPPORT],[
AC_REQUIRE([SWIG_PROG])
if test "$SWIG" != "false" ; then
SWIG="$SWIG -c"
# Check for SWIG library path
AC_MSG_CHECKING([for SWIG library path])
swig_path=${SWIG%/bin*}/lib
swig_path=`find $swig_path -type f -name libswig*.a -o -name libswig*.so -print`
for i in $swig_path ; do
swig_path=${i%/libswig*}
break
done
AC_MSG_RESULT([$swig_path])
if test -n "$swig_path" ; then
AC_SUBST(SWIG_LDFLAGS,[-L$swig_path])
else
AC_MSG_WARN([cannot find SWIG library path])
fi
fi
])
# SWIG_PYTHON([use-shadow-classes])
#
# Checks for Python and provides the $(SWIG_PYTHON_CFLAGS), $(SWIG_PYTHON_LIB) and
# $(SWIG_PYTHON_OPT) output variables. $(SWIG_PYTHON_OPT) contains all necessary swig
# options to generate code for Python. Shadow classes are enabled unless the
# value of the optional first argument is exactly 'no'. If you need multi module
# support use $(SWIG_PYTHON_LIB) (provided by the SWIG_MULTI_MODULE_SUPPORT() macro)
# to link against the appropriate library. It contains the SWIG Python runtime library
# that is needed by the type check system for example.
AC_DEFUN([SWIG_PYTHON],[
AC_REQUIRE([SWIG_PROG])
AC_REQUIRE([PYTHON_DEVEL])
if test "$SWIG" != "false" ; then
AC_SUBST(SWIG_PYTHON_LIB,[`$SWIG -python -ldflags`])
test ! "x$1" = "xno" && swig_shadow=" -shadow" || swig_shadow=""
AC_SUBST(SWIG_PYTHON_OPT,[-python$swig_shadow])
fi
AC_SUBST(SWIG_PYTHON_CFLAGS,[$PYTHON_CFLAGS])
])

View file

@ -1,7 +1,7 @@
# X11_DEVEL()
#
# Check for the presence of the X Window System headers and libraries.
# Sets the CXXFLAGS and LIBS variables as appropriate.
# Sets the CPPFLAGS and LIBS variables as appropriate.
AC_DEFUN([X11_DEVEL],
[
AC_PATH_X
@ -9,7 +9,7 @@ AC_DEFUN([X11_DEVEL],
test "$no_x" = "yes" && \
AC_MSG_ERROR([The X Window System could not be found.])
CXXFLAGS="$CXXFLAGS $X_CFLAGS"
CPPFLAGS="$CPPFLAGS $X_CFLAGS"
LIBS="$LIBS $X_PRE_LIBS $X_LIBS $X_EXTRA_LIBS"
# Check for required functions in -lX11
@ -73,14 +73,14 @@ AC_DEFUN([XFT_DEVEL],
# Store these
OLDLIBS=$LIBS
OLDCXXFLAGS=$CXXFLAGS
OLDCPPFLAGS=$CPPFLAGS
XFT_CFLAGS="`pkg-config --cflags xft`"
XFT_LIBS="`pkg-config --libs xft`"
# Set these for checking with the tests below. They'll be restored after
LIBS="$LIBS $XFT_LIBS"
CXXFLAGS="$XFT_CFLAGS $CXXFLAGS"
CPPFLAGS="$XFT_CFLAGS $CPPFLAGS"
AC_CHECK_LIB([Xft], [XftGetVersion], # this was not defined in < 2.0
if test "$XFT_MIN"; then
@ -162,7 +162,7 @@ AC_DEFUN([XFT_DEVEL],
# Restore the old values. Use XFT_CFLAGS and XFT_LIBS in the Makefile.am's
LIBS=$OLDLIBS
CXXFLAGS=$OLDCXXFLAGS
CPPFLAGS=$OLDCPPFLAGS
AC_SUBST([XFT_CFLAGS])
AC_SUBST([XFT_LIBS])

View file

@ -2,8 +2,7 @@ buttonsdir = $(pkgdatadir)/buttons
includeotkdir = $(includedir)/otk
pkgconfigdir = $(libdir)/pkgconfig
CXXFLAGS=$(XFT_CFLAGS) @CXXFLAGS@ \
-DBUTTONSDIR=\"$(buttonsdir)\"
CPPFLAGS=$(XFT_CFLAGS) @CPPFLAGS@ -DBUTTONSDIR=\"$(buttonsdir)\"
#noinst_LIBRARIES=libotk.a
lib_LTLIBRARIES=libotk.la
@ -35,12 +34,12 @@ otk.pc: otk.pc.in
@srcdir@/$^ > $@
distclean-local:
rm -f *\~ *.orig *.rej .\#*
$(RM) *\~ *.orig *.rej .\#*
otk_test: libotk.la otk_test.cc
$(CXX) $(CXXFLAGS) -DHAVE_CONFIG_H -I. -I. -I.. -I../src $(XFT_CFLAGS) -Wall -W -pedantic -DNDEBUG -g -O2 -o otk_test otk_test.cc $(XFT_LIBS) -L. -lotk @LIBS@
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -DHAVE_CONFIG_H -I. -I. -I.. -I../src $(XFT_CFLAGS) -Wall -W -pedantic -DNDEBUG -g -O2 -o otk_test otk_test.cc $(XFT_LIBS) -L. -lotk @LIBS@
rendertest: libotk.la rendertest.cc
$(CXX) $(CXXFLAGS) -DHAVE_CONFIG_H -I. -I. -I.. -I../src $(XFT_CFLAGS) -Wall -W -pedantic -DNDEBUG -g -O2 -o $@ rendertest.cc $(XFT_LIBS) -L. -lotk @LIBS@
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -DHAVE_CONFIG_H -I. -I. -I.. -I../src $(XFT_CFLAGS) -Wall -W -pedantic -DNDEBUG -g -O2 -o $@ rendertest.cc $(XFT_LIBS) -L. -lotk @LIBS@
# local dependencies

View file

@ -5,6 +5,6 @@ script_PYTHON = config.py defaults.py focus.py callbacks.py \
historyplacement.py stackedcycle.py focuscycle.py
distclean-local:
rm -f *\~ .\#*
#uninstall-am:
# rmdir -p $(scriptdir)
$(RM) *\~ .\#*
uninstall-am:
rmdir -p $(scriptdir)

View file

@ -21,8 +21,8 @@ def state_above(data, add=StateAdd):
StateToggle."""
if not data.client: return
ob.send_client_msg(otk.display.screenInfo(data.screen).rootWindow(),
otk.Property_atoms().net_wm_state, data.client.window(),
add, otk.Property_atoms().net_wm_state_above)
otk.atoms.net_wm_state, data.client.window(),
add, otk.atoms.net_wm_state_above)
def state_below(data, add=StateAdd):
"""Toggles, adds or removes the 'below' state on a window.
@ -30,8 +30,8 @@ def state_below(data, add=StateAdd):
StateToggle."""
if not data.client: return
ob.send_client_msg(otk.display.screenInfo(data.screen).rootWindow(),
otk.Property_atoms().net_wm_state, data.client.window(),
add, otk.Property_atoms().net_wm_state_below)
otk.atoms.net_wm_state, data.client.window(),
add, otk.atoms.net_wm_state_below)
def state_shaded(data, add=StateAdd):
"""Toggles, adds or removes the 'shaded' state on a window.
@ -39,8 +39,8 @@ def state_shaded(data, add=StateAdd):
StateToggle."""
if not data.client: return
ob.send_client_msg(otk.display.screenInfo(data.screen).rootWindow(),
otk.Property_atoms().net_wm_state, data.client.window(),
add, otk.Property_atoms().net_wm_state_shaded)
otk.atoms.net_wm_state, data.client.window(),
add, otk.atoms.net_wm_state_shaded)
def state_maximize(data, add=StateAdd):
"""Toggles, adds or removes the horizontal and vertical 'maximized' state
@ -48,9 +48,9 @@ def state_maximize(data, add=StateAdd):
or StateToggle."""
if not data.client: return
ob.send_client_msg(otk.display.screenInfo(data.screen).rootWindow(),
otk.Property_atoms().net_wm_state, data.client.window(),
add, otk.Property_atoms().net_wm_state_maximized_horz,
otk.Property_atoms().net_wm_state_maximized_vert)
otk.atoms.net_wm_state, data.client.window(),
add, otk.atoms.net_wm_state_maximized_horz,
otk.atoms.net_wm_state_maximized_vert)
def state_maximize_horz(data, add=StateAdd):
"""Toggles, adds or removes the horizontal 'maximized' state on a window.
@ -58,8 +58,8 @@ def state_maximize_horz(data, add=StateAdd):
StateToggle."""
if not data.client: return
ob.send_client_msg(otk.display.screenInfo(data.screen).rootWindow(),
otk.Property_atoms().net_wm_state, data.client.window(),
add, otk.Property_atoms().net_wm_state_maximized_horz)
otk.atoms.net_wm_state, data.client.window(),
add, otk.atoms.net_wm_state_maximized_horz)
def state_maximize_vert(data, add=StateAdd):
"""Toggles, adds or removes the vertical 'maximized' state on a window.
@ -67,8 +67,8 @@ def state_maximize_vert(data, add=StateAdd):
StateToggle."""
if not data.client: return
ob.send_client_msg(otk.display.screenInfo(data.screen).rootWindow(),
otk.Property_atoms().net_wm_state, data.client.window(),
add, otk.Property_atoms().net_wm_state_maximized_vert)
otk.atoms.net_wm_state, data.client.window(),
add, otk.atoms.net_wm_state_maximized_vert)
def state_skip_taskbar(data, add=StateAdd):
"""Toggles, adds or removes the 'skip_taskbar' state on a window.
@ -76,8 +76,8 @@ def state_skip_taskbar(data, add=StateAdd):
StateToggle."""
if not data.client: return
ob.send_client_msg(otk.display.screenInfo(data.screen).rootWindow(),
otk.Property_atoms().net_wm_state, data.client.window(),
add, otk.Property_atoms().net_wm_state_skip_taskbar)
otk.atoms.net_wm_state, data.client.window(),
add, otk.atoms.net_wm_state_skip_taskbar)
def state_skip_pager(data, add=StateAdd):
"""Toggles, adds or removes the 'skip_pager' state on a window.
@ -85,14 +85,14 @@ def state_skip_pager(data, add=StateAdd):
StateToggle."""
if not data.client: return
ob.send_client_msg(otk.display.screenInfo(data.screen).rootWindow(),
otk.Property_atoms().net_wm_state, data.client.window(),
add, otk.Property_atoms().net_wm_state_skip_pager)
otk.atoms.net_wm_state, data.client.window(),
add, otk.atoms.net_wm_state_skip_pager)
def iconify(data):
"""Iconifies the window on which the event occured"""
if not data.client: return
ob.send_client_msg(otk.display.screenInfo(data.screen).rootWindow(),
otk.Property_atoms().wm_change_state,
otk.atoms.wm_change_state,
data.client.window(), 3) # IconicState
def restore(data):
@ -101,14 +101,14 @@ def restore(data):
use the activate() function."""
if not data.client: return
ob.send_client_msg(otk.display.screenInfo(data.screen).rootWindow(),
otk.Property_atoms().wm_change_state,
otk.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
ob.send_client_msg(otk.display.screenInfo(data.screen).rootWindow(),
otk.Property_atoms().net_close_window,
otk.atoms.net_close_window,
data.client.window(), 0)
def focus(data):
@ -182,7 +182,7 @@ def unshade(data):
def change_desktop(data, num):
"""Switches to a specified desktop"""
root = otk.display.screenInfo(data.screen).rootWindow()
ob.send_client_msg(root, otk.Property_atoms().net_current_desktop,
ob.send_client_msg(root, otk.atoms.net_current_desktop,
root, num)
def next_desktop(data, no_wrap=0):
@ -213,7 +213,7 @@ def send_to_desktop(data, num):
"""Sends a client to a specified desktop"""
if not data.client: return
ob.send_client_msg(otk.display.screenInfo(data.screen).rootWindow(),
otk.Property_atoms().net_wm_desktop,
otk.atoms.net_wm_desktop,
data.client.window(),num)
def toggle_all_desktops(data):

View file

@ -1,3 +1,4 @@
import ob # base module
import focus # add some default focus handling and cycling functions
import focusmodel # default focus models
import behavior # defines default behaviors for interaction with windows

View file

@ -3,44 +3,26 @@ scriptdir = $(libdir)/openbox/python
DEFAULT_MENU=$(pkgdatadir)/menu
DEFAULT_STYLE=$(pkgdatadir)/styles/mbdtex
CXXFLAGS=$(XFT_CFLAGS) $(PYTHON_CFLAGS) @CXXFLAGS@ \
CPPFLAGS=$(XFT_CFLAGS) $(PYTHON_CFLAGS) @CPPFLAGS@ \
-DDEFAULTMENU=\"$(DEFAULT_MENU)\" \
-DDEFAULTSTYLE=\"$(DEFAULT_STYLE)\" \
-DLOCALEDIR=\"$(localedir)\" \
-DSCRIPTDIR=\"$(scriptdir)\"
LIBS=$(XFT_LIBS) $(PYTHON_LIBS) @LIBS@
INCLUDES= -I..
LIBS=$(XFT_LIBS) $(PYTHON_LIBS) @LIBS@ $(SWIG_PYTHON_LIB)
bin_PROGRAMS= openbox3
openbox3_LDADD=-L../otk -lotk @LIBINTL@
openbox3_LDFLAGS=-export-dynamic
openbox3_SOURCES= actions.cc client.cc frame.cc openbox.cc screen.cc \
main.cc backgroundwidget.cc labelwidget.cc \
buttonwidget.cc python.cc bindings.cc \
openbox_wrap.cc
buttonwidget.cc python.cc bindings.cc
noinst_HEADERS= actions.hh backgroundwidget.hh bindings.hh buttonwidget.hh \
client.hh frame.hh labelwidget.hh openbox.hh python.hh \
screen.hh widgetbase.hh
openbox3_LDFLAGS= $(PYTHON_LDFLAGS)
script_DATA = ob.py
EXTRA_DIST = $(script_DATA)
MAINTAINERCLEANFILES= Makefile.in
distclean-local:
rm -f *\~ *.orig *.rej .\#*
openbox.i: openbox.hh screen.hh client.hh python.hh frame.hh
touch $@
%.py: %_wrap.cc
%_wrap.cc: %.i
swig -c -I../otk $(filter -I%,$(CXXFLAGS)) -python -shadow -c++ -nodefault -o $@ $<
# local dependencies
$(RM) *\~ *.orig *.rej .\#*

View file

@ -9,7 +9,6 @@
#include "openbox.hh"
#include "client.hh"
#include "frame.hh"
#include "python.hh"
#include "otk/display.hh"
extern "C" {
@ -118,7 +117,7 @@ static void destroytree(KeyBindingTree *tree)
}
KeyBindingTree *Bindings::buildtree(const StringVect &keylist,
PyObject *callback) const
KeyCallback callback, void *data) const
{
if (keylist.empty()) return 0; // nothing in the list.. return 0
@ -131,7 +130,7 @@ KeyBindingTree *Bindings::buildtree(const StringVect &keylist,
if (!p) {
// this is the first built node, the bottom node of the tree
ret->chain = false;
ret->callbacks.push_back(callback);
ret->callbacks.push_back(KeyCallbackData(callback, data));
}
ret->first_child = p;
if (!translate(*it, ret->binding)) {
@ -148,7 +147,7 @@ Bindings::Bindings()
: _curpos(&_keytree),
_resetkey(0,0),
_timer((otk::Timer *) 0),
_keybgrab_callback(0)
_keybgrab_callback(0, 0)
{
// setResetKey("C-g"); // set the default reset key
}
@ -224,12 +223,13 @@ KeyBindingTree *Bindings::find(KeyBindingTree *search,
}
bool Bindings::addKey(const StringVect &keylist, PyObject *callback)
bool Bindings::addKey(const StringVect &keylist, KeyCallback callback,
void *data)
{
KeyBindingTree *tree, *t;
bool conflict;
if (!(tree = buildtree(keylist, callback)))
if (!(tree = buildtree(keylist, callback, data)))
return false; // invalid binding requested
t = find(tree, &conflict);
@ -241,7 +241,7 @@ bool Bindings::addKey(const StringVect &keylist, PyObject *callback)
if (t) {
// already bound to something
t->callbacks.push_back(callback);
t->callbacks.push_back(KeyCallbackData(callback, data));
destroytree(tree);
} else {
// grab the server here to make sure no key pressed go missed
@ -255,13 +255,11 @@ bool Bindings::addKey(const StringVect &keylist, PyObject *callback)
otk::display->ungrab();
}
Py_INCREF(callback);
return true;
}
/*
bool Bindings::removeKey(const StringVect &keylist, PyObject *callback)
bool Bindings::removeKey(const StringVect &keylist, KeyCallback callback, void *data)
{
assert(false); // XXX: function not implemented yet
@ -273,9 +271,9 @@ bool Bindings::removeKey(const StringVect &keylist, PyObject *callback)
KeyBindingTree *t = find(tree, &conflict);
if (t) {
CallbackList::iterator it = std::find(t->callbacks.begin(),
t->callbacks.end(),
callback);
KeyCallbackList::iterator it = std::find(t->callbacks.begin(),
t->callbacks.end(),
callback);
if (it != t->callbacks.end()) {
// grab the server here to make sure no key pressed go missed
otk::display->grab();
@ -320,7 +318,6 @@ static void remove_branch(KeyBindingTree *first)
remove_branch(p->first_child);
KeyBindingTree *s = p->next_sibling;
while(!p->callbacks.empty()) {
Py_XDECREF(p->callbacks.front());
p->callbacks.pop_front();
}
delete p;
@ -372,10 +369,10 @@ void Bindings::grabKeys(bool grab)
}
bool Bindings::grabKeyboard(int screen, PyObject *callback)
bool Bindings::grabKeyboard(int screen, KeyCallback callback, void *data)
{
assert(callback);
if (_keybgrab_callback) return false; // already grabbed
if (_keybgrab_callback.callback) return false; // already grabbed
if (!openbox->screen(screen))
return false; // the screen is not managed
@ -384,16 +381,17 @@ bool Bindings::grabKeyboard(int screen, PyObject *callback)
if (XGrabKeyboard(**otk::display, root, false, GrabModeAsync,
GrabModeAsync, CurrentTime))
return false;
_keybgrab_callback = callback;
_keybgrab_callback.callback = callback;
_keybgrab_callback.data = data;
return true;
}
void Bindings::ungrabKeyboard()
{
if (!_keybgrab_callback) return; // not grabbed
if (!_keybgrab_callback.callback) return; // not grabbed
_keybgrab_callback = 0;
_keybgrab_callback = KeyCallbackData(0, 0);
XUngrabKeyboard(**otk::display, CurrentTime);
XUngrabPointer(**otk::display, CurrentTime);
}
@ -420,10 +418,10 @@ void Bindings::ungrabPointer()
void Bindings::fireKey(int screen, unsigned int modifiers, unsigned int key,
Time time, KeyAction::KA action)
{
if (_keybgrab_callback) {
if (_keybgrab_callback.callback) {
Client *c = openbox->focusedClient();
KeyData data(screen, c, time, modifiers, key, action);
python_callback(_keybgrab_callback, &data);
_keybgrab_callback.fire(&data);
}
// KeyRelease events only occur during keyboard grabs
@ -450,9 +448,9 @@ void Bindings::fireKey(int screen, unsigned int modifiers, unsigned int key,
} else {
Client *c = openbox->focusedClient();
KeyData data(screen, c, time, modifiers, key, action);
CallbackList::iterator it, end = p->callbacks.end();
KeyCallbackList::iterator it, end = p->callbacks.end();
for (it = p->callbacks.begin(); it != end; ++it)
python_callback(*it, &data);
it->fire(&data);
resetChains(this);
}
break;
@ -478,7 +476,8 @@ void Bindings::resetChains(Bindings *self)
bool Bindings::addButton(const std::string &but, MouseContext::MC context,
MouseAction::MA action, PyObject *callback)
MouseAction::MA action, MouseCallback callback,
void *data)
{
assert(context >= 0 && context < MouseContext::NUM_MOUSE_CONTEXT);
assert(action >= 0 && action < MouseAction::NUM_MOUSE_ACTION);
@ -515,8 +514,7 @@ bool Bindings::addButton(const std::string &but, MouseContext::MC context,
}
} else
bind = *it;
bind->callbacks[action].push_back(callback);
Py_INCREF(callback);
bind->callbacks[action].push_back(MouseCallbackData(callback, data));
return true;
}
@ -527,7 +525,6 @@ void Bindings::removeAllButtons()
for (it = _buttons[i].begin(); it != end; ++it) {
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();
}
}
@ -593,17 +590,19 @@ void Bindings::fireButton(MouseData *data)
for (it = _buttons[data->context].begin(); it != end; ++it)
if ((*it)->binding.key == data->button &&
(*it)->binding.modifiers == data->state) {
CallbackList::iterator c_it,c_end = (*it)->callbacks[data->action].end();
MouseCallbackList::iterator c_it,
c_end = (*it)->callbacks[data->action].end();
for (c_it = (*it)->callbacks[data->action].begin();
c_it != c_end; ++c_it)
python_callback(*c_it, data);
c_it->fire(data);
}
}
bool Bindings::addEvent(EventAction::EA action, PyObject *callback)
bool Bindings::addEvent(EventAction::EA action, EventCallback callback,
void *data)
{
if (action < 0 || action >= EventAction::NUM_EVENTS) {
if (action < 0 || action >= EventAction::NUM_EVENT_ACTION) {
return false;
}
#ifdef XKB
@ -611,22 +610,22 @@ bool Bindings::addEvent(EventAction::EA action, PyObject *callback)
XkbSelectEvents(**otk::display, XkbUseCoreKbd,
XkbBellNotifyMask, XkbBellNotifyMask);
#endif // XKB
_eventlist[action].push_back(callback);
Py_INCREF(callback);
_eventlist[action].push_back(EventCallbackData(callback, data));
return true;
}
bool Bindings::removeEvent(EventAction::EA action, PyObject *callback)
bool Bindings::removeEvent(EventAction::EA action, EventCallback callback,
void *data)
{
if (action < 0 || action >= EventAction::NUM_EVENTS) {
if (action < 0 || action >= EventAction::NUM_EVENT_ACTION) {
return false;
}
CallbackList::iterator it = std::find(_eventlist[action].begin(),
_eventlist[action].end(),
callback);
EventCallbackList::iterator it = std::find(_eventlist[action].begin(),
_eventlist[action].end(),
EventCallbackData(callback,
data));
if (it != _eventlist[action].end()) {
Py_XDECREF(*it);
_eventlist[action].erase(it);
#ifdef XKB
if (action == EventAction::Bell && _eventlist[action].empty())
@ -640,9 +639,8 @@ bool Bindings::removeEvent(EventAction::EA action, PyObject *callback)
void Bindings::removeAllEvents()
{
for (int i = 0; i < EventAction::NUM_EVENTS; ++i) {
for (int i = 0; i < EventAction::NUM_EVENT_ACTION; ++i) {
while (!_eventlist[i].empty()) {
Py_XDECREF(_eventlist[i].front());
_eventlist[i].pop_front();
}
}
@ -650,9 +648,9 @@ void Bindings::removeAllEvents()
void Bindings::fireEvent(EventData *data)
{
CallbackList::iterator c_it, c_end = _eventlist[data->action].end();
EventCallbackList::iterator c_it, c_end = _eventlist[data->action].end();
for (c_it = _eventlist[data->action].begin(); c_it != c_end; ++c_it)
python_callback(*c_it, data);
c_it->fire(data);
}
}

View file

@ -10,10 +10,6 @@
#include "python.hh"
#include "otk/timer.hh"
extern "C" {
#include <Python.h>
}
#include <string>
#include <list>
#include <vector>
@ -22,7 +18,42 @@ namespace ob {
class Client;
typedef std::list<PyObject *> CallbackList;
struct MouseCallbackData {
MouseCallback callback;
void *data;
MouseCallbackData(MouseCallback c, void *d) : callback(c), data(d) {}
void fire(MouseData *d) { callback(d, data); }
bool operator==(const MouseCallbackData &other) { return (callback ==
other.callback &&
data ==
other.data); }
};
struct KeyCallbackData {
KeyCallback callback;
void *data;
KeyCallbackData(KeyCallback c, void *d) : callback(c), data(d) {}
void fire(KeyData *d) { callback(d, data); }
bool operator==(const KeyCallbackData &other) { return (callback ==
other.callback &&
data ==
other.data); }
};
struct EventCallbackData {
EventCallback callback;
void *data;
EventCallbackData(EventCallback c, void *d) : callback(c), data(d) {}
void fire(EventData *d) { callback(d, data); }
bool operator==(const EventCallbackData &other) { return (callback ==
other.callback &&
data ==
other.data); }
};
typedef std::list<MouseCallbackData> MouseCallbackList;
typedef std::list<KeyCallbackData> KeyCallbackList;
typedef std::list<EventCallbackData> EventCallbackList;
typedef struct Binding {
unsigned int modifiers;
@ -37,7 +68,7 @@ typedef struct Binding {
typedef struct KeyBindingTree {
Binding binding;
CallbackList callbacks; // the callbacks given for the binding in add()
KeyCallbackList callbacks; // the callbacks given for the binding in add()
bool chain; // true if this is a chain to another key (not an action)
struct KeyBindingTree *next_sibling; // the next binding in the tree at the same
@ -51,7 +82,7 @@ typedef struct KeyBindingTree {
typedef struct ButtonBinding {
Binding binding;
CallbackList callbacks[MouseAction::NUM_MOUSE_ACTION];
MouseCallbackList callbacks[MouseAction::NUM_MOUSE_ACTION];
ButtonBinding() : binding(0, 0) {}
};
@ -71,7 +102,7 @@ private:
KeyBindingTree *find(KeyBindingTree *search, bool *conflict) const;
KeyBindingTree *buildtree(const StringVect &keylist,
PyObject *callback) const;
KeyCallback callback, void *data) const;
void assimilate(KeyBindingTree *node);
static void resetChains(Bindings *self); // the timer's timeout function
@ -82,9 +113,9 @@ private:
void grabButton(bool grab, const Binding &b, MouseContext::MC context,
Client *client);
CallbackList _eventlist[EventAction::NUM_EVENTS];
EventCallbackList _eventlist[EventAction::NUM_EVENT_ACTION];
PyObject *_keybgrab_callback;
KeyCallbackData _keybgrab_callback;
public:
//! Initializes an Bindings object
@ -101,14 +132,14 @@ public:
a chain or not), or if any of the strings in the keylist are invalid.
@return true if the binding could be added; false if it could not.
*/
bool addKey(const StringVect &keylist, PyObject *callback);
bool addKey(const StringVect &keylist, KeyCallback callback, void *data);
////! Removes a key binding
///*!
// @return The callbackid of the binding, or '< 0' if there was no binding to
// be removed.
//*/
//bool removeKey(const StringVect &keylist, PyObject *callback);
//bool removeKey(const StringVect &keylist, KeyCallback callback, void *data);
//! Removes all key bindings
void removeAllKeys();
@ -120,14 +151,14 @@ public:
void grabKeys(bool grab);
bool grabKeyboard(int screen, PyObject *callback);
bool grabKeyboard(int screen, KeyCallback callback, void *data);
void ungrabKeyboard();
bool grabPointer(int screen);
void ungrabPointer();
bool addButton(const std::string &but, MouseContext::MC context,
MouseAction::MA action, PyObject *callback);
MouseAction::MA action, MouseCallback callback, void *data);
void grabButtons(bool grab, Client *client);
@ -137,10 +168,10 @@ public:
void fireButton(MouseData *data);
//! Bind a callback for an event
bool addEvent(EventAction::EA action, PyObject *callback);
bool addEvent(EventAction::EA action, EventCallback callback, void *data);
//! Unbind the callback function from an event
bool removeEvent(EventAction::EA action, PyObject *callback);
bool removeEvent(EventAction::EA action, EventCallback callback, void *data);
//! Remove all callback functions
void removeAllEvents();

View file

@ -8,12 +8,6 @@
#include "otk/display.hh"
#include "otk/util.hh"
extern "C" {
// The initializer in openbox_wrap.cc / otk_wrap.cc
extern void init_ob(void);
extern void init_otk(void);
}
namespace ob {
static PyObject *obdict = NULL;
@ -23,19 +17,17 @@ void python_init(char *argv0)
// start the python engine
Py_SetProgramName(argv0);
Py_Initialize();
// initialize the C python module
init_otk();
init_ob();
// prepend the openbox directories for python scripts to the sys path
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.insert(0, '" SCRIPTDIR "')");
PyRun_SimpleString(const_cast<char*>(("sys.path.insert(0, '" +
otk::expandTilde("~/.openbox/python") +
"')").c_str()));
PyRun_SimpleString("import ob; import otk; import config;");
//PyRun_SimpleString("import ob; import otk; import config;");
PyRun_SimpleString("import config;");
// set up convenience global variables
PyRun_SimpleString("ob.openbox = ob.Openbox_instance()");
PyRun_SimpleString("otk.display = otk.Display_instance()");
//PyRun_SimpleString("ob.openbox = ob.Openbox_instance()");
//PyRun_SimpleString("otk.display = otk.Display_instance()");
// set up access to the python global variables
PyObject *obmodule = PyImport_AddModule("config");
@ -90,180 +82,4 @@ bool python_get_stringlist(const char *name, std::vector<otk::ustring> *value)
return true;
}
// ************************************* //
// Stuff for calling from Python scripts //
// ************************************* //
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.");
return NULL;
}
if(context < 0 || context >= MouseContext::NUM_MOUSE_CONTEXT) {
PyErr_SetString(PyExc_ValueError, "Invalid MouseContext");
return NULL;
}
if(action < 0 || action >= MouseAction::NUM_MOUSE_ACTION) {
PyErr_SetString(PyExc_ValueError, "Invalid MouseAction");
return NULL;
}
if (!ob::openbox->bindings()->addButton(button, context,
action, func)) {
PyErr_SetString(PyExc_RuntimeError,"Unable to add binding.");
return NULL;
}
Py_INCREF(Py_None); return Py_None;
}
PyObject *ebind(ob::EventAction::EA action, PyObject *func)
{
if (!PyCallable_Check(func)) {
PyErr_SetString(PyExc_TypeError, "Invalid callback function.");
return NULL;
}
if (!ob::openbox->bindings()->addEvent(action, func)) {
PyErr_SetString(PyExc_RuntimeError,"Unable to add binding.");
return NULL;
}
Py_INCREF(Py_None); return Py_None;
}
PyObject *kgrab(int screen, PyObject *func)
{
if (!PyCallable_Check(func)) {
PyErr_SetString(PyExc_TypeError, "Invalid callback function.");
return NULL;
}
if (!ob::openbox->bindings()->grabKeyboard(screen, func)) {
PyErr_SetString(PyExc_RuntimeError,"Unable to grab keybaord.");
return NULL;
}
Py_INCREF(Py_None); return Py_None;
}
PyObject *kungrab()
{
ob::openbox->bindings()->ungrabKeyboard();
Py_INCREF(Py_None); return Py_None;
}
PyObject *mgrab(int screen)
{
if (!ob::openbox->bindings()->grabPointer(screen)) {
PyErr_SetString(PyExc_RuntimeError,"Unable to grab pointer.");
return NULL;
}
Py_INCREF(Py_None); return Py_None;
}
PyObject *mungrab()
{
ob::openbox->bindings()->ungrabPointer();
Py_INCREF(Py_None); return Py_None;
}
PyObject *kbind(PyObject *keylist, ob::KeyContext::KC context, PyObject *func)
{
if (!PyCallable_Check(func)) {
PyErr_SetString(PyExc_TypeError, "Invalid callback function.");
return NULL;
}
if (!PyList_Check(keylist)) {
PyErr_SetString(PyExc_TypeError, "Invalid keylist. Not a list.");
return NULL;
}
ob::Bindings::StringVect vectkeylist;
for (int i = 0, end = PyList_Size(keylist); i < end; ++i) {
PyObject *str = PyList_GetItem(keylist, i);
if (!PyString_Check(str)) {
PyErr_SetString(PyExc_TypeError,
"Invalid keylist. It must contain only strings.");
return NULL;
}
vectkeylist.push_back(PyString_AsString(str));
}
(void)context; // XXX use this sometime!
if (!ob::openbox->bindings()->addKey(vectkeylist, func)) {
PyErr_SetString(PyExc_RuntimeError,"Unable to add binding.");
return NULL;
}
Py_INCREF(Py_None); return Py_None;
}
/*
PyObject *kunbind(PyObject *keylist, PyObject *func)
{
if (!PyList_Check(keylist)) {
PyErr_SetString(PyExc_TypeError, "Invalid keylist. Not a list.");
return NULL;
}
if (!PyCallable_Check(func)) {
PyErr_SetString(PyExc_TypeError, "Invalid callback function.");
return NULL;
}
ob::Bindings::StringVect vectkeylist;
for (int i = 0, end = PyList_Size(keylist); i < end; ++i) {
PyObject *str = PyList_GetItem(keylist, i);
if (!PyString_Check(str)) {
PyErr_SetString(PyExc_TypeError,
"Invalid keylist. It must contain only strings.");
return NULL;
}
vectkeylist.push_back(PyString_AsString(str));
}
if (!ob::openbox->bindings()->removeKey(vectkeylist, func)) {
PyErr_SetString(PyExc_RuntimeError, "Could not remove callback.");
return NULL;
}
Py_INCREF(Py_None); return Py_None;
}
*/
void kunbind_all()
{
ob::openbox->bindings()->removeAllKeys();
}
void set_reset_key(const std::string &key)
{
ob::openbox->bindings()->setResetKey(key);
}
PyObject *send_client_msg(Window target, Atom type, Window about,
long data, long data1, long data2,
long data3, long data4)
{
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.format = 32;
e.xclient.message_type = type;
e.xclient.window = about;
e.xclient.data.l[0] = data;
e.xclient.data.l[1] = data1;
e.xclient.data.l[2] = data2;
e.xclient.data.l[3] = data3;
e.xclient.data.l[4] = data4;
XSendEvent(**otk::display, target, false,
SubstructureRedirectMask | SubstructureNotifyMask,
&e);
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());
}
}

View file

@ -121,7 +121,7 @@ struct EventAction {
*/
UrgentWindow
#if ! (defined(DOXYGEN_IGNORE) || defined(SWIG))
, NUM_EVENTS
, NUM_EVENT_ACTION
#endif
};
};
@ -222,6 +222,11 @@ public:
}
};
// The void*'s will be used to hold the native language's function pointer
typedef void (*MouseCallback)(MouseData*, void*);
typedef void (*KeyCallback)(KeyData*, void*);
typedef void (*EventCallback)(EventData*, void*);
#ifndef SWIG
void python_init(char *argv0);
@ -232,37 +237,8 @@ bool python_get_long(const char *name, long *value);
bool python_get_string(const char *name, otk::ustring *value);
bool python_get_stringlist(const char *name, std::vector<otk::ustring> *value);
/***********************************************
* These are found in openbox.i, not python.cc *
***********************************************/
void python_callback(PyObject *func, MouseData *data);
void python_callback(PyObject *func, EventData *data);
void python_callback(PyObject *func, KeyData *data);
#endif // SWIG
PyObject *mbind(const std::string &button, ob::MouseContext::MC context,
ob::MouseAction::MA action, PyObject *func);
PyObject *kbind(PyObject *keylist, ob::KeyContext::KC context, PyObject *func);
PyObject *kgrab(int screen, PyObject *func);
PyObject *kungrab();
PyObject *mgrab(int screen);
PyObject *mungrab();
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);
}

View file

@ -7,3 +7,9 @@ otkpy.la
otkpy_la-wrap_otk.lo
otkpy_la-wrap_otk.o
wrap_otk.cc
ob.py
obpy.la
obpy_la-wrap_ob.lo
wrap_ob.cc
wrap_ob.lo
wrap_otk.lo

View file

@ -1,35 +1,48 @@
# XXX - INSTALL THIS GLOBALLY!#&@(!!!
pythondir = $(libdir)/openbox/python
oblibdir = $(libdir)/openbox
CXXFLAGS = $(XFT_CFLAGS) $(filter-out -W -Wall,@CXXFLAGS@)
#pythondir = $(oblibdir)/python
obpythondir = $(oblibdir)/python
INCLUDES = -I.. -I../swig
CPPFLAGS = $(XFT_CFLAGS) $(SWIG_PYTHON_CFLAGS) @CPPFLAGS@
CXXFLAGS = $(filter-out -W -Wall,@CXXFLAGS@)
LDFLAGS = -module -avoid-version
INCLUDES = -I.. -I../otk -I../src
python_LTLIBRARIES = otkpy.la
obpython_LTLIBRARIES = otkpy.la obpy.la
obpython_PYTHON = otk.py ob.py
otkpy_la_CXXFLAGS = $(PYTHON_CFLAGS)
otkpy_la_LDFLAGS = -module
otkpy_la_SOURCES = wrap_otk.cc
otkpy_la_LIBADD = ../otk/libotk.la
#otkpy_la_LIBADD = ../otk/libotk.la # do this for the global version of otk
CLEANFILES = wrap_* otk.py
obpy_la_SOURCES = wrap_ob.cc
CLEANFILES = wrap_* *.py
MAINTAINERCLEANFILES = Makefile.in
python_PYTHON = otk.py
install-exec-hook:
$(mkinstalldirs) "$(DESTDIR)$(pythondir)"
cd "$(DESTDIR)$(pythondir)" && \
$(mkinstalldirs) "$(DESTDIR)$(obpythondir)"
cd "$(DESTDIR)$(obpythondir)" && \
$(RM) -f _otk.so && $(LN_S) otkpy.so _otk.so
$(mkinstalldirs) "$(DESTDIR)$(obpythondir)"
cd "$(DESTDIR)$(obpythondir)" && \
$(RM) -f _ob.so && $(LN_S) obpy.so _ob.so
uninstall-local:
rm -f "$(DESTDIR)$(pythondir)/_otk.so"
uninstall-am:
$(RM) "$(DESTDIR)$(obpythondir)/_otk.so"
$(RM) "$(DESTDIR)$(obpythondir)/_ob.so"
rmdir -p $(obpythondir) || true
%.py: wrap_%.cc
otk.i: $(wildcard ../otk/*.hh)
@touch $@
wrap_%.cc: %.i
swig $(INCLUDES) $(filter -I%,$(CXXFLAGS)) -python -shadow -c++ -nodefault -o $@ $<
ob.i: $(addprefix ../src/,openbox.hh screen.hh client.hh python.hh frame.hh)
@touch $@
wrap_otk.cc: otk.i
$(SWIG) $(SWIG_PYTHON_OPT) $(INCLUDES) $(filter -I%,$(CPPFLAGS)) -nodefault -o $@ $<
wrap_ob.cc: ob.i callback.i
$(SWIG) $(SWIG_PYTHON_OPT) $(INCLUDES) $(filter -I%,$(CPPFLAGS)) -nodefault -o $@ $<

208
wrap/callback.i Normal file
View file

@ -0,0 +1,208 @@
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
%{
/*
Calls a python callback for the MouseCallback function type
*/
static void PythonMouseCallback(ob::MouseData *data, void *pyfunc)
{
PyObject *func, *arglist, *pdata;
PyObject *result;
double dres = 0;
func = (PyObject*) pyfunc;
pdata = SWIG_NewPointerObj((void *) data, SWIGTYPE_p_ob__MouseData, 0);
arglist = Py_BuildValue("(O)", pdata);
Py_DECREF(pdata);
// call the callback
result = PyEval_CallObject(func, arglist);
if (!result || PyErr_Occurred()) {
// an exception occured in the script, display it
PyErr_Print();
}
Py_XDECREF(result);
Py_DECREF(arglist);
}
/*
Calls a python callback for the KeyCallback function type
*/
static void PythonKeyCallback(ob::KeyData *data, void *pyfunc)
{
PyObject *func, *arglist, *pdata;
PyObject *result;
double dres = 0;
func = (PyObject*) pyfunc;
pdata = SWIG_NewPointerObj((void *) data, SWIGTYPE_p_ob__KeyData, 0);
arglist = Py_BuildValue("(O)", pdata);
Py_DECREF(pdata);
// call the callback
result = PyEval_CallObject(func, arglist);
if (!result || PyErr_Occurred()) {
// an exception occured in the script, display it
PyErr_Print();
}
Py_XDECREF(result);
Py_DECREF(arglist);
}
/*
Calls a python callback for the EventCallback function type
*/
static void PythonEventCallback(ob::EventData *data, void *pyfunc)
{
PyObject *func, *arglist, *pdata;
PyObject *result;
double dres = 0;
func = (PyObject*) pyfunc;
pdata = SWIG_NewPointerObj((void *) data, SWIGTYPE_p_ob__EventData, 0);
arglist = Py_BuildValue("(O)", pdata);
Py_DECREF(pdata);
// call the callback
result = PyEval_CallObject(func, arglist);
if (!result || PyErr_Occurred()) {
// an exception occured in the script, display it
PyErr_Print();
}
Py_XDECREF(result);
Py_DECREF(arglist);
}
%}
// for all of these, PyErr_SetString is called before they return a false!
%exception mbind {
$action
if (!result) return NULL;
}
%exception kbind {
$action
if (!result) return NULL;
}
%exception ebind {
$action
if (!result) return NULL;
}
%exception kgrab {
$action
if (!result) return NULL;
}
%exception mgrab {
$action
if (!result) return NULL;
}
// Grab a Python function object as a Python object.
%typemap(python,in) PyObject *func {
if (!PyCallable_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Excepting a callable object.");
return NULL;
}
$1 = $input;
}
%inline %{
bool mbind(const std::string &button, ob::MouseContext::MC context,
ob::MouseAction::MA action, PyObject *func)
{
if(context < 0 || context >= ob::MouseContext::NUM_MOUSE_CONTEXT) {
PyErr_SetString(PyExc_ValueError, "Invalid MouseContext");
return false;
}
if(action < 0 || action >= ob::MouseAction::NUM_MOUSE_ACTION) {
PyErr_SetString(PyExc_ValueError, "Invalid MouseAction");
return false;
}
if (!ob::openbox->bindings()->addButton(button, context,
action, PythonMouseCallback, func)) {
PyErr_SetString(PyExc_RuntimeError,"Unable to add binding.");
return false;
}
return true;
}
bool ebind(ob::EventAction::EA action, PyObject *func)
{
if(action < 0 || action >= ob::EventAction::NUM_EVENT_ACTION) {
PyErr_SetString(PyExc_ValueError, "Invalid EventAction");
return false;
}
if (!ob::openbox->bindings()->addEvent(action, PythonEventCallback, func)) {
PyErr_SetString(PyExc_RuntimeError,"Unable to add binding.");
return false;
}
return true;
}
bool kgrab(int screen, PyObject *func)
{
if (!ob::openbox->bindings()->grabKeyboard(screen,
PythonKeyCallback, func)) {
PyErr_SetString(PyExc_RuntimeError,"Unable to grab keybaord.");
return false;
}
return true;
}
void kungrab()
{
ob::openbox->bindings()->ungrabKeyboard();
}
bool mgrab(int screen)
{
if (!ob::openbox->bindings()->grabPointer(screen)) {
PyErr_SetString(PyExc_RuntimeError,"Unable to grab pointer.");
return false;
}
return true;
}
void mungrab()
{
ob::openbox->bindings()->ungrabPointer();
}
bool kbind(PyObject *keylist, ob::KeyContext::KC context, PyObject *func)
{
if (!PyList_Check(keylist)) {
PyErr_SetString(PyExc_TypeError, "Invalid keylist. Not a list.");
return false;
}
if(context < 0 || context >= ob::KeyContext::NUM_KEY_CONTEXT) {
PyErr_SetString(PyExc_ValueError, "Invalid KeyContext");
return false;
}
ob::Bindings::StringVect vectkeylist;
for (int i = 0, end = PyList_Size(keylist); i < end; ++i) {
PyObject *str = PyList_GetItem(keylist, i);
if (!PyString_Check(str)) {
PyErr_SetString(PyExc_TypeError,
"Invalid keylist. It must contain only strings.");
return false;
}
vectkeylist.push_back(PyString_AsString(str));
}
(void)context; // XXX use this sometime!
if (!ob::openbox->bindings()->addKey(vectkeylist, PythonKeyCallback, func)) {
PyErr_SetString(PyExc_RuntimeError,"Unable to add binding.");
return false;
}
return true;
}
%};

102
wrap/ob.i Normal file
View file

@ -0,0 +1,102 @@
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
%module ob
%{
#ifdef HAVE_CONFIG_H
# include "../config.h"
#endif
#include "frame.hh"
#include "openbox.hh"
#include "screen.hh"
#include "client.hh"
#include "bindings.hh"
#include "actions.hh"
#include "python.hh"
#include "otk/otk.hh"
%}
%include "stl.i"
//%include std_list.i
//%template(ClientList) std::list<Client*>;
%include "callback.i"
%immutable ob::openbox;
/*
%ignore ob::openbox;
%inline %{
ob::Openbox *Openbox_instance() { return ob::openbox; }
%};
*/
%ignore ob::Screen::clients;
%{
#include <iterator>
%}
%extend ob::Screen {
Client *client(int i) {
if (i < 0 || i >= (int)self->clients.size())
return NULL;
ob::Client::List::iterator it = self->clients.begin();
std::advance(it,i);
return *it;
}
int clientCount() const {
return (int) self->clients.size();
}
};
%import "otk.i"
%import "widgetbase.hh"
%import "actions.hh"
%include "openbox.hh"
%include "screen.hh"
%include "client.hh"
%include "frame.hh"
%include "python.hh"
// for Window etc
%import "X11/X.h"
%inline %{
void set_reset_key(const std::string &key)
{
ob::openbox->bindings()->setResetKey(key);
}
void send_client_msg(Window target, Atom type, Window about,
long data, long data1, long data2,
long data3, long data4)
{
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.format = 32;
e.xclient.message_type = type;
e.xclient.window = about;
e.xclient.data.l[0] = data;
e.xclient.data.l[1] = data1;
e.xclient.data.l[2] = data2;
e.xclient.data.l[3] = data3;
e.xclient.data.l[4] = data4;
XSendEvent(**otk::display, target, false,
SubstructureRedirectMask | SubstructureNotifyMask,
&e);
}
void execute(const std::string &bin, int screen)
{
if (screen >= ScreenCount(**otk::display))
screen = 0;
otk::bexec(bin, otk::display->screenInfo(screen)->displayString());
}
%};
// globals
%pythoncode %{
openbox = cvar.openbox;
%}

View file

@ -10,15 +10,8 @@
//%include std_list.i
%include "ustring.i"
%ignore otk::display;
%inline %{
otk::Display *Display_instance() { return otk::display; }
%};
%ignore otk::Property::atoms;
%inline %{
const otk::Atoms& Property_atoms() { return otk::Property::atoms; }
%};
%immutable otk::display;
%immutable otk::Property::atoms;
namespace otk {
/*%rename(setValue_bool) Configuration::setValue(std::string const &,bool);
@ -77,5 +70,11 @@ namespace otk {
%include "timer.hh"
%include "util.hh"
// for Mod1Mask etc
%include "X11/X.h"
// for Window etc
%import "X11/X.h"
// globals
%pythoncode %{
display = cvar.display;
atoms = cvar.Property_atoms;
%}