#include "Python.h" #include #include #include #include "evilwm.h" struct cargs { int (*mainf)(int argc, char**argv); int argc; char **argv; }; void* main_runner(void* _args) { struct cargs *args = (struct cargs*)_args; args->mainf(args->argc, args->argv); free(args); return NULL; } PyObject* run(PyObject *_, PyObject *pyargs) { int sz; int i; pthread_t t; PyEval_InitThreads(); struct cargs *args = malloc(sizeof(struct cargs)); args->mainf = wm_main; if(!PyTuple_Check(pyargs)) return PyExc_TypeError; sz = PyTuple_Size(pyargs); for(i = 0; i < sz; ++i) if(!PyString_Check(PyTuple_GetItem(pyargs, i))) return PyExc_TypeError; args->argc = sz + 1; args->argv = malloc(args->argc * sizeof(char *)); args->argv[0] = "m@rcell.wm"; for(i = 1; i < args->argc; ++i) { const char *str = PyString_AsString(PyTuple_GetItem(pyargs, i - 1)); args->argv[i] = malloc(strlen(str + 1)); strcpy(args->argv[i], str); } pthread_create(&t, NULL, main_runner, args); Py_RETURN_NONE; } ;;;; typedef struct { PyObject_HEAD Client *cli; char *name; } ClientObject; void Client_dtor(ClientObject *o) { // puts("tu i tamo stogod se i obrise"); free(o->name); o->ob_type->tp_free((PyObject*)o); } int client_is_valid(Client *c) { Client *it; for (it = head_client; it; it = it->next) if(it == c) return 1; return 0; } PyObject *Client_hide(ClientObject *self) { if(!client_is_valid(self->cli)) Py_RETURN_NONE; hide(self->cli); Py_RETURN_NONE; } PyObject *Client_show(ClientObject *self) { if(!client_is_valid(self->cli)) Py_RETURN_NONE; unhide(self->cli, RAISE); Py_RETURN_NONE; } PyObject *Client_focus(ClientObject *self) { if(!client_is_valid(self->cli)) Py_RETURN_NONE; select_client(self->cli); Py_RETURN_NONE; } PyObject *Client_kill(ClientObject *self) { if(!client_is_valid(self->cli)) Py_RETURN_NONE; send_wm_delete(self->cli, 1); Py_RETURN_NONE; } PyObject *Client_foo(ClientObject *self) { //if(!client_is_valid(self->cli)) Py_RETURN_NONE; printf("get attro: %x\n", ((PyObject*)self)->ob_type->tp_getattro); puts("bar"); Py_RETURN_NONE; } PyObject *Client_grab_mask(ClientObject *self) { if(!client_is_valid(self->cli)) Py_RETURN_NONE; grab_button(self->cli->parent, grabmask2, AnyButton); Py_RETURN_NONE; } PyObject *Client_grab_all(ClientObject *self) { if(!client_is_valid(self->cli)) Py_RETURN_NONE; grab_button(self->cli->parent, AnyModifier, AnyButton); Py_RETURN_NONE; } static PyMethodDef Client_methods [] = { {"hide", (PyCFunction)Client_hide, METH_NOARGS, "Hide the client"}, {"show", (PyCFunction)Client_show, METH_NOARGS, "Show the client"}, {"focus", (PyCFunction)Client_focus, METH_NOARGS, "Show the client"}, {"kill", (PyCFunction)Client_kill, METH_NOARGS, "Kill the client"}, {"set_grab_button_mask", (PyCFunction)Client_grab_mask, METH_NOARGS, "Kill the client"}, {"unset_grab_button_mask", (PyCFunction)Client_grab_all, METH_NOARGS, "Kill the client"}, //todo: remove fun, just add different args {"foo", (PyCFunction)Client_foo, METH_NOARGS, "foobar the client"}, {NULL} }; PyObject *Client_get_name(ClientObject *self, void *_) {return PyString_FromString(self->name);} #define CLIENT_GET_INT(attr) \ static PyObject *Client_get_ ## attr(ClientObject *self, void *_) \ {return PyInt_FromLong(self -> cli -> attr);} #define CLIENT_SET_INT(attr) \ static int Client_set_ ## attr(ClientObject *self, PyObject *val, void *_) \ { \ Client *c = self -> cli; \ c -> attr = PyInt_AsLong(val); \ XLockDisplay(dpy); \ moveresize(c); \ XUnlockDisplay(dpy); \ return 0; \ } CLIENT_GET_INT(x) CLIENT_GET_INT(y) CLIENT_GET_INT(width) CLIENT_GET_INT(height) CLIENT_SET_INT(x) CLIENT_SET_INT(y) CLIENT_SET_INT(width) CLIENT_SET_INT(height) static PyGetSetDef Client_getset[] = { {"x", (getter)Client_get_x, (setter)Client_set_x, "x coord", NULL}, {"y", (getter)Client_get_y, (setter)Client_set_y, "y coord", NULL}, {"width", (getter)Client_get_width, (setter)Client_set_width, "width", NULL}, {"height", (getter)Client_get_height, (setter)Client_set_height, "height", NULL}, {"name", (getter)Client_get_name, NULL, "name", NULL}, {NULL} }; PyObject *Client_getattro(PyObject *self, PyObject *attr) { PyObject* attrval = PyObject_GenericGetAttr(self, attr); if(!PyErr_ExceptionMatches(PyExc_AttributeError)) return attrval; PyErr_Clear(); attrval = PyDict_GetItem(((ClientObject*)self)->cli->dict, attr); if(!attrval) PyErr_SetString(PyExc_AttributeError, "err!"); return attrval; } int Client_setattro(PyObject *self, PyObject *attr, PyObject *val) { int ret = PyObject_GenericSetAttr(self, attr, val); if(!PyErr_ExceptionMatches(PyExc_AttributeError)) return ret; PyErr_Clear(); return PyDict_SetItem(((ClientObject*)self)->cli->dict, attr, val); } static PyTypeObject mwm_ClientType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "mwm.Client", /*tp_name*/ sizeof(ClientObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Client_dtor, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ Client_getattro, /*tp_getattro*/ Client_setattro, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ "WM client", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Client_methods, /* tp_methods */ 0, /* tp_members */ Client_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ }; void set_name(ClientObject *o, const char *name) { int len = strlen(name); o->name = malloc(len + 1); strcpy(o->name, name); } PyObject* Client_ctor(Client*c) { ClientObject *o = (ClientObject*)mwm_ClientType.tp_alloc(&mwm_ClientType, 0); PyObject *pyo = (PyObject*)(o); o->cli = c; XTextProperty tp; if (!XGetWMName(dpy, c->window, &tp)) { set_name(o, "(no name)"); } else if (tp.nitems > 0) { int count = 0, i, ret; char **list = NULL; ret = XmbTextPropertyToTextList(dpy, &tp, &list, &count); if((ret == Success || ret > 0) && list != NULL) { for(i=0; inext) PyList_Append(lst, Client_ctor(c)); return lst; } PyObject* get_focused(PyObject*_, PyObject*__) { if(!current) Py_RETURN_NONE; Client_ctor(current); } ;;; #define HOOK_HANDLE(name) \ PyObject * name ## _hook = NULL; \ PyObject* set_ ## name ## _hook(PyObject *_, PyObject* pyargs) \ { \ if(!PyTuple_Check(pyargs)) return PyExc_TypeError; \ if(PyTuple_Size(pyargs) != 1) return PyExc_TypeError; \ PyObject* hook = PyTuple_GetItem(pyargs, 0); \ PyObject *ret = name ## _hook; \ if(!PyCallable_Check(hook)) return PyExc_TypeError; \ \ Py_INCREF(hook); \ name ## _hook = hook; \ \ if(ret) return ret; \ Py_RETURN_NONE; \ } \ PyObject* run_ ## name ## _hook(Client *c) \ { \ PyObject *ret; \ if(!name ## _hook) return NULL; \ PyGILState_STATE s = PyGILState_Ensure(); \ PyObject *arg = PyTuple_New(1); \ PyTuple_SetItem(arg, 0, Client_ctor(c)); \ ret = PyObject_CallObject(name ## _hook, arg); \ Py_DECREF(arg); \ PyGILState_Release(s); \ return ret; \ } HOOK_HANDLE(geometry); HOOK_HANDLE(drag_start); HOOK_HANDLE(drag_end); HOOK_HANDLE(sweep_start); HOOK_HANDLE(sweep_end); HOOK_HANDLE(mouse_enter); HOOK_HANDLE(mouse_leave); HOOK_HANDLE(mouse_button1); HOOK_HANDLE(mouse_button2); HOOK_HANDLE(mouse_button3); ;;; #define HOOK_EXPOSE(sname, hname) \ {#sname, set_ ## hname ## _hook, METH_VARARGS} PyObject* set_key_hook(PyObject *_, PyObject* pyargs); //todo: remove PyMODINIT_FUNC initmwm(void) { static PyMethodDef mtds[] = { HOOK_EXPOSE(set_post_geometry_hook, geometry), HOOK_EXPOSE(set_drag_start_hook, drag_start), HOOK_EXPOSE(set_drag_end_hook, drag_end), HOOK_EXPOSE(set_sweep_start_hook, sweep_start), HOOK_EXPOSE(set_sweep_end_hook, sweep_end), HOOK_EXPOSE(set_mouse_enter_hook, mouse_enter), HOOK_EXPOSE(set_mouse_leave_hook, mouse_leave), HOOK_EXPOSE(set_mouse_button1_hook, mouse_button1), HOOK_EXPOSE(set_mouse_button2_hook, mouse_button2), HOOK_EXPOSE(set_mouse_button3_hook, mouse_button3), HOOK_EXPOSE(set_key, key), //todo: remove // {"set_post_geometry_hook", set_post_geometry_hook, METH_VARARGS}, {"list", list, METH_VARARGS}, {"run", run, METH_VARARGS}, {"grab_keys", grab_keys, METH_VARARGS}, {"focused", get_focused, METH_VARARGS}, {NULL, NULL, 0, NULL}}; PyObject* m; mwm_ClientType.tp_new = PyType_GenericNew; if (PyType_Ready(&mwm_ClientType) < 0) return; m = Py_InitModule("mwm", mtds); Py_INCREF(&mwm_ClientType); PyModule_AddObject(m, "Client", (PyObject*)&mwm_ClientType); }