* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
+#include <config.h>
+
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <netinet/in.h>
#include <unistd.h>
+
#include "gdk.h"
-#include "config.h"
#include "gdkwindow.h"
+#include "gdkasync.h"
#include "gdkinputprivate.h"
#include "gdkdisplay-x11.h"
#include "gdkprivate-x11.h"
#include "gdkinternals.h"
#include "MwmUtil.h"
#include "gdkwindow-x11.h"
+#include "gdkalias.h"
#include <stdlib.h>
#include <stdio.h>
const int _gdk_nenvent_masks = sizeof (_gdk_event_mask_table) / sizeof (int);
/* Forward declarations */
-static gboolean gdk_window_gravity_works (GdkWindow *window);
static void gdk_window_set_static_win_gravity (GdkWindow *window,
gboolean on);
-static gboolean gdk_window_have_shape_ext (GdkDisplay *display);
static gboolean gdk_window_icon_name_set (GdkWindow *window);
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,
gint *width,
gint *height);
static GdkRegion* gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable);
-static void gdk_window_impl_x11_init (GdkWindowImplX11 *window);
-static void gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass);
static void gdk_window_impl_x11_finalize (GObject *object);
-static gpointer parent_class = NULL;
+#define WINDOW_IS_TOPLEVEL(window) \
+ (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
+ GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
-GType
-gdk_window_impl_x11_get_type (void)
-{
- static GType object_type = 0;
+/* Return whether time1 is considered later than time2 as far as xserver
+ * time is concerned. Accounts for wraparound.
+ */
+#define XSERVER_TIME_IS_LATER(time1, time2) \
+ ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) || \
+ (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 )) \
+ )
- if (!object_type)
- {
- static const GTypeInfo object_info =
- {
- sizeof (GdkWindowImplX11Class),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) gdk_window_impl_x11_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (GdkWindowImplX11),
- 0, /* n_preallocs */
- (GInstanceInitFunc) gdk_window_impl_x11_init,
- };
-
- object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_X11,
- "GdkWindowImplX11",
- &object_info, 0);
- }
-
- return object_type;
-}
+G_DEFINE_TYPE (GdkWindowImplX11, gdk_window_impl_x11, GDK_TYPE_DRAWABLE_IMPL_X11)
GType
_gdk_window_impl_get_type (void)
{
impl->width = 1;
impl->height = 1;
+ impl->toplevel_window_type = -1;
+}
+
+GdkToplevelX11 *
+_gdk_x11_window_get_toplevel (GdkWindow *window)
+{
+ GdkWindowObject *private;
+ GdkWindowImplX11 *impl;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
+ if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
+ return NULL;
+
+ private = (GdkWindowObject *)window;
+ impl = GDK_WINDOW_IMPL_X11 (private->impl);
+
+ if (!impl->toplevel)
+ impl->toplevel = g_new0 (GdkToplevelX11, 1);
+
+ return impl->toplevel;
}
static void
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
- parent_class = g_type_class_peek_parent (klass);
-
object_class->finalize = gdk_window_impl_x11_finalize;
drawable_class->set_colormap = gdk_window_impl_x11_set_colormap;
if (!GDK_WINDOW_DESTROYED (wrapper))
{
- _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (object), draw_impl->xid);
- if (window_impl->focus_window)
- _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (object), window_impl->focus_window);
+ GdkDisplay *display = GDK_WINDOW_DISPLAY (wrapper);
+
+ _gdk_xid_table_remove (display, draw_impl->xid);
+ if (window_impl->toplevel && window_impl->toplevel->focus_window)
+ _gdk_xid_table_remove (display, window_impl->toplevel->focus_window);
+ }
+
+ if (window_impl->toplevel)
+ g_free (window_impl->toplevel);
+
+ if (window_impl->cursor)
+ gdk_cursor_unref (window_impl->cursor);
+
+ G_OBJECT_CLASS (gdk_window_impl_x11_parent_class)->finalize (object);
+}
+
+static void
+tmp_unset_bg (GdkWindow *window)
+{
+ GdkWindowImplX11 *impl;
+ GdkWindowObject *obj;
+
+ obj = (GdkWindowObject *) window;
+ impl = GDK_WINDOW_IMPL_X11 (obj->impl);
+
+ /* For windows without EXPOSURE_MASK, we can't do this
+ * unsetting because such windows depend on the drawing
+ * that the X server is going to do
+ */
+ if (!(obj->event_mask & GDK_EXPOSURE_MASK))
+ return;
+
+ impl->position_info.no_bg = TRUE;
+
+ if (obj->bg_pixmap != GDK_NO_BG)
+ XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
+ GDK_DRAWABLE_XID (window), None);
+}
+
+static void
+tmp_reset_bg (GdkWindow *window)
+{
+ GdkWindowImplX11 *impl;
+ GdkWindowObject *obj;
+
+ obj = (GdkWindowObject *) window;
+ impl = GDK_WINDOW_IMPL_X11 (obj->impl);
+
+ if (!(obj->event_mask & GDK_EXPOSURE_MASK))
+ return;
+
+ impl->position_info.no_bg = FALSE;
+
+ if (obj->bg_pixmap == GDK_NO_BG)
+ return;
+
+ if (obj->bg_pixmap)
+ {
+ Pixmap xpixmap;
+
+ if (obj->bg_pixmap == GDK_PARENT_RELATIVE_BG)
+ xpixmap = ParentRelative;
+ else
+ xpixmap = GDK_DRAWABLE_XID (obj->bg_pixmap);
+
+ XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
+ GDK_DRAWABLE_XID (window), xpixmap);
+ }
+ else
+ {
+ XSetWindowBackground (GDK_DRAWABLE_XDISPLAY (window),
+ GDK_DRAWABLE_XID (window),
+ obj->bg_color.pixel);
+ }
+}
+
+/* Unsetting and resetting window backgrounds.
+ *
+ * In many cases it is possible to avoid flicker by unsetting the
+ * background of windows. For example if the background of the
+ * parent window is unset when a window is unmapped, a brief flicker
+ * of background painting is avoided.
+ */
+void
+_gdk_x11_window_tmp_unset_bg (GdkWindow *window,
+ gboolean recurse)
+{
+ GdkWindowObject *private;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ private = (GdkWindowObject *)window;
+
+ if (private->input_only || private->destroyed ||
+ (private->window_type != GDK_WINDOW_ROOT &&
+ !GDK_WINDOW_IS_MAPPED (window)))
+ {
+ return;
+ }
+
+ if (private->window_type != GDK_WINDOW_ROOT &&
+ private->window_type != GDK_WINDOW_FOREIGN)
+ {
+ tmp_unset_bg (window);
+ }
+
+ if (recurse)
+ {
+ GList *l;
+
+ for (l = private->children; l != NULL; l = l->next)
+ _gdk_x11_window_tmp_unset_bg (l->data, TRUE);
+ }
+}
+
+void
+_gdk_x11_window_tmp_reset_bg (GdkWindow *window,
+ gboolean recurse)
+{
+ GdkWindowObject *private;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ private = (GdkWindowObject *)window;
+
+ if (private->input_only || private->destroyed ||
+ (private->window_type != GDK_WINDOW_ROOT &&
+ !GDK_WINDOW_IS_MAPPED (window)))
+ {
+ return;
+ }
+
+ if (private->window_type != GDK_WINDOW_ROOT &&
+ private->window_type != GDK_WINDOW_FOREIGN)
+ {
+ tmp_reset_bg (window);
}
- G_OBJECT_CLASS (parent_class)->finalize (object);
+ if (recurse)
+ {
+ GList *l;
+
+ for (l = private->children; l != NULL; l = l->next)
+ _gdk_x11_window_tmp_reset_bg (l->data, TRUE);
+ }
}
static GdkColormap*
gdk_window_impl_x11_get_colormap (GdkDrawable *drawable)
{
GdkDrawableImplX11 *drawable_impl;
- GdkWindowImplX11 *window_impl;
g_return_val_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable), NULL);
drawable_impl = GDK_DRAWABLE_IMPL_X11 (drawable);
- window_impl = GDK_WINDOW_IMPL_X11 (drawable);
if (!((GdkWindowObject *) drawable_impl->wrapper)->input_only &&
drawable_impl->colormap == NULL)
gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
GdkColormap *cmap)
{
- GdkWindowImplX11 *impl;
GdkDrawableImplX11 *draw_impl;
g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable));
- impl = GDK_WINDOW_IMPL_X11 (drawable);
draw_impl = GDK_DRAWABLE_IMPL_X11 (drawable);
if (cmap && GDK_WINDOW_DESTROYED (draw_impl->wrapper))
return;
/* chain up */
- GDK_DRAWABLE_CLASS (parent_class)->set_colormap (drawable, cmap);
+ GDK_DRAWABLE_CLASS (gdk_window_impl_x11_parent_class)->set_colormap (drawable, cmap);
if (cmap)
{
GdkWindowImplX11 *impl;
GdkDrawableImplX11 *draw_impl;
GdkScreenX11 *screen_x11;
- XWindowAttributes xattributes;
- unsigned int width;
- unsigned int height;
- unsigned int border_width;
- unsigned int depth;
- int x, y;
screen_x11 = GDK_SCREEN_X11 (screen);
gdk_screen_set_default_colormap (screen,
gdk_screen_get_system_colormap (screen));
- XGetGeometry (screen_x11->xdisplay, screen_x11->xroot_window,
- &screen_x11->xroot_window, &x, &y, &width, &height, &border_width, &depth);
- XGetWindowAttributes (screen_x11->xdisplay, screen_x11->xroot_window, &xattributes);
-
screen_x11->root_window = g_object_new (GDK_TYPE_WINDOW, NULL);
private = (GdkWindowObject *)screen_x11->root_window;
impl = GDK_WINDOW_IMPL_X11 (private->impl);
g_object_ref (draw_impl->colormap);
private->window_type = GDK_WINDOW_ROOT;
- private->depth = depth;
+ private->depth = DefaultDepthOfScreen (screen_x11->xscreen);
- impl->width = width;
- impl->height = height;
+ impl->width = WidthOfScreen (screen_x11->xscreen);
+ impl->height = HeightOfScreen (screen_x11->xscreen);
_gdk_window_init_position (GDK_WINDOW (private));
set_wm_protocols (GdkWindow *window)
{
GdkDisplay *display = gdk_drawable_get_display (window);
- Atom protocols[3];
+ Atom protocols[4];
+ int n = 0;
- protocols[0] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
- protocols[1] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
- protocols[2] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
+ protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
+ protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
+ protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
- XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, 3);
+#ifdef HAVE_XSYNC
+ if (GDK_DISPLAY_X11 (display)->use_sync)
+ protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
+#endif
+
+ XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n);
}
static const gchar *
{
GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
- if (!display_x11->leader_window_title_set)
+ if (display_x11->leader_window && !display_x11->leader_window_title_set)
{
set_wm_name (display,
display_x11->leader_window,
}
}
+static Window
+create_focus_window (Display *xdisplay,
+ XID parent)
+{
+ Window focus_window = XCreateSimpleWindow (xdisplay, parent,
+ -1, -1, 1, 1, 0,
+ 0, 0);
+
+ /* FIXME: probably better to actually track the requested event mask for the toplevel
+ */
+ XSelectInput (xdisplay, focus_window,
+ KeyPressMask | KeyReleaseMask | FocusChangeMask);
+
+ XMapWindow (xdisplay, focus_window);
+
+ return focus_window;
+}
+
+static void
+ensure_sync_counter (GdkWindow *window)
+{
+#ifdef HAVE_XSYNC
+ if (!GDK_WINDOW_DESTROYED (window))
+ {
+ GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
+ GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
+
+ if (toplevel && impl->use_synchronized_configure &&
+ toplevel->update_counter == None &&
+ GDK_DISPLAY_X11 (display)->use_sync)
+ {
+ Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
+ XSyncValue value;
+ Atom atom;
+
+ XSyncIntToValue (&value, 0);
+
+ toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
+
+ atom = gdk_x11_get_xatom_by_name_for_display (display,
+ "_NET_WM_SYNC_REQUEST_COUNTER");
+
+ XChangeProperty (xdisplay, GDK_WINDOW_XID (window),
+ atom, XA_CARDINAL,
+ 32, PropModeReplace,
+ (guchar *)&toplevel->update_counter, 1);
+
+ XSyncIntToValue (&toplevel->current_counter_value, 0);
+ }
+ }
+#endif
+}
+
+static void
+setup_toplevel_window (GdkWindow *window,
+ GdkWindow *parent)
+{
+ GdkWindowObject *obj = (GdkWindowObject *)window;
+ GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
+ GdkWindowImplX11 *impl = (GdkWindowImplX11 *)obj->impl;
+ Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
+ XID xid = GDK_WINDOW_XID (window);
+ XID xparent = GDK_WINDOW_XID (parent);
+ GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (parent));
+ XSizeHints size_hints;
+ long pid;
+
+ if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_DIALOG)
+ XSetTransientForHint (xdisplay, xid, xparent);
+
+ set_wm_protocols (window);
+
+ if (!obj->input_only)
+ {
+ /* The focus window is off the visible area, and serves to receive key
+ * press events so they don't get sent to child windows.
+ */
+ toplevel->focus_window = create_focus_window (xdisplay, xid);
+ _gdk_xid_table_insert (screen_x11->display, &toplevel->focus_window, window);
+ }
+
+ check_leader_window_title (screen_x11->display);
+
+ /* FIXME: Is there any point in doing this? Do any WM's pay
+ * attention to PSize, and even if they do, is this the
+ * correct value???
+ */
+ size_hints.flags = PSize;
+ size_hints.width = impl->width;
+ size_hints.height = impl->height;
+
+ XSetWMNormalHints (xdisplay, xid, &size_hints);
+
+ /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
+ XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
+
+ pid = getpid ();
+ XChangeProperty (xdisplay, xid,
+ gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "_NET_WM_PID"),
+ XA_CARDINAL, 32,
+ PropModeReplace,
+ (guchar *)&pid, 1);
+
+ XChangeProperty (xdisplay, xid,
+ gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "WM_CLIENT_LEADER"),
+ XA_WINDOW, 32, PropModeReplace,
+ (guchar *) &GDK_DISPLAY_X11 (screen_x11->display)->leader_window, 1);
+
+ if (!obj->focus_on_map)
+ gdk_x11_window_set_user_time (window, 0);
+ else if (GDK_DISPLAY_X11 (screen_x11->display)->user_time != 0)
+ gdk_x11_window_set_user_time (window, GDK_DISPLAY_X11 (screen_x11->display)->user_time);
+
+ ensure_sync_counter (window);
+}
+
/**
* gdk_window_new:
* @parent: a #GdkWindow, or %NULL to create the window as a child of
XSetWindowAttributes xattributes;
long xattributes_mask;
- XSizeHints size_hints;
- XWMHints wm_hints;
XClassHint *class_hint;
int x, y, depth;
unsigned int class;
const char *title;
int i;
- long pid;
g_return_val_if_fail (attributes != NULL, NULL);
private->parent = (GdkWindowObject *)parent;
+ private->accept_focus = TRUE;
+ private->focus_on_map = TRUE;
+
xattributes_mask = 0;
if (attributes_mask & GDK_WA_X)
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;
else
xattributes.override_redirect = False;
+ impl->override_redirect = xattributes.override_redirect;
+
if (private->parent && private->parent->guffaw_gravity)
{
xattributes.win_gravity = StaticGravity;
}
private->bg_color.pixel = BlackPixel (xdisplay, screen_x11->screen_num);
+ private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
xattributes.background_pixel = private->bg_color.pixel;
private->bg_pixmap = NULL;
xattributes.override_redirect = True;
xattributes.cursor = None;
xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
+
+ impl->override_redirect = TRUE;
}
}
else
switch (GDK_WINDOW_TYPE (private))
{
case GDK_WINDOW_DIALOG:
- XSetTransientForHint (xdisplay, xid, xparent);
case GDK_WINDOW_TOPLEVEL:
case GDK_WINDOW_TEMP:
- set_wm_protocols (window);
+ if (attributes_mask & GDK_WA_TITLE)
+ title = attributes->title;
+ else
+ title = get_default_title ();
+
+ gdk_window_set_title (window, title);
+
+ if (attributes_mask & GDK_WA_WMCLASS)
+ {
+ class_hint = XAllocClassHint ();
+ class_hint->res_name = attributes->wmclass_name;
+ class_hint->res_class = attributes->wmclass_class;
+ XSetClassHint (xdisplay, xid, class_hint);
+ XFree (class_hint);
+ }
+
+ setup_toplevel_window (window, parent);
break;
+
case GDK_WINDOW_CHILD:
if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
(draw_impl->colormap != gdk_screen_get_system_colormap (screen)) &&
GDK_NOTE (MISC, g_message ("adding colormap window\n"));
gdk_window_add_colormap_windows (window);
}
+ break;
- return window;
default:
-
- return window;
- }
-
- if (class != InputOnly)
- {
- /* The focus window is off the visible area, and serves to receive key
- * press events so they don't get sent to child windows.
- */
- impl->focus_window = XCreateSimpleWindow (xdisplay, xid,
- -1, -1, 1, 1, 0,
- xattributes.background_pixel,
- xattributes.background_pixel);
- /* FIXME: probably better to actually track the requested event mask for the toplevel
- */
- XSelectInput (xdisplay, impl->focus_window,
- KeyPressMask | KeyReleaseMask | FocusChangeMask);
-
- XMapWindow (xdisplay, impl->focus_window);
- _gdk_xid_table_insert (screen_x11->display, &impl->focus_window, window);
+ break;
}
- size_hints.flags = PSize;
- size_hints.width = impl->width;
- size_hints.height = impl->height;
-
- check_leader_window_title (screen_x11->display);
-
- wm_hints.flags = StateHint | WindowGroupHint;
- wm_hints.window_group = GDK_DISPLAY_X11 (screen_x11->display)->leader_window;
- wm_hints.input = True;
- wm_hints.initial_state = NormalState;
-
- /* FIXME: Is there any point in doing this? Do any WM's pay
- * attention to PSize, and even if they do, is this the
- * correct value???
- */
- XSetWMNormalHints (xdisplay, xid, &size_hints);
-
- XSetWMHints (xdisplay, xid, &wm_hints);
-
- /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
- XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
-
- pid = getpid ();
- XChangeProperty (xdisplay, xid,
- gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "_NET_WM_PID"),
- XA_CARDINAL, 32,
- PropModeReplace,
- (guchar *)&pid, 1);
-
- XChangeProperty (xdisplay, xid,
- gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "WM_CLIENT_LEADER"),
- XA_WINDOW, 32, PropModeReplace,
- (guchar *) &GDK_DISPLAY_X11 (screen_x11->display)->leader_window, 1);
-
- if (attributes_mask & GDK_WA_TITLE)
- title = attributes->title;
- else
- title = get_default_title ();
-
- gdk_window_set_title (window, title);
-
- if (attributes_mask & GDK_WA_WMCLASS)
- {
- class_hint = XAllocClassHint ();
- class_hint->res_name = attributes->wmclass_name;
- class_hint->res_class = attributes->wmclass_class;
- XSetClassHint (xdisplay, xid, class_hint);
- XFree (class_hint);
- }
-
return window;
}
* @anid: a native window handle.
*
* Wraps a native window in a #GdkWindow.
- * This may fail if the window has been destroyed.
+ * This may fail if the window has been destroyed. If the window
+ * was already known to GDK, a new reference to the existing
+ * #GdkWindow is returned.
*
* For example in the X backend, a native window handle is an Xlib
* <type>XID</type>.
*
- * Return value: the newly-created #GdkWindow wrapper for the
- * native window or %NULL if the window has been destroyed.
+ * Return value: a #GdkWindow wrapper for the native window or
+ * %NULL if the window has been destroyed. The wrapper will be
+ * newly created, if one doesn't exist already.
*
* Since: 2.2
**/
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
display_x11 = GDK_DISPLAY_X11 (display);
-
+
+ if ((window = gdk_xid_table_lookup_for_display (display, anid)) != NULL)
+ return g_object_ref (window);
+
gdk_error_trap_push ();
result = XGetWindowAttributes (display_x11->xdisplay, anid, &attrs);
if (gdk_error_trap_pop () || !result)
return (GdkWindow*) gdk_xid_table_lookup (anid);
}
+static void
+gdk_toplevel_x11_free_contents (GdkDisplay *display,
+ GdkToplevelX11 *toplevel)
+{
+ if (toplevel->icon_window)
+ {
+ g_object_unref (toplevel->icon_window);
+ toplevel->icon_window = NULL;
+ }
+ if (toplevel->icon_pixmap)
+ {
+ g_object_unref (toplevel->icon_pixmap);
+ toplevel->icon_pixmap = NULL;
+ }
+ if (toplevel->icon_mask)
+ {
+ g_object_unref (toplevel->icon_mask);
+ toplevel->icon_mask = NULL;
+ }
+ if (toplevel->group_leader)
+ {
+ g_object_unref (toplevel->group_leader);
+ toplevel->group_leader = NULL;
+ }
+#ifdef HAVE_XSYNC
+ if (toplevel->update_counter != None)
+ {
+ XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display),
+ toplevel->update_counter);
+ toplevel->update_counter = None;
+
+ XSyncIntToValue (&toplevel->current_counter_value, 0);
+ }
+#endif
+}
+
void
_gdk_windowing_window_destroy (GdkWindow *window,
gboolean recursing,
gboolean foreign_destroy)
{
GdkWindowObject *private = (GdkWindowObject *)window;
-
+ GdkToplevelX11 *toplevel;
+
g_return_if_fail (GDK_IS_WINDOW (window));
_gdk_selection_window_destroyed (window);
if (private->extension_events != 0)
_gdk_input_window_destroy (window);
-#ifdef HAVE_XFT
- {
- GdkDrawableImplX11 *draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
+ toplevel = _gdk_x11_window_get_toplevel (window);
+ if (toplevel)
+ gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
-#ifdef HAVE_XFT2
- if (draw_impl->xft_draw)
- XftDrawDestroy (draw_impl->xft_draw);
-#else /* !HAVE_XFT2 */
- if (draw_impl->picture)
- XRenderFreePicture (GDK_DRAWABLE_XDISPLAY (window), draw_impl->picture);
-#endif /* HAVE_XFT2 */
- }
-#endif /* HAVE_XFT */
+ _gdk_x11_drawable_finish (private->impl);
- if (private->window_type == GDK_WINDOW_FOREIGN)
- {
- if (!foreign_destroy && (private->parent != NULL))
- {
- /* It's somebody else's window, but in our heirarchy,
- * so reparent it to the root window, and then send
- * it a delete event, as if we were a WM
- */
- XClientMessageEvent xevent;
-
- gdk_error_trap_push ();
- gdk_window_hide (window);
- gdk_window_reparent (window, NULL, 0, 0);
-
- xevent.type = ClientMessage;
- xevent.window = GDK_WINDOW_XID (window);
- xevent.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
- "WM_PROTOCOLS");
- xevent.format = 32;
- xevent.data.l[0] = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
- "WM_DELETE_WINDOW");
- xevent.data.l[1] = CurrentTime;
-
- XSendEvent (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- False, 0, (XEvent *)&xevent);
- gdk_display_sync (GDK_WINDOW_DISPLAY (window));
- gdk_error_trap_pop ();
- }
- }
- else if (!recursing && !foreign_destroy)
+ if (!recursing && !foreign_destroy)
{
XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
}
}
+void
+_gdk_windowing_window_destroy_foreign (GdkWindow *window)
+{
+ /* It's somebody else's window, but in our heirarchy,
+ * so reparent it to the root window, and then send
+ * it a delete event, as if we were a WM
+ */
+ XClientMessageEvent xevent;
+
+ gdk_error_trap_push ();
+ gdk_window_hide (window);
+ gdk_window_reparent (window, NULL, 0, 0);
+
+ xevent.type = ClientMessage;
+ xevent.window = GDK_WINDOW_XID (window);
+ xevent.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
+ "WM_PROTOCOLS");
+ xevent.format = 32;
+ xevent.data.l[0] = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
+ "WM_DELETE_WINDOW");
+ xevent.data.l[1] = CurrentTime;
+ xevent.data.l[2] = 0;
+ xevent.data.l[3] = 0;
+ xevent.data.l[4] = 0;
+
+ XSendEvent (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ False, 0, (XEvent *)&xevent);
+ gdk_display_sync (GDK_WINDOW_DISPLAY (window));
+ gdk_error_trap_pop ();
+}
+
+static GdkWindow *
+get_root (GdkWindow *window)
+{
+ GdkScreen *screen = gdk_drawable_get_screen (window);
+
+ return gdk_screen_get_root_window (screen);
+}
+
/* This function is called when the XWindow is really gone.
*/
void
{
GdkWindowImplX11 *window_impl;
- g_return_if_fail (window != NULL);
+ g_return_if_fail (GDK_IS_WINDOW (window));
window_impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
}
_gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), GDK_WINDOW_XID (window));
- if (window_impl->focus_window)
- _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), window_impl->focus_window);
+ if (window_impl->toplevel && window_impl->toplevel->focus_window)
+ _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), window_impl->toplevel->focus_window);
_gdk_xgrab_check_destroy (window);
}
static void
-set_initial_hints (GdkWindow *window)
+update_wm_hints (GdkWindow *window,
+ gboolean force)
{
- GdkWindowObject *private;
- Atom atoms[6];
- gint i;
-
- private = (GdkWindowObject*) window;
+ GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
+ XWMHints wm_hints;
+
+ if (!force &&
+ !toplevel->is_leader &&
+ private->state & GDK_WINDOW_STATE_WITHDRAWN)
+ return;
+ wm_hints.flags = StateHint | InputHint;
+ wm_hints.input = private->accept_focus ? True : False;
+ wm_hints.initial_state = NormalState;
+
if (private->state & GDK_WINDOW_STATE_ICONIFIED)
{
- XWMHints *wm_hints;
-
- wm_hints = XGetWMHints (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window));
- if (!wm_hints)
- wm_hints = XAllocWMHints ();
+ wm_hints.flags |= StateHint;
+ wm_hints.initial_state = IconicState;
+ }
- wm_hints->flags |= StateHint;
- wm_hints->initial_state = IconicState;
-
- XSetWMHints (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window), wm_hints);
- XFree (wm_hints);
+ if (toplevel->icon_window && !GDK_WINDOW_DESTROYED (toplevel->icon_window))
+ {
+ wm_hints.flags |= IconWindowHint;
+ wm_hints.icon_window = GDK_WINDOW_XID (toplevel->icon_window);
+ }
+
+ if (toplevel->icon_pixmap)
+ {
+ wm_hints.flags |= IconPixmapHint;
+ wm_hints.icon_pixmap = GDK_PIXMAP_XID (toplevel->icon_pixmap);
+ }
+
+ if (toplevel->icon_mask)
+ {
+ wm_hints.flags |= IconMaskHint;
+ wm_hints.icon_mask = GDK_PIXMAP_XID (toplevel->icon_mask);
+ }
+
+ wm_hints.flags |= WindowGroupHint;
+ if (toplevel->group_leader && !GDK_WINDOW_DESTROYED (toplevel->group_leader))
+ {
+ wm_hints.flags |= WindowGroupHint;
+ wm_hints.window_group = GDK_WINDOW_XID (toplevel->group_leader);
}
+ else
+ wm_hints.window_group = GDK_DISPLAY_X11 (display)->leader_window;
+
+ if (toplevel->urgency_hint)
+ wm_hints.flags |= XUrgencyHint;
+
+ XSetWMHints (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ &wm_hints);
+}
+
+static void
+set_initial_hints (GdkWindow *window)
+{
+ GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
+ Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
+ Window xwindow = GDK_WINDOW_XID (window);
+ GdkWindowObject *private;
+ GdkToplevelX11 *toplevel;
+ Atom atoms[9];
+ gint i;
+
+ private = (GdkWindowObject*) window;
+ toplevel = _gdk_x11_window_get_toplevel (window);
+ if (!toplevel)
+ return;
+
+ update_wm_hints (window, TRUE);
+
/* We set the spec hints regardless of whether the spec is supported,
* since it can't hurt and it's kind of expensive to check whether
* it's supported.
if (private->state & GDK_WINDOW_STATE_MAXIMIZED)
{
- atoms[i] = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
+ atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
"_NET_WM_STATE_MAXIMIZED_VERT");
++i;
- atoms[i] = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
+ atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
"_NET_WM_STATE_MAXIMIZED_HORZ");
++i;
}
+ if (private->state & GDK_WINDOW_STATE_ABOVE)
+ {
+ atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
+ "_NET_WM_STATE_ABOVE");
+ ++i;
+ }
+
+ if (private->state & GDK_WINDOW_STATE_BELOW)
+ {
+ atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
+ "_NET_WM_STATE_BELOW");
+ ++i;
+ }
+
if (private->state & GDK_WINDOW_STATE_STICKY)
{
- atoms[i] = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
+ atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
"_NET_WM_STATE_STICKY");
++i;
}
if (private->state & GDK_WINDOW_STATE_FULLSCREEN)
{
- atoms[i] = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
+ atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
"_NET_WM_STATE_FULLSCREEN");
++i;
}
-
+
if (private->modal_hint)
{
- atoms[i] = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
+ atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
"_NET_WM_STATE_MODAL");
++i;
}
+ if (toplevel->skip_taskbar_hint)
+ {
+ atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
+ "_NET_WM_STATE_SKIP_TASKBAR");
+ ++i;
+ }
+
+ if (toplevel->skip_pager_hint)
+ {
+ atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
+ "_NET_WM_STATE_SKIP_PAGER");
+ ++i;
+ }
+
if (i > 0)
{
- XChangeProperty (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), "_NET_WM_STATE"),
+ XChangeProperty (xdisplay,
+ xwindow,
+ gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
XA_ATOM, 32, PropModeReplace,
(guchar*) atoms, i);
}
+ else
+ {
+ XDeleteProperty (xdisplay,
+ xwindow,
+ gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"));
+ }
if (private->state & GDK_WINDOW_STATE_STICKY)
{
atoms[0] = 0xFFFFFFFF;
- XChangeProperty (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), "_NET_WM_DESKTOP"),
+ XChangeProperty (xdisplay,
+ xwindow,
+ gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
XA_CARDINAL, 32, PropModeReplace,
(guchar*) atoms, 1);
}
+ else
+ {
+ XDeleteProperty (xdisplay,
+ xwindow,
+ gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"));
+ }
+
+ toplevel->map_serial = NextRequest (xdisplay);
}
static void
gboolean raise)
{
GdkWindowObject *private;
+ GdkDisplay *display;
+ GdkDisplayX11 *display_x11;
+ GdkToplevelX11 *toplevel;
g_return_if_fail (GDK_IS_WINDOW (window));
private = (GdkWindowObject*) window;
if (!private->destroyed)
{
+ GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
+ Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
+ Window xwindow = GDK_WINDOW_XID (window);
+
if (raise)
- XRaiseWindow (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window));
+ XRaiseWindow (xdisplay, xwindow);
if (!GDK_WINDOW_IS_MAPPED (window))
{
}
g_assert (GDK_WINDOW_IS_MAPPED (window));
-
- if (GDK_WINDOW_IMPL_X11 (private->impl)->position_info.mapped)
- XMapWindow (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window));
+
+ if (WINDOW_IS_TOPLEVEL (window))
+ {
+ display = gdk_drawable_get_display (window);
+ display_x11 = GDK_DISPLAY_X11 (display);
+ toplevel = _gdk_x11_window_get_toplevel (window);
+
+ if (toplevel->user_time != 0 &&
+ display_x11->user_time != 0 &&
+ XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
+ gdk_x11_window_set_user_time (window, display_x11->user_time);
+ }
+
+ if (impl->position_info.mapped)
+ {
+ gboolean unset_bg = !private->input_only &&
+ (private->window_type == GDK_WINDOW_CHILD ||
+ impl->override_redirect) &&
+ gdk_window_is_viewable (window);
+
+ if (unset_bg)
+ _gdk_x11_window_tmp_unset_bg (window, TRUE);
+
+ XMapWindow (xdisplay, xwindow);
+
+ if (unset_bg)
+ {
+ _gdk_x11_window_tmp_reset_bg (window, TRUE);
+ gdk_window_invalidate_rect (window, NULL, TRUE);
+ }
+ }
}
}
show_window_internal (window, TRUE);
}
+static void
+pre_unmap (GdkWindow *window)
+{
+ GdkWindow *start_window = NULL;
+ GdkWindowObject *private = (GdkWindowObject *)window;
+
+ if (private->input_only)
+ return;
+
+ if (private->window_type == GDK_WINDOW_CHILD)
+ start_window = (GdkWindow *)private->parent;
+ else if (private->window_type == GDK_WINDOW_TEMP)
+ start_window = get_root (window);
+
+ if (start_window)
+ _gdk_x11_window_tmp_unset_bg (start_window, TRUE);
+}
+
+static void
+post_unmap (GdkWindow *window)
+{
+ GdkWindow *start_window = NULL;
+ GdkWindowObject *private = (GdkWindowObject *)window;
+
+ if (private->input_only)
+ return;
+
+ if (private->window_type == GDK_WINDOW_CHILD)
+ start_window = (GdkWindow *)private->parent;
+ else if (private->window_type == GDK_WINDOW_TEMP)
+ start_window = get_root (window);
+
+ if (start_window)
+ {
+ _gdk_x11_window_tmp_reset_bg (start_window, TRUE);
+
+ if (private->window_type == GDK_WINDOW_CHILD && private->parent)
+ {
+ GdkRectangle invalid_rect;
+
+ gdk_window_get_position (window, &invalid_rect.x, &invalid_rect.y);
+ gdk_drawable_get_size (GDK_DRAWABLE (window),
+ &invalid_rect.width, &invalid_rect.height);
+ gdk_window_invalidate_rect ((GdkWindow *)private->parent,
+ &invalid_rect, TRUE);
+ }
+ }
+}
+
/**
* gdk_window_hide:
* @window: a #GdkWindow
{
GdkWindowObject *private;
- g_return_if_fail (window != NULL);
+ g_return_if_fail (GDK_IS_WINDOW (window));
private = (GdkWindowObject*) window;
g_assert (!GDK_WINDOW_IS_MAPPED (window));
_gdk_window_clear_update_area (window);
+
+ pre_unmap (window);
XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window));
+
+ post_unmap (window);
}
}
{
GdkWindowObject *private;
- g_return_if_fail (window != NULL);
+ g_return_if_fail (GDK_IS_WINDOW (window));
private = (GdkWindowObject*) window;
if (!private->destroyed)
GDK_WINDOW_STATE_WITHDRAWN);
g_assert (!GDK_WINDOW_IS_MAPPED (window));
+
+ pre_unmap (window);
XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window), 0);
+
+ post_unmap (window);
}
}
GdkWindowObject *private = (GdkWindowObject *)window;
GdkWindowImplX11 *impl;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
impl = GDK_WINDOW_IMPL_X11 (private->impl);
-
+
if (!GDK_WINDOW_DESTROYED (window))
{
if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
- _gdk_window_move_resize_child (window, x, y,
- impl->width, impl->height);
+ {
+ _gdk_window_move_resize_child (window, x, y,
+ impl->width, impl->height);
+ }
else
{
XMoveWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
x, y);
+
+ if (impl->override_redirect)
+ {
+ private->x = x;
+ private->y = y;
+ }
}
}
}
{
GdkWindowObject *private;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (width < 1)
if (!GDK_WINDOW_DESTROYED (window))
{
if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
- _gdk_window_move_resize_child (window, private->x, private->y,
- width, height);
+ {
+ _gdk_window_move_resize_child (window, private->x, private->y,
+ width, height);
+ _gdk_x11_drawable_update_size (private->impl);
+ }
else
{
GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
-
- if (width != impl->width || height != impl->height)
- private->resize_count += 1;
XResizeWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
width, height);
+
+ if (impl->override_redirect)
+ {
+ impl->width = width;
+ impl->height = height;
+ _gdk_x11_drawable_update_size (private->impl);
+ }
+ else
+ {
+ if (width != impl->width || height != impl->height)
+ private->resize_count += 1;
+ }
}
+
+ _gdk_x11_drawable_update_size (private->impl);
}
}
{
GdkWindowObject *private;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (width < 1)
if (!GDK_WINDOW_DESTROYED (window))
{
if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
- _gdk_window_move_resize_child (window, x, y, width, height);
+ {
+ _gdk_window_move_resize_child (window, x, y, width, height);
+ _gdk_x11_drawable_update_size (private->impl);
+ }
else
{
GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
-
- if (width != impl->width || height != impl->height)
- private->resize_count += 1;
-
+
XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
x, y, width, height);
+ if (impl->override_redirect)
+ {
+ private->x = x;
+ private->y = y;
+ impl->width = width;
+ impl->height = height;
+
+ _gdk_x11_drawable_update_size (private->impl);
+ }
+ else
+ {
+ if (width != impl->width || height != impl->height)
+ private->resize_count += 1;
+ }
}
}
}
gint x,
gint y)
{
- GdkDisplay *display;
GdkWindowObject *window_private;
GdkWindowObject *parent_private;
GdkWindowObject *old_parent_private;
+ GdkWindowImplX11 *impl;
+ gboolean was_toplevel;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
+
+ if (GDK_WINDOW_DESTROYED (window) ||
+ (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
+ {
+ return;
+ }
if (!new_parent)
new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
- display = GDK_WINDOW_DISPLAY (window);
-
window_private = (GdkWindowObject*) window;
old_parent_private = (GdkWindowObject*)window_private->parent;
parent_private = (GdkWindowObject*) new_parent;
+ impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
- if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (new_parent))
- XReparentWindow (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- GDK_WINDOW_XID (new_parent),
- x, y);
+ XReparentWindow (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ GDK_WINDOW_XID (new_parent),
+ x, y);
window_private->x = x;
window_private->y = y;
{
case GDK_WINDOW_ROOT:
case GDK_WINDOW_FOREIGN:
- /* Now a toplevel */
- if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
- set_wm_protocols (window);
+ was_toplevel = WINDOW_IS_TOPLEVEL (window);
+
+ if (impl->toplevel_window_type != -1)
+ GDK_WINDOW_TYPE (window) = impl->toplevel_window_type;
+ else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
+ GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+
+ if (WINDOW_IS_TOPLEVEL (window) && !was_toplevel)
+ setup_toplevel_window (window, new_parent);
break;
case GDK_WINDOW_TOPLEVEL:
case GDK_WINDOW_CHILD:
case GDK_WINDOW_DIALOG:
case GDK_WINDOW_TEMP:
- if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&
- GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+ if (WINDOW_IS_TOPLEVEL (window))
{
- /* If we were being sophisticated, we'd save the old window type
- * here, and restore it if we were reparented back to the
- * toplevel. However, the difference between different types
- * of toplevels only really matters on creation anyways.
+ /* Save the original window type so we can restore it if the
+ * window is reparented back to be a toplevel
*/
+ impl->toplevel_window_type = GDK_WINDOW_TYPE (window);
GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
+ if (impl->toplevel)
+ {
+ if (impl->toplevel->focus_window)
+ {
+ XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
+ _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
+ }
+
+ gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window),
+ impl->toplevel);
+ g_free (impl->toplevel);
+ impl->toplevel = NULL;
+ }
}
}
gint width,
gint height)
{
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (!GDK_WINDOW_DESTROYED (window))
gint width,
gint height)
{
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (!GDK_WINDOW_DESTROYED (window))
void
gdk_window_raise (GdkWindow *window)
{
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (!GDK_WINDOW_DESTROYED (window))
void
gdk_window_lower (GdkWindow *window)
{
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (!GDK_WINDOW_DESTROYED (window))
XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
}
+/**
+ * gdk_x11_window_move_to_current_desktop:
+ * @window: a #GdkWindow
+ *
+ * Moves the window to the correct workspace when running under a
+ * window manager that supports multiple workspaces, as described
+ * in the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended
+ * Window Manager Hints</ulink>. Will not do anything if the
+ * window is already on all workspaces.
+ *
+ * Since: 2.8
+ */
+void
+gdk_x11_window_move_to_current_desktop (GdkWindow *window)
+{
+ GdkToplevelX11 *toplevel;
+ toplevel = _gdk_x11_window_get_toplevel (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")))
+ {
+ XEvent xev;
+ Atom type;
+ gint format;
+ gulong nitems;
+ gulong bytes_after;
+ guchar *data;
+ gulong *current_desktop;
+ GdkDisplay *display;
+
+ display = gdk_drawable_get_display (window);
+
+ /* 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);
+ }
+ }
+}
+
/**
* gdk_window_focus:
* @window: a #GdkWindow
* @timestamp: timestamp of the event triggering the window focus
*
- * Sets keyboard focus to @window. If @window is not onscreen this
- * will not work. In most cases, gtk_window_present() should be used on
- * a #GtkWindow, rather than calling this function.
+ * Sets keyboard focus to @window. In most cases, gtk_window_present()
+ * should be used on a #GtkWindow, rather than calling this function.
*
**/
void
gdk_window_focus (GdkWindow *window,
guint32 timestamp)
{
+ GdkDisplay *display;
+
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
return;
+ display = GDK_WINDOW_DISPLAY (window);
+
if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
- gdk_atom_intern ("_NET_ACTIVE_WINDOW", FALSE)))
+ gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
{
XEvent xev;
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 (GDK_WINDOW_DISPLAY (window),
+ xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
"_NET_ACTIVE_WINDOW");
xev.xclient.format = 32;
- xev.xclient.data.l[0] = 0;
+ xev.xclient.data.l[0] = 1; /* requestor type; we're an app */
+ xev.xclient.data.l[1] = timestamp;
+ xev.xclient.data.l[2] = None; /* currently active window */
+ xev.xclient.data.l[3] = 0;
+ xev.xclient.data.l[4] = 0;
- XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
+ XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
SubstructureRedirectMask | SubstructureNotifyMask,
&xev);
}
else
{
- XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
+ XRaiseWindow (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window));
- /* There is no way of knowing reliably whether we are viewable so we need
- * to trap errors so we don't cause a BadMatch.
+ /* There is no way of knowing reliably whether we are viewable;
+ * _gdk_x11_set_input_focus_safe() traps errors asynchronously.
*/
- gdk_error_trap_push ();
- XSetInputFocus (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XWINDOW (window),
- RevertToParent,
- timestamp);
- XSync (GDK_WINDOW_XDISPLAY (window), False);
- gdk_error_trap_pop ();
+ _gdk_x11_set_input_focus_safe (display, GDK_WINDOW_XID (window),
+ RevertToParent,
+ timestamp);
}
}
{
XSizeHints size_hints;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
GdkDisplay *display;
Atom atom;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
case GDK_WINDOW_TYPE_HINT_DESKTOP:
atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP");
break;
+ case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
+ atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU");
+ break;
+ case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
+ atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU");
+ break;
+ case GDK_WINDOW_TYPE_HINT_TOOLTIP:
+ atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP");
+ break;
+ case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
+ atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION");
+ break;
+ case GDK_WINDOW_TYPE_HINT_COMBO:
+ atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO");
+ break;
+ case GDK_WINDOW_TYPE_HINT_DND:
+ atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND");
+ break;
default:
g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
/* Fall thru */
(guchar *)&atom, 1);
}
-
-static void
-gdk_wmspec_change_state (gboolean add,
- GdkWindow *window,
- GdkAtom state1,
- GdkAtom state2)
+/**
+ * gdk_window_get_type_hint:
+ * @window: A toplevel #GdkWindow
+ *
+ * This function returns the type hint set for a window.
+ *
+ * Return value: The type hint set for @window
+ *
+ * Since: 2.10
+ **/
+GdkWindowTypeHint
+gdk_window_get_type_hint (GdkWindow *window)
{
- GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
- XEvent xev;
-
-#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
-#define _NET_WM_STATE_ADD 1 /* add/set property */
+ GdkDisplay *display;
+ GdkWindowTypeHint type;
+ Atom type_return;
+ gint format_return;
+ gulong nitems_return;
+ gulong bytes_after_return;
+ guchar *data = NULL;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return GDK_WINDOW_TYPE_HINT_NORMAL;
+
+ type = GDK_WINDOW_TYPE_HINT_NORMAL;
+
+ display = gdk_drawable_get_display (window);
+
+ if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
+ gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
+ 0, G_MAXLONG, False, XA_ATOM, &type_return,
+ &format_return, &nitems_return, &bytes_after_return,
+ &data) == Success)
+ {
+ if ((type_return == XA_ATOM) && (format_return == 32) &&
+ (data) && (nitems_return == 1))
+ {
+ Atom atom = *(Atom*)data;
+
+ if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG"))
+ type = GDK_WINDOW_TYPE_HINT_DIALOG;
+ else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU"))
+ type = GDK_WINDOW_TYPE_HINT_MENU;
+ else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR"))
+ type = GDK_WINDOW_TYPE_HINT_TOOLBAR;
+ else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY"))
+ type = GDK_WINDOW_TYPE_HINT_UTILITY;
+ else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH"))
+ type = GDK_WINDOW_TYPE_HINT_SPLASHSCREEN;
+ else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK"))
+ type = GDK_WINDOW_TYPE_HINT_DOCK;
+ else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP"))
+ type = GDK_WINDOW_TYPE_HINT_DESKTOP;
+ else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"))
+ type = GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU;
+ else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU"))
+ type = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
+ else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP"))
+ type = GDK_WINDOW_TYPE_HINT_TOOLTIP;
+ else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION"))
+ type = GDK_WINDOW_TYPE_HINT_NOTIFICATION;
+ else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO"))
+ type = GDK_WINDOW_TYPE_HINT_COMBO;
+ else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND"))
+ type = GDK_WINDOW_TYPE_HINT_DND;
+ }
+
+ if (type_return != None && data != NULL)
+ XFree (data);
+ }
+
+ return type;
+}
+
+static void
+gdk_wmspec_change_state (gboolean add,
+ GdkWindow *window,
+ GdkAtom state1,
+ GdkAtom state2)
+{
+ GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
+ XEvent xev;
+
+#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
+#define _NET_WM_STATE_ADD 1 /* add/set property */
#define _NET_WM_STATE_TOGGLE 2 /* toggle property */
xev.xclient.type = ClientMessage;
xev.xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
xev.xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
xev.xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
+ xev.xclient.data.l[3] = 0;
+ xev.xclient.data.l[4] = 0;
XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
SubstructureRedirectMask | SubstructureNotifyMask,
/**
* gdk_window_set_modal_hint:
* @window: A toplevel #GdkWindow
- * @modal: TRUE if the window is modal, FALSE otherwise.
+ * @modal: %TRUE if the window is modal, %FALSE otherwise.
*
* The application can use this hint to tell the window manager
* that a certain window has modal behaviour. The window manager
* way.
*
* You should only use this on windows for which you have
- * previously called #gdk_window_set_transient_for()
+ * previously called gdk_window_set_transient_for()
**/
void
gdk_window_set_modal_hint (GdkWindow *window,
{
GdkWindowObject *private;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
if (GDK_WINDOW_IS_MAPPED (window))
gdk_wmspec_change_state (modal, window,
- gdk_atom_intern ("_NET_WM_STATE_MODAL", FALSE),
- 0);
+ gdk_atom_intern_static_string ("_NET_WM_STATE_MODAL"),
+ NULL);
}
/**
* Toggles whether a window should appear in a task list or window
* list. If a window's semantic type as specified with
* gdk_window_set_type_hint() already fully describes the window, this
- * function should NOT be called in addition, instead you should allow
- * the window to be treated according to standard policy for its
- * semantic type.
+ * function should <emphasis>not</emphasis> be called in addition,
+ * instead you should allow the window to be treated according to
+ * standard policy for its semantic type.
*
* Since: 2.2
**/
gdk_window_set_skip_taskbar_hint (GdkWindow *window,
gboolean skips_taskbar)
{
- GdkWindowObject *private;
- GdkWindowImplX11 *impl;
+ GdkToplevelX11 *toplevel;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
if (GDK_WINDOW_DESTROYED (window))
return;
- private = (GdkWindowObject*) window;
- impl = GDK_WINDOW_IMPL_X11 (private->impl);
-
- impl->skip_taskbar_hint = skips_taskbar;
+ toplevel = _gdk_x11_window_get_toplevel (window);
+ toplevel->skip_taskbar_hint = skips_taskbar;
if (GDK_WINDOW_IS_MAPPED (window))
gdk_wmspec_change_state (skips_taskbar, window,
- gdk_atom_intern ("_NET_WM_STATE_SKIP_TASKBAR", FALSE),
- 0);
+ gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_TASKBAR"),
+ NULL);
}
/**
* switcher, or other desktop utility program that displays a small
* thumbnail representation of the windows on the desktop). If a
* window's semantic type as specified with gdk_window_set_type_hint()
- * already fully describes the window, this function should NOT be
- * called in addition, instead you should allow the window to be
- * treated according to standard policy for its semantic type.
+ * already fully describes the window, this function should
+ * <emphasis>not</emphasis> be called in addition, instead you should
+ * allow the window to be treated according to standard policy for
+ * its semantic type.
*
* Since: 2.2
**/
gdk_window_set_skip_pager_hint (GdkWindow *window,
gboolean skips_pager)
{
- GdkWindowObject *private;
- GdkWindowImplX11 *impl;
-
- g_return_if_fail (window != NULL);
+ GdkToplevelX11 *toplevel;
+
g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
if (GDK_WINDOW_DESTROYED (window))
return;
- private = (GdkWindowObject*) window;
- impl = GDK_WINDOW_IMPL_X11 (private->impl);
-
- impl->skip_pager_hint = skips_pager;
+ toplevel = _gdk_x11_window_get_toplevel (window);
+ toplevel->skip_pager_hint = skips_pager;
if (GDK_WINDOW_IS_MAPPED (window))
gdk_wmspec_change_state (skips_pager, window,
- gdk_atom_intern ("_NET_WM_STATE_SKIP_PAGER", FALSE),
- 0);
+ gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_PAGER"),
+ NULL);
+}
+
+/**
+ * gdk_window_set_urgency_hint:
+ * @window: a toplevel #GdkWindow
+ * @urgent: %TRUE if the window is urgent
+ *
+ * Toggles whether a window needs the user's
+ * urgent attention.
+ *
+ * Since: 2.8
+ **/
+void
+gdk_window_set_urgency_hint (GdkWindow *window,
+ gboolean urgent)
+{
+ GdkToplevelX11 *toplevel;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ toplevel = _gdk_x11_window_get_toplevel (window);
+ toplevel->urgency_hint = urgent;
+
+ update_wm_hints (window, FALSE);
}
/**
* gdk_window_move_resize().
*
* Note that on X11, this effect has no effect on windows
- * of type GDK_WINDOW_TEMP or windows where override_redirect
+ * of type %GDK_WINDOW_TEMP or windows where override redirect
* has been turned on via gdk_window_set_override_redirect()
* since these windows are not resizable by the user.
*
{
XSizeHints size_hints;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
Atom property,
const gchar *utf8_str)
{
- guchar *prop_text = NULL;
+ gchar *prop_text = NULL;
Atom prop_type;
gint prop_length;
gint prop_format;
+ gboolean is_compound_text;
if (utf8_is_latin1 (utf8_str))
{
prop_text = gdk_utf8_to_string_target (utf8_str);
prop_length = prop_text ? strlen (prop_text) : 0;
prop_format = 8;
+ is_compound_text = FALSE;
}
else
{
gdk_utf8_to_compound_text_for_display (display,
utf8_str, &gdk_type, &prop_format,
- &prop_text, &prop_length);
+ (guchar **)&prop_text, &prop_length);
prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
+ is_compound_text = TRUE;
}
if (prop_text)
xwindow,
property,
prop_type, prop_format,
- PropModeReplace, prop_text,
+ PropModeReplace, (guchar *)prop_text,
prop_length);
- g_free (prop_text);
+ if (is_compound_text)
+ gdk_free_compound_text ((guchar *)prop_text);
+ else
+ g_free (prop_text);
}
}
XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
- PropModeReplace, name, strlen (name));
+ PropModeReplace, (guchar *)name, strlen (name));
set_text_property (display, xwindow,
gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
Display *xdisplay;
Window xwindow;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (title != NULL);
XChangeProperty (xdisplay, xwindow,
gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
- PropModeReplace, title, strlen (title));
+ PropModeReplace, (guchar *)title, strlen (title));
set_text_property (display, xwindow,
gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
{
GdkDisplay *display;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
display = gdk_drawable_get_display (window);
if (role)
XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"),
- XA_STRING, 8, PropModeReplace, role, strlen (role));
+ XA_STRING, 8, PropModeReplace, (guchar *)role, strlen (role));
else
XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"));
gdk_window_set_transient_for (GdkWindow *window,
GdkWindow *parent)
{
- GdkWindowObject *private;
- GdkWindowObject *parent_private;
-
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
- private = (GdkWindowObject*) window;
- parent_private = (GdkWindowObject*) parent;
-
if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent))
XSetTransientForHint (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
*
**/
void
-gdk_window_set_background (GdkWindow *window,
- GdkColor *color)
+gdk_window_set_background (GdkWindow *window,
+ const GdkColor *color)
{
GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkColormap *colormap = gdk_drawable_get_colormap (window);
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (!GDK_WINDOW_DESTROYED (window))
GDK_WINDOW_XID (window), color->pixel);
private->bg_color = *color;
+ gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
if (private->bg_pixmap &&
private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
GdkWindowObject *private = (GdkWindowObject *)window;
Pixmap xpixmap;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (pixmap == NULL || !parent_relative);
g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
+
+ if (pixmap && !gdk_drawable_get_colormap (pixmap))
+ {
+ g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
+ return;
+ }
if (private->bg_pixmap &&
private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
gdk_window_set_cursor (GdkWindow *window,
GdkCursor *cursor)
{
+ GdkWindowObject *private;
+ GdkWindowImplX11 *impl;
GdkCursorPrivate *cursor_private;
Cursor xcursor;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
-
+
+ private = (GdkWindowObject *)window;
+ impl = GDK_WINDOW_IMPL_X11 (private->impl);
cursor_private = (GdkCursorPrivate*) cursor;
-
+
+ if (impl->cursor)
+ {
+ gdk_cursor_unref (impl->cursor);
+ impl->cursor = NULL;
+ }
+
if (!cursor)
xcursor = None;
else
- xcursor = cursor_private->xcursor;
+ {
+ _gdk_x11_cursor_update_theme (cursor);
+ xcursor = cursor_private->xcursor;
+ }
if (!GDK_WINDOW_DESTROYED (window))
- XDefineCursor (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- xcursor);
+ {
+ XDefineCursor (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ xcursor);
+
+ if (cursor)
+ impl->cursor = gdk_cursor_ref (cursor);
+ }
+}
+
+GdkCursor *
+_gdk_x11_window_get_cursor (GdkWindow *window)
+{
+ GdkWindowObject *private;
+ GdkWindowImplX11 *impl;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
+ private = (GdkWindowObject *)window;
+ impl = GDK_WINDOW_IMPL_X11 (private->impl);
+
+ return impl->cursor;
}
/**
* #GdkEventConfigure. gdk_window_get_position() in contrast gets the
* position from the most recent configure event.
*
+ * <note>
+ * If @window is not a toplevel, it is <emphasis>much</emphasis> better
+ * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
+ * because it avoids the roundtrip to the X server and because
+ * gdk_drawable_get_size() supports the full 32-bit coordinate space,
+ * whereas gdk_window_get_geometry() is restricted to the 16-bit
+ * coordinates of X11.
+ *</note>
**/
void
gdk_window_get_geometry (GdkWindow *window,
gint tx = 0;
gint ty = 0;
- g_return_val_if_fail (window != NULL, 0);
+ g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
if (!GDK_WINDOW_DESTROYED (window))
{
gulong number_return, bytes_after_return;
guchar *data_return;
- g_return_val_if_fail (window != NULL, 0);
- g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+ g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
if (!GDK_WINDOW_DESTROYED (window))
{
gdk_window_get_frame_extents (GdkWindow *window,
GdkRectangle *rect)
{
+ GdkDisplay *display;
GdkWindowObject *private;
Window xwindow;
Window xparent;
Window root;
Window *children;
- unsigned int nchildren;
+ guchar *data;
+ Window *vroots;
+ Atom type_return;
+ guint nchildren;
+ guint nvroots;
+ gulong nitems_return;
+ gulong bytes_after_return;
+ gint format_return;
+ gint i;
+ guint ww, wh, wb, wd;
+ gint wx, wy;
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (rect != NULL);
while (private->parent && ((GdkWindowObject*) private->parent)->parent)
private = (GdkWindowObject*) private->parent;
- if (GDK_WINDOW_DESTROYED (window))
+
+ /* Refine our fallback answer a bit using local information */
+ rect->x = private->x;
+ rect->y = private->y;
+ gdk_drawable_get_size ((GdkDrawable *)private, &rect->width, &rect->height);
+
+ if (GDK_WINDOW_DESTROYED (private))
return;
+
+ gdk_error_trap_push();
+ /* use NETWM_VIRTUAL_ROOTS if available */
+ display = gdk_drawable_get_display (window);
+ root = GDK_WINDOW_XROOTWIN (window);
+
+ nvroots = 0;
+ vroots = NULL;
+
+ if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), root,
+ gdk_x11_get_xatom_by_name_for_display (display,
+ "_NET_VIRTUAL_ROOTS"),
+ 0, G_MAXLONG, False, XA_WINDOW, &type_return,
+ &format_return, &nitems_return, &bytes_after_return,
+ &data)
+ == Success)
+ {
+ if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
+ {
+ nvroots = nitems_return;
+ vroots = (Window *)data;
+ }
+ }
+
xparent = GDK_WINDOW_XID (window);
+
do
{
xwindow = xparent;
- if (!XQueryTree (GDK_WINDOW_XDISPLAY (window), xwindow,
+
+ if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xwindow,
&root, &xparent,
&children, &nchildren))
- return;
+ goto fail;
if (children)
XFree (children);
+
+ /* check virtual roots */
+ for (i = 0; i < nvroots; i++)
+ {
+ if (xparent == vroots[i])
+ {
+ root = xparent;
+ break;
+ }
+ }
}
while (xparent != root);
- if (xparent == root)
+ if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
+ &root, &wx, &wy, &ww, &wh, &wb, &wd))
{
- unsigned int ww, wh, wb, wd;
- int wx, wy;
-
- if (XGetGeometry (GDK_WINDOW_XDISPLAY (window), xwindow, &root, &wx, &wy, &ww, &wh, &wb, &wd))
- {
- rect->x = wx;
- rect->y = wy;
- rect->width = ww;
- rect->height = wh;
- }
+ rect->x = wx;
+ rect->y = wy;
+ rect->width = ww;
+ rect->height = wh;
}
+
+ fail:
+ if (vroots)
+ XFree (vroots);
+
+ gdk_error_trap_pop ();
}
void
GdkModifierType *mask)
{
GdkScreen *default_screen;
+ Display *xdisplay;
+ Window xwindow;
Window root = None;
Window child;
int rootx, rooty;
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)
{
_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;
return return_val;
}
+/**
+ * gdk_display_warp_pointer:
+ * @display: a #GdkDisplay
+ * @screen: the screen of @display to warp the pointer to
+ * @x: the x coordinate of the destination
+ * @y: the y coordinate of the destination
+ *
+ * Warps the pointer of @display to the point @x,@y on
+ * the screen @screen, unless the pointer is confined
+ * to a window by a grab, in which case it will be moved
+ * as far as allowed by the grab. Warping the pointer
+ * creates events as if the user had moved the mouse
+ * instantaneously to the destination.
+ *
+ * Note that the pointer should normally be under the
+ * control of the user. This function was added to cover
+ * some rare use cases like keyboard navigation support
+ * for the color picker in the #GtkColorSelectionDialog.
+ *
+ * Since: 2.8
+ */
+void
+gdk_display_warp_pointer (GdkDisplay *display,
+ GdkScreen *screen,
+ gint x,
+ gint y)
+{
+ Display *xdisplay;
+ Window dest;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (display);
+ dest = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
+
+ XWarpPointer (xdisplay, None, dest, 0, 0, 0, 0, x, y);
+}
+
GdkWindow*
_gdk_windowing_window_at_pointer (GdkDisplay *display,
gint *win_x,
* than we'll end up with inaccurate values for win_x, win_y
* and the result.
*/
- XGrabServer (xdisplay);
- XQueryPointer (xdisplay, xwindow,
- &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
-
- if (root == xwindow)
- xwindow = child;
- else
- xwindow = root;
-
- while (xwindow)
+ gdk_x11_display_grab (display);
+ 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;
+ }
}
- XUngrabServer (xdisplay);
+
+ 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;
XWindowAttributes attrs;
GdkEventMask event_mask;
- g_return_val_if_fail (window != NULL, 0);
g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
if (GDK_WINDOW_DESTROYED (window))
long xevent_mask;
int i;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (!GDK_WINDOW_DESTROYED (window))
Window *new_windows;
int i, count;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
XFree (old_windows);
}
-static gboolean
-gdk_window_have_shape_ext (GdkDisplay *display)
-{
- GdkDisplayX11 *display_x11;
-
- g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
-
- display_x11 = GDK_DISPLAY_X11 (display);
-
- if (display_x11->have_shape == GDK_UNKNOWN)
- {
- int ignore;
- if (XQueryExtension (display_x11->xdisplay, "SHAPE", &ignore, &ignore, &ignore))
- display_x11->have_shape = GDK_YES;
- else
- display_x11->have_shape = GDK_NO;
- }
-
- return (display_x11->have_shape == GDK_YES);
-}
-
#define WARN_SHAPE_TOO_BIG() g_warning ("GdkWindow is too large to allow the use of shape masks or shape regions.")
/*
* If not available, shaped windows will look
* ugly, but programs still work. Stefan Wille
*/
-/**
- * gdk_window_shape_combine_mask:
- * @window: a #GdkWindow
- * @mask: shape mask
- * @x: X position of shape mask with respect to @window
- * @y: Y position of shape mask with respect to @window
- *
- * Applies a shape mask to @window. Pixels in @window corresponding to
- * set bits in the @mask will be visible; pixels in @window
- * corresponding to unset bits in the @mask will be transparent. This
- * gives a non-rectangular window.
- *
- * If @mask is %NULL, the shape mask will be unset, and the @x/@y
- * parameters are not used.
- *
- * On the X11 platform, this uses an X server extension which is
- * widely available on most common platforms, but not available on
- * very old X servers, and occasionally the implementation will be
- * buggy. On servers without the shape extension, this function
- * will do nothing.
- *
- * This function works on both toplevel and child windows.
- *
- **/
-void
-gdk_window_shape_combine_mask (GdkWindow *window,
- GdkBitmap *mask,
- gint x, gint y)
+static void
+do_shape_combine_mask (GdkWindow *window,
+ GdkBitmap *mask,
+ gint x,
+ gint y,
+ gint shape)
{
+ GdkWindowObject *private = (GdkWindowObject *)window;
Pixmap pixmap;
gint xoffset, yoffset;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
#ifdef HAVE_SHAPE_EXT
return;
}
- if (gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window)))
+ if (shape == ShapeBounding
+ ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
+ : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
{
if (mask)
{
pixmap = GDK_PIXMAP_XID (mask);
+
+ private->shaped = (shape == ShapeBounding);
}
else
{
x = 0;
y = 0;
pixmap = None;
+
+ private->shaped = FALSE;
}
XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
- ShapeBounding,
+ shape,
x, y,
pixmap,
ShapeSet);
}
/**
- * gdk_window_shape_combine_region:
+ * gdk_window_shape_combine_mask:
* @window: a #GdkWindow
- * @shape_region: region of window to be non-transparent
- * @offset_x: X position of @shape_region in @window coordinates
- * @offset_y: Y position of @shape_region in @window coordinates
+ * @mask: shape mask
+ * @x: X position of shape mask with respect to @window
+ * @y: Y position of shape mask with respect to @window
*
- * Makes pixels in @window outside @shape_region be transparent,
- * so that the window may be nonrectangular. See also
- * gdk_window_shape_combine_mask() to use a bitmap as the mask.
+ * Applies a shape mask to @window. Pixels in @window corresponding to
+ * set bits in the @mask will be visible; pixels in @window
+ * corresponding to unset bits in the @mask will be transparent. This
+ * gives a non-rectangular window.
+ *
+ * If @mask is %NULL, the shape mask will be unset, and the @x/@y
+ * parameters are not used.
*
- * If @shape_region is %NULL, the shape will be unset, so the whole
- * window will be opaque again. @offset_x and @offset_y are ignored
- * if @shape_region is %NULL.
- *
* On the X11 platform, this uses an X server extension which is
* widely available on most common platforms, but not available on
* very old X servers, and occasionally the implementation will be
*
**/
void
-gdk_window_shape_combine_region (GdkWindow *window,
- GdkRegion *shape_region,
- gint offset_x,
- gint offset_y)
+gdk_window_shape_combine_mask (GdkWindow *window,
+ GdkBitmap *mask,
+ gint x,
+ gint y)
+{
+ do_shape_combine_mask (window, mask, x, y, ShapeBounding);
+}
+
+/**
+ * gdk_window_input_shape_combine_mask:
+ * @window: a #GdkWindow
+ * @mask: shape mask
+ * @x: X position of shape mask with respect to @window
+ * @y: Y position of shape mask with respect to @window
+ *
+ * Like gdk_window_shape_combine_mask(), but the shape applies
+ * only to event handling. Mouse events which happen while
+ * the pointer position corresponds to an unset bit in the
+ * mask will be passed on the window below @window.
+ *
+ * An input shape is typically used with RGBA windows.
+ * The alpha channel of the window defines which pixels are
+ * invisible and allows for nicely antialiased borders,
+ * and the input shape controls where the window is
+ * "clickable".
+ *
+ * On the X11 platform, this requires version 1.1 of the
+ * shape extension.
+ *
+ * Since: 2.10
+ */
+void
+gdk_window_input_shape_combine_mask (GdkWindow *window,
+ GdkBitmap *mask,
+ gint x,
+ gint y)
+{
+#ifdef ShapeInput
+ do_shape_combine_mask (window, mask, x, y, ShapeInput);
+#endif
+}
+
+
+static void
+do_shape_combine_region (GdkWindow *window,
+ GdkRegion *shape_region,
+ gint offset_x,
+ gint offset_y,
+ gint shape)
{
+ GdkWindowObject *private = (GdkWindowObject *)window;
gint xoffset, yoffset;
g_return_if_fail (GDK_IS_WINDOW (window));
return;
}
- if (gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window)))
+ if (shape == ShapeBounding
+ ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
+ : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
{
gint n_rects = 0;
XRectangle *xrects = NULL;
+ private->shaped = shape == ShapeBounding;
+
_gdk_region_get_xrectangles (shape_region,
0, 0,
&xrects, &n_rects);
XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
- ShapeBounding,
+ shape,
offset_x, offset_y,
xrects, n_rects,
ShapeSet,
#endif /* HAVE_SHAPE_EXT */
}
+/**
+ * gdk_window_shape_combine_region:
+ * @window: a #GdkWindow
+ * @shape_region: region of window to be non-transparent
+ * @offset_x: X position of @shape_region in @window coordinates
+ * @offset_y: Y position of @shape_region in @window coordinates
+ *
+ * Makes pixels in @window outside @shape_region be transparent,
+ * so that the window may be nonrectangular. See also
+ * gdk_window_shape_combine_mask() to use a bitmap as the mask.
+ *
+ * If @shape_region is %NULL, the shape will be unset, so the whole
+ * window will be opaque again. @offset_x and @offset_y are ignored
+ * if @shape_region is %NULL.
+ *
+ * On the X11 platform, this uses an X server extension which is
+ * widely available on most common platforms, but not available on
+ * very old X servers, and occasionally the implementation will be
+ * buggy. On servers without the shape extension, this function
+ * will do nothing.
+ *
+ * This function works on both toplevel and child windows.
+ *
+ **/
+void
+gdk_window_shape_combine_region (GdkWindow *window,
+ GdkRegion *shape_region,
+ gint offset_x,
+ gint offset_y)
+{
+ do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
+}
+
+/**
+ * gdk_window_input_shape_combine_region:
+ * @window: a #GdkWindow
+ * @shape_region: region of window to be non-transparent
+ * @offset_x: X position of @shape_region in @window coordinates
+ * @offset_y: Y position of @shape_region in @window coordinates
+ *
+ * Like gdk_window_shape_combine_region(), but the shape applies
+ * only to event handling. Mouse events which happen while
+ * the pointer position corresponds to an unset bit in the
+ * mask will be passed on the window below @window.
+ *
+ * An input shape is typically used with RGBA windows.
+ * The alpha channel of the window defines which pixels are
+ * invisible and allows for nicely antialiased borders,
+ * and the input shape controls where the window is
+ * "clickable".
+ *
+ * On the X11 platform, this requires version 1.1 of the
+ * shape extension.
+ *
+ * Since: 2.10
+ */
+void
+gdk_window_input_shape_combine_region (GdkWindow *window,
+ GdkRegion *shape_region,
+ gint offset_x,
+ gint offset_y)
+{
+#ifdef ShapeInput
+ do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
+#endif
+}
+
/**
* gdk_window_set_override_redirect:
* @window: a toplevel #GdkWindow
* @override_redirect: %TRUE if window should be override redirect
*
- * An override redirect window is not under the control of the window manager.
- * This means it won't have a titlebar, won't be minimizable, etc. - it will
- * be entirely under the control of the application. The window manager
- * can't see the override redirect window at all.
+ * An override redirect window is not under the control of the window manager.
+ * This means it won't have a titlebar, won't be minimizable, etc. - it will
+ * be entirely under the control of the application. The window manager
+ * can't see the override redirect window at all.
+ *
+ * Override redirect should only be used for short-lived temporary
+ * windows, such as popup menus. #GtkMenu uses an override redirect
+ * window in its implementation, for example.
+ *
+ **/
+void
+gdk_window_set_override_redirect (GdkWindow *window,
+ gboolean override_redirect)
+{
+ XSetWindowAttributes attr;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (!GDK_WINDOW_DESTROYED (window))
+ {
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
+
+ attr.override_redirect = (override_redirect? True : False);
+ XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ CWOverrideRedirect,
+ &attr);
+
+ impl->override_redirect = attr.override_redirect;
+ }
+}
+
+/**
+ * gdk_window_set_accept_focus:
+ * @window: a toplevel #GdkWindow
+ * @accept_focus: %TRUE if the window should receive input focus
+ *
+ * Setting @accept_focus to %FALSE hints the desktop environment that the
+ * window doesn't want to receive input focus.
+ *
+ * On X, it is the responsibility of the window manager to interpret this
+ * hint. ICCCM-compliant window manager usually respect it.
+ *
+ * Since: 2.4
+ **/
+void
+gdk_window_set_accept_focus (GdkWindow *window,
+ gboolean accept_focus)
+{
+ GdkWindowObject *private;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ private = (GdkWindowObject *)window;
+
+ accept_focus = accept_focus != FALSE;
+
+ if (private->accept_focus != accept_focus)
+ {
+ private->accept_focus = accept_focus;
+
+ if (!GDK_WINDOW_DESTROYED (window))
+ update_wm_hints (window, FALSE);
+ }
+}
+
+/**
+ * gdk_window_set_focus_on_map:
+ * @window: a toplevel #GdkWindow
+ * @focus_on_map: %TRUE if the window should receive input focus when mapped
+ *
+ * Setting @focus_on_map to %FALSE hints the desktop environment that the
+ * window doesn't want to receive input focus when it is mapped.
+ * focus_on_map should be turned off for windows that aren't triggered
+ * interactively (such as popups from network activity).
+ *
+ * On X, it is the responsibility of the window manager to interpret
+ * this hint. Window managers following the freedesktop.org window
+ * manager extension specification should respect it.
+ *
+ * Since: 2.6
+ **/
+void
+gdk_window_set_focus_on_map (GdkWindow *window,
+ gboolean focus_on_map)
+{
+ GdkWindowObject *private;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ private = (GdkWindowObject *)window;
+
+ focus_on_map = focus_on_map != FALSE;
+
+ if (private->focus_on_map != focus_on_map)
+ {
+ private->focus_on_map = focus_on_map;
+
+ if ((!GDK_WINDOW_DESTROYED (window)) && (!private->focus_on_map))
+ gdk_x11_window_set_user_time (window, 0);
+ }
+}
+
+/**
+ * gdk_x11_window_set_user_time:
+ * @window: A toplevel #GdkWindow
+ * @timestamp: An XServer timestamp to which the property should be set
+ *
+ * The application can use this call to update the _NET_WM_USER_TIME
+ * property on a toplevel window. This property stores an Xserver
+ * time which represents the time of the last user input event
+ * received for this window. This property may be used by the window
+ * manager to alter the focus, stacking, and/or placement behavior of
+ * windows when they are mapped depending on whether the new window
+ * was created by a user action or is a "pop-up" window activated by a
+ * timer or some other event.
*
- * Override redirect should only be used for short-lived temporary
- * windows, such as popup menus. #GtkMenu uses an override redirect
- * window in its implementation, for example.
- *
+ * Note that this property is automatically updated by GDK, so this
+ * function should only be used by applications which handle input
+ * events bypassing GDK.
+ *
+ * Since: 2.6
**/
void
-gdk_window_set_override_redirect (GdkWindow *window,
- gboolean override_redirect)
+gdk_x11_window_set_user_time (GdkWindow *window,
+ guint32 timestamp)
{
- XSetWindowAttributes attr;
-
- g_return_if_fail (window != NULL);
+ GdkDisplay *display;
+ GdkDisplayX11 *display_x11;
+ GdkToplevelX11 *toplevel;
+ glong timestamp_long = (glong)timestamp;
+
g_return_if_fail (GDK_IS_WINDOW (window));
- if (!GDK_WINDOW_DESTROYED (window))
- {
- attr.override_redirect = (override_redirect == FALSE)?False:True;
- XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- CWOverrideRedirect,
- &attr);
- }
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ display = gdk_drawable_get_display (window);
+ display_x11 = GDK_DISPLAY_X11 (display);
+ toplevel = _gdk_x11_window_get_toplevel (window);
+
+ XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
+ gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"),
+ XA_CARDINAL, 32, PropModeReplace,
+ (guchar *)×tamp_long, 1);
+
+ if (timestamp_long != GDK_CURRENT_TIME)
+ display_x11->user_time = timestamp_long;
+
+ toplevel->user_time = timestamp_long;
}
+#define GDK_SELECTION_MAX_SIZE(display) \
+ MIN(262144, \
+ XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
+ ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100 \
+ : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
/**
* gdk_window_set_icon_list:
gint x, y;
gint n_channels;
GdkDisplay *display;
+ gint n;
g_return_if_fail (GDK_IS_WINDOW (window));
l = pixbufs;
size = 0;
-
+ n = 0;
while (l)
{
pixbuf = l->data;
width = gdk_pixbuf_get_width (pixbuf);
height = gdk_pixbuf_get_height (pixbuf);
+ /* silently ignore overlarge icons */
+ if (size + 2 + width * height > GDK_SELECTION_MAX_SIZE(display))
+ {
+ g_warning ("gdk_window_set_icon_list: icons too large");
+ break;
+ }
+
+ n++;
size += 2 + width * height;
-
+
l = g_list_next (l);
}
l = pixbufs;
p = data;
- while (l)
+ while (l && n > 0)
{
pixbuf = l->data;
}
l = g_list_next (l);
+ n--;
}
if (size > 0)
GdkPixmap *pixmap,
GdkBitmap *mask)
{
- XWMHints *wm_hints;
-
- g_return_if_fail (window != NULL);
- g_return_if_fail (GDK_IS_WINDOW (window));
+ GdkToplevelX11 *toplevel;
+ g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
+
if (GDK_WINDOW_DESTROYED (window))
return;
- wm_hints = XGetWMHints (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window));
- if (!wm_hints)
- wm_hints = XAllocWMHints ();
+ toplevel = _gdk_x11_window_get_toplevel (window);
- if (icon_window != NULL)
+ if (toplevel->icon_window != icon_window)
{
- wm_hints->flags |= IconWindowHint;
- wm_hints->icon_window = GDK_WINDOW_XID (icon_window);
+ if (toplevel->icon_window)
+ g_object_unref (toplevel->icon_window);
+ toplevel->icon_window = g_object_ref (icon_window);
}
- if (pixmap != NULL)
+ if (toplevel->icon_pixmap != pixmap)
{
- wm_hints->flags |= IconPixmapHint;
- wm_hints->icon_pixmap = GDK_PIXMAP_XID (pixmap);
+ if (pixmap)
+ g_object_ref (pixmap);
+ if (toplevel->icon_pixmap)
+ g_object_unref (toplevel->icon_pixmap);
+ toplevel->icon_pixmap = pixmap;
}
- if (mask != NULL)
+ if (toplevel->icon_mask != mask)
{
- wm_hints->flags |= IconMaskHint;
- wm_hints->icon_mask = GDK_PIXMAP_XID (mask);
+ if (mask)
+ g_object_ref (mask);
+ if (toplevel->icon_mask)
+ g_object_unref (toplevel->icon_mask);
+ toplevel->icon_mask = mask;
}
-
- XSetWMHints (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window), wm_hints);
- XFree (wm_hints);
+
+ update_wm_hints (window, FALSE);
}
static gboolean
{
GdkDisplay *display;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
GDK_WINDOW_XID (window),
gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
- PropModeReplace, name, strlen (name));
+ PropModeReplace, (guchar *)name, strlen (name));
set_text_property (display, GDK_WINDOW_XID (window),
gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
void
gdk_window_iconify (GdkWindow *window)
{
- GdkWindowObject *private;
-
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
return;
- private = (GdkWindowObject*) window;
-
if (GDK_WINDOW_IS_MAPPED (window))
{
XIconifyWindow (GDK_WINDOW_XDISPLAY (window),
void
gdk_window_deiconify (GdkWindow *window)
{
- GdkWindowObject *private;
-
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
return;
- private = (GdkWindowObject*) window;
-
if (GDK_WINDOW_IS_MAPPED (window))
{
gdk_window_show (window);
/* Request stick during viewport scroll */
gdk_wmspec_change_state (TRUE, window,
- gdk_atom_intern ("_NET_WM_STATE_STICKY", FALSE),
- 0);
+ gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
+ NULL);
/* Request desktop 0xFFFFFFFF */
xev.xclient.type = ClientMessage;
xev.xclient.format = 32;
xev.xclient.data.l[0] = 0xFFFFFFFF;
+ 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_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
SubstructureRedirectMask | SubstructureNotifyMask,
if (GDK_WINDOW_IS_MAPPED (window))
{
- XEvent xev;
- Atom type;
- gint format;
- gulong nitems;
- gulong bytes_after;
- 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),
- 0);
+ 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, (guchar **)¤t_desktop);
-
- if (type == XA_CARDINAL)
- {
- 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;
-
- XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
- SubstructureRedirectMask | SubstructureNotifyMask,
- &xev);
-
- XFree (current_desktop);
- }
+ move_to_current_desktop (window);
}
else
{
if (GDK_WINDOW_IS_MAPPED (window))
gdk_wmspec_change_state (TRUE, window,
- gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_VERT", FALSE),
- gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_HORZ", FALSE));
+ gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
+ gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
else
gdk_synthesize_window_state (window,
0,
if (GDK_WINDOW_IS_MAPPED (window))
gdk_wmspec_change_state (FALSE, window,
- gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_VERT", FALSE),
- gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_HORZ", FALSE));
+ gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
+ gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
else
gdk_synthesize_window_state (window,
GDK_WINDOW_STATE_MAXIMIZED,
if (GDK_WINDOW_IS_MAPPED (window))
gdk_wmspec_change_state (TRUE, window,
- gdk_atom_intern ("_NET_WM_STATE_FULLSCREEN", FALSE),
+ gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
GDK_NONE);
else
if (GDK_WINDOW_IS_MAPPED (window))
gdk_wmspec_change_state (FALSE, window,
- gdk_atom_intern ("_NET_WM_STATE_FULLSCREEN", FALSE),
+ gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
GDK_NONE);
else
0);
}
+/**
+ * gdk_window_set_keep_above:
+ * @window: a toplevel #GdkWindow
+ * @setting: whether to keep @window above other windows
+ *
+ * Set if @window must be kept above other windows. If the
+ * window was already above, then this function does nothing.
+ *
+ * On X11, asks the window manager to keep @window above, if the window
+ * manager supports this operation. Not all window managers support
+ * this, and some deliberately ignore it or don't have a concept of
+ * "keep above"; so you can't rely on the window being kept above.
+ * But it will happen with most standard window managers,
+ * and GDK makes a best effort to get it to happen.
+ *
+ * Since: 2.4
+ **/
+void
+gdk_window_set_keep_above (GdkWindow *window, gboolean setting)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ if (GDK_WINDOW_IS_MAPPED (window))
+ {
+ if (setting)
+ gdk_wmspec_change_state (FALSE, window,
+ gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
+ GDK_NONE);
+ gdk_wmspec_change_state (setting, window,
+ gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
+ GDK_NONE);
+ }
+ else
+ gdk_synthesize_window_state (window,
+ setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
+ setting ? GDK_WINDOW_STATE_ABOVE : 0);
+}
+
+/**
+ * gdk_window_set_keep_below:
+ * @window: a toplevel #GdkWindow
+ * @setting: whether to keep @window below other windows
+ *
+ * Set if @window must be kept below other windows. If the
+ * window was already below, then this function does nothing.
+ *
+ * On X11, asks the window manager to keep @window below, if the window
+ * manager supports this operation. Not all window managers support
+ * this, and some deliberately ignore it or don't have a concept of
+ * "keep below"; so you can't rely on the window being kept below.
+ * But it will happen with most standard window managers,
+ * and GDK makes a best effort to get it to happen.
+ *
+ * Since: 2.4
+ **/
+void
+gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ if (GDK_WINDOW_IS_MAPPED (window))
+ {
+ if (setting)
+ gdk_wmspec_change_state (FALSE, window,
+ gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
+ GDK_NONE);
+ gdk_wmspec_change_state (setting, window,
+ gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
+ GDK_NONE);
+ }
+ else
+ gdk_synthesize_window_state (window,
+ setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
+ setting ? GDK_WINDOW_STATE_BELOW : 0);
+}
+
+/**
+ * gdk_window_get_group:
+ * @window: a toplevel #GdkWindow
+ *
+ * Returns the group leader window for @window. See gdk_window_set_group().
+ *
+ * Return value: the group leader window for @window
+ *
+ * Since: 2.4
+ **/
+GdkWindow *
+gdk_window_get_group (GdkWindow *window)
+{
+ GdkToplevelX11 *toplevel;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+ g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return NULL;
+
+ toplevel = _gdk_x11_window_get_toplevel (window);
+
+ return toplevel->group_leader;
+}
/**
* gdk_window_set_group:
* @window: a toplevel #GdkWindow
- * @leader: group leader window
+ * @leader: group leader window, or %NULL to restore the default group leader window
*
* Sets the group leader window for @window. By default,
* GDK sets the group leader for all toplevel windows
* allow users to minimize/unminimize all windows belonging to an
* application at once. You should only set a non-default group window
* if your application pretends to be multiple applications.
- * The group leader window may not be changed after a window has been
- * mapped (with gdk_window_show() for example).
- *
**/
void
gdk_window_set_group (GdkWindow *window,
GdkWindow *leader)
{
- XWMHints *wm_hints;
+ GdkToplevelX11 *toplevel;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
- g_return_if_fail (leader != NULL);
- g_return_if_fail (GDK_IS_WINDOW (leader));
+ g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
+ g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
- if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (leader))
+ if (GDK_WINDOW_DESTROYED (window) || (leader != NULL && GDK_WINDOW_DESTROYED (leader)))
return;
-
- wm_hints = XGetWMHints (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window));
- if (!wm_hints)
- wm_hints = XAllocWMHints ();
- wm_hints->flags |= WindowGroupHint;
- wm_hints->window_group = GDK_WINDOW_XID (leader);
+ toplevel = _gdk_x11_window_get_toplevel (window);
- XSetWMHints (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window), wm_hints);
- XFree (wm_hints);
+ if (leader == NULL)
+ leader = gdk_display_get_default_group (gdk_drawable_get_display (window));
+
+ if (toplevel->group_leader != leader)
+ {
+ if (toplevel->group_leader)
+ g_object_unref (toplevel->group_leader);
+ toplevel->group_leader = g_object_ref (leader);
+ (_gdk_x11_window_get_toplevel (leader))->is_leader = TRUE;
+ }
+
+ update_wm_hints (window, FALSE);
}
static MotifWmHints *
{
GdkDisplay *display;
Atom hints_atom = None;
- MotifWmHints *hints;
+ guchar *data;
Atom type;
gint format;
gulong nitems;
XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
False, AnyPropertyType, &type, &format, &nitems,
- &bytes_after, (guchar **)&hints);
+ &bytes_after, &data);
if (type == None)
return NULL;
- return hints;
+ return (MotifWmHints *)data;
}
static void
{
GdkDisplay *display;
Atom hints_atom = None;
+ guchar *data;
MotifWmHints *hints;
Atom type;
gint format;
XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
False, AnyPropertyType, &type, &format, &nitems,
- &bytes_after, (guchar **)&hints);
+ &bytes_after, &data);
if (type == None)
hints = new_hints;
else
{
+ hints = (MotifWmHints *)data;
+
if (new_hints->flags & MWM_HINTS_FUNCTIONS)
{
hints->flags |= MWM_HINTS_FUNCTIONS;
{
MotifWmHints hints;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
+ /* initialize to zero to avoid writing uninitialized data to socket */
+ memset(&hints, 0, sizeof(hints));
hints.flags = MWM_HINTS_DECORATIONS;
hints.decorations = decorations;
* @window: a toplevel #GdkWindow
* @functions: bitmask of operations to allow on @window
*
- * This function isn't really good for much. It sets the traditional
- * Motif window manager hint for which operations the window manager
- * should allow on a toplevel window. However, few window managers do
+ * Sets hints about the window management functions to make available
+ * via buttons on the window frame.
+ *
+ * On the X backend, this function sets the traditional Motif window
+ * manager hint for this purpose. However, few window managers do
* anything reliable or interesting with this hint. Many ignore it
* entirely.
*
{
MotifWmHints hints;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
+ /* initialize to zero to avoid writing uninitialized data to socket */
+ memset(&hints, 0, sizeof(hints));
hints.flags = MWM_HINTS_FUNCTIONS;
hints.functions = functions;
static void
gdk_propagate_shapes (Display *disp,
Window win,
- gboolean merge)
+ gboolean merge,
+ int shape)
{
Window rt, par, *list = NULL;
gint i, j, num = 0, num_rects = 0;
/* set the rects as the shape mask */
if (rects)
{
- XShapeCombineRectangles (disp, win, ShapeBounding, 0, 0, rects, num_rects,
+ XShapeCombineRectangles (disp, win, shape, 0, 0, rects, num_rects,
ShapeSet, YXSorted);
g_free (rects);
}
void
gdk_window_set_child_shapes (GdkWindow *window)
{
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
+
#ifdef HAVE_SHAPE_EXT
if (!GDK_WINDOW_DESTROYED (window) &&
- gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window)))
+ gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window), FALSE);
+ GDK_WINDOW_XID (window), FALSE, ShapeBounding);
#endif
}
* This function is distinct from gdk_window_set_child_shapes()
* because it includes @window's shape mask in the set of shapes to
* be merged.
- *
**/
void
gdk_window_merge_child_shapes (GdkWindow *window)
{
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
#ifdef HAVE_SHAPE_EXT
if (!GDK_WINDOW_DESTROYED (window) &&
- gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window)))
+ gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window), TRUE);
+ GDK_WINDOW_XID (window), TRUE, ShapeBounding);
#endif
}
-/* Support for windows that can be guffaw-scrolled
- * (See http://www.gtk.org/~otaylor/whitepapers/guffaw-scrolling.txt)
- */
-
-static gboolean
-gdk_window_gravity_works (GdkWindow *window)
+/**
+ * gdk_window_set_child_input_shapes:
+ * @window: a #GdkWindow
+ *
+ * Sets the input shape mask of @window to the union of input shape masks
+ * for all children of @window, ignoring the input shape mask of @window
+ * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
+ * the input shape mask of @window in the masks to be merged.
+ *
+ * Since: 2.10
+ **/
+void
+gdk_window_set_child_input_shapes (GdkWindow *window)
{
- GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_DRAWABLE_DISPLAY (window));
+ g_return_if_fail (GDK_IS_WINDOW (window));
- if (display_x11->gravity_works == GDK_UNKNOWN)
- {
- GdkWindowAttr attr;
- GdkWindow *parent;
- GdkWindow *child;
- gint y;
-
- /* This particular server apparently has a bug so that the test
- * works but the actual code crashes it
- */
- if ((!strcmp (XServerVendor (display_x11->xdisplay),
- "Sun Microsystems, Inc.")) &&
- (VendorRelease (display_x11->xdisplay) == 3400))
- {
- display_x11->gravity_works = GDK_NO;
- return FALSE;
- }
-
- attr.window_type = GDK_WINDOW_TEMP;
- attr.wclass = GDK_INPUT_OUTPUT;
- attr.x = 0;
- attr.y = 0;
- attr.width = 100;
- attr.height = 100;
- attr.event_mask = 0;
-
- parent = gdk_window_new (gdk_screen_get_root_window (GDK_DRAWABLE_SCREEN (window)),
- &attr, GDK_WA_X | GDK_WA_Y);
-
- attr.window_type = GDK_WINDOW_CHILD;
- child = gdk_window_new (parent, &attr, GDK_WA_X | GDK_WA_Y);
-
- gdk_window_set_static_win_gravity (child, TRUE);
-
- gdk_window_resize (parent, 100, 110);
+#ifdef HAVE_SHAPE_EXT
+#ifdef ShapeInput
+ if (!GDK_WINDOW_DESTROYED (window) &&
+ gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
+ gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window), FALSE, ShapeInput);
+#endif
+#endif
+}
- gdk_window_move (parent, 0, -10);
- gdk_window_move_resize (parent, 0, 0, 100, 100);
-
- gdk_window_resize (parent, 100, 110);
- gdk_window_move (parent, 0, -10);
- gdk_window_move_resize (parent, 0, 0, 100, 100);
-
- gdk_window_get_geometry (child, NULL, &y, NULL, NULL, NULL);
-
- gdk_window_destroy (parent);
- gdk_window_destroy (child);
-
- display_x11->gravity_works = ((y == -20) ? GDK_YES : GDK_NO);
- }
+/**
+ * gdk_window_merge_child_input_shapes:
+ * @window: a #GdkWindow
+ *
+ * Merges the input shape masks for any child windows into the
+ * input shape mask for @window. i.e. the union of all input masks
+ * for @window and its children will become the new input mask
+ * for @window. See gdk_window_input_shape_combine_mask().
+ *
+ * This function is distinct from gdk_window_set_child_input_shapes()
+ * because it includes @window's input shape mask in the set of
+ * shapes to be merged.
+ *
+ * Since: 2.10
+ **/
+void
+gdk_window_merge_child_input_shapes (GdkWindow *window)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
- return (display_x11->gravity_works == GDK_YES);
+#ifdef HAVE_SHAPE_EXT
+#ifdef ShapeInput
+ if (!GDK_WINDOW_DESTROYED (window) &&
+ gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
+ gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window), TRUE, ShapeInput);
+#endif
+#endif
}
+
static void
gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
{
GdkWindowObject *private;
guint xattributes_mask = 0;
- g_return_if_fail (window != NULL);
+ g_return_if_fail (GDK_IS_WINDOW (window));
private = GDK_WINDOW_OBJECT (window);
if (private->input_only)
{
XSetWindowAttributes xattributes;
- g_return_if_fail (window != NULL);
+ g_return_if_fail (GDK_IS_WINDOW (window));
xattributes.win_gravity = on ? StaticGravity : NorthWestGravity;
GdkWindowObject *private = (GdkWindowObject *)window;
GList *tmp_list;
- g_return_val_if_fail (window != NULL, FALSE);
g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
if (!use_static == !private->guffaw_gravity)
return TRUE;
-
- if (use_static && !gdk_window_gravity_works (window))
- return FALSE;
-
+
private->guffaw_gravity = use_static;
if (!GDK_WINDOW_DESTROYED (window))
{
gdk_window_destroy (mv_resize->moveresize_emulation_window);
mv_resize->moveresize_emulation_window = NULL;
+ g_object_unref (mv_resize->moveresize_window);
mv_resize->moveresize_window = NULL;
if (mv_resize->moveresize_pending_event)
/* If this fails, some other client has grabbed the window
* already.
*/
- gdk_window_destroy (mv_resize->moveresize_emulation_window);
- mv_resize->moveresize_emulation_window = NULL;
+ finish_drag (mv_resize);
}
mv_resize->moveresize_process_time = 0;
* Begins a window resize operation (for a toplevel window).
* You might use this function to implement a "window resize grip," for
* example; in fact #GtkStatusbar uses it. The function works best
- * with window managers that support the Extended Window Manager Hints spec
- * (see http://www.freedesktop.org), but has a fallback implementation
- * for other window managers.
+ * with window managers that support the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended Window Manager Hints</ulink>, but has a
+ * fallback implementation for other window managers.
*
**/
void
return;
if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
- gdk_atom_intern ("_NET_WM_MOVERESIZE", FALSE)))
+ gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
wmspec_resize_drag (window, edge, button, root_x, root_y, timestamp);
else
emulate_resize_drag (window, edge, button, root_x, root_y, timestamp);
* Begins a window move operation (for a toplevel window). You might
* use this function to implement a "window move grip," for
* example. The function works best with window managers that support
- * the Extended Window Manager Hints spec (see
- * http://www.freedesktop.org), but has a fallback implementation for
+ * the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended
+ * Window Manager Hints</ulink>, but has a fallback implementation for
* other window managers.
*
**/
return;
if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
- gdk_atom_intern ("_NET_WM_MOVERESIZE", FALSE)))
+ gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE, root_x, root_y,
timestamp);
else
emulate_move_drag (window, button, root_x, root_y, timestamp);
}
+
+/**
+ * gdk_window_enable_synchronized_configure:
+ * @window: a toplevel #GdkWindow
+ *
+ * Indicates that the application will cooperate with the window
+ * system in synchronizing the window repaint with the window
+ * manager during resizing operations. After an application calls
+ * this function, it must call gdk_window_configure_finished() every
+ * time it has finished all processing associated with a set of
+ * Configure events. Toplevel GTK+ windows automatically use this
+ * protocol.
+ *
+ * On X, calling this function makes @window participate in the
+ * _NET_WM_SYNC_REQUEST window manager protocol.
+ *
+ * Since: 2.6
+ **/
+void
+gdk_window_enable_synchronized_configure (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowImplX11 *impl;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ impl = GDK_WINDOW_IMPL_X11 (private->impl);
+
+ if (!impl->use_synchronized_configure)
+ {
+ impl->use_synchronized_configure = TRUE;
+ ensure_sync_counter (window);
+ }
+}
+
+/**
+ * gdk_window_configure_finished:
+ * @window: a toplevel #GdkWindow
+ *
+ * Signal to the window system that the application has finished
+ * handling Configure events it has received. Window Managers can
+ * use this to better synchronize the frame repaint with the
+ * application. GTK+ applications will automatically call this
+ * function when appropriate.
+ *
+ * This function can only be called if gdk_window_enable_synchronized_configure()
+ * was called previously.
+ *
+ * Since: 2.6
+ **/
+void
+gdk_window_configure_finished (GdkWindow *window)
+{
+ GdkWindowImplX11 *impl;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
+ if (!impl->use_synchronized_configure)
+ return;
+
+#ifdef HAVE_XSYNC
+ if (!GDK_WINDOW_DESTROYED (window))
+ {
+ GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
+ GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
+
+ if (toplevel && toplevel->update_counter != None &&
+ GDK_DISPLAY_X11 (display)->use_sync &&
+ !XSyncValueIsZero (toplevel->current_counter_value))
+ {
+ XSyncSetCounter (GDK_WINDOW_XDISPLAY (window),
+ toplevel->update_counter,
+ toplevel->current_counter_value);
+
+ XSyncIntToValue (&toplevel->current_counter_value, 0);
+ }
+ }
+#endif
+}
+
+#define __GDK_WINDOW_X11_C__
+#include "gdkaliasdef.c"