#include "python.hh"
#include "openbox.hh"
+#include "actions.hh"
+#include "python.hh"
+#include "bindings.hh"
#include "otk/display.hh"
-
-#include <vector>
-#include <algorithm>
-
-extern "C" {
-#include <Python.h>
-
-// The initializer in openbox_wrap.cc
-extern void init_openbox(void);
-// The initializer in otk_wrap.cc
-extern void init_otk(void);
-}
+#include "otk/util.hh"
namespace ob {
-typedef std::vector<PyObject*> FunctionList;
-
-static FunctionList callbacks[OBActions::NUM_ACTIONS];
-static FunctionList bindfuncs;
-
-static PyObject *obdict;
+static PyObject *obdict = NULL;
void python_init(char *argv0)
{
+ // start the python engine
Py_SetProgramName(argv0);
Py_Initialize();
- init_otk();
- init_openbox();
- PyRun_SimpleString("from _otk import *; from _openbox import *;");
+ // 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 config;");
+ // set up convenience global variables
+ //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("__main__");
+ PyObject *obmodule = PyImport_AddModule("config");
obdict = PyModule_GetDict(obmodule);
}
-bool python_exec(const char *file) {
- FILE *rcpyfd = fopen(file, "r");
- if (!rcpyfd) {
- printf("failed to load python file %s\n", file);
- return false;
- }
- PyRun_SimpleFile(rcpyfd, const_cast<char*>(file));
- fclose(rcpyfd);
- return true;
-}
-
-bool python_get_string(const char *name, std::string *value)
+void python_destroy()
{
- PyObject *val = PyDict_GetItemString(obdict, const_cast<char*>(name));
- if (!val) return false;
-
- *value = PyString_AsString(val);
- return true;
+ Py_Finalize();
}
-
-bool python_register(int action, PyObject *callback)
+bool python_exec(const std::string &path)
{
- if (action < 0 || action >= OBActions::NUM_ACTIONS ||
- action == OBActions::Action_KeyPress) {
- PyErr_SetString(PyExc_AssertionError, "Invalid action type.");
- return false;
- }
- if (!PyCallable_Check(callback)) {
- PyErr_SetString(PyExc_AssertionError, "Invalid callback function.");
+ FILE *rcpyfd = fopen(path.c_str(), "r");
+ if (!rcpyfd) {
+ printf("Failed to load python file %s\n", path.c_str());
return false;
}
-
- FunctionList::iterator it = std::find(callbacks[action].begin(),
- callbacks[action].end(),
- callback);
- if (it == callbacks[action].end()) { // not already in there
- Py_XINCREF(callback); // Add a reference to new callback
- callbacks[action].push_back(callback);
- }
+ PyRun_SimpleFile(rcpyfd, const_cast<char*>(path.c_str()));
+ fclose(rcpyfd);
return true;
}
-bool python_preregister(int action, PyObject *callback)
+bool python_get_long(const char *name, long *value)
{
- if (action < 0 || action >= OBActions::NUM_ACTIONS ||
- action == OBActions::Action_KeyPress) {
- PyErr_SetString(PyExc_AssertionError, "Invalid action type.");
- return false;
- }
- if (!PyCallable_Check(callback)) {
- PyErr_SetString(PyExc_AssertionError, "Invalid callback function.");
- return false;
- }
+ PyObject *val = PyDict_GetItemString(obdict, const_cast<char*>(name));
+ if (!(val && PyInt_Check(val))) return false;
- FunctionList::iterator it = std::find(callbacks[action].begin(),
- callbacks[action].end(),
- callback);
- if (it == callbacks[action].end()) { // not already in there
- Py_XINCREF(callback); // Add a reference to new callback
- callbacks[action].insert(callbacks[action].begin(), callback);
- }
+ *value = PyInt_AsLong(val);
return true;
}
-bool python_unregister(int action, PyObject *callback)
+bool python_get_string(const char *name, otk::ustring *value)
{
- if (action < 0 || action >= OBActions::NUM_ACTIONS ||
- action == OBActions::Action_KeyPress) {
- PyErr_SetString(PyExc_AssertionError, "Invalid action type.");
- return false;
- }
- if (!PyCallable_Check(callback)) {
- PyErr_SetString(PyExc_AssertionError, "Invalid callback function.");
- return false;
- }
-
- FunctionList::iterator it = std::find(callbacks[action].begin(),
- callbacks[action].end(),
- callback);
- if (it != callbacks[action].end()) { // its been registered before
- Py_XDECREF(*it); // Dispose of previous callback
- callbacks[action].erase(it);
- }
+ PyObject *val = PyDict_GetItemString(obdict, const_cast<char*>(name));
+ if (!(val && PyString_Check(val))) return false;
+
+ *value = PyString_AsString(val);
return true;
}
-bool python_unregister_all(int action)
+bool python_get_stringlist(const char *name, std::vector<otk::ustring> *value)
{
- if (action < 0 || action >= OBActions::NUM_ACTIONS) {
- PyErr_SetString(PyExc_AssertionError, "Invalid action type.");
- return false;
- }
+ PyObject *val = PyDict_GetItemString(obdict, const_cast<char*>(name));
+ if (!(val && PyList_Check(val))) return false;
- while (!callbacks[action].empty()) {
- Py_XDECREF(callbacks[action].back());
- callbacks[action].pop_back();
+ for (int i = 0, end = PyList_Size(val); i < end; ++i) {
+ PyObject *str = PyList_GetItem(val, i);
+ if (PyString_Check(str))
+ value->push_back(PyString_AsString(str));
}
return true;
}
-void python_callback(OBActions::ActionType action, Window window,
- OBWidget::WidgetType type, unsigned int state,
- long d1, long d2, long d3, long d4)
-{
- PyObject *arglist;
- PyObject *result;
-
- assert(action >= 0 && action < OBActions::NUM_ACTIONS);
-
- if (d4 != LONG_MIN)
- arglist = Py_BuildValue("iliillll", action, window, type, state,
- d1, d2, d3, d4);
- else if (d3 != LONG_MIN)
- arglist = Py_BuildValue("iliilll", action, window, type, state,
- d1, d2, d3);
- else if (d2 != LONG_MIN)
- arglist = Py_BuildValue("iliill", action, window, type, state, d1, d2);
- else if (d1 != LONG_MIN)
- arglist = Py_BuildValue("iliil", action, window, type, state, d1);
- else
- arglist = Py_BuildValue("ilii", action, window, type, state);
-
- FunctionList::iterator it, end = callbacks[action].end();
- for (it = callbacks[action].begin(); it != end; ++it) {
- // call the callback
- result = PyEval_CallObject(*it, arglist);
- if (result) {
- Py_DECREF(result);
- } else {
- // an exception occured in the script, display it
- PyErr_Print();
- }
- }
-
- Py_DECREF(arglist);
-}
-
-
-
-
-
-
-bool python_bind(PyObject *keylist, PyObject *callback)
-{
- if (!PyList_Check(keylist)) {
- PyErr_SetString(PyExc_AssertionError, "Invalid keylist. Not a list.");
- return false;
- }
- if (!PyCallable_Check(callback)) {
- PyErr_SetString(PyExc_AssertionError, "Invalid callback function.");
- return false;
- }
-
- OBBindings::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_AssertionError,
- "Invalid keylist. It must contain only strings.");
- return false;
- }
- vectkeylist.push_back(PyString_AsString(str));
- }
-
- // the id is what the binding class can call back with so it doesnt have to
- // worry about the python function pointer
- int id = bindfuncs.size();
- if (Openbox::instance->bindings()->add(vectkeylist, id)) {
- Py_XINCREF(callback); // Add a reference to new callback
- bindfuncs.push_back(callback);
- return true;
- } else {
- PyErr_SetString(PyExc_AssertionError,"Unable to create binding. Invalid.");
- return false;
- }
-}
-
-bool python_unbind(PyObject *keylist)
-{
- if (!PyList_Check(keylist)) {
- PyErr_SetString(PyExc_AssertionError, "Invalid keylist. Not a list.");
- return false;
- }
-
- OBBindings::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_AssertionError,
- "Invalid keylist. It must contain only strings.");
- return false;
- }
- vectkeylist.push_back(PyString_AsString(str));
- }
-
- int id;
- if ((id =
- Openbox::instance->bindings()->remove(vectkeylist)) >= 0) {
- assert(bindfuncs[id]); // shouldn't be able to remove it twice
- Py_XDECREF(bindfuncs[id]); // Dispose of previous callback
- // important note: we don't erase the item from the list cuz that would
- // ruin all the id's that are in use. simply nullify it.
- bindfuncs[id] = 0;
- return true;
- }
-
- return false;
-}
-
-void python_set_reset_key(const std::string &key)
-{
- Openbox::instance->bindings()->setResetKey(key);
-}
-
-void python_unbind_all()
-{
- Openbox::instance->bindings()->remove_all();
-}
-
-
-void python_callback_binding(int id, Window window, unsigned int state,
- unsigned int keybutton, Time time)
-{
- if (!bindfuncs[id]) return; // the key was unbound
-
- PyObject *arglist;
- PyObject *result;
-
- arglist = Py_BuildValue("lisl", window, state,
- XKeysymToString(
- XKeycodeToKeysym(otk::OBDisplay::display,
- keybutton, 0)),
- time);
-
- // call the callback
- result = PyEval_CallObject(bindfuncs[id], arglist);
- if (result) {
- Py_DECREF(result);
- } else {
- // an exception occured in the script, display it
- PyErr_Print();
- }
-
- Py_DECREF(arglist);
-}
-
}