#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <netinet/in.h>
+#include <unistd.h>
#include "gdk.h"
#include "config.h"
#include <X11/extensions/shape.h>
#endif
-const int gdk_event_mask_table[21] =
+const int _gdk_event_mask_table[21] =
{
ExposureMask,
PointerMotionMask,
SubstructureNotifyMask,
ButtonPressMask /* SCROLL; on X mouse wheel events is treated as mouse button 4/5 */
};
-const int gdk_nevent_masks = sizeof (gdk_event_mask_table) / sizeof (int);
+const int _gdk_nenvent_masks = sizeof (_gdk_event_mask_table) / sizeof (int);
/* Forward declarations */
-static gboolean gdk_window_gravity_works (void);
-static void gdk_window_set_static_win_gravity (GdkWindow *window,
+static gboolean gdk_window_gravity_works (void);
+static void gdk_window_set_static_win_gravity (GdkWindow *window,
gboolean on);
-static gboolean gdk_window_have_shape_ext (void);
+static gboolean gdk_window_have_shape_ext (void);
+static gboolean gdk_window_icon_name_set (GdkWindow *window);
static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable);
static void gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
- GdkColormap *cmap);
-static void gdk_window_impl_x11_get_size (GdkDrawable *drawable,
- gint *width,
- gint *height);
+ GdkColormap *cmap);
+static void gdk_window_impl_x11_get_size (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);
object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_X11,
"GdkWindowImplX11",
- &object_info);
+ &object_info, 0);
}
return object_type;
drawable_class->set_colormap = gdk_window_impl_x11_set_colormap;
drawable_class->get_colormap = gdk_window_impl_x11_get_colormap;
drawable_class->get_size = gdk_window_impl_x11_get_size;
+
+ /* Visible and clip regions are the same */
+ drawable_class->get_clip_region = gdk_window_impl_x11_get_visible_region;
+ drawable_class->get_visible_region = gdk_window_impl_x11_get_visible_region;
}
static void
if (!GDK_WINDOW_DESTROYED (wrapper))
{
gdk_xid_table_remove (draw_impl->xid);
+ if (window_impl->focus_window)
+ gdk_xid_table_remove (window_impl->focus_window);
}
G_OBJECT_CLASS (parent_class)->finalize (object);
drawable_impl->colormap == NULL)
{
XWindowAttributes window_attributes;
-
+
XGetWindowAttributes (drawable_impl->xdisplay,
drawable_impl->xid,
&window_attributes);
GdkDrawableImplX11 *draw_impl;
g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable));
- g_return_if_fail (gdk_colormap_get_visual (cmap) != gdk_drawable_get_visual (drawable));
impl = GDK_WINDOW_IMPL_X11 (drawable);
draw_impl = GDK_DRAWABLE_IMPL_X11 (drawable);
- GDK_DRAWABLE_GET_CLASS (draw_impl)->set_colormap (drawable, cmap);
-
- XSetWindowColormap (draw_impl->xdisplay,
- draw_impl->xid,
- GDK_COLORMAP_XCOLORMAP (cmap));
+ /* chain up */
+ GDK_DRAWABLE_CLASS (parent_class)->set_colormap (drawable, cmap);
- if (((GdkWindowObject*)draw_impl->wrapper)->window_type !=
- GDK_WINDOW_TOPLEVEL)
- gdk_window_add_colormap_windows (GDK_WINDOW (draw_impl->wrapper));
+ if (cmap)
+ {
+ XSetWindowColormap (draw_impl->xdisplay,
+ draw_impl->xid,
+ GDK_COLORMAP_XCOLORMAP (cmap));
+
+ if (((GdkWindowObject*)draw_impl->wrapper)->window_type !=
+ GDK_WINDOW_TOPLEVEL)
+ gdk_window_add_colormap_windows (GDK_WINDOW (draw_impl->wrapper));
+ }
}
*height = GDK_WINDOW_IMPL_X11 (drawable)->height;
}
+static GdkRegion*
+gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable)
+{
+ GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (drawable);
+ GdkRectangle result_rect;
+
+ result_rect.x = 0;
+ result_rect.y = 0;
+ result_rect.width = impl->width;
+ result_rect.height = impl->height;
+
+ gdk_rectangle_intersect (&result_rect, &impl->position_info.clip_rect, &result_rect);
+
+ return gdk_region_rectangle (&result_rect);
+}
+
void
_gdk_windowing_window_init (void)
{
unsigned int depth;
int x, y;
- g_assert (gdk_parent_root == NULL);
+ g_assert (_gdk_parent_root == NULL);
- XGetGeometry (gdk_display, gdk_root_window, &gdk_root_window,
+ XGetGeometry (gdk_display, _gdk_root_window, &_gdk_root_window,
&x, &y, &width, &height, &border_width, &depth);
- XGetWindowAttributes (gdk_display, gdk_root_window, &xattributes);
+ XGetWindowAttributes (gdk_display, _gdk_root_window, &xattributes);
- gdk_parent_root = g_object_new (GDK_TYPE_WINDOW, NULL);
- private = (GdkWindowObject *)gdk_parent_root;
+ _gdk_parent_root = g_object_new (GDK_TYPE_WINDOW, NULL);
+ private = (GdkWindowObject *)_gdk_parent_root;
impl = GDK_WINDOW_IMPL_X11 (private->impl);
draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
draw_impl->xdisplay = gdk_display;
- draw_impl->xid = gdk_root_window;
+ draw_impl->xid = _gdk_root_window;
draw_impl->wrapper = GDK_DRAWABLE (private);
private->window_type = GDK_WINDOW_ROOT;
impl->width = width;
impl->height = height;
- gdk_xid_table_insert (&gdk_root_window, gdk_parent_root);
+ gdk_xid_table_insert (&_gdk_root_window, _gdk_parent_root);
}
-static GdkAtom wm_client_leader_atom = GDK_NONE;
+static Atom wm_client_leader_atom = None;
+/**
+ * gdk_window_new:
+ * @parent: a #GdkWindow
+ * @attributes: attributes of the new window
+ * @attributes_mask: mask indicating which fields in @attributes are valid
+ *
+ * Creates a new #GdkWindow using the attributes from @attributes. See
+ * #GdkWindowAttr and #GdkWindowAttributesType for more details.
+ *
+ * Return value: the new #GdkWindow
+ **/
GdkWindow*
gdk_window_new (GdkWindow *parent,
GdkWindowAttr *attributes,
{
GdkWindow *window;
GdkWindowObject *private;
- GdkWindowObject *parent_private;
GdkWindowImplX11 *impl;
GdkDrawableImplX11 *draw_impl;
GdkVisual *visual;
Window xparent;
Visual *xvisual;
+ Display *xdisplay;
+ Window xid;
XSetWindowAttributes xattributes;
long xattributes_mask;
unsigned int class;
char *title;
int i;
+ long pid;
g_return_val_if_fail (attributes != NULL, NULL);
if (!parent)
- parent = gdk_parent_root;
+ parent = _gdk_parent_root;
g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
- parent_private = (GdkWindowObject*) parent;
if (GDK_WINDOW_DESTROYED (parent))
return NULL;
impl = GDK_WINDOW_IMPL_X11 (private->impl);
draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
draw_impl->wrapper = GDK_DRAWABLE (window);
-
- draw_impl->xdisplay = GDK_WINDOW_XDISPLAY (parent);
+
+ xdisplay = draw_impl->xdisplay = GDK_WINDOW_XDISPLAY (parent);
+
+ /* Windows with a foreign parent are treated as if they are children
+ * of the root window, except for actual creation.
+ */
+ if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
+ parent = _gdk_parent_root;
private->parent = (GdkWindowObject *)parent;
private->y = y;
impl->width = (attributes->width > 1) ? (attributes->width) : (1);
impl->height = (attributes->height > 1) ? (attributes->height) : (1);
- private->window_type = attributes->window_type;
+
+ if (attributes->wclass == GDK_INPUT_ONLY)
+ {
+ /* Backwards compatiblity - we've always ignored
+ * attributes->window_type for input-only windows
+ * before
+ */
+ if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
+ private->window_type = GDK_WINDOW_TEMP;
+ else
+ private->window_type = GDK_WINDOW_CHILD;
+ }
+ else
+ private->window_type = attributes->window_type;
_gdk_window_init_position (GDK_WINDOW (private));
if (impl->position_info.big)
xvisual = ((GdkVisualPrivate*) visual)->xvisual;
xattributes.event_mask = StructureNotifyMask;
- for (i = 0; i < gdk_nevent_masks; i++)
+ for (i = 0; i < _gdk_nenvent_masks; i++)
{
if (attributes->event_mask & (1 << (i + 1)))
- xattributes.event_mask |= gdk_event_mask_table[i];
+ xattributes.event_mask |= _gdk_event_mask_table[i];
}
if (xattributes.event_mask)
else
xattributes.override_redirect = False;
- if (parent_private && parent_private->guffaw_gravity)
+ if (private->parent && private->parent->guffaw_gravity)
{
xattributes.win_gravity = StaticGravity;
xattributes_mask |= CWWinGravity;
}
+ /* Sanity checks */
+ switch (private->window_type)
+ {
+ case GDK_WINDOW_TOPLEVEL:
+ case GDK_WINDOW_DIALOG:
+ case GDK_WINDOW_TEMP:
+ if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
+ {
+ g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
+ "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
+ xparent = _gdk_root_window;
+ }
+ case GDK_WINDOW_CHILD:
+ break;
+ default:
+ g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
+ return NULL;
+ }
+
if (attributes->wclass == GDK_INPUT_OUTPUT)
{
class = InputOutput;
}
}
- private->bg_color.pixel = BlackPixel (gdk_display, gdk_screen);
+ private->bg_color.pixel = BlackPixel (gdk_display, _gdk_screen);
xattributes.background_pixel = private->bg_color.pixel;
private->bg_pixmap = NULL;
- xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen);
+ xattributes.border_pixel = BlackPixel (gdk_display, _gdk_screen);
xattributes_mask |= CWBorderPixel | CWBackPixel;
if (private->guffaw_gravity)
xattributes.bit_gravity = NorthWestGravity;
xattributes_mask |= CWBitGravity;
-
- switch (private->window_type)
+
+ xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap);
+ xattributes_mask |= CWColormap;
+
+ if (private->window_type == GDK_WINDOW_TEMP)
{
- case GDK_WINDOW_TOPLEVEL:
- xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap);
- xattributes_mask |= CWColormap;
-
- xparent = gdk_root_window;
- break;
-
- case GDK_WINDOW_CHILD:
- xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap);
- xattributes_mask |= CWColormap;
- break;
-
- case GDK_WINDOW_DIALOG:
- xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap);
- xattributes_mask |= CWColormap;
-
- xparent = gdk_root_window;
- break;
-
- case GDK_WINDOW_TEMP:
- xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap);
- xattributes_mask |= CWColormap;
-
- xparent = gdk_root_window;
-
xattributes.save_under = True;
xattributes.override_redirect = True;
xattributes.cursor = None;
xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
- break;
- case GDK_WINDOW_ROOT:
- g_error ("cannot make windows of type GDK_WINDOW_ROOT");
- break;
}
}
else
private->depth = 0;
class = InputOnly;
private->input_only = TRUE;
- draw_impl->colormap = NULL;
+ draw_impl->colormap = gdk_colormap_get_system ();
+ gdk_colormap_ref (draw_impl->colormap);
}
- draw_impl->xid = XCreateWindow (GDK_WINDOW_XDISPLAY (parent),
- xparent,
- x, y,
- impl->width, impl->height,
- 0, depth, class, xvisual,
- xattributes_mask, &xattributes);
+ xid = draw_impl->xid = XCreateWindow (xdisplay, xparent,
+ impl->position_info.x, impl->position_info.y,
+ impl->position_info.width, impl->position_info.height,
+ 0, depth, class, xvisual,
+ xattributes_mask, &xattributes);
gdk_drawable_ref (window);
- gdk_xid_table_insert (&GDK_WINDOW_XID (window), window);
+ gdk_xid_table_insert (&draw_impl->xid, window);
gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
(attributes->cursor) :
NULL));
- if (parent_private)
- parent_private->children = g_list_prepend (parent_private->children, window);
+ if (private->parent)
+ private->parent->children = g_list_prepend (private->parent->children, window);
switch (GDK_WINDOW_TYPE (private))
{
case GDK_WINDOW_DIALOG:
- XSetTransientForHint (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- xparent);
+ XSetTransientForHint (xdisplay, xid, xparent);
case GDK_WINDOW_TOPLEVEL:
case GDK_WINDOW_TEMP:
- XSetWMProtocols (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- gdk_wm_window_protocols, 2);
+ XSetWMProtocols (xdisplay, xid,
+ _gdk_wm_window_protocols, 3);
break;
case GDK_WINDOW_CHILD:
if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
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 (&impl->focus_window, window);
+ }
+
size_hints.flags = PSize;
size_hints.width = impl->width;
size_hints.height = impl->height;
- wm_hints.flags = InputHint | StateHint | WindowGroupHint;
- wm_hints.window_group = gdk_leader_window;
+ wm_hints.flags = StateHint | WindowGroupHint;
+ wm_hints.window_group = _gdk_leader_window;
wm_hints.input = True;
wm_hints.initial_state = NormalState;
* attention to PSize, and even if they do, is this the
* correct value???
*/
- XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- &size_hints);
+ XSetWMNormalHints (xdisplay, xid, &size_hints);
- XSetWMHints (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- &wm_hints);
+ XSetWMHints (xdisplay, xid, &wm_hints);
if (!wm_client_leader_atom)
- wm_client_leader_atom = gdk_atom_intern ("WM_CLIENT_LEADER", FALSE);
+ wm_client_leader_atom = gdk_x11_get_xatom_by_name ("WM_CLIENT_LEADER");
+
+ /* 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 ("_NET_WM_PID"),
+ XA_CARDINAL, 32,
+ PropModeReplace,
+ (guchar *)&pid, 1);
- XChangeProperty (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
+ XChangeProperty (xdisplay, xid,
wm_client_leader_atom,
XA_WINDOW, 32, PropModeReplace,
- (guchar*) &gdk_leader_window, 1);
+ (guchar*) &_gdk_leader_window, 1);
if (attributes_mask & GDK_WA_TITLE)
title = attributes->title;
else
title = g_get_prgname ();
-
- XmbSetWMProperties (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- title, title,
- NULL, 0,
- NULL, NULL, NULL);
+
+ 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 (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- class_hint);
+ XSetClassHint (xdisplay, xid, class_hint);
XFree (class_hint);
}
return window;
}
+/**
+ * gdk_window_foreign_new:
+ * @anid: a native window handle.
+ *
+ * Wraps a native window in a #GdkWindow.
+ * This may fail if the window has been destroyed.
+ *
+ * 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.
+ **/
GdkWindow *
gdk_window_foreign_new (GdkNativeWindow anid)
{
GdkWindow *window;
GdkWindowObject *private;
- GdkWindowObject *parent_private;
GdkWindowImplX11 *impl;
GdkDrawableImplX11 *draw_impl;
XWindowAttributes attrs;
draw_impl->wrapper = GDK_DRAWABLE (window);
private->parent = gdk_xid_table_lookup (parent);
+ if (!private->parent || GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_FOREIGN)
+ private->parent = (GdkWindowObject *)_gdk_parent_root;
- parent_private = (GdkWindowObject *)private->parent;
-
- if (parent_private)
- parent_private->children = g_list_prepend (parent_private->children, window);
+ private->parent->children = g_list_prepend (private->parent->children, window);
draw_impl->xid = anid;
draw_impl->xdisplay = gdk_display;
impl->height = attrs.height;
private->window_type = GDK_WINDOW_FOREIGN;
private->destroyed = FALSE;
- private->mapped = (attrs.map_state != IsUnmapped);
+
+ if (attrs.map_state == IsUnmapped)
+ private->state = GDK_WINDOW_STATE_WITHDRAWN;
+ else
+ private->state = 0;
+
private->depth = attrs.depth;
+ _gdk_window_init_position (GDK_WINDOW (private));
+
gdk_drawable_ref (window);
gdk_xid_table_insert (&GDK_WINDOW_XID (window), window);
return window;
}
+/**
+ * gdk_window_lookup:
+ * @anid: a native window handle.
+ *
+ * Looks up the #GdkWindow that wraps the given native window handle.
+ *
+ * For example in the X backend, a native window handle is an Xlib
+ * <type>XID</type>.
+ *
+ * Return value: the #GdkWindow wrapper for the native window,
+ * or %NULL if there is none.
+ **/
+GdkWindow *
+gdk_window_lookup (GdkNativeWindow anid)
+{
+ return (GdkWindow*) gdk_xid_table_lookup (anid);
+}
+
void
_gdk_windowing_window_destroy (GdkWindow *window,
gboolean recursing,
GdkWindowObject *private = (GdkWindowObject *)window;
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);
+
+ if (draw_impl->picture)
+ XRenderFreePicture (draw_impl->xdisplay, draw_impl->picture);
+ }
+#endif /* HAVE_XFT */
+
if (private->window_type == GDK_WINDOW_FOREIGN)
{
if (!foreign_destroy && (private->parent != NULL))
xevent.type = ClientMessage;
xevent.window = GDK_WINDOW_XID (window);
- xevent.message_type = gdk_wm_protocols;
+ xevent.message_type = gdk_x11_get_xatom_by_name ("WM_PROTOCOLS");
xevent.format = 32;
- xevent.data.l[0] = gdk_wm_delete_window;
+ xevent.data.l[0] = gdk_x11_get_xatom_by_name ("WM_DELETE_WINDOW");
xevent.data.l[1] = CurrentTime;
XSendEvent (GDK_WINDOW_XDISPLAY (window),
void
gdk_window_destroy_notify (GdkWindow *window)
{
+ GdkWindowImplX11 *window_impl;
+
g_return_if_fail (window != NULL);
+ window_impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
+
if (!GDK_WINDOW_DESTROYED (window))
{
if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
}
gdk_xid_table_remove (GDK_WINDOW_XID (window));
+ if (window_impl->focus_window)
+ gdk_xid_table_remove (window_impl->focus_window);
+
gdk_drawable_unref (window);
}
-void
-gdk_window_show (GdkWindow *window)
+static void
+set_initial_hints (GdkWindow *window)
+{
+ GdkWindowObject *private;
+ Atom atoms[5];
+ gint i;
+
+ private = (GdkWindowObject*) window;
+
+ 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;
+
+ XSetWMHints (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window), wm_hints);
+ XFree (wm_hints);
+ }
+
+ /* 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.
+ */
+
+ i = 0;
+
+ if (private->state & GDK_WINDOW_STATE_MAXIMIZED)
+ {
+ atoms[i] = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_MAXIMIZED_VERT");
+ ++i;
+ atoms[i] = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_MAXIMIZED_HORZ");
+ ++i;
+ }
+
+ if (private->state & GDK_WINDOW_STATE_STICKY)
+ {
+ atoms[i] = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_STICKY");
+ ++i;
+ }
+
+ if (private->modal_hint)
+ {
+ atoms[i] = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_MODAL");
+ ++i;
+ }
+
+ if (i > 0)
+ {
+ XChangeProperty (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ gdk_x11_get_xatom_by_name ("_NET_WM_STATE"),
+ XA_ATOM, 32, PropModeReplace,
+ (guchar*) atoms, i);
+ }
+
+ 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 ("_NET_WM_DESKTOP"),
+ XA_CARDINAL, 32, PropModeReplace,
+ (guchar*) atoms, 1);
+ }
+}
+
+static void
+show_window_internal (GdkWindow *window,
+ gboolean raise)
{
GdkWindowObject *private;
private = (GdkWindowObject*) window;
if (!private->destroyed)
{
- private->mapped = TRUE;
- XRaiseWindow (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window));
+ if (raise)
+ XRaiseWindow (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window));
+
+ if (!GDK_WINDOW_IS_MAPPED (window))
+ {
+ set_initial_hints (window);
+
+ gdk_synthesize_window_state (window,
+ GDK_WINDOW_STATE_WITHDRAWN,
+ 0);
+ }
+
+ 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));
+ XMapWindow (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window));
}
}
+/**
+ * gdk_window_show_unraised:
+ * @window: a #GdkWindow
+ *
+ * Shows a #GdkWindow onscreen, but does not modify its stacking
+ * order. In contrast, gdk_window_show() will raise the window
+ * to the top of the window stack.
+ *
+ * On the X11 platform, in Xlib terms, this function calls
+ * XMapWindow() (it also updates some internal GDK state, which means
+ * that you can't really use XMapWindow() directly on a GDK window).
+ *
+ **/
+void
+gdk_window_show_unraised (GdkWindow *window)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ show_window_internal (window, FALSE);
+}
+
+/**
+ * gdk_window_show:
+ * @window: a #GdkWindow
+ *
+ * Like gdk_window_show_unraised(), but also raises the window to the
+ * top of the window stack (moves the window to the front of the
+ * Z-order).
+ *
+ * This function maps a window so it's visible onscreen. Its opposite
+ * is gdk_window_hide().
+ *
+ * When implementing a #GtkWidget, you should call this function on the widget's
+ * #GdkWindow as part of the "map" method.
+ *
+ **/
+void
+gdk_window_show (GdkWindow *window)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ show_window_internal (window, TRUE);
+}
+
+/**
+ * gdk_window_hide:
+ * @window: a #GdkWindow
+ *
+ * For toplevel windows, withdraws them, so they will no longer be
+ * known to the window manager; for all windows, unmaps them, so
+ * they won't be displayed. Normally done automatically as
+ * part of gtk_widget_hide().
+ *
+ **/
void
gdk_window_hide (GdkWindow *window)
{
g_return_if_fail (window != NULL);
private = (GdkWindowObject*) window;
+
+ /* You can't simply unmap toplevel windows. */
+ switch (private->window_type)
+ {
+ case GDK_WINDOW_TOPLEVEL:
+ case GDK_WINDOW_DIALOG:
+ case GDK_WINDOW_TEMP: /* ? */
+ gdk_window_withdraw (window);
+ return;
+ break;
+
+ case GDK_WINDOW_FOREIGN:
+ case GDK_WINDOW_ROOT:
+ case GDK_WINDOW_CHILD:
+ break;
+ }
+
if (!private->destroyed)
{
- private->mapped = FALSE;
+ if (GDK_WINDOW_IS_MAPPED (window))
+ gdk_synthesize_window_state (window,
+ 0,
+ GDK_WINDOW_STATE_WITHDRAWN);
+ g_assert (!GDK_WINDOW_IS_MAPPED (window));
+
_gdk_window_clear_update_area (window);
XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window));
+ GDK_WINDOW_XID (window));
}
}
+/**
+ * gdk_window_withdraw:
+ * @window: a toplevel #GdkWindow
+ *
+ * Withdraws a window (unmaps it and asks the window manager to forget about it).
+ * Normally done automatically by gtk_widget_hide() called on a #GtkWindow.
+ *
+ **/
void
gdk_window_withdraw (GdkWindow *window)
{
private = (GdkWindowObject*) window;
if (!private->destroyed)
- XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window), 0);
+ {
+ if (GDK_WINDOW_IS_MAPPED (window))
+ gdk_synthesize_window_state (window,
+ 0,
+ GDK_WINDOW_STATE_WITHDRAWN);
+
+ g_assert (!GDK_WINDOW_IS_MAPPED (window));
+
+ XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window), 0);
+ }
}
+/**
+ * gdk_window_move:
+ * @window: a #GdkWindow
+ * @x: X coordinate relative to window's parent
+ * @y: Y coordinate relative to window's parent
+ *
+ * Repositions a window relative to its parent window.
+ * For toplevel windows, window managers may ignore or modify the move;
+ * you should probably use gtk_window_move() on a #GtkWindow widget
+ * anyway, instead of using GDK functions. For child windows,
+ * the move will reliably succeed.
+ *
+ * If you're also planning to resize the window, use gdk_window_move_resize()
+ * to both move and resize simultaneously, for a nicer visual effect.
+ *
+ **/
void
gdk_window_move (GdkWindow *window,
gint x,
g_return_if_fail (GDK_IS_WINDOW (window));
impl = GDK_WINDOW_IMPL_X11 (private->impl);
-
- gdk_window_move_resize (window, x, y,
- impl->width, impl->height);
+
+ 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);
+ else
+ {
+ XMoveWindow (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ x, y);
+ }
+ }
}
+/**
+ * gdk_window_resize:
+ * @window: a #GdkWindow
+ * @width: new width of the window
+ * @height: new height of the window
+ *
+ * Resizes @window; for toplevel windows, asks the window manager to resize
+ * the window. The window manager may not allow the resize. When using GTK+,
+ * use gtk_window_resize() instead of this low-level GDK function.
+ *
+ * Windows may not be resized below 1x1.
+ *
+ * If you're also planning to move the window, use gdk_window_move_resize()
+ * to both move and resize simultaneously, for a nicer visual effect.
+ *
+ **/
void
gdk_window_resize (GdkWindow *window,
gint width,
width, height);
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);
- private->resize_count += 1;
}
}
}
+/**
+ * gdk_window_move_resize:
+ * @window: a #GdkWindow
+ * @x: new X position relative to window's parent
+ * @y: new Y position relative to window's parent
+ * @width: new width
+ * @height: new height
+ *
+ * Equivalent to calling gdk_window_move() and gdk_window_resize(),
+ * except that both operations are performed at once, avoiding strange
+ * visual effects. (i.e. the user may be able to see the window first
+ * move, then resize, if youu don't use gdk_window_move_resize().)
+ *
+ **/
void
gdk_window_move_resize (GdkWindow *window,
gint x,
_gdk_window_move_resize_child (window, x, y, width, height);
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);
}
}
+/**
+ * gdk_window_reparent:
+ * @window: a #GdkWindow
+ * @new_parent: new parent to move @window into
+ * @x: X location inside the new parent
+ * @y: Y location inside the new parent
+ *
+ * Reparents @window into the given @new_parent. The window being
+ * reparented will be unmapped as a side effect.
+ *
+ **/
void
gdk_window_reparent (GdkWindow *window,
GdkWindow *new_parent,
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
- g_return_if_fail (new_parent != NULL);
- g_return_if_fail (GDK_IS_WINDOW (new_parent));
+ g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
+ g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
if (!new_parent)
- new_parent = gdk_parent_root;
+ new_parent = _gdk_parent_root;
window_private = (GdkWindowObject*) window;
old_parent_private = (GdkWindowObject*)window_private->parent;
GDK_WINDOW_XID (window),
GDK_WINDOW_XID (new_parent),
x, y);
+
+ /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
+ * the root window
+ */
+ if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
+ new_parent = _gdk_parent_root;
window_private->parent = (GdkWindowObject *)new_parent;
-
+
+ /* Switch the window type as appropriate */
+
+ switch (GDK_WINDOW_TYPE (new_parent))
+ {
+ case GDK_WINDOW_ROOT:
+ case GDK_WINDOW_FOREIGN:
+ /* Now a toplevel */
+ if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
+ {
+ GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+ XSetWMProtocols (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ _gdk_wm_window_protocols, 3);
+ }
+ 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 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.
+ */
+ GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
+ }
+ }
+
if (old_parent_private)
old_parent_private->children = g_list_remove (old_parent_private->children, window);
gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
parent_private->children = g_list_prepend (parent_private->children, window);
+ _gdk_window_init_position (GDK_WINDOW (window_private));
}
void
x, y, width, height, True);
}
+
+/**
+ * gdk_window_raise:
+ * @window: a #GdkWindow
+ *
+ * Raises @window to the top of the Z-order (stacking order), so that
+ * other windows with the same parent window appear below @window.
+ * If @window is a toplevel, the window manager may choose to deny the
+ * request to move the window in the Z-order, gdk_window_raise() only
+ * requests the restack, does not guarantee it.
+ *
+ **/
void
gdk_window_raise (GdkWindow *window)
{
XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
}
+/**
+ * gdk_window_lower:
+ * @window: a #GdkWindow
+ *
+ * Lowers @window to the bottom of the Z-order (stacking order), so that
+ * other windows with the same parent window appear above @window.
+ * If @window is a toplevel, the window manager may choose to deny the
+ * request to move the window in the Z-order, gdk_window_lower() only
+ * requests the restack, does not guarantee it.
+ *
+ * Note that gdk_window_show() raises the window again, so don't call this
+ * function before gdk_window_show(). (Try gdk_window_show_unraised().)
+ *
+ **/
void
gdk_window_lower (GdkWindow *window)
{
XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
}
+/**
+ * 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.
+ *
+ **/
+void
+gdk_window_focus (GdkWindow *window,
+ guint32 timestamp)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ if (gdk_net_wm_supports (gdk_atom_intern ("_NET_ACTIVE_WINDOW", FALSE)))
+ {
+ XEvent xev;
+
+ xev.xclient.type = ClientMessage;
+ xev.xclient.serial = 0;
+ xev.xclient.send_event = True;
+ xev.xclient.window = GDK_WINDOW_XWINDOW (window);
+ xev.xclient.display = gdk_display;
+ xev.xclient.message_type = gdk_x11_get_xatom_by_name ("_NET_ACTIVE_WINDOW");
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = 0;
+
+ XSendEvent (gdk_display, _gdk_root_window, False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &xev);
+ }
+ else
+ {
+ XRaiseWindow (GDK_WINDOW_XDISPLAY (window), 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.
+ */
+ gdk_error_trap_push ();
+ XSetInputFocus (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XWINDOW (window),
+ RevertToNone,
+ timestamp);
+ XSync (GDK_WINDOW_XDISPLAY (window), False);
+ gdk_error_trap_pop ();
+ }
+}
+
+/**
+ * gdk_window_set_hints:
+ * @window: a #GdkWindow
+ * @x: ignored field, does not matter
+ * @y: ignored field, does not matter
+ * @min_width: minimum width hint
+ * @min_height: minimum height hint
+ * @max_width: max width hint
+ * @max_height: max height hint
+ * @flags: logical OR of GDK_HINT_POS, GDK_HINT_MIN_SIZE, and/or GDK_HINT_MAX_SIZE
+ *
+ * This function is broken and useless and you should ignore it.
+ * If using GTK+, use functions such as gtk_window_resize(), gtk_window_set_size_request(),
+ * gtk_window_move(), gtk_window_parse_geometry(), and gtk_window_set_geometry_hints(),
+ * depending on what you're trying to do.
+ *
+ * If using GDK directly, use gdk_window_set_geometry_hints().
+ *
+ **/
void
gdk_window_set_hints (GdkWindow *window,
gint x,
size_hints.max_height = max_height;
}
- /* FIXME: Would it be better to delete this property of
+ /* FIXME: Would it be better to delete this property if
* flags == 0? It would save space on the server
*/
XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
&size_hints);
}
-void
-gdk_window_set_geometry_hints (GdkWindow *window,
- GdkGeometry *geometry,
- GdkWindowHints geom_mask)
+/**
+ * gdk_window_set_type_hint:
+ * @window: A #GdkWindow
+ * @hint: A hint of the function this window will have
+ *
+ * The application can use this call to provide a hint to the window
+ * manager about the functionality of a window. The window manager
+ * can use this information when determining the decoration and behaviour
+ * of the window.
+ *
+ * The hint must be set before the window is mapped.
+ **/
+void
+gdk_window_set_type_hint (GdkWindow *window,
+ GdkWindowTypeHint hint)
+{
+ Atom atom;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ switch (hint)
+ {
+ case GDK_WINDOW_TYPE_HINT_DIALOG:
+ atom = gdk_x11_get_xatom_by_name ("_NET_WM_WINDOW_TYPE_DIALOG");
+ break;
+ case GDK_WINDOW_TYPE_HINT_MENU:
+ atom = gdk_x11_get_xatom_by_name ("_NET_WM_WINDOW_TYPE_MENU");
+ break;
+ case GDK_WINDOW_TYPE_HINT_TOOLBAR:
+ atom = gdk_x11_get_xatom_by_name ("_NET_WM_WINDOW_TYPE_TOOLBAR");
+ break;
+ default:
+ g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
+ /* Fall thru */
+ case GDK_WINDOW_TYPE_HINT_NORMAL:
+ atom = gdk_x11_get_xatom_by_name ("_NET_WM_WINDOW_TYPE_NORMAL");
+ break;
+ }
+
+ XChangeProperty (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ gdk_x11_get_xatom_by_name ("_NET_WM_WINDOW_TYPE"),
+ XA_ATOM, 32, PropModeReplace,
+ (guchar *)&atom, 1);
+}
+
+
+static void
+gdk_wmspec_change_state (gboolean add,
+ GdkWindow *window,
+ GdkAtom state1,
+ GdkAtom state2)
+{
+ 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.serial = 0;
+ xev.xclient.send_event = True;
+ xev.xclient.display = gdk_display;
+ xev.xclient.window = GDK_WINDOW_XID (window);
+ xev.xclient.message_type = gdk_x11_get_xatom_by_name ("_NET_WM_STATE");
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
+ xev.xclient.data.l[1] = gdk_x11_atom_to_xatom (state1);
+ xev.xclient.data.l[2] = gdk_x11_atom_to_xatom (state2);
+
+ XSendEvent (gdk_display, _gdk_root_window, False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &xev);
+}
+/**
+ * gdk_window_set_modal_hint:
+ * @window: A #GdkWindow
+ * @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
+ * can use this information to handle modal windows in a special
+ * way.
+ *
+ * You should only use this on windows for which you have
+ * previously called #gdk_window_set_transient_for()
+ **/
+void
+gdk_window_set_modal_hint (GdkWindow *window,
+ gboolean modal)
+{
+ 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;
+
+ private->modal_hint = modal;
+
+ if (GDK_WINDOW_IS_MAPPED (window))
+ gdk_wmspec_change_state (modal, window,
+ gdk_atom_intern ("_NET_WM_STATE_MODAL", FALSE),
+ 0);
+}
+
+/**
+ * gdk_window_set_geometry_hints:
+ * @window: a #GdkWindow
+ * @geometry: geometry hints
+ * @geom_mask: bitmask indicating fields of @geometry to pay attention to
+ *
+ * Sets the geometry hints for @window. Hints flagged in @geom_mask
+ * are set, hints not flagged in @geom_mask are unset.
+ * To unset all hints, use a @geom_mask of 0 and a @geometry of %NULL.
+ *
+ **/
+void
+gdk_window_set_geometry_hints (GdkWindow *window,
+ GdkGeometry *geometry,
+ GdkWindowHints geom_mask)
{
XSizeHints size_hints;
size_hints.x = 0;
size_hints.y = 0;
}
+
+ if (geom_mask & GDK_HINT_USER_POS)
+ {
+ size_hints.flags |= USPosition;
+ }
+
+ if (geom_mask & GDK_HINT_USER_SIZE)
+ {
+ size_hints.flags |= USSize;
+ }
if (geom_mask & GDK_HINT_MIN_SIZE)
{
}
}
- /* FIXME: Would it be better to delete this property of
+ if (geom_mask & GDK_HINT_WIN_GRAVITY)
+ {
+ size_hints.flags |= PWinGravity;
+ size_hints.win_gravity = geometry->win_gravity;
+ }
+
+ /* FIXME: Would it be better to delete this property if
* geom_mask == 0? It would save space on the server
*/
XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
&size_hints);
}
+static void
+gdk_window_get_geometry_hints (GdkWindow *window,
+ GdkGeometry *geometry,
+ GdkWindowHints *geom_mask)
+{
+ XSizeHints size_hints;
+ glong junk_size_mask = 0;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (geometry != NULL);
+ g_return_if_fail (geom_mask != NULL);
+
+ *geom_mask = 0;
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ if (!XGetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ &size_hints,
+ &junk_size_mask))
+ return;
+
+ if (size_hints.flags & PMinSize)
+ {
+ *geom_mask |= GDK_HINT_MIN_SIZE;
+ geometry->min_width = size_hints.min_width;
+ geometry->min_height = size_hints.min_height;
+ }
+
+ if (size_hints.flags & PMaxSize)
+ {
+ *geom_mask |= GDK_HINT_MAX_SIZE;
+ geometry->max_width = MAX (size_hints.max_width, 1);
+ geometry->max_height = MAX (size_hints.max_height, 1);
+ }
+
+ if (size_hints.flags & PResizeInc)
+ {
+ *geom_mask |= GDK_HINT_RESIZE_INC;
+ geometry->width_inc = size_hints.width_inc;
+ geometry->height_inc = size_hints.height_inc;
+ }
+
+ if (size_hints.flags & PAspect)
+ {
+ *geom_mask |= GDK_HINT_ASPECT;
+
+ geometry->min_aspect = (gdouble) size_hints.min_aspect.x / (gdouble) size_hints.min_aspect.y;
+ geometry->max_aspect = (gdouble) size_hints.max_aspect.x / (gdouble) size_hints.max_aspect.y;
+ }
+
+ if (size_hints.flags & PWinGravity)
+ {
+ *geom_mask |= GDK_HINT_WIN_GRAVITY;
+ geometry->win_gravity = size_hints.win_gravity;
+ }
+}
+
+static gboolean
+utf8_is_latin1 (const gchar *str)
+{
+ const char *p = str;
+
+ while (*p)
+ {
+ gunichar ch = g_utf8_get_char (p);
+
+ if (ch > 0xff)
+ return FALSE;
+
+ p = g_utf8_next_char (p);
+ }
+
+ return TRUE;
+}
+
+/* Set the property to @utf8_str as STRING if the @utf8_str is fully
+ * convertable to STRING, otherwise, set it as compound text
+ */
+static void
+set_text_property (GdkWindow *window,
+ Atom property,
+ const gchar *utf8_str)
+{
+ guchar *prop_text = NULL;
+ Atom prop_type;
+ gint prop_length;
+ gint prop_format;
+
+ if (utf8_is_latin1 (utf8_str))
+ {
+ prop_type = XA_STRING;
+ prop_text = gdk_utf8_to_string_target (utf8_str);
+ prop_length = strlen (prop_text);
+ prop_format = 8;
+ }
+ else
+ {
+ GdkAtom gdk_type;
+
+ gdk_utf8_to_compound_text (utf8_str, &gdk_type, &prop_format,
+ &prop_text, &prop_length);
+ prop_type = gdk_x11_atom_to_xatom (gdk_type);
+ }
+
+ if (prop_text)
+ {
+ XChangeProperty (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ property,
+ prop_type, prop_format,
+ PropModeReplace, prop_text,
+ prop_length);
+
+ g_free (prop_text);
+ }
+}
+
+/**
+ * gdk_window_set_title:
+ * @window: a #GdkWindow
+ * @title: title of @window
+ *
+ * Sets the title of a toplevel window, to be displayed in the titlebar.
+ * If you haven't explicitly set the icon name for the window
+ * (using gdk_window_set_icon_name()), the icon name will be set to
+ * @title as well. @title must be in UTF-8 encoding (as with all
+ * user-readable strings in GDK/GTK+). @title may not be %NULL.
+ *
+ **/
void
gdk_window_set_title (GdkWindow *window,
const gchar *title)
{
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (title != NULL);
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
- if (!GDK_WINDOW_DESTROYED (window))
- XmbSetWMProperties (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- title, title, NULL, 0, NULL, NULL, NULL);
+ XChangeProperty (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ gdk_x11_get_xatom_by_name ("_NET_WM_NAME"),
+ gdk_x11_get_xatom_by_name ("UTF8_STRING"), 8,
+ PropModeReplace, title,
+ strlen (title));
+
+ set_text_property (window, gdk_x11_get_xatom_by_name ("WM_NAME"), title);
+ if (!gdk_window_icon_name_set (window))
+ {
+ XChangeProperty (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ gdk_x11_get_xatom_by_name ("_NET_WM_ICON_NAME"),
+ gdk_x11_get_xatom_by_name ("UTF8_STRING"), 8,
+ PropModeReplace, title,
+ strlen (title));
+ set_text_property (window, gdk_x11_get_xatom_by_name ("WM_ICON_NAME"), title);
+ }
}
+/**
+ * gdk_window_set_role:
+ * @window: a #GdkWindow
+ * @role: a string indicating its role
+ *
+ * When using GTK+, typically you should use gtk_window_set_role() instead
+ * of this low-level function.
+ *
+ * The window manager and session manager use a window's role to
+ * distinguish it from other kinds of window in the same application.
+ * When an application is restarted after being saved in a previous
+ * session, all windows with the same title and role are treated as
+ * interchangeable. So if you have two windows with the same title
+ * that should be distinguished for session management purposes, you
+ * should set the role on those windows. It doesn't matter what string
+ * you use for the role, as long as you have a different role for each
+ * non-interchangeable kind of window.
+ *
+ **/
void
gdk_window_set_role (GdkWindow *window,
const gchar *role)
{
if (role)
XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
- gdk_atom_intern ("WM_WINDOW_ROLE", FALSE), XA_STRING,
+ gdk_x11_get_xatom_by_name ("WM_WINDOW_ROLE"), XA_STRING,
8, PropModeReplace, role, strlen (role));
else
XDeleteProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
- gdk_atom_intern ("WM_WINDOW_ROLE", FALSE));
+ gdk_x11_get_xatom_by_name ("WM_WINDOW_ROLE"));
}
}
+/**
+ * gdk_window_set_transient_for:
+ * @window: a toplevel #GdkWindow
+ * @parent: another toplevel #GdkWindow
+ *
+ * Indicates to the window manager that @window is a transient dialog
+ * associated with the application window @parent. This allows the
+ * window manager to do things like center @window on @parent and
+ * keep @window above @parent.
+ *
+ * See gtk_window_set_transient_for() if you're using #GtkWindow or
+ * #GtkDialog.
+ *
+ **/
void
gdk_window_set_transient_for (GdkWindow *window,
GdkWindow *parent)
GDK_WINDOW_XID (parent));
}
+/**
+ * gdk_window_set_background:
+ * @window: a #GdkWindow
+ * @color: an allocated #GdkColor
+ *
+ * Sets the background color of @window. (However, when using GTK+,
+ * set the background of a widget with gtk_widget_modify_bg() - if
+ * you're an application - or gtk_style_set_background() - if you're
+ * implementing a custom widget.)
+ *
+ * The @color must be allocated; gdk_rgb_find_color() is the best way
+ * to allocate a color.
+ *
+ * See also gdk_window_set_back_pixmap().
+ *
+ **/
void
gdk_window_set_background (GdkWindow *window,
GdkColor *color)
}
}
+/**
+ * gdk_window_set_back_pixmap:
+ * @window: a #GdkWindow
+ * @pixmap: a #GdkPixmap, or %NULL
+ * @parent_relative: whether the tiling origin is at the origin of @window's parent
+ *
+ * Sets the background pixmap of @window. May also be used to set a background of
+ * "None" on @window, by setting a background pixmap of %NULL.
+ * A background pixmap will be tiled, positioning the first tile at the origin of
+ * @window, or if @parent_relative is %TRUE, the tiling will be done based on the
+ * origin of the parent window (useful to align tiles in a parent with tiles
+ * in a child).
+ *
+ * A background pixmap of %NULL means that the window will have no
+ * background. A window with no background will never have its
+ * background filled by the windowing system, instead the window will
+ * contain whatever pixels were already in the corresponding area of
+ * the display.
+ *
+ * The windowing system will normally fill a window with its background
+ * when the window is obscured then exposed, and when you call
+ * gdk_window_clear().
+ *
+ **/
void
gdk_window_set_back_pixmap (GdkWindow *window,
GdkPixmap *pixmap,
GDK_WINDOW_XID (window), xpixmap);
}
+/**
+ * gdk_window_set_cursor:
+ * @window: a #GdkWindow
+ * @cursor: a cursor
+ *
+ * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new() or
+ * gdk_cursor_new_from_pixmap() to create the cursor.
+ * To make the cursor invisible, use gdk_cursor_new_from_pixmap() to create
+ * a cursor with no pixels in it. Passing %NULL for the @cursor argument
+ * to gdk_window_set_cursor() means that @window will use the cursor of
+ * its parent window. Most windows should use this default.
+ *
+ **/
void
gdk_window_set_cursor (GdkWindow *window,
GdkCursor *cursor)
xcursor);
}
+/**
+ * gdk_window_get_geometry:
+ * @window: a #GdkWindow
+ * @x: return location for X coordinate of window (relative to its parent)
+ * @y: return location for Y coordinate of window (relative to its parent)
+ * @width: return location for width of window
+ * @height: return location for height of window
+ * @depth: return location for bit depth of window
+ *
+ * Any of the return location arguments to this function may be %NULL,
+ * if you aren't interested in getting the value of that field.
+ *
+ * The X and Y coordinates returned are relative to the parent window
+ * of @window, which for toplevels usually means relative to the
+ * window decorations (titlebar, etc.) rather than relative to the
+ * root window (screen-size background window).
+ *
+ * On the X11 platform, the geometry is obtained from the X server,
+ * so reflects the latest position of @window; this may be out-of-sync
+ * with the position of @window delivered in the most-recently-processed
+ * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
+ * position from the most recent configure event.
+ *
+ **/
void
gdk_window_get_geometry (GdkWindow *window,
gint *x,
g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
if (!window)
- window = gdk_parent_root;
+ window = _gdk_parent_root;
if (!GDK_WINDOW_DESTROYED (window))
{
}
}
+/**
+ * gdk_window_get_origin:
+ * @window: a #GdkWindow
+ * @x: return location for X coordinate
+ * @y: return location for Y coordinate
+ *
+ * Obtains the position of a window in root window coordinates.
+ * (Compare with gdk_window_get_position() and
+ * gdk_window_get_geometry() which return the position of a window
+ * relative to its parent window.)
+ *
+ * Return value: not meaningful, ignore
+ **/
gint
gdk_window_get_origin (GdkWindow *window,
gint *x,
{
return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
- gdk_root_window,
+ _gdk_root_window,
0, 0, &tx, &ty,
&child);
return return_val;
}
+/**
+ * gdk_window_get_deskrelative_origin:
+ * @window: a #GdkWindow
+ * @x: return location for X coordinate
+ * @y: return location for Y coordinate
+ *
+ * This gets the origin of a #GdkWindow relative to
+ * an Enlightenment-window-manager desktop. As long as you don't
+ * assume that the user's desktop/workspace covers the entire
+ * root window (i.e. you don't assume that the desktop begins
+ * at root window coordinate 0,0) this function is not necessary.
+ * It's deprecated for that reason.
+ *
+ * Return value: not meaningful
+ **/
gboolean
gdk_window_get_deskrelative_origin (GdkWindow *window,
gint *x,
if (!GDK_WINDOW_DESTROYED (window))
{
if (!atom)
- atom = gdk_atom_intern ("ENLIGHTENMENT_DESKTOP", FALSE);
+ atom = gdk_x11_get_xatom_by_name ("ENLIGHTENMENT_DESKTOP");
win = GDK_WINDOW_XID (window);
while (XQueryTree (GDK_WINDOW_XDISPLAY (window), win, &root, &parent,
return return_val;
}
+/**
+ * gdk_window_get_root_origin:
+ * @window: a #GdkWindow
+ * @x: return location for X position of window frame
+ * @y: return location for Y position of window frame
+ *
+ * Obtains the top-left corner of the window manager frame in root
+ * window coordinates.
+ *
+ **/
void
gdk_window_get_root_origin (GdkWindow *window,
gint *x,
gint *y)
+{
+ GdkRectangle rect;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ gdk_window_get_frame_extents (window, &rect);
+
+ if (x)
+ *x = rect.x;
+
+ if (y)
+ *y = rect.y;
+}
+
+/**
+ * gdk_window_get_frame_extents:
+ * @window: a #GdkWindow
+ * @rect: rectangle to fill with bounding box of the window frame
+ *
+ * Obtains the bounding box of the window, including window manager
+ * titlebar/borders if any. The frame position is given in root window
+ * coordinates. To get the position of the window itself (rather than
+ * the frame) in root window coordinates, use gdk_window_get_origin().
+ *
+ **/
+void
+gdk_window_get_frame_extents (GdkWindow *window,
+ GdkRectangle *rect)
{
GdkWindowObject *private;
Window xwindow;
Window *children;
unsigned int nchildren;
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (rect != NULL);
private = (GdkWindowObject*) window;
- if (x)
- *x = 0;
- if (y)
- *y = 0;
-
+
+ rect->x = 0;
+ rect->y = 0;
+ rect->width = 1;
+ rect->height = 1;
+
if (GDK_WINDOW_DESTROYED (window))
return;
if (XGetGeometry (GDK_WINDOW_XDISPLAY (window), xwindow, &root, &wx, &wy, &ww, &wh, &wb, &wd))
{
- if (x)
- *x = wx;
- if (y)
- *y = wy;
+ rect->x = wx;
+ rect->y = wy;
+ rect->width = ww;
+ rect->height = wh;
}
}
}
GdkWindow*
-gdk_window_get_pointer (GdkWindow *window,
- gint *x,
- gint *y,
- GdkModifierType *mask)
+_gdk_windowing_window_get_pointer (GdkWindow *window,
+ gint *x,
+ gint *y,
+ GdkModifierType *mask)
{
GdkWindow *return_val;
Window root;
g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
if (!window)
- window = gdk_parent_root;
+ window = _gdk_parent_root;
_gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
}
GdkWindow*
-gdk_window_at_pointer (gint *win_x,
- gint *win_y)
+_gdk_windowing_window_at_pointer (gint *win_x,
+ gint *win_y)
{
GdkWindow *window;
Window root;
xwindow = GDK_ROOT_WINDOW ();
xdisplay = GDK_DISPLAY ();
-
- XGrabServer (xdisplay);
+
+ gdk_x11_grab_server ();
while (xwindow)
{
xwindow_last = xwindow;
&winx, &winy,
&xmask);
}
- XUngrabServer (xdisplay);
+ gdk_x11_ungrab_server ();
window = gdk_window_lookup (xwindow_last);
return window;
}
+/**
+ * gdk_window_get_events:
+ * @window: a #GdkWindow
+ *
+ * Gets the event mask for @window. See gdk_window_set_events().
+ *
+ * Return value: event mask for @window
+ **/
GdkEventMask
gdk_window_get_events (GdkWindow *window)
{
&attrs);
event_mask = 0;
- for (i = 0; i < gdk_nevent_masks; i++)
+ for (i = 0; i < _gdk_nenvent_masks; i++)
{
- if (attrs.your_event_mask & gdk_event_mask_table[i])
+ if (attrs.your_event_mask & _gdk_event_mask_table[i])
event_mask |= 1 << (i + 1);
}
}
}
+/**
+ * gdk_window_set_events:
+ * @window: a #GdkWindow
+ * @event_mask: event mask for @window
+ *
+ * The event mask for a window determines which events will be reported
+ * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
+ * means the window should report button press events. The event mask
+ * is the bitwise OR of values from the #GdkEventMask enumeration.
+ *
+ **/
void
gdk_window_set_events (GdkWindow *window,
GdkEventMask event_mask)
if (!GDK_WINDOW_DESTROYED (window))
{
xevent_mask = StructureNotifyMask;
- for (i = 0; i < gdk_nevent_masks; i++)
+ for (i = 0; i < _gdk_nenvent_masks; i++)
{
if (event_mask & (1 << (i + 1)))
- xevent_mask |= gdk_event_mask_table[i];
+ xevent_mask |= _gdk_event_mask_table[i];
}
XSelectInput (GDK_WINDOW_XDISPLAY (window),
return (have_shape == YES);
}
+#define WARN_SHAPE_TOO_BIG() g_warning ("GdkWindow is too large to allow the use of shape masks or shape regions.")
+
/*
* This needs the X11 shape extension.
* 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.
+ *
+ **/
void
gdk_window_shape_combine_mask (GdkWindow *window,
GdkBitmap *mask,
gint x, gint y)
{
Pixmap pixmap;
+ gint xoffset, yoffset;
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
#ifdef HAVE_SHAPE_EXT
if (GDK_WINDOW_DESTROYED (window))
return;
+
+ _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
+
+ if (xoffset != 0 || yoffset != 0)
+ {
+ WARN_SHAPE_TOO_BIG ();
+ return;
+ }
if (gdk_window_have_shape_ext ())
{
#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.
+ *
+ **/
+void
+gdk_window_shape_combine_region (GdkWindow *window,
+ GdkRegion *shape_region,
+ gint offset_x,
+ gint offset_y)
+{
+ gint xoffset, yoffset;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+#ifdef HAVE_SHAPE_EXT
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
+
+ if (xoffset != 0 || yoffset != 0)
+ {
+ WARN_SHAPE_TOO_BIG ();
+ return;
+ }
+
+ if (shape_region == NULL)
+ {
+ /* Use NULL mask to unset the shape */
+ gdk_window_shape_combine_mask (window, NULL, 0, 0);
+ return;
+ }
+
+ if (gdk_window_have_shape_ext ())
+ {
+ gint n_rects = 0;
+ XRectangle *xrects = NULL;
+
+ _gdk_region_get_xrectangles (shape_region,
+ 0, 0,
+ &xrects, &n_rects);
+
+ XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ ShapeBounding,
+ offset_x, offset_y,
+ xrects, n_rects,
+ ShapeSet,
+ YXBanded);
+
+ g_free (xrects);
+ }
+#endif /* HAVE_SHAPE_EXT */
+}
+
+
+/**
+ * gdk_window_set_override_redirect:
+ * @window: a #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.
+ *
+ * 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)
}
}
+
+/**
+ * gdk_window_set_icon_list:
+ * @window: The #GdkWindow toplevel window to set the icon of.
+ * @pixbufs: A list of pixbufs, of different sizes.
+ *
+ * Sets a list of icons for the window. One of these will be used
+ * to represent the window when it has been iconified. The icon is
+ * usually shown in an icon box or some sort of task bar. Which icon
+ * size is shown depends on the window manager. The window manager
+ * can scale the icon but setting several size icons can give better
+ * image quality since the window manager may only need to scale the
+ * icon by a small amount or not at all.
+ *
+ **/
+void
+gdk_window_set_icon_list (GdkWindow *window,
+ GList *pixbufs)
+{
+ gulong *data;
+ guchar *pixels;
+ gulong *p;
+ gint size;
+ GList *l;
+ GdkPixbuf *pixbuf;
+ gint width, height, stride;
+ gint x, y;
+ gint n_channels;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ l = pixbufs;
+ size = 0;
+
+ while (l)
+ {
+ pixbuf = l->data;
+ g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+
+ size += 2 + width * height;
+
+ l = g_list_next (l);
+ }
+
+ data = g_malloc (size * sizeof (gulong));
+
+ l = pixbufs;
+ p = data;
+ while (l)
+ {
+ pixbuf = l->data;
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+ stride = gdk_pixbuf_get_rowstride (pixbuf);
+ n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+
+ *p++ = width;
+ *p++ = height;
+
+ pixels = gdk_pixbuf_get_pixels (pixbuf);
+
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < width; x++)
+ {
+ guchar r, g, b, a;
+
+ r = pixels[y*stride + x*n_channels + 0];
+ g = pixels[y*stride + x*n_channels + 1];
+ b = pixels[y*stride + x*n_channels + 2];
+ if (n_channels >= 4)
+ a = pixels[y*stride + x*n_channels + 3];
+ else
+ a = 255;
+
+ *p++ = a << 24 | r << 16 | g << 8 | b ;
+ }
+ }
+
+ l = g_list_next (l);
+ }
+
+ if (size > 0)
+ {
+ XChangeProperty (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ gdk_x11_get_xatom_by_name ("_NET_WM_ICON"),
+ XA_CARDINAL, 32,
+ PropModeReplace,
+ (guchar*) data, size);
+ }
+ else
+ {
+ XDeleteProperty (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ gdk_x11_get_xatom_by_name ("_NET_WM_ICON"));
+ }
+}
+
+/**
+ * gdk_window_set_icon:
+ * @window: a #GdkWindow
+ * @icon_window: a #GdkWindow to use for the icon, or %NULL to unset
+ * @pixmap: a #GdkPixmap to use as the icon, or %NULL to unset
+ * @mask: a 1-bit pixmap (#GdkBitmap) to use as mask for @pixmap, or %NULL to have none
+ *
+ * Sets the icon of @window as a pixmap or window. If using GTK+, investigate
+ * gtk_window_set_default_icon_list() first, and then gtk_window_set_icon_list()
+ * and gtk_window_set_icon(). If those don't meet your needs, look at
+ * gdk_window_set_icon_list(). Only if all those are too high-level do you
+ * want to fall back to gdk_window_set_icon().
+ *
+ **/
void
gdk_window_set_icon (GdkWindow *window,
GdkWindow *icon_window,
wm_hints->icon_mask = GDK_PIXMAP_XID (mask);
}
- XSetWMHints (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window), wm_hints);
- XFree (wm_hints);
+ XSetWMHints (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window), wm_hints);
+ XFree (wm_hints);
+}
+
+static gboolean
+gdk_window_icon_name_set (GdkWindow *window)
+{
+ return GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (window),
+ g_quark_from_static_string ("gdk-icon-name-set")));
+}
+
+/**
+ * gdk_window_set_icon_name:
+ * @window: a #GdkWindow
+ * @name: name of window while iconified (minimized)
+ *
+ * Windows may have a name used while minimized, distinct from the
+ * name they display in their titlebar. Most of the time this is a bad
+ * idea from a user interface standpoint. But you can set such a name
+ * with this function, if you like.
+ *
+ **/
+void
+gdk_window_set_icon_name (GdkWindow *window,
+ const gchar *name)
+{
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
+ GUINT_TO_POINTER (TRUE));
+
+ XChangeProperty (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ gdk_x11_get_xatom_by_name ("_NET_WM_ICON_NAME"),
+ gdk_x11_get_xatom_by_name ("UTF8_STRING"), 8,
+ PropModeReplace, name,
+ strlen (name));
+ set_text_property (window, gdk_x11_get_xatom_by_name ("WM_ICON_NAME"), name);
+}
+
+/**
+ * gdk_window_iconify:
+ * @window: a #GdkWindow
+ *
+ * Asks to iconify (minimize) @window. The window manager may choose
+ * to ignore the request, but normally will honor it. Using
+ * gtk_window_iconify() is preferred, if you have a #GtkWindow widget.
+ *
+ **/
+void
+gdk_window_iconify (GdkWindow *window)
+{
+ Display *display;
+ GdkWindowObject *private;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ display = GDK_WINDOW_XDISPLAY (window);
+
+ private = (GdkWindowObject*) window;
+
+ if (GDK_WINDOW_IS_MAPPED (window))
+ {
+ XIconifyWindow (display, GDK_WINDOW_XWINDOW (window), DefaultScreen (display));
+
+ }
+ else
+ {
+ /* Flip our client side flag, the real work happens on map. */
+ gdk_synthesize_window_state (window,
+ 0,
+ GDK_WINDOW_STATE_ICONIFIED);
+ }
+}
+
+/**
+ * gdk_window_deiconify:
+ * @window: a #GdkWindow
+ *
+ * Attempt to deiconify (unminimize) @window. On X11 the window manager may
+ * choose to ignore the request to deiconify. When using GTK+,
+ * use gtk_window_deiconify() instead of the #GdkWindow variant. Or better yet,
+ * you probably want to use gtk_window_present(), which raises the window, focuses it,
+ * unminimizes it, and puts it on the current desktop.
+ *
+ **/
+void
+gdk_window_deiconify (GdkWindow *window)
+{
+ Display *display;
+ GdkWindowObject *private;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ display = GDK_WINDOW_XDISPLAY (window);
+
+ private = (GdkWindowObject*) window;
+
+ if (GDK_WINDOW_IS_MAPPED (window))
+ {
+ gdk_window_show (window);
+ }
+ else
+ {
+ /* Flip our client side flag, the real work happens on map. */
+ gdk_synthesize_window_state (window,
+ GDK_WINDOW_STATE_ICONIFIED,
+ 0);
+ }
+}
+
+/**
+ * gdk_window_stick:
+ * @window: a toplevel #GdkWindow
+ *
+ * "Pins" a window such that it's on all workspaces and does not scroll
+ * with viewports, for window managers that have scrollable viewports.
+ * (When using #GtkWindow, gtk_window_stick() may be more useful.)
+ *
+ * On the X11 platform, this function depends on window manager
+ * support, so may have no effect with many window managers. However,
+ * GDK will do the best it can to convince the window manager to stick
+ * the window. For window managers that don't support this operation,
+ * there's nothing you can do to force it to happen.
+ *
+ **/
+void
+gdk_window_stick (GdkWindow *window)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ if (GDK_WINDOW_IS_MAPPED (window))
+ {
+ /* "stick" means stick to all desktops _and_ do not scroll with the
+ * viewport. i.e. glue to the monitor glass in all cases.
+ */
+
+ XEvent xev;
+
+ /* Request stick during viewport scroll */
+ gdk_wmspec_change_state (TRUE, window,
+ gdk_atom_intern ("_NET_WM_STATE_STICKY", FALSE),
+ 0);
+
+ /* Request desktop 0xFFFFFFFF */
+ xev.xclient.type = ClientMessage;
+ xev.xclient.serial = 0;
+ xev.xclient.send_event = True;
+ xev.xclient.window = GDK_WINDOW_XWINDOW (window);
+ xev.xclient.display = gdk_display;
+ xev.xclient.message_type = gdk_x11_get_xatom_by_name ("_NET_WM_DESKTOP");
+ xev.xclient.format = 32;
+
+ xev.xclient.data.l[0] = 0xFFFFFFFF;
+
+ XSendEvent (gdk_display, _gdk_root_window, False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &xev);
+ }
+ else
+ {
+ /* Flip our client side flag, the real work happens on map. */
+ gdk_synthesize_window_state (window,
+ 0,
+ GDK_WINDOW_STATE_STICKY);
+ }
+}
+
+/**
+ * gdk_window_unstick:
+ * @window: a toplevel #GdkWindow
+ *
+ * Reverse operation for gdk_window_stick(); see gdk_window_stick(),
+ * and gtk_window_unstick().
+ *
+ **/
+void
+gdk_window_unstick (GdkWindow *window)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ if (GDK_WINDOW_IS_MAPPED (window))
+ {
+ XEvent xev;
+ Atom type;
+ gint format;
+ gulong nitems;
+ gulong bytes_after;
+ gulong *current_desktop;
+
+ /* Request unstick from viewport */
+ gdk_wmspec_change_state (FALSE, window,
+ gdk_atom_intern ("_NET_WM_STATE_STICKY", FALSE),
+ 0);
+
+ /* Get current desktop, then set it; this is a race, but not
+ * one that matters much in practice.
+ */
+ XGetWindowProperty (gdk_display, _gdk_root_window,
+ gdk_x11_get_xatom_by_name ("_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.display = gdk_display;
+ xev.xclient.message_type = gdk_x11_get_xatom_by_name ("_NET_WM_DESKTOP");
+ xev.xclient.format = 32;
+
+ xev.xclient.data.l[0] = *current_desktop;
+
+ XSendEvent (gdk_display, _gdk_root_window, False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &xev);
+
+ XFree (current_desktop);
+ }
+ }
+ else
+ {
+ /* Flip our client side flag, the real work happens on map. */
+ gdk_synthesize_window_state (window,
+ GDK_WINDOW_STATE_STICKY,
+ 0);
+
+ }
+}
+
+/**
+ * gdk_window_maximize:
+ * @window: a #GdkWindow
+ *
+ * Asks the window manager to maximize @window, 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 "maximized"; so you can't rely on the
+ * maximization actually happening. But it will happen with most standard
+ * window managers, and GDK makes a best effort to get it to happen.
+ *
+ * If the window was already maximized, then this function does nothing.
+ *
+ **/
+void
+gdk_window_maximize (GdkWindow *window)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ 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));
+ else
+ gdk_synthesize_window_state (window,
+ 0,
+ GDK_WINDOW_STATE_MAXIMIZED);
}
-void
-gdk_window_set_icon_name (GdkWindow *window,
- const gchar *name)
+/**
+ * gdk_window_unmaximize:
+ * @window: a #GdkWindow
+ *
+ * Asks the window manager to unmaximize @window, 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 "maximized"; so you can't rely on the
+ * unmaximization actually happening. But it will happen with most standard
+ * window managers, and GDK makes a best effort to get it to happen.
+ *
+ * If the window wasn't maximized, then this function does nothing.
+ *
+ **/
+void
+gdk_window_unmaximize (GdkWindow *window)
{
- XTextProperty property;
- gint res;
-
- g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
return;
-
- res = XmbTextListToTextProperty (GDK_WINDOW_XDISPLAY (window),
- &name, 1, XStdICCTextStyle,
- &property);
- if (res < 0)
- {
- g_warning ("Error converting icon name to text property: %d\n", res);
- return;
- }
-
- XSetWMIconName (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- &property);
-
- if (property.value)
- XFree (property.value);
+
+ 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));
+ else
+ gdk_synthesize_window_state (window,
+ GDK_WINDOW_STATE_MAXIMIZED,
+ 0);
}
+/**
+ * gdk_window_set_group:
+ * @window: a #GdkWindow
+ * @leader: group leader window
+ *
+ * Sets the group leader window for @window. By default,
+ * GDK sets the group leader for all toplevel windows
+ * to a global window implicitly created by GDK. With this function
+ * you can override this default.
+ *
+ * The group leader window allows the window manager to distinguish
+ * all windows that belong to a single application. It may for example
+ * 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)
XFree (wm_hints);
}
+static MotifWmHints *
+gdk_window_get_mwm_hints (GdkWindow *window)
+{
+ static Atom hints_atom = None;
+ MotifWmHints *hints;
+ Atom type;
+ gint format;
+ gulong nitems;
+ gulong bytes_after;
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return NULL;
+
+ if (!hints_atom)
+ hints_atom = XInternAtom (GDK_WINDOW_XDISPLAY (window),
+ _XA_MOTIF_WM_HINTS, FALSE);
+
+ 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);
+
+ if (type == None)
+ return NULL;
+
+ return hints;
+}
+
static void
gdk_window_set_mwm_hints (GdkWindow *window,
MotifWmHints *new_hints)
XFree (hints);
}
+/**
+ * gdk_window_set_decorations:
+ * @window: a #GdkWindow
+ * @decorations: decoration hint mask
+ *
+ * "Decorations" are the features the window manager adds to a toplevel #GdkWindow.
+ * This function sets the traditional Motif window manager hints that tell the
+ * window manager which decorations you would like your window to have.
+ * Usually you should use gtk_window_set_decorated() on a #GtkWindow instead of
+ * using the GDK function directly.
+ *
+ * The @decorations argument is the logical OR of the fields in
+ * the #GdkWMDecoration enumeration. If #GDK_DECOR_ALL is included in the
+ * mask, the other bits indicate which decorations should be turned off.
+ * If #GDK_DECOR_ALL is not included, then the other bits indicate
+ * which decorations should be turned on.
+ *
+ * Most window managers honor a decorations hint of 0 to disable all decorations,
+ * but very few honor all possible combinations of bits.
+ *
+ **/
void
gdk_window_set_decorations (GdkWindow *window,
GdkWMDecoration decorations)
gdk_window_set_mwm_hints (window, &hints);
}
+/**
+ * gdk_window_get_decorations:
+ * @window: The #GdkWindow to get the decorations from
+ * @decorations: The window decorations will be written here
+ *
+ * Returns the decorations set on the GdkWindow with #gdk_window_set_decorations
+ * Returns: TRUE if the window has decorations set, FALSE otherwise.
+ **/
+gboolean
+gdk_window_get_decorations(GdkWindow *window,
+ GdkWMDecoration *decorations)
+{
+ MotifWmHints *hints;
+ gboolean result = FALSE;
+
+ hints = gdk_window_get_mwm_hints (window);
+
+ if (hints)
+ {
+ if (hints->flags & MWM_HINTS_DECORATIONS)
+ {
+ *decorations = hints->decorations;
+ result = TRUE;
+ }
+
+ XFree (hints);
+ }
+
+ return result;
+}
+
+/**
+ * gdk_window_set_functions:
+ * @window: a #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
+ * anything reliable or interesting with this hint. Many ignore it
+ * entirely.
+ *
+ * The @functions argument is the logical OR of values from the
+ * #GdkWMFunction enumeration. If the bitmask includes #GDK_FUNC_ALL,
+ * then the other bits indicate which functions to disable; if
+ * it doesn't include #GDK_FUNC_ALL, it indicates which functions to
+ * enable.
+ *
+ **/
void
gdk_window_set_functions (GdkWindow *window,
GdkWMFunction functions)
gdk_window_set_mwm_hints (window, &hints);
}
+#ifdef HAVE_SHAPE_EXT
+
/*
* propagate the shapes from all child windows of a GDK window to the parent
* window. Shamelessly ripped from Enlightenment's code
g_free (spans);
}
+#endif /* HAVE_SHAPE_EXT */
+
+/**
+ * gdk_window_set_child_shapes:
+ * @window: a #GdkWindow
+ *
+ * Sets the shape mask of @window to the union of shape masks
+ * for all children of @window, ignoring the shape mask of @window
+ * itself. Contrast with gdk_window_merge_child_shapes() which includes
+ * the shape mask of @window in the masks to be merged.
+ **/
void
gdk_window_set_child_shapes (GdkWindow *window)
{
#endif
}
+/**
+ * gdk_window_merge_child_shapes:
+ * @window: a #GdkWindow
+ *
+ * Merges the shape masks for any child windows into the
+ * shape mask for @window. i.e. the union of all masks
+ * for @window and its children will become the new mask
+ * for @window. See gdk_window_shape_combine_mask().
+ *
+ * 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)
{
CWWinGravity, &xattributes);
}
-/*************************************************************
+/**
* gdk_window_set_static_gravities:
- * Set the bit gravity of the given window to static,
- * and flag it so all children get static subwindow
- * gravity.
- * arguments:
- * window: window for which to set static gravity
- * use_static: Whether to turn static gravity on or off.
- * results:
- * Does the XServer support static gravity?
- *************************************************************/
-
+ * @window: a #GdkWindow
+ * @use_static: %TRUE to turn on static gravity
+ *
+ * Set the bit gravity of the given window to static, and flag it so
+ * all children get static subwindow gravity. This is used if you are
+ * implementing scary features that involve deep knowledge of the
+ * windowing system. Don't worry about it unless you have to.
+ *
+ * Return value: %TRUE if the server supports static gravity
+ **/
gboolean
gdk_window_set_static_gravities (GdkWindow *window,
gboolean use_static)
tmp_list = private->children;
while (tmp_list)
{
- gdk_window_set_static_win_gravity (window, use_static);
+ gdk_window_set_static_win_gravity (tmp_list->data, use_static);
tmp_list = tmp_list->next;
}
unsigned int num;
int i;
- window = gdk_parent_root;
+ window = _gdk_parent_root;
xdisplay = GDK_WINDOW_XDISPLAY (window);
root = GDK_WINDOW_XID (window);
num = g_list_length (excludes);
- XGrabServer (xdisplay);
+ gdk_x11_grab_server ();
if (!XQueryTree (xdisplay, root, &root_win, &parent_win, &list, &num))
{
- XUngrabServer (xdisplay);
+ gdk_x11_ungrab_server ();
return root;
}
if (list)
if (!g_list_find (excludes, (gpointer *) child))
{
XFree (list);
- XUngrabServer (xdisplay);
+ gdk_x11_ungrab_server ();
return child;
}
}
else
{
XFree (list);
- XUngrabServer (xdisplay);
+ gdk_x11_ungrab_server ();
return child;
}
} while (--i > 0);
XFree (list);
}
- XUngrabServer (xdisplay);
+ gdk_x11_ungrab_server ();
return root;
}
+static void
+wmspec_moveresize (GdkWindow *window,
+ gint direction,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp)
+{
+ XEvent xev;
+
+ /* Release passive grab */
+ gdk_pointer_ungrab (timestamp);
+
+ xev.xclient.type = ClientMessage;
+ xev.xclient.serial = 0;
+ xev.xclient.send_event = True;
+ xev.xclient.display = gdk_display;
+ xev.xclient.window = GDK_WINDOW_XID (window);
+ xev.xclient.message_type = gdk_x11_get_xatom_by_name ("_NET_WM_MOVERESIZE");
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = root_x;
+ xev.xclient.data.l[1] = root_y;
+ xev.xclient.data.l[2] = direction;
+ xev.xclient.data.l[3] = 0;
+ xev.xclient.data.l[4] = 0;
+
+ XSendEvent (gdk_display, _gdk_root_window, False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &xev);
+}
+
+/* From the WM spec */
+#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
+#define _NET_WM_MOVERESIZE_SIZE_TOP 1
+#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
+#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
+#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
+#define _NET_WM_MOVERESIZE_MOVE 8
+
+static void
+wmspec_resize_drag (GdkWindow *window,
+ GdkWindowEdge edge,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp)
+{
+ gint direction;
+
+ /* Let the compiler turn a switch into a table, instead
+ * of doing the table manually, this way is easier to verify.
+ */
+ switch (edge)
+ {
+ case GDK_WINDOW_EDGE_NORTH_WEST:
+ direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
+ break;
+
+ case GDK_WINDOW_EDGE_NORTH:
+ direction = _NET_WM_MOVERESIZE_SIZE_TOP;
+ break;
+
+ case GDK_WINDOW_EDGE_NORTH_EAST:
+ direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
+ break;
+
+ case GDK_WINDOW_EDGE_WEST:
+ direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
+ break;
+
+ case GDK_WINDOW_EDGE_EAST:
+ direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
+ break;
+
+ case GDK_WINDOW_EDGE_SOUTH_WEST:
+ direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
+ break;
+
+ case GDK_WINDOW_EDGE_SOUTH:
+ direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
+ break;
+
+ case GDK_WINDOW_EDGE_SOUTH_EAST:
+ direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
+ break;
+
+ default:
+ g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
+ edge);
+ return;
+ break;
+ }
+
+ wmspec_moveresize (window, direction, root_x, root_y, timestamp);
+}
+
+/* This is global for use in gdkevents-x11.c */
+GdkWindow *_gdk_moveresize_window;
+
+static GdkWindow *moveresize_emulation_window = NULL;
+static gboolean is_resize = FALSE;
+static GdkWindowEdge resize_edge;
+static gint moveresize_button;
+static gint moveresize_x;
+static gint moveresize_y;
+static gint moveresize_orig_x;
+static gint moveresize_orig_y;
+static gint moveresize_orig_width;
+static gint moveresize_orig_height;
+static GdkWindowHints moveresize_geom_mask = 0;
+static GdkGeometry moveresize_geometry;
+static Time moveresize_process_time;
+
+static XEvent *moveresize_pending_event;
+
+static void
+update_pos (gint new_root_x,
+ gint new_root_y)
+{
+ gint dx, dy;
+
+ dx = new_root_x - moveresize_x;
+ dy = new_root_y - moveresize_y;
+
+ if (is_resize)
+ {
+ gint w, h;
+
+ w = moveresize_orig_width;
+ h = moveresize_orig_height;
+
+ switch (resize_edge)
+ {
+ case GDK_WINDOW_EDGE_SOUTH_EAST:
+ w += dx;
+ h += dy;
+ break;
+ }
+
+ w = MAX (w, 1);
+ h = MAX (h, 1);
+
+ if (moveresize_geom_mask)
+ {
+ gdk_window_constrain_size (&moveresize_geometry,
+ moveresize_geom_mask,
+ w, h,
+ &w, &h);
+ }
+
+ gdk_window_resize (_gdk_moveresize_window, w, h);
+ }
+ else
+ {
+ gint x, y;
+
+ x = moveresize_orig_x + dx;
+ y = moveresize_orig_y + dy;
+
+ gdk_window_move (_gdk_moveresize_window, x, y);
+ }
+}
+
+static void
+finish_drag (void)
+{
+ gdk_window_destroy (moveresize_emulation_window);
+ moveresize_emulation_window = NULL;
+ _gdk_moveresize_window = NULL;
+
+ if (moveresize_pending_event)
+ {
+ g_free (moveresize_pending_event);
+ moveresize_pending_event = NULL;
+ }
+}
+
+static int
+lookahead_motion_predicate (Display *display,
+ XEvent *event,
+ XPointer arg)
+{
+ gboolean *seen_release = (gboolean *)arg;
+
+ if (*seen_release)
+ return False;
+
+ switch (event->xany.type)
+ {
+ case ButtonRelease:
+ *seen_release = TRUE;
+ break;
+ case MotionNotify:
+ moveresize_process_time = event->xmotion.time;
+ break;
+ default:
+ break;
+ }
+
+ return False;
+}
+
+static gboolean
+moveresize_lookahead (XEvent *event)
+{
+ XEvent tmp_event;
+ gboolean seen_release = FALSE;
+
+ if (moveresize_process_time)
+ {
+ if (event->xmotion.time == moveresize_process_time)
+ {
+ moveresize_process_time = 0;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ XCheckIfEvent (gdk_display, &tmp_event,
+ lookahead_motion_predicate, (XPointer)&seen_release);
+
+ return moveresize_process_time == 0;
+}
+
+void
+_gdk_moveresize_handle_event (XEvent *event)
+{
+ guint button_mask = 0;
+ GdkWindowObject *window_private = (GdkWindowObject *) _gdk_moveresize_window;
+
+ button_mask = GDK_BUTTON1_MASK << (moveresize_button - 1);
+
+ switch (event->xany.type)
+ {
+ case MotionNotify:
+ if (window_private->resize_count > 0)
+ {
+ if (moveresize_pending_event)
+ *moveresize_pending_event = *event;
+ else
+ moveresize_pending_event = g_memdup (event, sizeof (XEvent));
+
+ break;
+ }
+ if (!moveresize_lookahead (event))
+ break;
+
+ update_pos (event->xmotion.x_root,
+ event->xmotion.y_root);
+
+ /* This should never be triggered in normal cases, but in the
+ * case where the drag started without an implicit grab being
+ * in effect, we could miss the release if it occurs before
+ * we grab the pointer; this ensures that we will never
+ * get a permanently stuck grab.
+ */
+ if ((event->xmotion.state & button_mask) == 0)
+ finish_drag ();
+ break;
+
+ case ButtonRelease:
+ update_pos (event->xbutton.x_root,
+ event->xbutton.y_root);
+
+ if (event->xbutton.button == moveresize_button)
+ finish_drag ();
+ break;
+ }
+}
+
+void
+_gdk_moveresize_configure_done (void)
+{
+ XEvent *tmp_event;
+
+ if (moveresize_pending_event)
+ {
+ tmp_event = moveresize_pending_event;
+ moveresize_pending_event = NULL;
+ _gdk_moveresize_handle_event (tmp_event);
+ g_free (tmp_event);
+ }
+}
+
+static void
+create_moveresize_window (guint32 timestamp)
+{
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ GdkGrabStatus status;
+
+ g_assert (moveresize_emulation_window == NULL);
+
+ attributes.x = -100;
+ attributes.y = -100;
+ attributes.width = 10;
+ attributes.height = 10;
+ attributes.window_type = GDK_WINDOW_TEMP;
+ attributes.wclass = GDK_INPUT_ONLY;
+ attributes.override_redirect = TRUE;
+ attributes.event_mask = 0;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
+
+ moveresize_emulation_window =
+ gdk_window_new (NULL, &attributes, attributes_mask);
+
+ gdk_window_show (moveresize_emulation_window);
+
+ status = gdk_pointer_grab (moveresize_emulation_window,
+ FALSE,
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK,
+ FALSE,
+ NULL,
+ timestamp);
+
+ if (status != GDK_GRAB_SUCCESS)
+ {
+ /* If this fails, some other client has grabbed the window
+ * already.
+ */
+ gdk_window_destroy (moveresize_emulation_window);
+ moveresize_emulation_window = NULL;
+ }
+
+ moveresize_process_time = 0;
+}
+
+static void
+emulate_resize_drag (GdkWindow *window,
+ GdkWindowEdge edge,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp)
+{
+ is_resize = TRUE;
+ moveresize_button = button;
+ resize_edge = edge;
+ moveresize_x = root_x;
+ moveresize_y = root_y;
+ _gdk_moveresize_window = GDK_WINDOW (g_object_ref (G_OBJECT (window)));
+
+ gdk_window_get_size (window, &moveresize_orig_width, &moveresize_orig_height);
+
+ moveresize_geom_mask = 0;
+ gdk_window_get_geometry_hints (window,
+ &moveresize_geometry,
+ &moveresize_geom_mask);
+
+ create_moveresize_window (timestamp);
+}
+
+static void
+emulate_move_drag (GdkWindow *window,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp)
+{
+ is_resize = FALSE;
+ moveresize_button = button;
+ moveresize_x = root_x;
+ moveresize_y = root_y;
+ _gdk_moveresize_window = GDK_WINDOW (g_object_ref (G_OBJECT (window)));
+
+ gdk_window_get_deskrelative_origin (_gdk_moveresize_window,
+ &moveresize_orig_x,
+ &moveresize_orig_y);
+
+ create_moveresize_window (timestamp);
+}
+
+/**
+ * gdk_window_begin_resize_drag:
+ * @window: a #GdkWindow
+ * @button: the button being used to drag
+ * @root_x: root window X coordinate of mouse click that began the drag
+ * @root_y: root window Y coordinate of mouse click that began the drag
+ * @timestamp: timestamp of mouse click that began the drag (use gdk_event_get_time())
+ *
+ * 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.
+ *
+ **/
+void
+gdk_window_begin_resize_drag (GdkWindow *window,
+ GdkWindowEdge edge,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (moveresize_emulation_window == NULL);
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ if (gdk_net_wm_supports (gdk_atom_intern ("_NET_WM_MOVERESIZE", FALSE)))
+ wmspec_resize_drag (window, edge, button, root_x, root_y, timestamp);
+ else
+ emulate_resize_drag (window, edge, button, root_x, root_y, timestamp);
+}
+
+/**
+ * gdk_window_begin_move_drag:
+ * @window: a #GdkWindow
+ * @button: the button being used to drag
+ * @root_x: root window X coordinate of mouse click that began the drag
+ * @root_y: root window Y coordinate of mouse click that began the drag
+ * @timestamp: timestamp of mouse click that began the drag
+ *
+ * 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
+ * other window managers.
+ *
+ **/
+void
+gdk_window_begin_move_drag (GdkWindow *window,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (moveresize_emulation_window == NULL);
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ if (gdk_net_wm_supports (gdk_atom_intern ("_NET_WM_MOVERESIZE", FALSE)))
+ wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE,
+ root_x, root_y, timestamp);
+ else
+ emulate_move_drag (window, button, root_x, root_y, timestamp);
+}