Hi,
Here is a patch for pygtk that exposes some of the lower-level gdk_window
functionality (creation of a gdk_window, show, hide, & destroy) to Python.
The motivation for this was a need to use an INPUT_ONLY GDK window to set
the cursor on the entire surface of a window, and to block mouse and
keyboard interaction with that window during that time (as you would when
the GUI is going to be unresponsive for a while due to some more lengthy
syncronous operation).
This could be used for other things as well, wherever there is a need to
temporarily overlay an existing window with an event-trapping transparent
window.
With this patch, you can now say something like this to set up a watch
cursor on any gtk_window:
gdk_window = my_gtkwindow.get_window()
attribs = { 'wmclass': GDK.INPUT_ONLY,
'window_type': GDK.WINDOW_CHILD,
'event_mask': 0,
'x': 0,
'y': 0,
'width': gtk.screen_width(),
'height': gtk.screen_height() }
cursor_win = gtk.gdk_window_new(gdk_window, attribs)
gdk_cursor = gtk.cursor_new(GDK.WATCH)
cursor_win.set_cursor(gdk_cursor)
cursor_win._show()
To set things back to normal you do this:
cursor_win._hide()
To show the watch again later:
cursor_win._show()
And when you're done with the cursor-setting window you say:
cursor_win.destroy()
cursor_win = None
This patch replaces the one that was sent by me to this list on Fri, 20
Oct 2000 20:28:38 -0400 (EDT). It is a cdiff based on a somewhat modified
pygtk 0.6.5, so may not apply automatically. But hopefully it's not too
hard to figure out, since it's just a set of added functions in several
files. The 'WINGIDE_EXTENSION' ifdefs and comments can of course be
removed.
Please let me know if you have any questions or run into any problems
with this.
I hope that it's something that can be considered for a future version
of pygtk.
Thanks,
- Stephan
------------------------------------------------------------------------
Archaeopteryx Software, Inc. Wing IDE for Python
www.archaeopteryx.com Take Flight!
Index: GDK.py
===================================================================
RCS file: /home/cvs/src/ide/external/pygtk-0.6.5-wing/GDK.py,v
retrieving revision 1.1
diff -c -r1.1 GDK.py
*** GDK.py 2000/03/13 18:45:37 1.1
--- GDK.py 2000/10/27 15:04:30
***************
*** 294,299 ****
--- 294,313 ----
XTERM = 152
CURSOR_IS_PIXMAP = -1
+ # WINGIDE_EXTENSIONS
+ # GdkWindowClass's
+ INPUT_OUTPUT = 0
+ INPUT_ONLY = 1
+
+ # GdkWindowType's
+ WINDOW_ROOT = 0
+ WINDOW_TOPLEVEL = 1
+ WINDOW_CHILD = 2
+ WINDOW_DIALOG = 3
+ WINDOW_TEMP = 4
+ WINDOW_PIXMAP = 5
+ WINDOW_FOREIGN = 6
+ # END WINGIDE_EXTENSIONS
# these are the Key Symbols for GDK
# they were created with sed -n 's/#define GDK)\([^ ]*\)/\1 =/p' <gdkkeysyms.h
Index: gtk.py
===================================================================
RCS file: /home/cvs/src/ide/external/pygtk-0.6.5-wing/gtk.py,v
retrieving revision 1.8
diff -c -r1.8 gtk.py
*** gtk.py 2000/09/25 19:47:24 1.8
--- gtk.py 2000/10/27 15:04:41
***************
*** 2738,2743 ****
--- 2738,2769 ----
keyval_to_upper = _gtk.gdk_keyval_to_upper
keyval_to_lower = _gtk.gdk_keyval_to_lower
+ # WINGIDE_EXTENSIONS
+ # Low-level function to create new gdk window
+ def gdk_window_new(parent, attribs):
+ """ Creates a new gdk window which must be destroyed with an
+ explicit call to the _destroy() method. parent is the new
+ window's parent PyGdkWindow or None if the window should be a
+ child of the root window. attribs must be a dictionary of
+ attribute values for the window; the following attribs must
+ be specified:
+ window_type -- GDK.WINDOW_TOPLEVEL, GDK.WINDOW_CHILD
+ GDK.WINDOW_DIALOG, GDK.WINDOW_TEMP
+ GDK.WINDOW_PIXMAP, or GDK.WINDOW_FOREIGN
+ event_mask -- the events to get
+ width -- width of window
+ height -- height of window
+ The following attributes are optional:
+ wmclass -- GDK.INPUT_OUTPUT or GDK.INPUT_ONLY
+ x -- x offset from parent
+ y -- y offset from parent
+ colormap -- PyGdkColormap to use to interpret colors
+ override_redirect -- see gdk / X documentation
+ """
+
+ return _gtk.gdk_window_new(parent, attribs)
+ # END WINGIDE_EXTENSIONS
+
# screen size
def screen_width():
return _gtk.gdk_screen_width()
Index: gtkmodule.c
===================================================================
RCS file: /home/cvs/src/ide/external/pygtk-0.6.5-wing/gtkmodule.c,v
retrieving revision 1.10
diff -c -r1.10 gtkmodule.c
*** gtkmodule.c 2000/09/28 22:49:52 1.10
--- gtkmodule.c 2000/10/27 15:05:30
***************
*** 1665,1670 ****
--- 1665,1700 ----
return Py_None;
}
+ #define WINGIDE_EXTENSIONS
+ #ifdef WINGIDE_EXTENSIONS
+ static PyObject *PyGdkWindow_Show(PyGdkWindow_Object *self,
+ PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":GdkWindow._show"))
+ return NULL;
+ gdk_window_show(self->obj);
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ static PyObject *PyGdkWindow_Hide(PyGdkWindow_Object *self,
+ PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":GdkWindow._hide"))
+ return NULL;
+ gdk_window_hide(self->obj);
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ static PyObject *PyGdkWindow_Destroy(PyGdkWindow_Object *self,
+ PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":GdkWindow._destroy"))
+ return NULL;
+ gdk_window_destroy(self->obj);
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ #endif
+
static PyObject *PyGdkWindow_InputGetPointer(PyGdkWindow_Object *self,
PyObject *args) {
guint32 deviceid;
***************
*** 1685,1690 ****
--- 1715,1725 ----
{"property_change", (PyCFunction)PyGdkWindow_PropertyChange, METH_VARARGS, NULL},
{"property_delete", (PyCFunction)PyGdkWindow_PropertyDelete, METH_VARARGS, NULL},
{"_raise", (PyCFunction)PyGdkWindow_Raise, METH_VARARGS, NULL},
+ #ifdef WINGIDE_EXTENSIONS
+ {"_show", (PyCFunction)PyGdkWindow_Show, METH_VARARGS, NULL},
+ {"_hide", (PyCFunction)PyGdkWindow_Hide, METH_VARARGS, NULL},
+ {"_destroy", (PyCFunction)PyGdkWindow_Destroy, METH_VARARGS, NULL},
+ #endif
{"lower", (PyCFunction)PyGdkWindow_Lower, METH_VARARGS, NULL},
{"input_get_pointer", (PyCFunction)PyGdkWindow_InputGetPointer, METH_VARARGS,
NULL},
{NULL, 0, 0, NULL}
***************
*** 6524,6529 ****
--- 6559,6706 ----
return Py_BuildValue("i", lower_val);
}
+
+ #ifdef WINGIDE_EXTENSIONS
+ static PyObject* _wrap_gdk_window_new(PyObject *self, PyObject *args) {
+ PyObject *parent;
+ PyObject *attr_map;
+ GdkWindow* gdk_parent;
+ GdkWindow* gdk_win;
+ PyObject* pygdk_win;
+ GdkWindowAttr attr;
+ guint attr_mask = 0;
+ PyObject *tmp;
+
+ // Parse args
+ if (!PyArg_ParseTuple(args, "OO!:gdk_window_new", &parent, &PyDict_Type,
+ &attr_map))
+ return NULL;
+
+ if (parent == Py_None)
+ gdk_parent = NULL;
+ else if (PyGdkWindow_Check(parent))
+ gdk_parent = ((PyGdkWindow_Object *) parent)->obj;
+ else {
+ PyErr_SetString(PyExc_TypeError, "window must be a PyGdkWindow or None");
+ return NULL;
+ }
+
+ // Fill in attribs
+ tmp = PyDict_GetItemString(attr_map, "window_type");
+ if (tmp == NULL) {
+ PyErr_SetString(PyExc_ValueError, "window_type value must be specified");
+ return NULL;
+ }
+ else {
+ if (!PyInt_Check(tmp)) {
+ PyErr_SetString(PyExc_TypeError, "window_type value must be an int");
+ return NULL;
+ }
+ attr.window_type = PyInt_AsLong(tmp);
+ }
+ tmp = PyDict_GetItemString(attr_map, "event_mask");
+ if (tmp == NULL) {
+ PyErr_SetString(PyExc_ValueError, "event_mask value must be specified");
+ return NULL;
+ }
+ else {
+ if (!PyInt_Check(tmp)) {
+ PyErr_SetString(PyExc_TypeError, "event_mask value must be an int");
+ return NULL;
+ }
+ attr.event_mask = PyInt_AsLong(tmp);
+ }
+ tmp = PyDict_GetItemString(attr_map, "width");
+ if (tmp == NULL) {
+ PyErr_SetString(PyExc_ValueError, "width value must be specified");
+ return NULL;
+ }
+ else {
+ if (!PyInt_Check(tmp)) {
+ PyErr_SetString(PyExc_TypeError, "width value must be an int");
+ return NULL;
+ }
+ attr.width = PyInt_AsLong(tmp);
+ }
+ tmp = PyDict_GetItemString(attr_map, "height");
+ if (tmp == NULL) {
+ PyErr_SetString(PyExc_ValueError, "height value must be specified");
+ return NULL;
+ }
+ else {
+ if (!PyInt_Check(tmp)) {
+ PyErr_SetString(PyExc_TypeError, "height value must be an int");
+ return NULL;
+ }
+ attr.height = PyInt_AsLong(tmp);
+ }
+ tmp = PyDict_GetItemString(attr_map, "wclass");
+ if (tmp != NULL) {
+ if (!PyInt_Check(tmp)) {
+ PyErr_SetString(PyExc_TypeError, "wmclass value must be an int");
+ return NULL;
+ }
+ attr.wclass = PyInt_AsLong(tmp);
+ attr_mask |= GDK_WA_WMCLASS;
+ }
+ /*
+ tmp = PyDict_GetItemString(attr_map, "visual");
+ if (tmp != NULL) {
+ if (!PyGtkVisual_Check(tmp)) {
+ PyErr_SetString(PyExc_TypeError, "visual value must be a PyGtkVisual");
+ return NULL;
+ }
+ attr.visual = ((PyGtkVisual*)tmp)->obj;
+ attr_mask |= GDK_WA_VISUAL;
+ }
+ */
+ tmp = PyDict_GetItemString(attr_map, "colormap");
+ if (tmp != NULL) {
+ if (!PyGdkColormap_Check(tmp)) {
+ PyErr_SetString(PyExc_TypeError, "colormap value must be a
+PyGdkColormap");
+ return NULL;
+ }
+ attr.colormap = ((PyGdkColormap_Object*)tmp)->obj;
+ attr_mask |= GDK_WA_COLORMAP;
+ }
+ tmp = PyDict_GetItemString(attr_map, "override_redirect");
+ if (tmp != NULL) {
+ if (!PyInt_Check(tmp)) {
+ PyErr_SetString(PyExc_TypeError, "override_redirect value must be an
+int");
+ return NULL;
+ }
+ attr.override_redirect = PyInt_AsLong(tmp);
+ attr_mask |= GDK_WA_NOREDIR;
+ }
+ tmp = PyDict_GetItemString(attr_map, "x");
+ if (tmp != NULL) {
+ if (!PyInt_Check(tmp)) {
+ PyErr_SetString(PyExc_TypeError, "x value must be an int");
+ return NULL;
+ }
+ attr.x = PyInt_AsLong(tmp);
+ attr_mask |= GDK_WA_X;
+ }
+ tmp = PyDict_GetItemString(attr_map, "y");
+ if (tmp != NULL) {
+ if (!PyInt_Check(tmp)) {
+ PyErr_SetString(PyExc_TypeError, "y value must be an int");
+ return NULL;
+ }
+ attr.y = PyInt_AsLong(tmp);
+ attr_mask |= GDK_WA_Y;
+ }
+
+ gdk_win = gdk_window_new(gdk_parent, &attr, attr_mask);
+ pygdk_win = PyGdkWindow_New(gdk_win);
+ if (pygdk_win == NULL) {
+ gdk_window_destroy(gdk_win);
+ return NULL;
+ }
+ return pygdk_win;
+ }
+ #endif
+
static PyMethodDef _gtkmoduleMethods[] = {
{ "gtk_signal_connect", _wrap_gtk_signal_connect, 1 },
{ "gtk_signal_connect_after", _wrap_gtk_signal_connect_after, 1 },
***************
*** 6566,6571 ****
--- 6743,6751 ----
{ "gtk_window_set_icon", _wrap_gtk_window_set_icon, 1 },
{ "gtk_window_set_icon_name", _wrap_gtk_window_set_icon_name, 1 },
{ "gtk_window_set_geometry_hints", _wrap_gtk_window_set_geometry_hints, 1 },
+ #ifdef WINGIDE_EXTENSIONS
+ { "gdk_window_new", _wrap_gdk_window_new, 1 },
+ #endif
{ "gtk_box_query_child_packing", _wrap_gtk_box_query_child_packing, 1 },
{ "gtk_button_box_get_child_size_default",
_wrap_gtk_button_box_get_child_size_default, 1 },
{ "gtk_button_box_get_child_ipadding_default",
_wrap_gtk_button_box_get_child_ipadding_default, 1 },