/* vim:set noet ts=4: */ /** * scim-python * * Copyright (c) 2007-2008 Huang Peng * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA * * $Id: $ */ #include "scim-python.h" #include using namespace scim; struct PyHelperAgentObject { PyListObject list; /* Type-specific fields go here. */ PyHelperAgent helper_agent; }; PyHelperAgent::PyHelperAgent (PyObject *self) :self ((PyHelperAgentObject *)self) { Py_INCREF (self); exit_signal_connection = signal_connect_exit (slot (this, &PyHelperAgent::slot_exit)); attach_input_context_signal_connection = signal_connect_attach_input_context (slot (this, &PyHelperAgent::slot_attach_input_context)); detach_input_context_signal_connection = signal_connect_detach_input_context (slot (this, &PyHelperAgent::slot_detach_input_context)); reload_config_signal_connection = signal_connect_reload_config (slot (this, &PyHelperAgent::slot_reload_config)); update_screen_signal_connection = signal_connect_update_screen (slot (this, &PyHelperAgent::slot_update_screen)); update_spot_location_signal_connection = signal_connect_update_spot_location (slot (this, &PyHelperAgent::slot_update_spot_location)); trigger_property_connection = signal_connect_trigger_property (slot (this, &PyHelperAgent::slot_trigger_property)); process_imengine_event_connection = signal_connect_process_imengine_event (slot (this, &PyHelperAgent::slot_process_imengine_event)); }; PyHelperAgent::~PyHelperAgent () { exit_signal_connection.disconnect (); attach_input_context_signal_connection.disconnect (); detach_input_context_signal_connection.disconnect (); reload_config_signal_connection.disconnect (); update_screen_signal_connection.disconnect (); update_spot_location_signal_connection.disconnect (); trigger_property_connection.disconnect (); process_imengine_event_connection.disconnect (); Py_XDECREF ((PyObject *)self); } void PyHelperAgent::operator delete (void *p) { // do nothing } PyObject * PyHelperAgent::py_open_connection (PyHelperAgentObject *self, PyObject *args) { char *uuid = NULL; char *name = NULL; char *icon = NULL; char *desc = NULL; int opt = 0; char *display; int retval; if (!PyArg_ParseTuple (args, "(ssssi)s:open_connection", &uuid, &name, &icon, &desc, &opt, &display)) return NULL; retval = self->helper_agent.open_connection (HelperInfo (uuid, name, icon, desc, opt), display); return PyInt_FromLong (retval); } PyObject * PyHelperAgent::py_close_connection (PyHelperAgentObject *self, PyObject *args) { self->helper_agent.close_connection (); Py_INCREF (Py_None); return Py_None; } PyObject * PyHelperAgent::py_get_connection_number (PyHelperAgentObject *self, PyObject *args) { int retval; retval = self->helper_agent.get_connection_number (); return PyInt_FromLong (retval); } PyObject * PyHelperAgent::py_is_connected (PyHelperAgentObject *self, PyObject *args) { PyObject *result = NULL; bool retval; retval = self->helper_agent.is_connected (); if (retval) { result = Py_True; } else { result = Py_False; } Py_INCREF (result); return result; } PyObject * PyHelperAgent::py_has_pending_event (PyHelperAgentObject *self, PyObject *args) { PyObject *result = NULL; bool retval; retval = self->helper_agent.has_pending_event (); if (retval) { result = Py_True; } else { result = Py_False; } Py_INCREF (result); return result; } PyObject * PyHelperAgent::py_filter_event (PyHelperAgentObject *self, PyObject *args) { PyObject *result = NULL; bool retval; retval = self->helper_agent.filter_event (); if (retval) { result = Py_True; } else { result = Py_False; } Py_INCREF (result); return result; } PyObject * PyHelperAgent::py_reload_config (PyHelperAgentObject *self, PyObject *args) { self->helper_agent.reload_config (); Py_INCREF (Py_None); return Py_None; } PyObject * PyHelperAgent::py_register_properties (PyHelperAgentObject *self, PyObject *args) { PyObject *props = NULL; PropertyList proplist; int i; if (!PyArg_ParseTuple (args, "O:register_properties", &props)) return NULL; if (PyList_Check (props)) { for (i = 0; i < PyList_Size (props); i++) { PyObject *prop = PyList_GetItem (props, i); proplist.push_back (PyProperty_AsProperty (prop)); } } else if (PyTuple_Check (props)) { for (i = 0; i < PyTuple_Size (props); i++) { PyObject *prop = PyTuple_GetItem (props, i); proplist.push_back (PyProperty_AsProperty (prop)); } } else { PyErr_SetString (PyExc_TypeError, "the argument must be a list or a tuple that contains propertys"); return NULL; } self->helper_agent.register_properties (proplist); Py_INCREF (Py_None); return Py_None; } PyObject * PyHelperAgent::py_update_property (PyHelperAgentObject *self, PyObject *args) { PyObject *prop = NULL; if (!PyArg_ParseTuple (args, "O:update_property", &prop)) return NULL; self->helper_agent.update_property (PyProperty_AsProperty (prop)); Py_INCREF (Py_None); return Py_None; } PyObject * PyHelperAgent::py_send_imengine_event (PyHelperAgentObject *self, PyObject *args) { int ic; char *ic_uuid = NULL; char *buf = NULL; int len = 0; Transaction trans; if (!PyArg_ParseTuple (args, "isst#:send_imengine_event", &ic, &ic_uuid, &buf, &len)) { return NULL; } trans.read_from_buffer (buf, len); self->helper_agent.send_imengine_event (ic, String (ic_uuid), trans); Py_INCREF (Py_None); return Py_None; Py_INCREF (Py_None); return Py_None; } PyObject * PyHelperAgent::py_send_key_event (PyHelperAgentObject *self, PyObject *args) { int ic; char *ic_uuid = NULL; int code, mask, layout; if (!PyArg_ParseTuple (args, "isiii:send_key_event", &ic, &ic_uuid, &code, &mask, &layout)) { return NULL; } self->helper_agent.send_key_event (ic, String (ic_uuid), KeyEvent (code, mask, layout)); Py_INCREF (Py_None); return Py_None; } PyObject * PyHelperAgent::py_forward_key_event (PyHelperAgentObject *self, PyObject *args) { int ic; char *ic_uuid = NULL; int code, mask, layout; if (!PyArg_ParseTuple (args, "isiii:forward_key_event", &ic, &ic_uuid, &code, &mask, &layout)) { return NULL; } self->helper_agent.forward_key_event (ic, String (ic_uuid), KeyEvent (code, mask, layout)); Py_INCREF (Py_None); return Py_None; } PyObject * PyHelperAgent::py_commit_string (PyHelperAgentObject *self, PyObject *args) { int ic; char *ic_uuid = NULL; char *str = NULL; if (!PyArg_ParseTuple (args, "iss:commit_string", &ic, &ic_uuid, &str)) { return NULL; } self->helper_agent.commit_string (ic, String (ic_uuid), utf8_mbstowcs (str)); Py_INCREF (Py_None); return Py_None; } #define PY_CALL(fun, args) ({ \ PyObject *pValue = NULL; \ PyObject *pFunc = NULL; \ pFunc = PyObject_GetAttrString ((PyObject *)this->self, fun);\ if (pFunc != NULL) { \ pValue = PyObject_CallObject (pFunc, args); \ Py_DECREF (pFunc); \ } \ pValue;}) #define PY_CHECK_RET(v) \ if (v == NULL) { \ PyErr_Print (); \ return; \ } void PyHelperAgent::slot_exit (const HelperAgent *helper, int ic, const String &ic_uuid) { } void PyHelperAgent::slot_attach_input_context (const HelperAgent *helper, int ic, const String &ic_uuid) { } void PyHelperAgent::slot_detach_input_context (const HelperAgent *helper, int ic, const String &ic_uuid) { } void PyHelperAgent::slot_reload_config (const HelperAgent *helper, int ic, const String &ic_uuid) { } void PyHelperAgent::slot_update_screen (const HelperAgent *helper, int ic, const String &ic_uuid, int screen_number) { } void PyHelperAgent::slot_update_spot_location (const HelperAgent *helper, int ic, const String &ic_uuid, int x, int y) { } void PyHelperAgent::slot_trigger_property (const HelperAgent *helper, int ic, const String &ic_uuid, const String &property) { PyObject *pValue = NULL; PyObject *pArgs = NULL; pArgs = Py_BuildValue ("(iss)", ic, ic_uuid.c_str (), property.c_str ()); pValue = PY_CALL ("trigger_property", pArgs); PY_CHECK_RET (pValue); Py_XDECREF (pArgs); Py_XDECREF (pValue); } void PyHelperAgent::slot_process_imengine_event (const HelperAgent *helper, int ic, const String &ic_uuid, const Transaction &transaction) { } PyMethodDef PyHelperAgent::py_methods[] = { { "open_connection", (PyCFunction)PyHelperAgent::py_open_connection, METH_VARARGS, "open a connection" }, { "get_connection_number", (PyCFunction)PyHelperAgent::py_get_connection_number, METH_NOARGS, "return id, that was returned by open_connection previously." }, { "close_connection", (PyCFunction)PyHelperAgent::py_close_connection, METH_NOARGS, "close the connection" }, { "is_connected", (PyCFunction)PyHelperAgent::py_is_connected, METH_NOARGS, "If agent is connected, the function returns True" }, { "has_pending_event", (PyCFunction)PyHelperAgent::py_has_pending_event, METH_NOARGS, "If agent has pending event, the function returns True" }, { "filter_event", (PyCFunction)PyHelperAgent::py_filter_event, METH_NOARGS, "filter events" }, { "reload_config", (PyCFunction)PyHelperAgent::py_reload_config, METH_NOARGS, "This function will cause all IM engines to reload config" }, { "register_properties", (PyCFunction)PyHelperAgent::py_register_properties, METH_VARARGS, "Register properties" }, { "update_property", (PyCFunction)PyHelperAgent::py_update_property, METH_VARARGS, "Update a property" }, { "send_imengine_event", (PyCFunction)PyHelperAgent::py_send_imengine_event, METH_VARARGS, "Send a event to IMEngine" }, { "send_key_event", (PyCFunction)PyHelperAgent::py_send_key_event, METH_VARARGS, "Send a keyevent" }, { "forward_key_event", (PyCFunction)PyHelperAgent::py_forward_key_event, METH_VARARGS, "Forward a keyevent" }, { "commit_string", (PyCFunction)PyHelperAgent::py_commit_string, METH_VARARGS, "Commit a string to IC" }, { NULL } }; PyObject * PyHelperAgent::py_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { PyHelperAgentObject *self; self = (PyHelperAgentObject *)type->tp_alloc (type, 0); return (PyObject *)self; } int PyHelperAgent::py_init (PyHelperAgentObject *self, PyObject *args, PyObject *kwds) { new (&self->helper_agent) PyHelperAgent ((PyObject *)self); return 0; } void PyHelperAgent::py_dealloc (PyHelperAgentObject *self) { self->helper_agent.~PyHelperAgent (); ((PyObject *) self)->ob_type->tp_free (self); } HelperAgent * PyHelperAgent::from_pyobject (PyObject *object) { PyHelperAgentObject *self = (PyHelperAgentObject *) object; return (HelperAgent *)&self->helper_agent; } PyTypeObject PyHelperAgentType = { PyObject_HEAD_INIT (NULL) 0, /*ob_size*/ "scim.HelperAgent", /*tp_name*/ sizeof (PyHelperAgentObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PyHelperAgent::py_dealloc, /*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*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "HelperAgent objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PyHelperAgent::py_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)PyHelperAgent::py_init, /* tp_init */ 0, /* tp_alloc */ PyHelperAgent::py_new, /* tp_new */ }; static void setint (PyObject *d, const char *name, long value) { PyObject *o = PyInt_FromLong (value); if (o && PyDict_SetItemString (d, name, o) == 0) { Py_DECREF (o); } } void init_helper (PyObject *module) { PyObject *dict = NULL; if (PyType_Ready (&PyHelperAgentType) < 0) return; Py_INCREF (&PyHelperAgentType); PyModule_AddObject (module, "HelperAgent", (PyObject *)&PyHelperAgentType); dict = PyModule_GetDict (module); setint (dict, "SCIM_HELPER_STAND_ALONE", SCIM_HELPER_STAND_ALONE); setint (dict, "SCIM_HELPER_AUTO_START", SCIM_HELPER_AUTO_START); setint (dict, "SCIM_HELPER_AUTO_RESTART", SCIM_HELPER_AUTO_RESTART); setint (dict, "SCIM_HELPER_NEED_SCREEN_INFO", SCIM_HELPER_NEED_SCREEN_INFO); setint (dict, "SCIM_HELPER_NEED_SPOT_LOCATION_INFO", SCIM_HELPER_NEED_SPOT_LOCATION_INFO); }