Remmina - The GTK+ Remote Desktop Client  v1.4.33
Remmina is a remote desktop client written in GTK+, aiming to be useful for system administrators and travellers, who need to work with lots of remote computers in front of either large monitors or tiny netbooks. Remmina supports multiple network protocols in an integrated and consistent user interface. Currently RDP, VNC, NX, XDMCP and SSH are supported.
src/pygobject.h
Go to the documentation of this file.
1 /* -*- Mode: C; c-basic-offset: 4 -*- */
2 /*
3  * Remmina - The GTK+ Remote Desktop Client
4  * Copyright (C) 2016-2023 Antenore Gatta, Giovanni Panozzo
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  * In addition, as a special exception, the copyright holders give
22  * permission to link the code of portions of this program with the
23  * OpenSSL library under certain conditions as described in each
24  * individual source file, and distribute linked combinations
25  * including the two.
26  * You must obey the GNU General Public License in all respects
27  * for all of the code used other than OpenSSL. * If you modify
28  * file(s) with this exception, you may extend this exception to your
29  * version of the file(s), but you are not obligated to do so. * If you
30  * do not wish to do so, delete this exception statement from your
31  * version. * If you delete this exception statement from all source
32  * files in the program, then also delete it here.
33  *
34  */
35 
36 #ifndef _PYGOBJECT_H_
37 #define _PYGOBJECT_H_
38 
39 #include <Python.h>
40 
41 #include <glib.h>
42 #include <glib-object.h>
43 
44 G_BEGIN_DECLS
45 
46 /* PyGClosure is a _private_ structure */
47 typedef void (* PyClosureExceptionHandler) (GValue *ret, guint n_param_values, const GValue *params);
48 typedef struct _PyGClosure PyGClosure;
49 typedef struct _PyGObjectData PyGObjectData;
50 
51 struct _PyGClosure {
52  GClosure closure;
53  PyObject *callback;
54  PyObject *extra_args; /* tuple of extra args to pass to callback */
55  PyObject *swap_data; /* other object for gtk_signal_connect__object */
57 };
58 
59 typedef enum {
63 
64  /* closures is just an alias for what is found in the
65  * PyGObjectData */
66 typedef struct {
67  PyObject_HEAD
68  GObject *obj;
69  PyObject *inst_dict; /* the instance dictionary -- must be last */
70  PyObject *weakreflist; /* list of weak references */
71 
72  /*< private >*/
73  /* using union to preserve ABI compatibility (structure size
74  * must not change) */
75  union {
76  GSList *closures; /* stale field; no longer updated DO-NOT-USE! */
78  } private_flags;
79 
80 } PyGObject;
81 
82 #define pygobject_get(v) (((PyGObject *)(v))->obj)
83 #define pygobject_check(v,base) (PyObject_TypeCheck(v,base))
84 
85 typedef struct {
86  PyObject_HEAD
87  gpointer boxed;
88  GType gtype;
89  gboolean free_on_dealloc;
90 } PyGBoxed;
91 
92 #define pyg_boxed_get(v,t) ((t *)((PyGBoxed *)(v))->boxed)
93 #define pyg_boxed_check(v,typecode) (PyObject_TypeCheck(v, &PyGBoxed_Type) && ((PyGBoxed *)(v))->gtype == typecode)
94 
95 typedef struct {
96  PyObject_HEAD
97  gpointer pointer;
98  GType gtype;
99 } PyGPointer;
100 
101 #define pyg_pointer_get(v,t) ((t *)((PyGPointer *)(v))->pointer)
102 #define pyg_pointer_check(v,typecode) (PyObject_TypeCheck(v, &PyGPointer_Type) && ((PyGPointer *)(v))->gtype == typecode)
103 
104 typedef void (*PyGFatalExceptionFunc) (void);
105 typedef void (*PyGThreadBlockFunc) (void);
106 
107 typedef struct {
108  PyObject_HEAD
109  GParamSpec *pspec;
110 } PyGParamSpec;
111 
112 #define PyGParamSpec_Get(v) (((PyGParamSpec *)v)->pspec)
113 #define PyGParamSpec_Check(v) (PyObject_TypeCheck(v, &PyGParamSpec_Type))
114 
115 typedef int (*PyGClassInitFunc) (gpointer gclass, PyTypeObject *pyclass);
116 typedef PyTypeObject * (*PyGTypeRegistrationFunction) (const gchar *name,
117  gpointer data);
118 
120  /*
121  * All field names in here are considered private,
122  * use the macros below instead, which provides stability
123  */
124  void (* register_class)(PyObject *dict, const gchar *class_name,
125  GType gtype, PyTypeObject *type, PyObject *bases);
126  void (* register_wrapper)(PyObject *self);
127  PyTypeObject *(* lookup_class)(GType type);
128  PyObject *(* newgobj)(GObject *obj);
129 
130  GClosure *(* closure_new)(PyObject *callback, PyObject *extra_args,
131  PyObject *swap_data);
132  void (* object_watch_closure)(PyObject *self, GClosure *closure);
133  GDestroyNotify destroy_notify;
134 
135  GType (* type_from_object)(PyObject *obj);
136  PyObject *(* type_wrapper_new)(GType type);
137 
138  gint (* enum_get_value)(GType enum_type, PyObject *obj, gint *val);
139  gint (* flags_get_value)(GType flag_type, PyObject *obj, gint *val);
140  void (* register_gtype_custom)(GType gtype,
141  PyObject *(* from_func)(const GValue *value),
142  int (* to_func)(GValue *value, PyObject *obj));
143  int (* value_from_pyobject)(GValue *value, PyObject *obj);
144  PyObject *(* value_as_pyobject)(const GValue *value, gboolean copy_boxed);
145 
146  void (* register_interface)(PyObject *dict, const gchar *class_name,
147  GType gtype, PyTypeObject *type);
148 
149  PyTypeObject *boxed_type;
150  void (* register_boxed)(PyObject *dict, const gchar *class_name,
151  GType boxed_type, PyTypeObject *type);
152  PyObject *(* boxed_new)(GType boxed_type, gpointer boxed,
153  gboolean copy_boxed, gboolean own_ref);
154 
155  PyTypeObject *pointer_type;
156  void (* register_pointer)(PyObject *dict, const gchar *class_name,
157  GType pointer_type, PyTypeObject *type);
158  PyObject *(* pointer_new)(GType boxed_type, gpointer pointer);
159 
160  void (* enum_add_constants)(PyObject *module, GType enum_type,
161  const gchar *strip_prefix);
162  void (* flags_add_constants)(PyObject *module, GType flags_type,
163  const gchar *strip_prefix);
164 
165  const gchar *(* constant_strip_prefix)(const gchar *name,
166  const gchar *strip_prefix);
167 
168  gboolean (* error_check)(GError **error);
169 
170  /* hooks to register handlers for getting GDK threads to cooperate
171  * with python threading */
172  void (* set_thread_block_funcs) (PyGThreadBlockFunc block_threads_func,
173  PyGThreadBlockFunc unblock_threads_func);
176  PyTypeObject *paramspec_type;
177  PyObject *(* paramspec_new)(GParamSpec *spec);
178  GParamSpec *(*paramspec_get)(PyObject *tuple);
179  int (*pyobj_to_unichar_conv)(PyObject *pyobj, void* ptr);
180  gboolean (*parse_constructor_args)(GType obj_type,
181  char **arg_names,
182  char **prop_names,
183  GParameter *params,
184  guint *nparams,
185  PyObject **py_args);
186  PyObject *(* param_gvalue_as_pyobject) (const GValue* gvalue,
187  gboolean copy_boxed,
188  const GParamSpec* pspec);
189  int (* gvalue_from_param_pyobject) (GValue* value,
190  PyObject* py_obj,
191  const GParamSpec* pspec);
192  PyTypeObject *enum_type;
193  PyObject *(*enum_add)(PyObject *module,
194  const char *type_name_,
195  const char *strip_prefix,
196  GType gtype);
197  PyObject* (*enum_from_gtype)(GType gtype, int value);
198 
199  PyTypeObject *flags_type;
200  PyObject *(*flags_add)(PyObject *module,
201  const char *type_name_,
202  const char *strip_prefix,
203  GType gtype);
204  PyObject* (*flags_from_gtype)(GType gtype, int value);
205 
206  gboolean threads_enabled;
207  int (*enable_threads) (void);
208 
209  int (*gil_state_ensure) (void);
210  void (*gil_state_release) (int flag);
211 
212  void (*register_class_init) (GType gtype, PyGClassInitFunc class_init);
213  void (*register_interface_info) (GType gtype, const GInterfaceInfo *info);
214  void (*closure_set_exception_handler) (GClosure *closure, PyClosureExceptionHandler handler);
215 
216  void (*add_warning_redirection) (const char *domain,
217  PyObject *warning);
218  void (*disable_warning_redirections) (void);
219  void (*type_register_custom)(const gchar *type_name,
221  gpointer data);
222  gboolean (*gerror_exception_check) (GError **error);
223  PyObject* (*option_group_new) (GOptionGroup *group);
224  GType (* type_from_object_strict) (PyObject *obj, gboolean strict);
225 };
226 
227 #ifndef _INSIDE_PYGOBJECT_
228 
229 #if defined(NO_IMPORT) || defined(NO_IMPORT_PYGOBJECT)
230 extern struct _PyGObject_Functions *_PyGObject_API;
231 #else
233 #endif
234 
235 #define pygobject_register_class (_PyGObject_API->register_class)
236 #define pygobject_register_wrapper (_PyGObject_API->register_wrapper)
237 #define pygobject_lookup_class (_PyGObject_API->lookup_class)
238 #define pygobject_new (_PyGObject_API->newgobj)
239 #define pyg_closure_new (_PyGObject_API->closure_new)
240 #define pygobject_watch_closure (_PyGObject_API->object_watch_closure)
241 #define pyg_closure_set_exception_handler (_PyGObject_API->closure_set_exception_handler)
242 #define pyg_destroy_notify (_PyGObject_API->destroy_notify)
243 #define pyg_type_from_object_strict (_PyGObject_API->type_from_object_strict)
244 #define pyg_type_from_object (_PyGObject_API->type_from_object)
245 #define pyg_type_wrapper_new (_PyGObject_API->type_wrapper_new)
246 #define pyg_enum_get_value (_PyGObject_API->enum_get_value)
247 #define pyg_flags_get_value (_PyGObject_API->flags_get_value)
248 #define pyg_register_gtype_custom (_PyGObject_API->register_gtype_custom)
249 #define pyg_value_from_pyobject (_PyGObject_API->value_from_pyobject)
250 #define pyg_value_as_pyobject (_PyGObject_API->value_as_pyobject)
251 #define pyg_register_interface (_PyGObject_API->register_interface)
252 #define PyGBoxed_Type (*_PyGObject_API->boxed_type)
253 #define pyg_register_boxed (_PyGObject_API->register_boxed)
254 #define pyg_boxed_new (_PyGObject_API->boxed_new)
255 #define PyGPointer_Type (*_PyGObject_API->pointer_type)
256 #define pyg_register_pointer (_PyGObject_API->register_pointer)
257 #define pyg_pointer_new (_PyGObject_API->pointer_new)
258 #define pyg_enum_add_constants (_PyGObject_API->enum_add_constants)
259 #define pyg_flags_add_constants (_PyGObject_API->flags_add_constants)
260 #define pyg_constant_strip_prefix (_PyGObject_API->constant_strip_prefix)
261 #define pyg_error_check (_PyGObject_API->error_check)
262 #define pyg_set_thread_block_funcs (_PyGObject_API->set_thread_block_funcs)
263 #define PyGParamSpec_Type (*_PyGObject_API->paramspec_type)
264 #define pyg_param_spec_new (_PyGObject_API->paramspec_new)
265 #define pyg_param_spec_from_object (_PyGObject_API->paramspec_get)
266 #define pyg_pyobj_to_unichar_conv (_PyGObject_API->pyobj_to_unichar_conv)
267 #define pyg_parse_constructor_args (_PyGObject_API->parse_constructor_args)
268 #define pyg_param_gvalue_as_pyobject (_PyGObject_API->value_as_pyobject)
269 #define pyg_param_gvalue_from_pyobject (_PyGObject_API->gvalue_from_param_pyobject)
270 #define PyGEnum_Type (*_PyGObject_API->enum_type)
271 #define pyg_enum_add (_PyGObject_API->enum_add)
272 #define pyg_enum_from_gtype (_PyGObject_API->enum_from_gtype)
273 #define PyGFlags_Type (*_PyGObject_API->flags_type)
274 #define pyg_flags_add (_PyGObject_API->flags_add)
275 #define pyg_flags_from_gtype (_PyGObject_API->flags_from_gtype)
276 #define pyg_enable_threads (_PyGObject_API->enable_threads)
277 #define pyg_gil_state_ensure (_PyGObject_API->gil_state_ensure)
278 #define pyg_gil_state_release (_PyGObject_API->gil_state_release)
279 #define pyg_register_class_init (_PyGObject_API->register_class_init)
280 #define pyg_register_interface_info (_PyGObject_API->register_interface_info)
281 #define pyg_add_warning_redirection (_PyGObject_API->add_warning_redirection)
282 #define pyg_disable_warning_redirections (_PyGObject_API->disable_warning_redirections)
283 #define pyg_type_register_custom_callback (_PyGObject_API->type_register_custom)
284 #define pyg_gerror_exception_check (_PyGObject_API->gerror_exception_check)
285 #define pyg_option_group_new (_PyGObject_API->option_group_new)
286 
287 #define pyg_block_threads() G_STMT_START { \
288  if (_PyGObject_API->block_threads != NULL) \
289  (* _PyGObject_API->block_threads)(); \
290  } G_STMT_END
291 #define pyg_unblock_threads() G_STMT_START { \
292  if (_PyGObject_API->unblock_threads != NULL) \
293  (* _PyGObject_API->unblock_threads)(); \
294  } G_STMT_END
295 
296 #define pyg_threads_enabled (_PyGObject_API->threads_enabled)
297 
298 #define pyg_begin_allow_threads \
299  G_STMT_START { \
300  PyThreadState *_save = NULL; \
301  if (_PyGObject_API->threads_enabled) \
302  _save = PyEval_SaveThread();
303 #define pyg_end_allow_threads \
304  if (_PyGObject_API->threads_enabled) \
305  PyEval_RestoreThread(_save); \
306  } G_STMT_END
307 
308 
322 static inline PyObject *
323 pygobject_init(int req_major, int req_minor, int req_micro)
324 {
325  PyObject *gobject, *cobject;
326 
327  gobject = PyImport_ImportModule("gi._gobject");
328  if (!gobject) {
329  if (PyErr_Occurred())
330  {
331  PyObject *type, *value, *traceback;
332  PyObject *py_orig_exc;
333  PyErr_Fetch(&type, &value, &traceback);
334  py_orig_exc = PyObject_Repr(value);
335  Py_XDECREF(type);
336  Py_XDECREF(value);
337  Py_XDECREF(traceback);
338 
339 
340 #if PY_VERSION_HEX < 0x03000000
341  PyErr_Format(PyExc_ImportError,
342  "could not import gobject (error was: %s)",
343  PyString_AsString(py_orig_exc));
344 #else
345  {
346  /* Can not use PyErr_Format because it doesn't have
347  * a format string for dealing with PyUnicode objects
348  * like PyUnicode_FromFormat has
349  */
350  PyObject *errmsg = PyUnicode_FromFormat("could not import gobject (error was: %U)",
351  py_orig_exc);
352 
353  if (errmsg) {
354  PyErr_SetObject(PyExc_ImportError,
355  errmsg);
356  Py_DECREF(errmsg);
357  }
358  /* if errmsg is NULL then we might have OOM
359  * PyErr should already be set and trying to
360  * return our own error would be futile
361  */
362  }
363 #endif
364  Py_DECREF(py_orig_exc);
365  } else {
366  PyErr_SetString(PyExc_ImportError,
367  "could not import gobject (no error given)");
368  }
369  return NULL;
370  }
371 
372  cobject = PyObject_GetAttrString(gobject, "_PyGObject_API");
373 #if PY_VERSION_HEX >= 0x03000000
374  if (cobject && PyCapsule_CheckExact(cobject))
375  _PyGObject_API = (struct _PyGObject_Functions *) PyCapsule_GetPointer(cobject, "gobject._PyGObject_API");
376 
377 #else
378  if (cobject && PyCObject_Check(cobject))
379  _PyGObject_API = (struct _PyGObject_Functions *) PyCObject_AsVoidPtr(cobject);
380 #endif
381  else {
382  PyErr_SetString(PyExc_ImportError,
383  "could not import gobject (could not find _PyGObject_API object)");
384  Py_DECREF(gobject);
385  return NULL;
386  }
387 
388  if (req_major != -1)
389  {
390  int found_major, found_minor, found_micro;
391  PyObject *version;
392 
393  version = PyObject_GetAttrString(gobject, "pygobject_version");
394  if (!version) {
395  PyErr_SetString(PyExc_ImportError,
396  "could not import gobject (version too old)");
397  Py_DECREF(gobject);
398  return NULL;
399  }
400  if (!PyArg_ParseTuple(version, "iii",
401  &found_major, &found_minor, &found_micro)) {
402  PyErr_SetString(PyExc_ImportError,
403  "could not import gobject (version has invalid format)");
404  Py_DECREF(version);
405  Py_DECREF(gobject);
406  return NULL;
407  }
408  Py_DECREF(version);
409  if (req_major != found_major ||
410  req_minor > found_minor ||
411  (req_minor == found_minor && req_micro > found_micro)) {
412  PyErr_Format(PyExc_ImportError,
413  "could not import gobject (version mismatch, %d.%d.%d is required, "
414  "found %d.%d.%d)", req_major, req_minor, req_micro,
415  found_major, found_minor, found_micro);
416  Py_DECREF(gobject);
417  return NULL;
418  }
419  }
420  return gobject;
421 }
422 
437  #define PYLIST_FROMGLIBLIST(type,prefix,py_list,list,item_convert_func,\
438  list_free,list_item_free) \
439 G_STMT_START \
440 { \
441  gint i, len; \
442  PyObject *item; \
443  void (*glib_list_free)(type*) = list_free; \
444  GFunc glib_list_item_free = (GFunc)list_item_free; \
445  \
446  len = prefix##_length(list); \
447  py_list = PyList_New(len); \
448  for (i = 0; i < len; i++) { \
449  gpointer list_item = prefix##_nth_data(list, i); \
450  \
451  item = item_convert_func; \
452  PyList_SetItem(py_list, i, item); \
453  } \
454  if (glib_list_item_free != NULL) \
455  prefix##_foreach(list, glib_list_item_free, NULL); \
456  if (glib_list_free != NULL) \
457  glib_list_free(list); \
458 } G_STMT_END
459 
492 #define PYLIST_FROMGLIST(py_list,list,item_convert_func,list_free,\
493  list_item_free) \
494  PYLIST_FROMGLIBLIST(GList,g_list,py_list,list,item_convert_func,\
495  list_free,list_item_free)
496 
529 #define PYLIST_FROMGSLIST(py_list,list,item_convert_func,list_free,\
530  list_item_free) \
531  PYLIST_FROMGLIBLIST(GSList,g_slist,py_list,list,item_convert_func,\
532  list_free,list_item_free)
533 
548 #define PYLIST_ASGLIBLIST(type,prefix,py_list,list,check_func,\
549  convert_func,child_free_func,errormsg,errorreturn) \
550 G_STMT_START \
551 { \
552  Py_ssize_t i, n_list; \
553  GFunc glib_child_free_func = (GFunc)child_free_func; \
554  \
555  if (!(py_list = PySequence_Fast(py_list, ""))) { \
556  errormsg; \
557  return errorreturn; \
558  } \
559  n_list = PySequence_Fast_GET_SIZE(py_list); \
560  for (i = 0; i < n_list; i++) { \
561  PyObject *py_item = PySequence_Fast_GET_ITEM(py_list, i); \
562  \
563  if (!check_func) { \
564  if (glib_child_free_func) \
565  prefix##_foreach(list, glib_child_free_func, NULL); \
566  prefix##_free(list); \
567  Py_DECREF(py_list); \
568  errormsg; \
569  return errorreturn; \
570  } \
571  list = prefix##_prepend(list, convert_func); \
572  }; \
573  Py_DECREF(py_list); \
574  list = prefix##_reverse(list); \
575 } \
576 G_STMT_END
577 
616 #define PYLIST_ASGLIST(py_list,list,check_func,convert_func,child_free_func,\
617  errormsg,errorreturn) \
618  PYLIST_ASGLIBLIST(GList,g_list,py_list,list,check_func,convert_func,\
619  child_free_func,errormsg,errorreturn)
620 
660 #define PYLIST_ASGSLIST(py_list,list,check_func,convert_func,child_free_func,\
661  errormsg,errorreturn) \
662  PYLIST_ASGLIBLIST(GSList,g_slist,py_list,list,check_func,convert_func,\
663  child_free_func,errormsg,errorreturn)
664 
665 #endif /* !_INSIDE_PYGOBJECT_ */
666 
667 G_END_DECLS
668 
669 #endif /* !_PYGOBJECT_H_ */
PyTypeObject *(* PyGTypeRegistrationFunction)(const gchar *name, gpointer data)
int(* PyGClassInitFunc)(gpointer gclass, PyTypeObject *pyclass)
PyTypeObject * pointer_type
PyGThreadBlockFunc block_threads
void(* PyGFatalExceptionFunc)(void)
PyClosureExceptionHandler exception_handler
Definition: src/pygobject.h:56
PyObject * inst_dict
Definition: src/pygobject.h:69
PyGObjectFlags flags
Definition: src/pygobject.h:77
PyObject_HEAD GParamSpec * pspec
G_BEGIN_DECLS typedef void(* PyClosureExceptionHandler)(GValue *ret, guint n_param_values, const GValue *params)
Definition: src/pygobject.h:47
PyTypeObject * boxed_type
GSList * closures
Definition: src/pygobject.h:76
PyTypeObject * enum_type
PyGObjectFlags
Definition: src/pygobject.h:59
PyTypeObject * flags_type
PyObject * callback
Definition: src/pygobject.h:53
struct _PyGObjectData PyGObjectData
Definition: src/pygobject.h:49
struct _PyGObject_Functions * _PyGObject_API
GType gtype
Definition: src/pygobject.h:88
PyTypeObject * paramspec_type
PyObject * extra_args
Definition: src/pygobject.h:54
static PyObject * pygobject_init(int req_major, int req_minor, int req_micro)
pygobject_init: : minimum version major number, or -1 : minimum version minor number, or -1 : minimum version micro number, or -1
GDestroyNotify destroy_notify
PyObject * weakreflist
Definition: src/pygobject.h:70
GClosure closure
Definition: src/pygobject.h:52
PyObject * swap_data
Definition: src/pygobject.h:55
PyObject_HEAD gpointer boxed
Definition: src/pygobject.h:87
void(* PyGThreadBlockFunc)(void)
gboolean free_on_dealloc
Definition: src/pygobject.h:89
PyGThreadBlockFunc unblock_threads
PyObject_HEAD GObject * obj
Definition: src/pygobject.h:68
PyObject_HEAD gpointer pointer
Definition: src/pygobject.h:97