]> Dogcows Code - chaz/openbox/blob - src/python.cc
all broken now. working on adding mouse binding support
[chaz/openbox] / src / python.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #include "python.hh"
4 #include "openbox.hh"
5
6 #include <vector>
7 #include <algorithm>
8
9 namespace ob {
10
11 typedef std::vector<PyObject*> FunctionList;
12
13 static FunctionList callbacks[OBActions::NUM_ACTIONS];
14 static FunctionList keyfuncs;
15 static FunctionList mousefuncs;
16
17 bool python_register(int action, PyObject *callback)
18 {
19 if (action < 0 || action >= OBActions::NUM_ACTIONS) {
20 PyErr_SetString(PyExc_AssertionError, "Invalid action type.");
21 return false;
22 }
23 if (!PyCallable_Check(callback)) {
24 PyErr_SetString(PyExc_AssertionError, "Invalid callback function.");
25 return false;
26 }
27
28 FunctionList::iterator it = std::find(callbacks[action].begin(),
29 callbacks[action].end(),
30 callback);
31 if (it == callbacks[action].end()) { // not already in there
32 Py_XINCREF(callback); // Add a reference to new callback
33 callbacks[action].push_back(callback);
34 }
35 return true;
36 }
37
38 bool python_preregister(int action, PyObject *callback)
39 {
40 if (action < 0 || action >= OBActions::NUM_ACTIONS) {
41 PyErr_SetString(PyExc_AssertionError, "Invalid action type.");
42 return false;
43 }
44 if (!PyCallable_Check(callback)) {
45 PyErr_SetString(PyExc_AssertionError, "Invalid callback function.");
46 return false;
47 }
48
49 FunctionList::iterator it = std::find(callbacks[action].begin(),
50 callbacks[action].end(),
51 callback);
52 if (it == callbacks[action].end()) { // not already in there
53 Py_XINCREF(callback); // Add a reference to new callback
54 callbacks[action].insert(callbacks[action].begin(), callback);
55 }
56 return true;
57 }
58
59 bool python_unregister(int action, PyObject *callback)
60 {
61 if (action < 0 || action >= OBActions::NUM_ACTIONS) {
62 PyErr_SetString(PyExc_AssertionError, "Invalid action type.");
63 return false;
64 }
65 if (!PyCallable_Check(callback)) {
66 PyErr_SetString(PyExc_AssertionError, "Invalid callback function.");
67 return false;
68 }
69
70 FunctionList::iterator it = std::find(callbacks[action].begin(),
71 callbacks[action].end(),
72 callback);
73 if (it != callbacks[action].end()) { // its been registered before
74 Py_XDECREF(*it); // Dispose of previous callback
75 callbacks[action].erase(it);
76 }
77 return true;
78 }
79
80 bool python_unregister_all(int action)
81 {
82 if (action < 0 || action >= OBActions::NUM_ACTIONS) {
83 PyErr_SetString(PyExc_AssertionError, "Invalid action type.");
84 return false;
85 }
86
87 while (!callbacks[action].empty()) {
88 Py_XDECREF(callbacks[action].back());
89 callbacks[action].pop_back();
90 }
91 return true;
92 }
93
94 void python_callback(OBActions::ActionType action, Window window,
95 OBWidget::WidgetType type, unsigned int state,
96 long d1, long d2, long d3, long d4)
97 {
98 PyObject *arglist;
99 PyObject *result;
100
101 assert(action >= 0 && action < OBActions::NUM_ACTIONS);
102
103 if (d4 != LONG_MIN)
104 arglist = Py_BuildValue("iliillll", action, window, type, state,
105 d1, d2, d3, d4);
106 else if (d3 != LONG_MIN)
107 arglist = Py_BuildValue("iliilll", action, window, type, state,
108 d1, d2, d3);
109 else if (d2 != LONG_MIN)
110 arglist = Py_BuildValue("iliill", action, window, type, state, d1, d2);
111 else if (d1 != LONG_MIN)
112 arglist = Py_BuildValue("iliil", action, window, type, state, d1);
113 else
114 arglist = Py_BuildValue("ilii", action, window, type, state);
115
116 FunctionList::iterator it, end = callbacks[action].end();
117 for (it = callbacks[action].begin(); it != end; ++it) {
118 // call the callback
119 result = PyEval_CallObject(*it, arglist);
120 if (result) {
121 Py_DECREF(result);
122 } else {
123 // an exception occured in the script, display it
124 PyErr_Print();
125 }
126 }
127
128 Py_DECREF(arglist);
129 }
130
131
132
133
134
135
136 bool python_bind_key(PyObject *keylist, PyObject *callback)
137 {
138 if (!PyList_Check(keylist)) {
139 PyErr_SetString(PyExc_AssertionError, "Invalid keylist. Not a list.");
140 return false;
141 }
142 if (!PyCallable_Check(callback)) {
143 PyErr_SetString(PyExc_AssertionError, "Invalid callback function.");
144 return false;
145 }
146
147 OBBindings::StringVect vectkeylist;
148 for (int i = 0, end = PyList_Size(keylist); i < end; ++i) {
149 PyObject *str = PyList_GetItem(keylist, i);
150 if (!PyString_Check(str)) {
151 PyErr_SetString(PyExc_AssertionError,
152 "Invalid keylist. It must contain only strings.");
153 return false;
154 }
155 vectkeylist.push_back(PyString_AsString(str));
156 }
157
158 // the id is what the binding class can call back with so it doesnt have to
159 // worry about the python function pointer
160 int id = keyfuncs.size();
161 if (Openbox::instance->bindings()->add_key(vectkeylist, id)) {
162 Py_XINCREF(callback); // Add a reference to new callback
163 keyfuncs.push_back(callback);
164 return true;
165 } else {
166 PyErr_SetString(PyExc_AssertionError,"Unable to create binding. Invalid.");
167 return false;
168 }
169 }
170
171 bool python_unbind_key(PyObject *keylist)
172 {
173 if (!PyList_Check(keylist)) {
174 PyErr_SetString(PyExc_AssertionError, "Invalid keylist. Not a list.");
175 return false;
176 }
177
178 OBBindings::StringVect vectkeylist;
179 for (int i = 0, end = PyList_Size(keylist); i < end; ++i) {
180 PyObject *str = PyList_GetItem(keylist, i);
181 if (!PyString_Check(str)) {
182 PyErr_SetString(PyExc_AssertionError,
183 "Invalid keylist. It must contain only strings.");
184 return false;
185 }
186 vectkeylist.push_back(PyString_AsString(str));
187 }
188
189 int id;
190 if ((id =
191 Openbox::instance->bindings()->remove_key(vectkeylist)) >= 0) {
192 assert(keyfuncs[id]); // shouldn't be able to remove it twice
193 Py_XDECREF(keyfuncs[id]); // Dispose of previous callback
194 // important note: we don't erase the item from the list cuz that would
195 // ruin all the id's that are in use. simply nullify it.
196 keyfuncs[id] = 0;
197 return true;
198 }
199
200 return false;
201 }
202
203 bool python_bind_mouse(const std::string &button, PyObject *callback)
204 {
205 if (!PyCallable_Check(callback)) {
206 PyErr_SetString(PyExc_AssertionError, "Invalid callback function.");
207 return false;
208 }
209
210 // the id is what the binding class can call back with so it doesnt have to
211 // worry about the python function pointer
212 int id = mousefuncs.size();
213 if (Openbox::instance->bindings()->add_mouse(button, id)) {
214 Py_XINCREF(callback); // Add a reference to new callback
215 mousefuncs.push_back(callback);
216 return true;
217 } else {
218 PyErr_SetString(PyExc_AssertionError,"Unable to create binding. Invalid.");
219 return false;
220 }
221 }
222
223 bool python_unbind_mouse(const std::string &button)
224 {
225 int id;
226 if ((id =
227 Openbox::instance->bindings()->remove_mouse(button)) >= 0) {
228 assert(mousefuncs[id]); // shouldn't be able to remove it twice
229 Py_XDECREF(mousefuncs[id]); // Dispose of previous callback
230 // important note: we don't erase the item from the list cuz that would
231 // ruin all the id's that are in use. simply nullify it.
232 mousefuncs[id] = 0;
233 return true;
234 }
235
236 return false;
237 }
238
239 bool python_unbind_all()
240 {
241 Openbox::instance->bindings()->remove_all();
242 return true;
243 }
244
245
246 }
This page took 0.054704 seconds and 5 git commands to generate.