Brad [2006-06-10, 06:06:07]: > I noticed this from the Gtk+ 2.9.2 release notes.. > > * Make GTK+ work as an untrused X client
applies reasonably well to the in tree version. i did some very minimal testing on i386, it seems to work. obviously, more testing with this is appreciated... Index: Makefile =================================================================== RCS file: /cvs/ports/x11/gtk+2/Makefile,v retrieving revision 1.38 diff -u -r1.38 Makefile --- Makefile 2006/06/03 19:56:56 1.38 +++ Makefile 2006/06/10 12:57:43 @@ -7,7 +7,7 @@ VERSION= 2.8.18 DISTNAME= gtk+-${VERSION} -PKGNAME= gtk+2-${VERSION}p1 +PKGNAME= gtk+2-${VERSION}p2 PKGNAME-docs= gtk+2-docs-${VERSION} CATEGORIES= x11 devel Index: patches/patch-gdk_x11_gdkdisplay-x11_c =================================================================== RCS file: patch-gdk_x11_gdkdisplay-x11_c diff -N patch-gdk_x11_gdkdisplay-x11_c --- /dev/null Sat Aug 30 18:16:59 1997 +++ patches/patch-gdk_x11_gdkdisplay-x11_c Sat Jun 10 12:57:43 2006 @@ -0,0 +1,38 @@ +$OpenBSD$ +--- gdk/x11/gdkdisplay-x11.c.orig Thu Jun 30 05:35:30 2005 ++++ gdk/x11/gdkdisplay-x11.c Sat Jun 10 14:32:57 2006 +@@ -224,6 +224,24 @@ gdk_display_open (const gchar *display_n + #endif + display_x11->have_xfixes = FALSE; + ++ display_x11->trusted_client = TRUE; ++ { ++ Window root, child; ++ int rootx, rooty, winx, winy; ++ unsigned int xmask; ++ ++ gdk_error_trap_push (); ++ XQueryPointer (display_x11->xdisplay, ++ GDK_SCREEN_X11 (display_x11->default_screen)->xroot_window, ++ &root, &child, &rootx, &rooty, &winx, &winy, &xmask); ++ gdk_flush (); ++ if (G_UNLIKELY (gdk_error_trap_pop () == BadWindow)) ++ { ++ g_warning ("Connection to display %s appears to be untrusted. Pointer and keyboard grabs and inter-client communication may not work as expected.", gdk_display_get_name (display)); ++ display_x11->trusted_client = FALSE; ++ } ++ } ++ + if (_gdk_synchronize) + XSynchronize (display_x11->xdisplay, True); + +@@ -1043,6 +1061,9 @@ gdk_notify_startup_complete (void) + display_x11 = GDK_DISPLAY_X11 (display); + + if (display_x11->startup_notification_id == NULL) ++ return; ++ ++ if (!G_LIKELY (display_x11->trusted_client)) + return; + + escaped_id = escape_for_xmessage (display_x11->startup_notification_id); Index: patches/patch-gdk_x11_gdkdisplay-x11_h =================================================================== RCS file: patch-gdk_x11_gdkdisplay-x11_h diff -N patch-gdk_x11_gdkdisplay-x11_h --- /dev/null Sat Aug 30 18:16:59 1997 +++ patches/patch-gdk_x11_gdkdisplay-x11_h Sat Jun 10 12:57:43 2006 @@ -0,0 +1,15 @@ +$OpenBSD$ +--- gdk/x11/gdkdisplay-x11.h.orig Thu Jun 30 05:35:30 2005 ++++ gdk/x11/gdkdisplay-x11.h Sat Jun 10 14:32:57 2006 +@@ -81,6 +81,11 @@ struct _GdkDisplayX11 + gboolean have_xfixes; + gint xfixes_event_base; + ++ /* If the SECURITY extension is in place, whether this client holds ++ * a trusted authorization and so is allowed to make various requests ++ * (grabs, properties etc.) Otherwise always TRUE. */ ++ gboolean trusted_client; ++ + /* Information about current pointer and keyboard grabs held by this + * client. If gdk_pointer_xgrab_window or gdk_keyboard_xgrab_window + * window is NULL, then the other associated fields are ignored Index: patches/patch-gdk_x11_gdkdnd-x11_c =================================================================== RCS file: patch-gdk_x11_gdkdnd-x11_c diff -N patch-gdk_x11_gdkdnd-x11_c --- /dev/null Sat Aug 30 18:16:59 1997 +++ patches/patch-gdk_x11_gdkdnd-x11_c Sat Jun 10 12:57:43 2006 @@ -0,0 +1,39 @@ +$OpenBSD$ +--- gdk/x11/gdkdnd-x11.c.orig Thu May 18 20:15:40 2006 ++++ gdk/x11/gdkdnd-x11.c Sat Jun 10 14:32:57 2006 +@@ -489,6 +489,25 @@ gdk_window_cache_new (GdkScreen *screen) + + XGetWindowAttributes (xdisplay, GDK_WINDOW_XWINDOW (root_window), &xwa); + result->old_event_mask = xwa.your_event_mask; ++ ++ if (G_UNLIKELY (!GDK_DISPLAY_X11 (GDK_SCREEN_X11 (screen)->display)->trusted_client)) ++ { ++ GList *toplevel_windows, *list; ++ GdkWindow *window; ++ gint x, y, width, height; ++ ++ toplevel_windows = gdk_screen_get_toplevel_windows (screen); ++ for (list = toplevel_windows; list; list = list->next) { ++ window = GDK_WINDOW (list->data); ++ gdk_window_get_geometry (window, &x, &y, &width, &height, NULL); ++ gdk_window_cache_add (result, GDK_WINDOW_XID (window), ++ x, y, width, height, ++ gdk_window_is_visible (window)); ++ } ++ g_list_free (toplevel_windows); ++ return result; ++ } ++ + XSelectInput (xdisplay, GDK_WINDOW_XWINDOW (root_window), + result->old_event_mask | SubstructureNotifyMask); + gdk_window_add_filter (root_window, gdk_window_cache_filter, result); +@@ -1315,6 +1334,9 @@ motif_send_enter (GdkDragContext *conte + GdkDragContextPrivateX11 *private = PRIVATE_DATA (context); + GdkDisplay *display = GDK_DRAWABLE_DISPLAY (context->source_window); + XEvent xev; ++ ++ if (!G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) ++ return; /* Motif Dnd requires getting properties on the root window */ + + xev.xclient.type = ClientMessage; + xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_MOTIF_DRAG_AND_DROP_MESSAGE"); Index: patches/patch-gdk_x11_gdkevents-x11_c =================================================================== RCS file: patch-gdk_x11_gdkevents-x11_c diff -N patch-gdk_x11_gdkevents-x11_c --- /dev/null Sat Aug 30 18:16:59 1997 +++ patches/patch-gdk_x11_gdkevents-x11_c Sat Jun 10 12:57:43 2006 @@ -0,0 +1,32 @@ +$OpenBSD$ +--- gdk/x11/gdkevents-x11.c.orig Wed Jan 11 07:30:38 2006 ++++ gdk/x11/gdkevents-x11.c Sat Jun 10 14:32:57 2006 +@@ -2551,6 +2551,8 @@ fetch_net_wm_check_window (GdkScreen *sc + + screen_x11 = GDK_SCREEN_X11 (screen); + display = screen_x11->display; ++ ++ g_return_if_fail (GDK_DISPLAY_X11 (display)->trusted_client); + + if (screen_x11->wmspec_check_window != None) + return; /* already have it */ +@@ -2608,6 +2610,9 @@ gdk_x11_screen_get_window_manager_name ( + + screen_x11 = GDK_SCREEN_X11 (screen); + ++ if (!G_LIKELY (GDK_DISPLAY_X11 (screen_x11->display)->trusted_client)) ++ return screen_x11->window_manager_name; ++ + fetch_net_wm_check_window (screen); + + if (screen_x11->need_refetch_wm_name) +@@ -2702,6 +2707,9 @@ gdk_x11_screen_supports_net_wm_hint (Gdk + + screen_x11 = GDK_SCREEN_X11 (screen); + display = screen_x11->display; ++ ++ if (!G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) ++ return FALSE; + + supported_atoms = g_object_get_data (G_OBJECT (screen), "gdk-net-wm-supported-atoms"); + if (!supported_atoms) Index: patches/patch-gdk_x11_gdkmain-x11_c =================================================================== RCS file: patch-gdk_x11_gdkmain-x11_c diff -N patch-gdk_x11_gdkmain-x11_c --- /dev/null Sat Aug 30 18:16:59 1997 +++ patches/patch-gdk_x11_gdkmain-x11_c Sat Jun 10 12:57:43 2006 @@ -0,0 +1,70 @@ +$OpenBSD$ +--- gdk/x11/gdkmain-x11.c.orig Thu Jul 7 21:05:33 2005 ++++ gdk/x11/gdkmain-x11.c Sat Jun 10 14:32:57 2006 +@@ -191,6 +191,7 @@ gdk_pointer_grab (GdkWindow * window, + { + gint return_val; + GdkCursorPrivate *cursor_private; ++ GdkDisplayX11 *display_x11; + guint xevent_mask; + Window xwindow; + Window xconfine_to; +@@ -202,6 +203,8 @@ gdk_pointer_grab (GdkWindow * window, + g_return_val_if_fail (GDK_IS_WINDOW (window), 0); + g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0); + ++ display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window)); ++ + cursor_private = (GdkCursorPrivate*) cursor; + + xwindow = GDK_WINDOW_XID (window); +@@ -233,7 +236,8 @@ gdk_pointer_grab (GdkWindow * window, + confine_to, + time); + +- if (return_val == GrabSuccess) ++ if (return_val == GrabSuccess || ++ G_UNLIKELY (!display_x11->trusted_client && return_val == AlreadyGrabbed)) + { + if (!GDK_WINDOW_DESTROYED (window)) + { +@@ -257,7 +261,6 @@ gdk_pointer_grab (GdkWindow * window, + + if (return_val == GrabSuccess) + { +- GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window)); + if (display_x11->pointer_xgrab_window != NULL && + display_x11->pointer_xgrab_window != (GdkWindowObject *)window) + generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window), +@@ -338,10 +341,13 @@ gdk_keyboard_grab (GdkWindow * window + { + gint return_val; + unsigned long serial; ++ GdkDisplayX11 *display_x11; + + g_return_val_if_fail (window != NULL, 0); + g_return_val_if_fail (GDK_IS_WINDOW (window), 0); + ++ display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window)); ++ + serial = NextRequest (GDK_WINDOW_XDISPLAY (window)); + + if (!GDK_WINDOW_DESTROYED (window)) +@@ -356,13 +362,16 @@ gdk_keyboard_grab (GdkWindow * window + owner_events, + GrabModeAsync, GrabModeAsync, + time); ++ if (G_UNLIKELY (!display_x11->trusted_client && ++ return_val == AlreadyGrabbed)) ++ /* we can't grab the keyboard, but we can do a GTK-local grab */ ++ return_val = GrabSuccess; + } + else + return_val = AlreadyGrabbed; + + if (return_val == GrabSuccess) + { +- GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window)); + if (display_x11->keyboard_xgrab_window != NULL && + display_x11->keyboard_xgrab_window != (GdkWindowObject *)window) + generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window), Index: patches/patch-gdk_x11_gdkwindow-x11_c =================================================================== RCS file: patch-gdk_x11_gdkwindow-x11_c diff -N patch-gdk_x11_gdkwindow-x11_c --- /dev/null Sat Aug 30 18:16:59 1997 +++ patches/patch-gdk_x11_gdkwindow-x11_c Sat Jun 10 12:57:43 2006 @@ -0,0 +1,275 @@ +$OpenBSD$ +--- gdk/x11/gdkwindow-x11.c.orig Sun Apr 16 07:05:03 2006 ++++ gdk/x11/gdkwindow-x11.c Sat Jun 10 14:37:24 2006 +@@ -89,6 +89,7 @@ static void gdk_window_add_colormap_ + static void set_wm_name (GdkDisplay *display, + Window xwindow, + const gchar *name); ++static void move_to_current_desktop (GdkWindow *window); + + static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable); + static void gdk_window_impl_x11_set_colormap (GdkDrawable *drawable, +@@ -761,6 +762,17 @@ gdk_window_new (GdkWindow *parent, + else + private->window_type = attributes->window_type; + ++ /* Work around a bug where Xorg refuses to map toplevel InputOnly windows ++ * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988 ++ */ ++ if (attributes->wclass == GDK_INPUT_ONLY && ++ GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT && ++ !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client)) ++ { ++ g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server"); ++ attributes->wclass = GDK_INPUT_OUTPUT; ++ } ++ + _gdk_window_init_position (GDK_WINDOW (private)); + if (impl->position_info.big) + private->guffaw_gravity = TRUE; +@@ -2040,7 +2052,13 @@ gdk_x11_window_move_to_current_desktop ( + + if (toplevel->on_all_desktops) + return; ++ ++ move_to_current_desktop (window); ++} + ++static void ++move_to_current_desktop (GdkWindow *window) ++{ + if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window), + gdk_atom_intern ("_NET_WM_DESKTOP", FALSE))) + { +@@ -3374,6 +3392,8 @@ _gdk_windowing_get_pointer (GdkDisplay + GdkModifierType *mask) + { + GdkScreen *default_screen; ++ Display *xdisplay; ++ Window xwindow; + Window root = None; + Window child; + int rootx, rooty; +@@ -3385,10 +3405,27 @@ _gdk_windowing_get_pointer (GdkDisplay + return; + + default_screen = gdk_display_get_default_screen (display); ++ ++ xdisplay = GDK_SCREEN_XDISPLAY (default_screen); ++ xwindow = GDK_SCREEN_XROOTWIN (default_screen); + +- XQueryPointer (GDK_SCREEN_XDISPLAY (default_screen), +- GDK_SCREEN_XROOTWIN (default_screen), +- &root, &child, &rootx, &rooty, &winx, &winy, &xmask); ++ if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) ++ { ++ XQueryPointer (xdisplay, xwindow, ++ &root, &child, &rootx, &rooty, &winx, &winy, &xmask); ++ } ++ else ++ { ++ XSetWindowAttributes attributes; ++ Window w; ++ ++ w = XCreateWindow (xdisplay, xwindow, 0, 0, 1, 1, 0, ++ CopyFromParent, InputOnly, CopyFromParent, ++ 0, &attributes); ++ XQueryPointer (xdisplay, w, ++ &root, &child, &rootx, &rooty, &winx, &winy, &xmask); ++ XDestroyWindow (xdisplay, w); ++ } + + if (root != None) + { +@@ -3422,13 +3459,28 @@ _gdk_windowing_window_get_pointer (GdkDi + _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset); + + return_val = NULL; +- if (!GDK_WINDOW_DESTROYED (window) && +- XQueryPointer (GDK_WINDOW_XDISPLAY (window), +- GDK_WINDOW_XID (window), +- &root, &child, &rootx, &rooty, &winx, &winy, &xmask)) ++ if (!GDK_WINDOW_DESTROYED (window)) + { +- if (child) +- return_val = gdk_window_lookup_for_display (GDK_WINDOW_DISPLAY (window), child); ++ if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) ++ { ++ if (XQueryPointer (GDK_WINDOW_XDISPLAY (window), ++ GDK_WINDOW_XID (window), ++ &root, &child, &rootx, &rooty, &winx, &winy, &xmask)) ++ { ++ if (child) ++ return_val = gdk_window_lookup_for_display (GDK_WINDOW_DISPLAY (window), child); ++ } ++ } ++ else ++ { ++ GdkScreen *screen; ++ int originx, originy; ++ _gdk_windowing_get_pointer (gdk_drawable_get_display (window), &screen, ++ &rootx, &rooty, &xmask); ++ gdk_window_get_origin (window, &originx, &originy); ++ winx = rootx - originx; ++ winy = rooty - originy; ++ } + } + + *x = winx + xoffset; +@@ -3501,24 +3553,89 @@ _gdk_windowing_window_at_pointer (GdkDis + * and the result. + */ + gdk_x11_display_grab (display); +- XQueryPointer (xdisplay, xwindow, +- &root, &child, &rootx, &rooty, &winx, &winy, &xmask); +- +- if (root == xwindow) +- xwindow = child; +- else +- xwindow = root; +- +- while (xwindow) ++ if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) + { +- xwindow_last = xwindow; + XQueryPointer (xdisplay, xwindow, +- &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask); ++ &root, &child, &rootx, &rooty, &winx, &winy, &xmask); ++ if (root == xwindow) ++ xwindow = child; ++ else ++ xwindow = root; ++ ++ while (xwindow) ++ { ++ xwindow_last = xwindow; ++ XQueryPointer (xdisplay, xwindow, ++ &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask); ++ } ++ } ++ else ++ { ++ gint i, screens, width, height; ++ GList *toplevels, *list; ++ Window pointer_window; ++ ++ pointer_window = None; ++ screens = gdk_display_get_n_screens (display); ++ for (i = 0; i < screens; ++i) { ++ screen = gdk_display_get_screen (display, i); ++ toplevels = gdk_screen_get_toplevel_windows (screen); ++ for (list = toplevels; list != NULL; list = g_list_next (list)) { ++ window = GDK_WINDOW (list->data); ++ xwindow = GDK_WINDOW_XWINDOW (window); ++ gdk_error_trap_push (); ++ XQueryPointer (xdisplay, xwindow, ++ &root, &child, &rootx, &rooty, &winx, &winy, &xmask); ++ gdk_flush (); ++ if (gdk_error_trap_pop ()) ++ continue; ++ if (child != None) ++ { ++ pointer_window = child; ++ break; ++ } ++ gdk_window_get_geometry (window, NULL, NULL, &width, &height, NULL); ++ if (winx >= 0 && winy >= 0 && winx < width && winy < height) ++ { ++ /* A childless toplevel, or below another window? */ ++ XSetWindowAttributes attributes; ++ Window w; ++ ++ w = XCreateWindow (xdisplay, xwindow, winx, winy, 1, 1, 0, ++ CopyFromParent, InputOnly, CopyFromParent, ++ 0, &attributes); ++ XMapWindow (xdisplay, w); ++ XQueryPointer (xdisplay, xwindow, ++ &root, &child, &rootx, &rooty, &winx, &winy, &xmask); ++ XDestroyWindow (xdisplay, w); ++ if (child == w) ++ { ++ pointer_window = xwindow; ++ break; ++ } ++ } ++ } ++ g_list_free (toplevels); ++ if (pointer_window != None) ++ break; ++ } ++ xwindow = pointer_window; ++ ++ while (xwindow) ++ { ++ xwindow_last = xwindow; ++ gdk_error_trap_push (); ++ XQueryPointer (xdisplay, xwindow, ++ &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask); ++ gdk_flush (); ++ if (gdk_error_trap_pop ()) ++ break; ++ } + } ++ + gdk_x11_display_ungrab (display); + +- window = gdk_window_lookup_for_display (GDK_SCREEN_DISPLAY(screen), +- xwindow_last); ++ window = gdk_window_lookup_for_display (display, xwindow_last); + *win_x = window ? winx : -1; + *win_y = window ? winy : -1; + +@@ -4353,52 +4470,12 @@ gdk_window_unstick (GdkWindow *window) + + if (GDK_WINDOW_IS_MAPPED (window)) + { +- XEvent xev; +- Atom type; +- gint format; +- gulong nitems; +- gulong bytes_after; +- guchar *data; +- gulong *current_desktop; +- GdkDisplay *display = gdk_drawable_get_display (window); +- + /* Request unstick from viewport */ + gdk_wmspec_change_state (FALSE, window, + gdk_atom_intern ("_NET_WM_STATE_STICKY", FALSE), + NULL); + +- /* Get current desktop, then set it; this is a race, but not +- * one that matters much in practice. +- */ +- XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), +- gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"), +- 0, G_MAXLONG, +- False, XA_CARDINAL, &type, &format, &nitems, +- &bytes_after, &data); +- +- if (type == XA_CARDINAL) +- { +- current_desktop = (gulong *)data; +- +- xev.xclient.type = ClientMessage; +- xev.xclient.serial = 0; +- xev.xclient.send_event = True; +- xev.xclient.window = GDK_WINDOW_XWINDOW (window); +- xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"); +- xev.xclient.format = 32; +- +- xev.xclient.data.l[0] = *current_desktop; +- xev.xclient.data.l[1] = 0; +- xev.xclient.data.l[2] = 0; +- xev.xclient.data.l[3] = 0; +- xev.xclient.data.l[4] = 0; +- +- XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False, +- SubstructureRedirectMask | SubstructureNotifyMask, +- &xev); +- +- XFree (current_desktop); +- } ++ move_to_current_desktop (window); + } + else + { Index: patches/patch-gtk_gtkcolorsel_c =================================================================== RCS file: patch-gtk_gtkcolorsel_c diff -N patch-gtk_gtkcolorsel_c --- /dev/null Sat Aug 30 18:16:59 1997 +++ patches/patch-gtk_gtkcolorsel_c Sat Jun 10 12:57:43 2006 @@ -0,0 +1,35 @@ +$OpenBSD$ +--- gtk/gtkcolorsel.c.orig Sat Jun 25 09:09:58 2005 ++++ gtk/gtkcolorsel.c Sat Jun 10 14:32:20 2006 +@@ -1227,6 +1227,17 @@ grab_color_at_mouse (GdkScreen *screen, + priv = colorsel->private_data; + + image = gdk_drawable_get_image (root_window, x_root, y_root, 1, 1); ++ if (!image) ++ { ++ gint x, y; ++ GdkDisplay *display = gdk_screen_get_display (screen); ++ GdkWindow *window = gdk_display_get_window_at_pointer (display, &x, &y); ++ if (!window) ++ return; ++ image = gdk_drawable_get_image (window, x, y, 1, 1); ++ if (!image) ++ return; ++ } + pixel = gdk_image_get_pixel (image, 0, 0); + g_object_unref (image); + +@@ -1436,11 +1447,11 @@ get_screen_color (GtkWidget *button) + gtk_widget_add_events (priv->dropper_grab_widget, + GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); + ++ gtk_widget_set_parent_window (priv->dropper_grab_widget, ++ GTK_WIDGET (colorsel)->window); + gtk_widget_show (priv->dropper_grab_widget); + + gdk_window_set_user_data (priv->dropper_grab_widget->window, colorsel); +- gdk_window_reparent (priv->dropper_grab_widget->window, +- GTK_WIDGET (colorsel)->window, 0, 0); + } + + if (gdk_keyboard_grab (priv->dropper_grab_widget->window, Index: patches/patch-gtk_gtkinvisible_c =================================================================== RCS file: patch-gtk_gtkinvisible_c diff -N patch-gtk_gtkinvisible_c --- /dev/null Sat Aug 30 18:16:59 1997 +++ patches/patch-gtk_gtkinvisible_c Sat Jun 10 12:57:43 2006 @@ -0,0 +1,30 @@ +$OpenBSD$ +--- gtk/gtkinvisible.c.orig Tue Mar 22 03:14:55 2005 ++++ gtk/gtkinvisible.c Sat Jun 10 14:32:20 2006 +@@ -246,11 +246,16 @@ gtk_invisible_get_screen (GtkInvisible * + static void + gtk_invisible_realize (GtkWidget *widget) + { ++ GdkWindow *parent; + GdkWindowAttr attributes; + gint attributes_mask; + + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + ++ parent = gtk_widget_get_parent_window (widget); ++ if (parent == NULL) ++ parent = gtk_widget_get_root_window (widget); ++ + attributes.x = -100; + attributes.y = -100; + attributes.width = 10; +@@ -262,8 +267,7 @@ gtk_invisible_realize (GtkWidget *widget + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR; + +- widget->window = gdk_window_new (gtk_widget_get_root_window (widget), +- &attributes, attributes_mask); ++ widget->window = gdk_window_new (parent, &attributes, attributes_mask); + + gdk_window_set_user_data (widget->window, widget); + Index: patches/patch-gtk_gtkwidget_c =================================================================== RCS file: patch-gtk_gtkwidget_c diff -N patch-gtk_gtkwidget_c --- /dev/null Sat Aug 30 18:16:59 1997 +++ patches/patch-gtk_gtkwidget_c Sat Jun 10 12:57:43 2006 @@ -0,0 +1,17 @@ +$OpenBSD$ +--- gtk/gtkwidget.c.orig Sat Apr 29 08:58:25 2006 ++++ gtk/gtkwidget.c Sat Jun 10 14:32:20 2006 +@@ -5616,11 +5616,11 @@ gtk_widget_get_parent_window (GtkWidge + GdkWindow *parent_window; + + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); +- g_return_val_if_fail (widget->parent != NULL, NULL); + + parent_window = g_object_get_qdata (G_OBJECT (widget), quark_parent_window); + +- return (parent_window != NULL) ? parent_window : widget->parent->window; ++ return (parent_window != NULL) ? parent_window : ++ (widget->parent != NULL) ? widget->parent->window : NULL; + } + + /** Disclaimer: http://www.kuleuven.be/cwis/email_disclaimer.htm