summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog56
-rw-r--r--ChangeLog.pre-2-1056
-rw-r--r--gdk/x11/gdkdisplay-x11.c21
-rw-r--r--gdk/x11/gdkdisplay-x11.h5
-rw-r--r--gdk/x11/gdkdnd-x11.c22
-rw-r--r--gdk/x11/gdkevents-x11.c8
-rw-r--r--gdk/x11/gdkmain-x11.c15
-rw-r--r--gdk/x11/gdkwindow-x11.c203
-rw-r--r--gtk/gtkcolorsel.c15
-rw-r--r--gtk/gtkinvisible.c8
-rw-r--r--gtk/gtkwidget.c4
11 files changed, 341 insertions, 72 deletions
diff --git a/ChangeLog b/ChangeLog
index e53f1cfb10..cc8143eee3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,59 @@
+2006-05-25 Matthias Clasen <mclasen@redhat.com>
+
+ Make GTK+ work as an untrusted X client. (#136571,
+ Ed Catmur)
+
+ * gdk/x11/gdkdisplay-x11.h:
+ * gdk/x11/gdkdisplay-x11.c (gdk_display_open): When
+ opening a display, determine if we are untrusted.
+
+ * gdk/x11/gdkdisplay-x11.c (gdk_notify_startup_complete):
+ Just bail out when we are untrusted.
+
+ * gdk/x11/gdkwindow-x11.c (gdk_window_new): Work around
+ a bug in the Xorg XSECURITY implementation by coercing
+ toplevel InputOnly windows to InputOutput.
+
+ * gdk/x11/gdkwindow-x11.c (_gdk_windowing_get_pointer):
+ (_gdk_windowing_window_get_pointer):
+ When untrusted, call XQueryPointer on an auxiliary
+ window, not on the root window.
+
+ * gdk/x11/gdkwindow-x11.c (_gdk_windowing_window_at_pointer):
+ If untrusted, loop through all GDK-aware toplevels on all
+ screens in the hope we hit one containing the pointer;
+ then use that as the basis of the current XQueryPointer
+ child recursion.
+
+ * gdk/x11/gdkmain-x11.c (gdk_pointer_grab):
+ (gdk_keyboard_grab): Ignore failed grabs when untrusted.
+
+ * gdk/x11/gdkdnd-x11.c (gdk_window_cache_new): Only
+ cache our own toplevels when untrusted.
+
+ * gdk/x11/gdkdnd-x11.c (motif_send_enter): Don't try
+ to do Motif DND as untrusted client.
+
+ * gdk/x11/gdkevents-x11.c (fetch_net_wm_check_window):
+ (gdk_x11_screen_get_window_manager_name):
+ (gdk_x11_screen_supports_net_wm_hint):
+ Bail out early if untrusted.
+
+ * gtk/gtkcolorsel.c (grab_color_at_mouse): If getting
+ the color under the pointer by screenshooting the root
+ window fails, it tries to get the color from our own
+ window.
+
+ * gtk/gtkcolorsel.c (get_screen_color): Make the
+ dropper_grab_widget a child of the dialog, not a
+ toplevel.
+
+ * gtk/gtkinvisible.c (gtk_invisible_realize): Respect
+ a parent window that has been set before realizing.
+
+ * gtk/gtkwidget.c (gtk_widget_get_parent_window):
+ Always return a previously set parent window.
+
2006-05-24 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkfontbutton.c (gtk_font_button_clicked):
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
index e53f1cfb10..cc8143eee3 100644
--- a/ChangeLog.pre-2-10
+++ b/ChangeLog.pre-2-10
@@ -1,3 +1,59 @@
+2006-05-25 Matthias Clasen <mclasen@redhat.com>
+
+ Make GTK+ work as an untrusted X client. (#136571,
+ Ed Catmur)
+
+ * gdk/x11/gdkdisplay-x11.h:
+ * gdk/x11/gdkdisplay-x11.c (gdk_display_open): When
+ opening a display, determine if we are untrusted.
+
+ * gdk/x11/gdkdisplay-x11.c (gdk_notify_startup_complete):
+ Just bail out when we are untrusted.
+
+ * gdk/x11/gdkwindow-x11.c (gdk_window_new): Work around
+ a bug in the Xorg XSECURITY implementation by coercing
+ toplevel InputOnly windows to InputOutput.
+
+ * gdk/x11/gdkwindow-x11.c (_gdk_windowing_get_pointer):
+ (_gdk_windowing_window_get_pointer):
+ When untrusted, call XQueryPointer on an auxiliary
+ window, not on the root window.
+
+ * gdk/x11/gdkwindow-x11.c (_gdk_windowing_window_at_pointer):
+ If untrusted, loop through all GDK-aware toplevels on all
+ screens in the hope we hit one containing the pointer;
+ then use that as the basis of the current XQueryPointer
+ child recursion.
+
+ * gdk/x11/gdkmain-x11.c (gdk_pointer_grab):
+ (gdk_keyboard_grab): Ignore failed grabs when untrusted.
+
+ * gdk/x11/gdkdnd-x11.c (gdk_window_cache_new): Only
+ cache our own toplevels when untrusted.
+
+ * gdk/x11/gdkdnd-x11.c (motif_send_enter): Don't try
+ to do Motif DND as untrusted client.
+
+ * gdk/x11/gdkevents-x11.c (fetch_net_wm_check_window):
+ (gdk_x11_screen_get_window_manager_name):
+ (gdk_x11_screen_supports_net_wm_hint):
+ Bail out early if untrusted.
+
+ * gtk/gtkcolorsel.c (grab_color_at_mouse): If getting
+ the color under the pointer by screenshooting the root
+ window fails, it tries to get the color from our own
+ window.
+
+ * gtk/gtkcolorsel.c (get_screen_color): Make the
+ dropper_grab_widget a child of the dialog, not a
+ toplevel.
+
+ * gtk/gtkinvisible.c (gtk_invisible_realize): Respect
+ a parent window that has been set before realizing.
+
+ * gtk/gtkwidget.c (gtk_widget_get_parent_window):
+ Always return a previously set parent window.
+
2006-05-24 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkfontbutton.c (gtk_font_button_clicked):
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index 1304a83125..af90587f76 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -219,6 +219,24 @@ gdk_display_open (const gchar *display_name)
}
#endif
+ 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);
@@ -1056,6 +1074,9 @@ gdk_notify_startup_complete (void)
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);
message = g_strdup_printf ("remove: ID=%s", escaped_id);
g_free (escaped_id);
diff --git a/gdk/x11/gdkdisplay-x11.h b/gdk/x11/gdkdisplay-x11.h
index 36defc8d98..14b8fd5b29 100644
--- a/gdk/x11/gdkdisplay-x11.h
+++ b/gdk/x11/gdkdisplay-x11.h
@@ -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
diff --git a/gdk/x11/gdkdnd-x11.c b/gdk/x11/gdkdnd-x11.c
index b4eb8e9d39..7e0961c771 100644
--- a/gdk/x11/gdkdnd-x11.c
+++ b/gdk/x11/gdkdnd-x11.c
@@ -460,6 +460,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);
@@ -1287,6 +1306,9 @@ motif_send_enter (GdkDragContext *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");
xev.xclient.format = 8;
diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c
index 46cdd12857..d64925b9e5 100644
--- a/gdk/x11/gdkevents-x11.c
+++ b/gdk/x11/gdkevents-x11.c
@@ -2574,6 +2574,8 @@ fetch_net_wm_check_window (GdkScreen *screen)
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 */
@@ -2631,6 +2633,9 @@ gdk_x11_screen_get_window_manager_name (GdkScreen *screen)
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)
@@ -2726,6 +2731,9 @@ gdk_x11_screen_supports_net_wm_hint (GdkScreen *screen,
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)
{
diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c
index 72f7339749..75e69479d3 100644
--- a/gdk/x11/gdkmain-x11.c
+++ b/gdk/x11/gdkmain-x11.c
@@ -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),
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
index dd26bca996..55b153a9ba 100644
--- a/gdk/x11/gdkwindow-x11.c
+++ b/gdk/x11/gdkwindow-x11.c
@@ -88,6 +88,7 @@ static void gdk_window_add_colormap_windows (GdkWindow *window);
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,
@@ -731,6 +732,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;
@@ -2007,7 +2019,13 @@ gdk_x11_window_move_to_current_desktop (GdkWindow *window)
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_static_string ("_NET_WM_DESKTOP")))
{
@@ -3428,6 +3446,8 @@ _gdk_windowing_get_pointer (GdkDisplay *display,
GdkModifierType *mask)
{
GdkScreen *default_screen;
+ Display *xdisplay;
+ Window xwindow;
Window root = None;
Window child;
int rootx, rooty;
@@ -3439,10 +3459,27 @@ _gdk_windowing_get_pointer (GdkDisplay *display,
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)
{
@@ -3476,13 +3513,28 @@ _gdk_windowing_window_get_pointer (GdkDisplay *display,
_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;
@@ -3555,24 +3607,89 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
* 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;
@@ -4480,52 +4597,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_static_string ("_NET_WM_STATE_STICKY"),
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
{
diff --git a/gtk/gtkcolorsel.c b/gtk/gtkcolorsel.c
index 24eae26ba5..eec02636af 100644
--- a/gtk/gtkcolorsel.c
+++ b/gtk/gtkcolorsel.c
@@ -1224,6 +1224,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);
@@ -1429,11 +1440,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,
diff --git a/gtk/gtkinvisible.c b/gtk/gtkinvisible.c
index 3cf3a2ae9f..c944b770be 100644
--- a/gtk/gtkinvisible.c
+++ b/gtk/gtkinvisible.c
@@ -214,11 +214,16 @@ gtk_invisible_get_screen (GtkInvisible *invisible)
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;
@@ -230,8 +235,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);
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index c43b35cd72..d9d3b53bd2 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -5822,11 +5822,11 @@ gtk_widget_get_parent_window (GtkWidget *widget)
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;
}
/**