summaryrefslogtreecommitdiff
path: root/gdk
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@src.gnome.org>1998-11-06 22:05:02 +0000
committerOwen Taylor <otaylor@src.gnome.org>1998-11-06 22:05:02 +0000
commite2a521922085c8010028e227f61bba59ea6b8242 (patch)
tree2500d6aa6f63aab4b58c17546532ecce8fdcca37 /gdk
parent3c0df19a588bd96f328bda975db8eb9fa7f79e81 (diff)
downloadgtk+-e2a521922085c8010028e227f61bba59ea6b8242.tar.gz
Merge from themes-2. See the ChangeLog for a somewhat detailed
history of the evolution of the changes involved. Most of this is actually minor painting tweaks.
Diffstat (limited to 'gdk')
-rw-r--r--gdk/Makefile.am17
-rw-r--r--gdk/gdk.c283
-rw-r--r--gdk/gdk.h22
-rw-r--r--gdk/gdkcursors.h18
-rw-r--r--gdk/gdkdnd.c89
-rw-r--r--gdk/gdkgc.c2
-rw-r--r--gdk/gdkimage.c3
-rw-r--r--gdk/gdkinputxfree.h2
-rw-r--r--gdk/gdkprivate.h16
-rw-r--r--gdk/gdkrectangle.c14
-rw-r--r--gdk/gdkrgb.c18
-rw-r--r--gdk/gdkwindow.c408
-rwxr-xr-xgdk/makecursors.awk4
-rwxr-xr-xgdk/makekeysyms.awk5
-rw-r--r--gdk/x11/gdkdnd-x11.c89
-rw-r--r--gdk/x11/gdkimage-x11.c3
-rw-r--r--gdk/x11/gdkinput-xfree.c2
-rw-r--r--gdk/x11/gdkmain-x11.c283
-rw-r--r--gdk/x11/gdkwindow-x11.c408
19 files changed, 1342 insertions, 344 deletions
diff --git a/gdk/Makefile.am b/gdk/Makefile.am
index b81e7d9aad..c9046e29ca 100644
--- a/gdk/Makefile.am
+++ b/gdk/Makefile.am
@@ -67,15 +67,14 @@ gxid_LDADD = \
@x_libs@ \
-lm
-BUILT_SOURCES = gdkcursors.h gdkkeysyms.h
-
-EXTRA_DIST = makecursors.awk makekeysyms.awk
-
-gdkcursors.h:
- awk -f $(srcdir)/makecursors.awk @x_includes@/X11/cursorfont.h > $@
-
-gdkkeysyms.h:
- awk -f $(srcdir)/makekeysyms.awk @x_includes@/X11/keysymdef.h > $@
+X-derived-headers:
+ sed -e 's/^#define[ ]*XC\([^ ]*\)[ ]*\([^ ]*\)[ ]*.*$$/GDK\1 = \2,/' \
+ -e 'tb' -e 'd' -e ':b' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
+ < @x_includes@/X11/cursorfont.h > gdkcursors.h ; \
+ sed -e 's/^#define[ ]*XK\([^ ]*\)[ ]*\([^ ]*\)[ ]*.*$$/#define GDK\1 \2/' \
+ -e 'tb' -e 'd' -e ':b' -e 's/ 0X/ 0x/' \
+ < @x_includes@/X11/keysymdef.h > gdkkeysyms.h
.PHONY: files
diff --git a/gdk/gdk.c b/gdk/gdk.c
index 449ad4add8..217724417c 100644
--- a/gdk/gdk.c
+++ b/gdk/gdk.c
@@ -116,10 +116,6 @@ static Bool gdk_event_get_type (Display *display,
static void gdk_synthesize_click (GdkEvent *event,
gint nclicks);
-#ifdef DEBUG_DND
-static void gdk_print_atom (GdkAtom anatom);
-#endif
-
#ifndef HAVE_XCONVERTCASE
static void gdkx_XConvertCase (KeySym symbol,
KeySym *lower,
@@ -156,12 +152,12 @@ static gint gdk_im_open (XrmDatabase db,
static void gdk_im_close (void);
static void gdk_ic_cleanup (void);
+#endif /* USE_XIM */
+
GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev,
GdkEvent *event,
gpointer data);
-#endif /* USE_XIM */
-
/* Private variable declarations
*/
static int gdk_initialized = 0; /* 1 if the library is initialized,
@@ -743,6 +739,194 @@ gdk_event_get_graphics_expose (GdkWindow *window)
return NULL;
}
+/************************
+ * Exposure compression *
+ ************************/
+
+/*
+ * The following implements simple exposure compression. It is
+ * modelled after the way Xt does exposure compression - in
+ * particular compress_expose = XtExposeCompressMultiple.
+ * It compress consecutive sequences of exposure events,
+ * but not sequences that cross other events. (This is because
+ * if it crosses a ConfigureNotify, we could screw up and
+ * mistakenly compress the exposures generated for the new
+ * size - could we just check for ConfigureNotify?)
+ *
+ * Xt compresses to a region / bounding rectangle, we compress
+ * to two rectangles, and try find the two rectangles of minimal
+ * area for this - this is supposed to handle the typical
+ * L-shaped regions generated by OpaqueMove.
+ */
+
+/* Given three rectangles, find the two rectangles that cover
+ * them with the smallest area.
+ */
+static void
+gdk_add_rect_to_rects (GdkRectangle *rect1,
+ GdkRectangle *rect2,
+ GdkRectangle *new_rect)
+{
+ GdkRectangle t1, t2, t3;
+ gint size1, size2, size3;
+
+ gdk_rectangle_union (rect1, rect2, &t1);
+ gdk_rectangle_union (rect1, new_rect, &t2);
+ gdk_rectangle_union (rect2, new_rect, &t3);
+
+ size1 = t1.width * t1.height + new_rect->width * new_rect->height;
+ size2 = t2.width * t2.height + rect2->width * rect2->height;
+ size3 = t1.width * t1.height + rect1->width * rect1->height;
+
+ if (size1 < size2)
+ {
+ if (size1 < size3)
+ {
+ *rect1 = t1;
+ *rect2 = *new_rect;
+ }
+ else
+ *rect2 = t3;
+ }
+ else
+ {
+ if (size2 < size3)
+ *rect1 = t2;
+ else
+ *rect2 = t3;
+ }
+}
+
+typedef struct _GdkExposeInfo GdkExposeInfo;
+
+struct _GdkExposeInfo {
+ Window window;
+ gboolean seen_nonmatching;
+};
+
+Bool
+expose_predicate (Display *display, XEvent *xevent, XPointer arg)
+{
+ GdkExposeInfo *info = (GdkExposeInfo *)arg;
+
+ if (xevent->xany.type != Expose)
+ {
+ info->seen_nonmatching = TRUE;
+ }
+
+ if (info->seen_nonmatching || (xevent->xany.window != info->window))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+void
+gdk_compress_exposures (XEvent *xevent, GdkWindow *window)
+{
+ gint nrects = 1;
+ gint count = 0;
+ GdkRectangle rect1;
+ GdkRectangle rect2;
+ GdkRectangle tmp_rect;
+ XEvent tmp_event;
+ GdkFilterReturn result;
+ GdkExposeInfo info;
+ GdkEvent event;
+
+ info.window = xevent->xany.window;
+ info.seen_nonmatching = FALSE;
+
+ rect1.x = xevent->xexpose.x;
+ rect1.y = xevent->xexpose.y;
+ rect1.width = xevent->xexpose.width;
+ rect1.height = xevent->xexpose.height;
+
+ while (1)
+ {
+ if (count == 0)
+ {
+ if (!XCheckIfEvent (gdk_display,
+ &tmp_event,
+ expose_predicate,
+ (XPointer)&info))
+ break;
+ }
+ else
+ XIfEvent (gdk_display,
+ &tmp_event,
+ expose_predicate,
+ (XPointer)&info);
+
+ /* We apply filters here, and if it was filtered, completely
+ * ignore the return
+ */
+ result = gdk_event_apply_filters (xevent, &event,
+ window ?
+ ((GdkWindowPrivate *)window)->filters
+ : gdk_default_filters);
+
+ if (result != GDK_FILTER_CONTINUE)
+ {
+ if (result == GDK_FILTER_TRANSLATE)
+ gdk_event_put (&event);
+ continue;
+ }
+
+ if (nrects == 1)
+ {
+ rect2.x = tmp_event.xexpose.x;
+ rect2.y = tmp_event.xexpose.y;
+ rect2.width = tmp_event.xexpose.width;
+ rect2.height = tmp_event.xexpose.height;
+
+ nrects++;
+ }
+ else
+ {
+ tmp_rect.x = tmp_event.xexpose.x;
+ tmp_rect.y = tmp_event.xexpose.y;
+ tmp_rect.width = tmp_event.xexpose.width;
+ tmp_rect.height = tmp_event.xexpose.height;
+
+ gdk_add_rect_to_rects (&rect1, &rect2, &tmp_rect);
+ }
+
+ count = tmp_event.xexpose.count;
+ }
+
+ if (nrects == 2)
+ {
+ gdk_rectangle_union (&rect1, &rect2, &tmp_rect);
+
+ if ((tmp_rect.width * tmp_rect.height) <
+ 2 * (rect1.height * rect1.width +
+ rect2.height * rect2.width))
+ {
+ rect1 = tmp_rect;
+ nrects = 1;
+ }
+ }
+
+ if (nrects == 2)
+ {
+ event.expose.type = GDK_EXPOSE;
+ event.expose.window = window;
+ event.expose.area.x = rect2.x;
+ event.expose.area.y = rect2.y;
+ event.expose.area.width = rect2.width;
+ event.expose.area.height = rect2.height;
+ event.expose.count = 0;
+
+ gdk_event_put (&event);
+ }
+
+ xevent->xexpose.count = nrects - 1;
+ xevent->xexpose.x = rect1.x;
+ xevent->xexpose.y = rect1.y;
+ xevent->xexpose.width = rect1.width;
+ xevent->xexpose.height = rect1.height;
+}
+
/*
*--------------------------------------------------------------
* gdk_event_get
@@ -834,6 +1018,7 @@ gdk_event_get (void)
#else
XNextEvent (gdk_display, &xevent);
#endif
+
event = gdk_event_new ();
event->any.type = GDK_NOTHING;
@@ -2005,6 +2190,13 @@ gdk_event_translate (GdkEvent *event,
case KeyRelease:
/* Lookup the string corresponding to the given keysym.
*/
+#ifdef USE_XIM
+ if (buf_len == 0)
+ {
+ buf_len = 128;
+ buf = g_new (gchar, buf_len);
+ }
+#endif
keysym = GDK_VoidSymbol;
charcount = XLookupString (&xevent->xkey, buf, 16,
&keysym, &compose);
@@ -2031,8 +2223,7 @@ gdk_event_translate (GdkEvent *event,
/* Print debugging info.
*/
GDK_NOTE (EVENTS,
- g_message ("button press[%d]:\t\twindow: %ld x,y: %d %d button: %d",
- window_private?window_private->dnd_drag_enabled:0,
+ g_message ("button press:\t\twindow: %ld x,y: %d %d button: %d",
xevent->xbutton.window - base_id,
xevent->xbutton.x, xevent->xbutton.y,
xevent->xbutton.button));
@@ -2102,8 +2293,7 @@ gdk_event_translate (GdkEvent *event,
/* Print debugging info.
*/
GDK_NOTE (EVENTS,
- g_message ("button release[%d]:\twindow: %ld x,y: %d %d button: %d",
- window_private?window_private->dnd_drag_enabled:0,
+ g_message ("button release:\twindow: %ld x,y: %d %d button: %d",
xevent->xbutton.window - base_id,
xevent->xbutton.x, xevent->xbutton.y,
xevent->xbutton.button));
@@ -2178,6 +2368,7 @@ gdk_event_translate (GdkEvent *event,
/* Tell XInput stuff about it if appropriate */
if (window_private &&
+ !window_private->destroyed &&
(window_private->extension_events != 0) &&
gdk_input_vtable.enter_event)
gdk_input_vtable.enter_event (&xevent->xcrossing, window);
@@ -2357,6 +2548,7 @@ gdk_event_translate (GdkEvent *event,
xevent->xexpose.window - base_id, xevent->xexpose.count,
xevent->xexpose.x, xevent->xexpose.y,
xevent->xexpose.width, xevent->xexpose.height));
+ gdk_compress_exposures (xevent, window);
event->expose.type = GDK_EXPOSE;
event->expose.window = window;
@@ -2539,10 +2731,11 @@ gdk_event_translate (GdkEvent *event,
xevent->xconfigure.above - base_id,
xevent->xconfigure.override_redirect));
- if ((window_private->extension_events != 0) &&
+ if (!window_private->destroyed &&
+ (window_private->extension_events != 0) &&
gdk_input_vtable.configure_event)
gdk_input_vtable.configure_event (&xevent->xconfigure, window);
-
+
if (window_private->window_type == GDK_WINDOW_CHILD)
return_val = FALSE;
else
@@ -2714,6 +2907,7 @@ gdk_event_translate (GdkEvent *event,
/* something else - (e.g., a Xinput event) */
if (window_private &&
+ !window_private->destroyed &&
(window_private->extension_events != 0) &&
gdk_input_vtable.other_event)
return_val = gdk_input_vtable.other_event(event, xevent, window);
@@ -3638,61 +3832,6 @@ _g_mbtowc (wchar_t *wstr, const char *str, size_t len)
#endif /* X_LOCALE */
-/*
- * used for debugging only
- */
-#ifdef DEBUG_DND
-static void
-gdk_print_atom (GdkAtom anatom)
-{
- gchar *tmpstr = NULL;
- tmpstr = (anatom!=None)?gdk_atom_name(anatom):"(none)";
- g_message("Atom %lu has name %s", anatom, tmpstr);
- if(tmpstr)
- g_free(tmpstr);
-}
-#endif
-
-#ifdef WE_HAVE_MOTIF_DROPS_DONE
-static GdkWindow *
-gdk_drop_get_real_window (GdkWindow *w,
- guint16 *x,
- guint16 *y)
-{
- GdkWindow *retval = w;
- GdkWindowPrivate *awin;
- GList *children;
- gint16 myx = *x, myy = *y;
-
- g_return_val_if_fail (w != NULL && x != NULL && y != NULL, NULL);
-
- myx = *x;
- myy = *y;
-
- descend:
- for (children = gdk_window_get_children(retval);
- children && children->next;
- children = children->next)
- {
- awin = (GdkWindowPrivate *) children->data;
- if ((myx >= awin->x) && (myy >= awin->y)
- && (myx < (awin->x + awin->width))
- && (myy < (awin->y + awin->height)))
- {
- retval = (GdkWindow *) awin;
- myx -= awin->x;
- myy -= awin->y;
- goto descend;
- }
- }
-
- *x = myx;
- *y = myy;
-
- return retval;
-}
-#endif
-
/* Sends a ClientMessage to all toplevel client windows */
gboolean
gdk_event_send_client_message (GdkEvent *event, guint32 xid)
@@ -3716,7 +3855,7 @@ gdk_event_send_client_message (GdkEvent *event, guint32 xid)
gboolean
gdk_event_send_client_message_to_all_recurse (XEvent *xev,
guint32 xid,
- gboolean send_anyways)
+ guint level)
{
static GdkAtom wm_state_atom = GDK_NONE;
@@ -3729,7 +3868,7 @@ gdk_event_send_client_message_to_all_recurse (XEvent *xev,
unsigned int ret_nchildren;
int i;
- gboolean send = TRUE;
+ gboolean send = FALSE;
gboolean found = FALSE;
if (!wm_state_atom)
@@ -3761,13 +3900,13 @@ gdk_event_send_client_message_to_all_recurse (XEvent *xev,
return FALSE;
for(i = 0; i < ret_nchildren; i++)
- if (gdk_event_send_client_message_to_all_recurse(xev, ret_children[i], FALSE))
+ if (gdk_event_send_client_message_to_all_recurse(xev, ret_children[i], level + 1))
found = TRUE;
XFree(ret_children);
}
- if (send || (!found && send_anyways))
+ if (send || (!found && (level == 1)))
{
xev->xclient.window = xid;
gdk_send_xevent (xid, False, NoEventMask, xev);
@@ -3791,7 +3930,7 @@ gdk_event_send_clientmessage_toall (GdkEvent *event)
memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
sev.xclient.message_type = event->client.message_type;
- gdk_event_send_client_message_to_all_recurse(&sev, gdk_root_window, TRUE);
+ gdk_event_send_client_message_to_all_recurse(&sev, gdk_root_window, 0);
gdk_error_warnings = old_warnings;
}
diff --git a/gdk/gdk.h b/gdk/gdk.h
index 1d188c78a1..5ee53061b5 100644
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -196,6 +196,23 @@ void gdk_window_shape_combine_mask (GdkWindow *window,
GdkBitmap *shape_mask,
gint offset_x,
gint offset_y);
+/*
+ * This routine allows you to quickly take the shapes of all the child windows
+ * of a window and use their shapes as the shape mask for this window - useful
+ * for container windows that dont want to look like a big box
+ *
+ * - Raster
+ */
+void gdk_window_set_child_shapes (GdkWindow *window);
+
+/*
+ * This routine allows you to merge (ie ADD) child shapes to your
+ * own window's shape keeping its current shape and ADDING the shild
+ * shapes to it.
+ *
+ * - Raster
+ */
+void gdk_window_merge_child_shapes (GdkWindow *window);
/*
* The following function adds a global filter for all client
@@ -726,6 +743,9 @@ void gdk_property_delete (GdkWindow *window,
gint gdk_rectangle_intersect (GdkRectangle *src1,
GdkRectangle *src2,
GdkRectangle *dest);
+void gdk_rectangle_union (GdkRectangle *src1,
+ GdkRectangle *src2,
+ GdkRectangle *dest);
/* XInput support
*/
@@ -894,6 +914,8 @@ void gdk_threads_wake (void);
/* Miscellaneous */
void gdk_event_send_clientmessage_toall (GdkEvent *event);
+gboolean gdk_event_send_client_message (GdkEvent *event,
+ guint32 xid);
/* Key values
*/
diff --git a/gdk/gdkcursors.h b/gdk/gdkcursors.h
index 63400fa99f..1d2ae0131e 100644
--- a/gdk/gdkcursors.h
+++ b/gdk/gdkcursors.h
@@ -1,21 +1,3 @@
-/* GDK - The GIMP Drawing Kit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
GDK_NUM_GLYPHS = 154,
GDK_X_CURSOR = 0,
GDK_ARROW = 2,
diff --git a/gdk/gdkdnd.c b/gdk/gdkdnd.c
index 67720ad6bd..c4dc41a078 100644
--- a/gdk/gdkdnd.c
+++ b/gdk/gdkdnd.c
@@ -377,15 +377,17 @@ gdk_window_cache_destroy (GdkWindowCache *cache)
static Window
get_client_window_at_coords_recurse (Window win,
- gint x_root,
- gint y_root)
+ gint x,
+ gint y)
{
- Window child;
+ Window root, tmp_parent, *children;
+ unsigned int nchildren;
+ int i;
+ Window child = None;
Atom type = None;
int format;
unsigned long nitems, after;
unsigned char *data;
- int dest_x, dest_y;
static Atom wm_state_atom = None;
@@ -408,6 +410,8 @@ get_client_window_at_coords_recurse (Window win,
return win;
}
+#if 0
+ /* This is beautiful! Damn Enlightenment and click-to-focus */
XTranslateCoordinates (gdk_display, gdk_root_window, win,
x_root, y_root, &dest_x, &dest_y, &child);
@@ -416,18 +420,49 @@ get_client_window_at_coords_recurse (Window win,
gdk_error_code = 0;
return None;
}
+
+#else
+ if (XQueryTree(gdk_display, win,
+ &root, &tmp_parent, &children, &nchildren) == 0)
+ return 0;
+
+ if (gdk_error_code == 0)
+ {
+ for (i = nchildren - 1; (i >= 0) && (child == None); i--)
+ {
+ XWindowAttributes xwa;
+
+ XGetWindowAttributes (gdk_display, children[i], &xwa);
+
+ if (gdk_error_code != 0)
+ gdk_error_code = 0;
+ else if ((xwa.map_state == IsViewable) && (xwa.class == InputOutput) &&
+ (x >= xwa.x) && (x < xwa.x + (gint)xwa.width) &&
+ (y >= xwa.y) && (y < xwa.y + (gint)xwa.height))
+ {
+ x -= xwa.x;
+ y -= xwa.y;
+ child = children[i];
+ }
+ }
+
+ XFree (children);
+ }
+ else
+ gdk_error_code = 0;
+#endif
if (child)
- return get_client_window_at_coords_recurse (child, x_root, y_root);
+ return get_client_window_at_coords_recurse (child, x, y);
else
return None;
}
Window
get_client_window_at_coords (GdkWindowCache *cache,
- Window ignore,
- gint x_root,
- gint y_root)
+ Window ignore,
+ gint x_root,
+ gint y_root)
{
GList *tmp_list;
Window retval = None;
@@ -449,7 +484,8 @@ get_client_window_at_coords (GdkWindowCache *cache,
(y_root >= child->y) && (y_root < child->y + child->height))
{
retval = get_client_window_at_coords_recurse (child->xid,
- x_root, y_root);
+ x_root - child->x,
+ y_root - child->y);
if (!retval)
retval = child->xid;
}
@@ -532,7 +568,7 @@ get_client_window_at_coords (Window ignore,
if (XQueryTree(gdk_display, gdk_root_window,
&root, &parent, &children, &nchildren) == 0)
return 0;
-
+
for (i = nchildren - 1; (i >= 0) && (retval == None); i--)
{
if (children[i] != ignore)
@@ -883,7 +919,12 @@ motif_read_target_table (void)
goto error;
n_targets = card16_to_host (*(gushort *)p, header->byte_order);
- targets = (guint32 *)(p + sizeof(guint16));
+
+ /* We need to make a copy of the targets, since it may
+ * be unaligned
+ */
+ targets = g_new (guint32, n_targets);
+ memcpy (targets, p + sizeof(guint16), sizeof(guint32) * n_targets);
p += sizeof(guint16) + n_targets * sizeof(guint32);
if (p - target_bytes > nitems)
@@ -894,7 +935,7 @@ motif_read_target_table (void)
g_list_prepend (motif_target_lists[i],
GUINT_TO_POINTER (card32_to_host (targets[j],
header->byte_order)));
-
+ g_free (targets);
motif_target_lists[i] = g_list_reverse (motif_target_lists[i]);
}
@@ -1001,7 +1042,6 @@ motif_add_to_target_table (GList *targets)
guchar *data;
guchar *p;
guint16 *p16;
- guint32 *p32;
MotifTargetTableHeader *header;
if (!motif_target_lists)
@@ -1035,20 +1075,27 @@ motif_add_to_target_table (GList *targets)
for (i = 0; i < motif_n_target_lists ; i++)
{
- guint16 count = 0;
+ guint16 n_targets = g_list_length (motif_target_lists[i]);
+ guint32 *targets = g_new (guint32, n_targets);
+ guint32 *p32 = targets;
- p16 = (guint16 *)p;
- p += sizeof(guint16);
- p32 = (guint32 *)p;
tmp_list = motif_target_lists[i];
while (tmp_list)
{
- *p32++ = GPOINTER_TO_UINT (tmp_list->data);
+ *p32 = GPOINTER_TO_UINT (tmp_list->data);
+
tmp_list = tmp_list->next;
- count++;
+ p32++;
}
- *p16 = count;
- p = (guchar *)p32;
+
+ p16 = (guint16 *)p;
+ p += sizeof(guint16);
+
+ memcpy (p, targets, n_targets * sizeof(guint32));
+
+ *p16 = n_targets;
+ p += sizeof(guint32) * n_targets;
+ g_free (targets);
}
XChangeProperty (gdk_display, motif_drag_window,
diff --git a/gdk/gdkgc.c b/gdk/gdkgc.c
index 0b8f91266e..730ec63ad9 100644
--- a/gdk/gdkgc.c
+++ b/gdk/gdkgc.c
@@ -676,7 +676,7 @@ gdk_gc_set_clip_rectangle (GdkGC *gc,
{
GdkGCPrivate *private;
XRectangle xrectangle;
-
+
g_return_if_fail (gc != NULL);
private = (GdkGCPrivate*) gc;
diff --git a/gdk/gdkimage.c b/gdk/gdkimage.c
index 4d009f9f42..2cc850b532 100644
--- a/gdk/gdkimage.c
+++ b/gdk/gdkimage.c
@@ -353,7 +353,8 @@ gdk_image_get (GdkWindow *window,
image->mem = private->ximage->data;
image->bpl = private->ximage->bytes_per_line;
- image->bpp = 1;
+ image->bpp = private->ximage->bits_per_pixel;
+ image->byte_order = private->ximage->byte_order;
return image;
}
diff --git a/gdk/gdkinputxfree.h b/gdk/gdkinputxfree.h
index 997fdd207b..7b69d6197f 100644
--- a/gdk/gdkinputxfree.h
+++ b/gdk/gdkinputxfree.h
@@ -173,7 +173,7 @@ gdk_input_xfree_configure_event (XConfigureEvent *xevent, GdkWindow *window)
static void
gdk_input_xfree_enter_event (XCrossingEvent *xevent,
- GdkWindow *window)
+ GdkWindow *window)
{
GdkInputWindow *input_window;
gint root_x, root_y;
diff --git a/gdk/gdkprivate.h b/gdk/gdkprivate.h
index 781db81b1f..d7f71cd224 100644
--- a/gdk/gdkprivate.h
+++ b/gdk/gdkprivate.h
@@ -24,8 +24,6 @@
#include <X11/Xutil.h>
#include <gdk/gdktypes.h>
-#define DND_PROTOCOL_VERSION 0
-
#define gdk_window_lookup(xid) ((GdkWindow*) gdk_xid_table_lookup (xid))
#define gdk_pixmap_lookup(xid) ((GdkPixmap*) gdk_xid_table_lookup (xid))
#define gdk_font_lookup(xid) ((GdkFont*) gdk_xid_table_lookup (xid))
@@ -65,20 +63,6 @@ struct _GdkWindowPrivate
guint8 window_type;
guint ref_count;
guint destroyed : 2;
- guint dnd_drag_enabled : 1,
- dnd_drag_datashow : 1,
- dnd_drag_destructive_op : 1,
- dnd_drag_accepted : 1,
- dnd_drop_enabled : 1,
- dnd_drop_destructive_op : 1;
- GdkAtom dnd_drag_data_type, *dnd_drag_data_typesavail;
- guint dnd_drag_data_numtypesavail;
- /* We have to turn on MotionMask/EnterWindowMask/LeaveWindowMask
- during drags, then set it back to what it was after */
- glong dnd_drag_savedeventmask, dnd_drag_eventmask;
- GdkAtom *dnd_drop_data_typesavail;
- guint dnd_drop_data_numtypesavail;
- /* need to allow custom drag/drop cursors */
gint extension_events;
diff --git a/gdk/gdkrectangle.c b/gdk/gdkrectangle.c
index 18bfa653a4..e1d1d300fa 100644
--- a/gdk/gdkrectangle.c
+++ b/gdk/gdkrectangle.c
@@ -19,6 +19,20 @@
#include "gdk.h"
+
+void
+gdk_rectangle_union (GdkRectangle *src1,
+ GdkRectangle *src2,
+ GdkRectangle *dest)
+{
+ dest->x = MIN (src1->x, src2->x);
+ dest->y = MIN (src1->y, src2->y);
+ dest->width =
+ MAX (src1->x + src1->width, src2->x + src2->width) - dest->x;
+ dest->height =
+ MAX (src1->y + src1->height, src2->y + src2->height) - dest->y;
+}
+
gint
gdk_rectangle_intersect (GdkRectangle *src1,
GdkRectangle *src2,
diff --git a/gdk/gdkrgb.c b/gdk/gdkrgb.c
index 011dd290a4..455246c7fe 100644
--- a/gdk/gdkrgb.c
+++ b/gdk/gdkrgb.c
@@ -538,12 +538,12 @@ gdk_rgb_init (void)
gint byte_order[1] = { 1 };
/* check endian sanity */
-#ifdef WORDS_BIGENDIAN
+#if G_BYTE_ORDER == G_BIG_ENDIAN
if (((char *)byte_order)[0] == 1)
- g_error ("gdk_rgb_init: WORDS_BIGENDIAN is defined, but this is a little endian machine.\n\n");
+ g_error ("gdk_rgb_init: compiled for big endian, but this is a little endian machine.\n\n");
#else
if (((char *)byte_order)[0] != 1)
- g_error ("gdk_rgb_init: WORDS_BIGENDIAN is not defined, but this is a big endian machine.\n\n");
+ g_error ("gdk_rgb_init: compiled for little endian, but this is a big endian machine.\n\n");
#endif
if (image_info == NULL)
@@ -649,7 +649,7 @@ gdk_rgb_init (void)
gulong
gdk_rgb_xpixel_from_rgb (guint32 rgb)
{
- gulong pixel;
+ gulong pixel = 0;
if (image_info->bitmap)
{
@@ -722,7 +722,7 @@ gdk_rgb_gc_set_background (GdkGC *gc, guint32 rgb)
gdk_gc_set_background (gc, &color);
}
-#ifndef WORDS_BIGENDIAN
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
#define HAIRY_CONVERT_8
#endif
@@ -1186,7 +1186,7 @@ gdk_rgb_convert_gray8_gray (GdkImage *image,
}
}
-#ifndef WORDS_BIGENDIAN
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
#define HAIRY_CONVERT_565
#endif
@@ -1729,7 +1729,7 @@ gdk_rgb_convert_888_msb (GdkImage *image,
}
/* todo: optimize this */
-#ifndef WORDS_BIGENDIAN
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
#define HAIRY_CONVERT_888
#endif
@@ -2668,7 +2668,7 @@ gdk_rgb_select_conv (GdkImage *image)
(gint)(((GdkVisualPrivate *)image_info->visual)->xvisual->visualid),
bpp, byte_order == GDK_LSB_FIRST ? "lsb" : "msb");
-#ifdef WORDS_BIGENDIAN
+#if G_BYTE_ORDER == G_BIG_ENDIAN
byterev = (byte_order == GDK_LSB_FIRST);
#else
byterev = (byte_order == GDK_MSB_FIRST);
@@ -2733,7 +2733,7 @@ gdk_rgb_select_conv (GdkImage *image)
((mask_rgb && byte_order == GDK_MSB_FIRST) ||
(mask_bgr && byte_order == GDK_LSB_FIRST)))
conv = gdk_rgb_convert_888_msb;
-#ifdef WORDS_BIGENDIAN
+#if G_BYTE_ORDER == G_BIG_ENDIAN
else if (bpp == 32 && depth == 24 && vtype == GDK_VISUAL_TRUE_COLOR &&
(mask_rgb && byte_order == GDK_LSB_FIRST))
conv = gdk_rgb_convert_0888_br;
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 3df6ac8ac1..002696b872 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -58,6 +58,7 @@ int event_mask_table[20] =
SubstructureNotifyMask
};
+static gboolean gdk_window_have_shape_ext (void);
/* internal function created for and used by gdk_window_xid_at_coords */
Window
@@ -285,14 +286,6 @@ gdk_window_new (GdkWindow *parent,
private->height = (attributes->height > 1) ? (attributes->height) : (1);
private->window_type = attributes->window_type;
private->extension_events = FALSE;
- private->dnd_drag_data_type = None;
- private->dnd_drag_data_typesavail =
- private->dnd_drop_data_typesavail = NULL;
- private->dnd_drop_enabled = private->dnd_drag_enabled =
- private->dnd_drag_accepted = private->dnd_drag_datashow =
- private->dnd_drop_data_numtypesavail =
- private->dnd_drag_data_numtypesavail = 0;
- private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;
private->filters = NULL;
private->children = NULL;
@@ -506,15 +499,6 @@ gdk_window_foreign_new (guint32 anid)
private->colormap = NULL;
- private->dnd_drag_data_type = None;
- private->dnd_drag_data_typesavail =
- private->dnd_drop_data_typesavail = NULL;
- private->dnd_drop_enabled = private->dnd_drag_enabled =
- private->dnd_drag_accepted = private->dnd_drag_datashow =
- private->dnd_drop_data_numtypesavail =
- private->dnd_drag_data_numtypesavail = 0;
- private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;
-
private->filters = NULL;
private->children = NULL;
@@ -584,17 +568,6 @@ gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy,
if (private->extension_events != 0)
gdk_input_window_destroy (window);
- if(private->dnd_drag_data_numtypesavail > 0)
- {
- g_free (private->dnd_drag_data_typesavail);
- private->dnd_drag_data_typesavail = NULL;
- }
- if(private->dnd_drop_data_numtypesavail > 0)
- {
- g_free (private->dnd_drop_data_typesavail);
- private->dnd_drop_data_typesavail = NULL;
- }
-
if (private->filters)
{
tmp = private->filters;
@@ -1629,6 +1602,24 @@ gdk_window_add_colormap_windows (GdkWindow *window)
XFree (old_windows);
}
+static gboolean
+gdk_window_have_shape_ext (void)
+{
+ enum { UNKNOWN, NO, YES };
+ static gint have_shape = UNKNOWN;
+
+ if (have_shape == UNKNOWN)
+ {
+ int ignore;
+ if (XQueryExtension(gdk_display, "SHAPE", &ignore, &ignore, &ignore))
+ have_shape = YES;
+ else
+ have_shape = NO;
+ }
+
+ return (have_shape == YES);
+}
+
/*
* This needs the X11 shape extension.
* If not available, shaped windows will look
@@ -1639,31 +1630,18 @@ gdk_window_shape_combine_mask (GdkWindow *window,
GdkBitmap *mask,
gint x, gint y)
{
- enum { UNKNOWN, NO, YES };
-
- static gint have_shape = UNKNOWN;
-
GdkWindowPrivate *window_private;
Pixmap pixmap;
g_return_if_fail (window != NULL);
#ifdef HAVE_SHAPE_EXT
- if (have_shape == UNKNOWN)
- {
- int ignore;
- if (XQueryExtension(gdk_display, "SHAPE", &ignore, &ignore, &ignore))
- have_shape = YES;
- else
- have_shape = NO;
- }
-
- if (have_shape == YES)
+ window_private = (GdkWindowPrivate*) window;
+ if (window_private->destroyed)
+ return;
+
+ if (gdk_window_have_shape_ext())
{
- window_private = (GdkWindowPrivate*) window;
- if (window_private->destroyed)
- return;
-
if (mask)
{
GdkWindowPrivate *pixmap_private;
@@ -1960,6 +1938,344 @@ gdk_window_get_toplevels (void)
return new_list;
}
+/*
+ * propagate the shapes from all child windows of a GDK window to the parent
+ * window. Shamelessly ripped from Enlightenment's code
+ *
+ * - Raster
+ */
+
+struct _gdk_span
+{
+ gint start;
+ gint end;
+ struct _gdk_span *next;
+};
+
+static void
+gdk_add_to_span(struct _gdk_span **s, int x, int xx)
+{
+ struct _gdk_span *ptr1, *ptr2, *noo, *ss;
+ gchar spanning;
+
+ ptr2 = NULL;
+ ptr1 = *s;
+ spanning = 0;
+ ss = NULL;
+ /* scan the spans for this line */
+ while (ptr1)
+ {
+ /* -- -> new span */
+ /* == -> existing span */
+ /* ## -> spans intersect */
+ /* if we are in the middle of spanning the span into the line */
+ if (spanning)
+ {
+ /* case: ---- ==== */
+ if (xx < ptr1->start - 1)
+ {
+ /* ends before next span - extend to here */
+ ss->end = xx;
+ return;
+ }
+ /* case: ----##=== */
+ else if (xx <= ptr1->end)
+ {
+ /* crosses into next span - delete next span and append */
+ ss->end = ptr1->end;
+ ss->next = ptr1->next;
+ g_free(ptr1);
+ return;
+ }
+ /* case: ---###--- */
+ else
+ {
+ /* overlaps next span - delete and keep checking */
+ ss->next = ptr1->next;
+ g_free(ptr1);
+ ptr1 = ss;
+ }
+ }
+ /* otherwise havent started spanning it in yet */
+ else
+ {
+ /* case: ---- ==== */
+ if (xx < ptr1->start - 1)
+ {
+ /* insert span here in list */
+ noo = g_malloc(sizeof(struct _gdk_span));
+
+ if (noo)
+ {
+ noo->start = x;
+ noo->end = xx;
+ noo->next = ptr1;
+ if (ptr2)
+ ptr2->next = noo;
+ else
+ *s = noo;
+ }
+ return;
+ }
+ /* case: ----##=== */
+ else if ((x < ptr1->start) && (xx <= ptr1->end))
+ {
+ /* expand this span to the left point of the new one */
+ ptr1->start = x;
+ return;
+ }
+ /* case: ===###=== */
+ else if ((x >= ptr1->start) && (xx <= ptr1->end))
+ {
+ /* throw the span away */
+ return;
+ }
+ /* case: ---###--- */
+ else if ((x < ptr1->start) && (xx > ptr1->end))
+ {
+ ss = ptr1;
+ spanning = 1;
+ ptr1->start = x;
+ ptr1->end = xx;
+ }
+ /* case: ===##---- */
+ else if ((x >= ptr1->start) && (x <= ptr1->end + 1) && (xx > ptr1->end))
+ {
+ ss = ptr1;
+ spanning = 1;
+ ptr1->end = xx;
+ }
+ /* case: ==== ---- */
+ /* case handled by next loop iteration - first case */
+ }
+ ptr2 = ptr1;
+ ptr1 = ptr1->next;
+ }
+ /* it started in the middle but spans beyond your current list */
+ if (spanning)
+ {
+ ptr2->end = xx;
+ return;
+ }
+ /* it does not start inside a span or in the middle, so add it to the end */
+ noo = g_malloc(sizeof(struct _gdk_span));
+
+ if (noo)
+ {
+ noo->start = x;
+ noo->end = xx;
+ if (ptr2)
+ {
+ noo->next = ptr2->next;
+ ptr2->next = noo;
+ }
+ else
+ {
+ noo->next = NULL;
+ *s = noo;
+ }
+ }
+ return;
+}
+
+static void
+gdk_add_rectangles (Display *disp, Window win, struct _gdk_span **spans,
+ gint basew, gint baseh, gint x, gint y)
+{
+ gint a, k;
+ gint x1, y1, x2, y2;
+ gint rn, ord;
+ XRectangle *rl;
+
+ rl = XShapeGetRectangles(disp, win, ShapeBounding, &rn, &ord);
+ if (rl)
+ {
+ /* go through all clip rects in this window's shape */
+ for (k = 0; k < rn; k++)
+ {
+ /* for each clip rect, add it to each line's spans */
+ x1 = x + rl[k].x;
+ x2 = x + rl[k].x + (rl[k].width - 1);
+ y1 = y + rl[k].y;
+ y2 = y + rl[k].y + (rl[k].height - 1);
+ if (x1 < 0)
+ x1 = 0;
+ if (y1 < 0)
+ y1 = 0;
+ if (x2 >= basew)
+ x2 = basew - 1;
+ if (y2 >= baseh)
+ y2 = baseh - 1;
+ for (a = y1; a <= y2; a++)
+ {
+ if ((x2 - x1) >= 0)
+ gdk_add_to_span(&spans[a], x1, x2);
+ }
+ }
+ XFree(rl);
+ }
+}
+
+static void
+gdk_propagate_shapes(Display *disp, Window win, gboolean merge)
+{
+ Window rt, par, *list = NULL;
+ gint i, j, num = 0, num_rects = 0;
+ gint x, y, contig;
+ guint w, h, d;
+ gint baseh, basew;
+ XRectangle *rects = NULL;
+ struct _gdk_span **spans = NULL, *ptr1, *ptr2, *ptr3;
+ XWindowAttributes xatt;
+
+ XGetGeometry(disp, win, &rt, &x, &y, &w, &h, &d, &d);
+ if (h <= 0)
+ return;
+ basew = w;
+ baseh = h;
+ spans = g_malloc(sizeof(struct _gdk_span *) * h);
+
+ for (i = 0; i < h; i++)
+ spans[i] = NULL;
+ XQueryTree(disp, win, &rt, &par, &list, (unsigned int *)&num);
+ if (list)
+ {
+ /* go through all child windows and create/insert spans */
+ for (i = 0; i < num; i++)
+ {
+ if (XGetWindowAttributes(disp, list[i], &xatt) && (xatt.map_state != IsUnmapped))
+ if (XGetGeometry(disp, list[i], &rt, &x, &y, &w, &h, &d, &d))
+ gdk_add_rectangles (disp, list[i], spans, basew, baseh, x, y);
+ }
+ if (merge)
+ gdk_add_rectangles (disp, win, spans, basew, baseh, x, y);
+
+ /* go through the spans list and build a list of rects */
+ rects = g_malloc(sizeof(XRectangle) * 256);
+ num_rects = 0;
+ for (i = 0; i < baseh; i++)
+ {
+ ptr1 = spans[i];
+ /* go through the line for all spans */
+ while (ptr1)
+ {
+ rects[num_rects].x = ptr1->start;
+ rects[num_rects].y = i;
+ rects[num_rects].width = ptr1->end - ptr1->start + 1;
+ rects[num_rects].height = 1;
+ j = i + 1;
+ /* if there are more lines */
+ contig = 1;
+ /* while contigous rects (same start/end coords) exist */
+ while ((contig) && (j < baseh))
+ {
+ /* search next line for spans matching this one */
+ contig = 0;
+ ptr2 = spans[j];
+ ptr3 = NULL;
+ while (ptr2)
+ {
+ /* if we have an exact span match set contig */
+ if ((ptr2->start == ptr1->start) &&
+ (ptr2->end == ptr1->end))
+ {
+ contig = 1;
+ /* remove the span - not needed */
+ if (ptr3)
+ {
+ ptr3->next = ptr2->next;
+ g_free(ptr2);
+ ptr2 = NULL;
+ }
+ else
+ {
+ spans[j] = ptr2->next;
+ g_free(ptr2);
+ ptr2 = NULL;
+ }
+ break;
+ }
+ /* gone past the span point no point looking */
+ else if (ptr2->start < ptr1->start)
+ break;
+ if (ptr2)
+ {
+ ptr3 = ptr2;
+ ptr2 = ptr2->next;
+ }
+ }
+ /* if a contiguous span was found increase the rect h */
+ if (contig)
+ {
+ rects[num_rects].height++;
+ j++;
+ }
+ }
+ /* up the rect count */
+ num_rects++;
+ /* every 256 new rects increase the rect array */
+ if ((num_rects % 256) == 0)
+ rects = g_realloc(rects, sizeof(XRectangle) * (num_rects + 256));
+ ptr1 = ptr1->next;
+ }
+ }
+ /* set the rects as the shape mask */
+ if (rects)
+ {
+ XShapeCombineRectangles(disp, win, ShapeBounding, 0, 0, rects, num_rects,
+ ShapeSet, YXSorted);
+ g_free(rects);
+ }
+ XFree(list);
+ }
+ /* free up all the spans we made */
+ for (i = 0; i < baseh; i++)
+ {
+ ptr1 = spans[i];
+ while (ptr1)
+ {
+ ptr2 = ptr1;
+ ptr1 = ptr1->next;
+ g_free(ptr2);
+ }
+ }
+ g_free(spans);
+}
+
+void
+gdk_window_set_child_shapes (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+#ifdef HAVE_SHAPE_EXT
+ private = (GdkWindowPrivate*) window;
+ if (private->destroyed)
+ return;
+
+ if (gdk_window_have_shape_ext())
+ gdk_propagate_shapes (private->xdisplay, private->xwindow, FALSE);
+#endif
+}
+
+void
+gdk_window_merge_child_shapes (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+#ifdef HAVE_SHAPE_EXT
+ private = (GdkWindowPrivate*) window;
+ if (private->destroyed)
+ return;
+
+ if (gdk_window_have_shape_ext())
+ gdk_propagate_shapes (private->xdisplay, private->xwindow, TRUE);
+#endif
+}
+
void
gdk_drawable_set_data (GdkDrawable *drawable,
const gchar *key,
diff --git a/gdk/makecursors.awk b/gdk/makecursors.awk
deleted file mode 100755
index aee14c8a64..0000000000
--- a/gdk/makecursors.awk
+++ /dev/null
@@ -1,4 +0,0 @@
-$1 == "#define" && NF >= 3 {
- sub(/^XC/,"GDK",$2)
- printf("%s = %s,\n",toupper($2),$3)
-}
diff --git a/gdk/makekeysyms.awk b/gdk/makekeysyms.awk
deleted file mode 100755
index dbf2a1b94a..0000000000
--- a/gdk/makekeysyms.awk
+++ /dev/null
@@ -1,5 +0,0 @@
-$1 == "#define" && NF >= 3 {
- sub(/^XK/,"GDK",$2)
- sub(/0X/,"0x",$3)
- print $1,$2,$3
-}
diff --git a/gdk/x11/gdkdnd-x11.c b/gdk/x11/gdkdnd-x11.c
index 67720ad6bd..c4dc41a078 100644
--- a/gdk/x11/gdkdnd-x11.c
+++ b/gdk/x11/gdkdnd-x11.c
@@ -377,15 +377,17 @@ gdk_window_cache_destroy (GdkWindowCache *cache)
static Window
get_client_window_at_coords_recurse (Window win,
- gint x_root,
- gint y_root)
+ gint x,
+ gint y)
{
- Window child;
+ Window root, tmp_parent, *children;
+ unsigned int nchildren;
+ int i;
+ Window child = None;
Atom type = None;
int format;
unsigned long nitems, after;
unsigned char *data;
- int dest_x, dest_y;
static Atom wm_state_atom = None;
@@ -408,6 +410,8 @@ get_client_window_at_coords_recurse (Window win,
return win;
}
+#if 0
+ /* This is beautiful! Damn Enlightenment and click-to-focus */
XTranslateCoordinates (gdk_display, gdk_root_window, win,
x_root, y_root, &dest_x, &dest_y, &child);
@@ -416,18 +420,49 @@ get_client_window_at_coords_recurse (Window win,
gdk_error_code = 0;
return None;
}
+
+#else
+ if (XQueryTree(gdk_display, win,
+ &root, &tmp_parent, &children, &nchildren) == 0)
+ return 0;
+
+ if (gdk_error_code == 0)
+ {
+ for (i = nchildren - 1; (i >= 0) && (child == None); i--)
+ {
+ XWindowAttributes xwa;
+
+ XGetWindowAttributes (gdk_display, children[i], &xwa);
+
+ if (gdk_error_code != 0)
+ gdk_error_code = 0;
+ else if ((xwa.map_state == IsViewable) && (xwa.class == InputOutput) &&
+ (x >= xwa.x) && (x < xwa.x + (gint)xwa.width) &&
+ (y >= xwa.y) && (y < xwa.y + (gint)xwa.height))
+ {
+ x -= xwa.x;
+ y -= xwa.y;
+ child = children[i];
+ }
+ }
+
+ XFree (children);
+ }
+ else
+ gdk_error_code = 0;
+#endif
if (child)
- return get_client_window_at_coords_recurse (child, x_root, y_root);
+ return get_client_window_at_coords_recurse (child, x, y);
else
return None;
}
Window
get_client_window_at_coords (GdkWindowCache *cache,
- Window ignore,
- gint x_root,
- gint y_root)
+ Window ignore,
+ gint x_root,
+ gint y_root)
{
GList *tmp_list;
Window retval = None;
@@ -449,7 +484,8 @@ get_client_window_at_coords (GdkWindowCache *cache,
(y_root >= child->y) && (y_root < child->y + child->height))
{
retval = get_client_window_at_coords_recurse (child->xid,
- x_root, y_root);
+ x_root - child->x,
+ y_root - child->y);
if (!retval)
retval = child->xid;
}
@@ -532,7 +568,7 @@ get_client_window_at_coords (Window ignore,
if (XQueryTree(gdk_display, gdk_root_window,
&root, &parent, &children, &nchildren) == 0)
return 0;
-
+
for (i = nchildren - 1; (i >= 0) && (retval == None); i--)
{
if (children[i] != ignore)
@@ -883,7 +919,12 @@ motif_read_target_table (void)
goto error;
n_targets = card16_to_host (*(gushort *)p, header->byte_order);
- targets = (guint32 *)(p + sizeof(guint16));
+
+ /* We need to make a copy of the targets, since it may
+ * be unaligned
+ */
+ targets = g_new (guint32, n_targets);
+ memcpy (targets, p + sizeof(guint16), sizeof(guint32) * n_targets);
p += sizeof(guint16) + n_targets * sizeof(guint32);
if (p - target_bytes > nitems)
@@ -894,7 +935,7 @@ motif_read_target_table (void)
g_list_prepend (motif_target_lists[i],
GUINT_TO_POINTER (card32_to_host (targets[j],
header->byte_order)));
-
+ g_free (targets);
motif_target_lists[i] = g_list_reverse (motif_target_lists[i]);
}
@@ -1001,7 +1042,6 @@ motif_add_to_target_table (GList *targets)
guchar *data;
guchar *p;
guint16 *p16;
- guint32 *p32;
MotifTargetTableHeader *header;
if (!motif_target_lists)
@@ -1035,20 +1075,27 @@ motif_add_to_target_table (GList *targets)
for (i = 0; i < motif_n_target_lists ; i++)
{
- guint16 count = 0;
+ guint16 n_targets = g_list_length (motif_target_lists[i]);
+ guint32 *targets = g_new (guint32, n_targets);
+ guint32 *p32 = targets;
- p16 = (guint16 *)p;
- p += sizeof(guint16);
- p32 = (guint32 *)p;
tmp_list = motif_target_lists[i];
while (tmp_list)
{
- *p32++ = GPOINTER_TO_UINT (tmp_list->data);
+ *p32 = GPOINTER_TO_UINT (tmp_list->data);
+
tmp_list = tmp_list->next;
- count++;
+ p32++;
}
- *p16 = count;
- p = (guchar *)p32;
+
+ p16 = (guint16 *)p;
+ p += sizeof(guint16);
+
+ memcpy (p, targets, n_targets * sizeof(guint32));
+
+ *p16 = n_targets;
+ p += sizeof(guint32) * n_targets;
+ g_free (targets);
}
XChangeProperty (gdk_display, motif_drag_window,
diff --git a/gdk/x11/gdkimage-x11.c b/gdk/x11/gdkimage-x11.c
index 4d009f9f42..2cc850b532 100644
--- a/gdk/x11/gdkimage-x11.c
+++ b/gdk/x11/gdkimage-x11.c
@@ -353,7 +353,8 @@ gdk_image_get (GdkWindow *window,
image->mem = private->ximage->data;
image->bpl = private->ximage->bytes_per_line;
- image->bpp = 1;
+ image->bpp = private->ximage->bits_per_pixel;
+ image->byte_order = private->ximage->byte_order;
return image;
}
diff --git a/gdk/x11/gdkinput-xfree.c b/gdk/x11/gdkinput-xfree.c
index 997fdd207b..7b69d6197f 100644
--- a/gdk/x11/gdkinput-xfree.c
+++ b/gdk/x11/gdkinput-xfree.c
@@ -173,7 +173,7 @@ gdk_input_xfree_configure_event (XConfigureEvent *xevent, GdkWindow *window)
static void
gdk_input_xfree_enter_event (XCrossingEvent *xevent,
- GdkWindow *window)
+ GdkWindow *window)
{
GdkInputWindow *input_window;
gint root_x, root_y;
diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c
index 449ad4add8..217724417c 100644
--- a/gdk/x11/gdkmain-x11.c
+++ b/gdk/x11/gdkmain-x11.c
@@ -116,10 +116,6 @@ static Bool gdk_event_get_type (Display *display,
static void gdk_synthesize_click (GdkEvent *event,
gint nclicks);
-#ifdef DEBUG_DND
-static void gdk_print_atom (GdkAtom anatom);
-#endif
-
#ifndef HAVE_XCONVERTCASE
static void gdkx_XConvertCase (KeySym symbol,
KeySym *lower,
@@ -156,12 +152,12 @@ static gint gdk_im_open (XrmDatabase db,
static void gdk_im_close (void);
static void gdk_ic_cleanup (void);
+#endif /* USE_XIM */
+
GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev,
GdkEvent *event,
gpointer data);
-#endif /* USE_XIM */
-
/* Private variable declarations
*/
static int gdk_initialized = 0; /* 1 if the library is initialized,
@@ -743,6 +739,194 @@ gdk_event_get_graphics_expose (GdkWindow *window)
return NULL;
}
+/************************
+ * Exposure compression *
+ ************************/
+
+/*
+ * The following implements simple exposure compression. It is
+ * modelled after the way Xt does exposure compression - in
+ * particular compress_expose = XtExposeCompressMultiple.
+ * It compress consecutive sequences of exposure events,
+ * but not sequences that cross other events. (This is because
+ * if it crosses a ConfigureNotify, we could screw up and
+ * mistakenly compress the exposures generated for the new
+ * size - could we just check for ConfigureNotify?)
+ *
+ * Xt compresses to a region / bounding rectangle, we compress
+ * to two rectangles, and try find the two rectangles of minimal
+ * area for this - this is supposed to handle the typical
+ * L-shaped regions generated by OpaqueMove.
+ */
+
+/* Given three rectangles, find the two rectangles that cover
+ * them with the smallest area.
+ */
+static void
+gdk_add_rect_to_rects (GdkRectangle *rect1,
+ GdkRectangle *rect2,
+ GdkRectangle *new_rect)
+{
+ GdkRectangle t1, t2, t3;
+ gint size1, size2, size3;
+
+ gdk_rectangle_union (rect1, rect2, &t1);
+ gdk_rectangle_union (rect1, new_rect, &t2);
+ gdk_rectangle_union (rect2, new_rect, &t3);
+
+ size1 = t1.width * t1.height + new_rect->width * new_rect->height;
+ size2 = t2.width * t2.height + rect2->width * rect2->height;
+ size3 = t1.width * t1.height + rect1->width * rect1->height;
+
+ if (size1 < size2)
+ {
+ if (size1 < size3)
+ {
+ *rect1 = t1;
+ *rect2 = *new_rect;
+ }
+ else
+ *rect2 = t3;
+ }
+ else
+ {
+ if (size2 < size3)
+ *rect1 = t2;
+ else
+ *rect2 = t3;
+ }
+}
+
+typedef struct _GdkExposeInfo GdkExposeInfo;
+
+struct _GdkExposeInfo {
+ Window window;
+ gboolean seen_nonmatching;
+};
+
+Bool
+expose_predicate (Display *display, XEvent *xevent, XPointer arg)
+{
+ GdkExposeInfo *info = (GdkExposeInfo *)arg;
+
+ if (xevent->xany.type != Expose)
+ {
+ info->seen_nonmatching = TRUE;
+ }
+
+ if (info->seen_nonmatching || (xevent->xany.window != info->window))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+void
+gdk_compress_exposures (XEvent *xevent, GdkWindow *window)
+{
+ gint nrects = 1;
+ gint count = 0;
+ GdkRectangle rect1;
+ GdkRectangle rect2;
+ GdkRectangle tmp_rect;
+ XEvent tmp_event;
+ GdkFilterReturn result;
+ GdkExposeInfo info;
+ GdkEvent event;
+
+ info.window = xevent->xany.window;
+ info.seen_nonmatching = FALSE;
+
+ rect1.x = xevent->xexpose.x;
+ rect1.y = xevent->xexpose.y;
+ rect1.width = xevent->xexpose.width;
+ rect1.height = xevent->xexpose.height;
+
+ while (1)
+ {
+ if (count == 0)
+ {
+ if (!XCheckIfEvent (gdk_display,
+ &tmp_event,
+ expose_predicate,
+ (XPointer)&info))
+ break;
+ }
+ else
+ XIfEvent (gdk_display,
+ &tmp_event,
+ expose_predicate,
+ (XPointer)&info);
+
+ /* We apply filters here, and if it was filtered, completely
+ * ignore the return
+ */
+ result = gdk_event_apply_filters (xevent, &event,
+ window ?
+ ((GdkWindowPrivate *)window)->filters
+ : gdk_default_filters);
+
+ if (result != GDK_FILTER_CONTINUE)
+ {
+ if (result == GDK_FILTER_TRANSLATE)
+ gdk_event_put (&event);
+ continue;
+ }
+
+ if (nrects == 1)
+ {
+ rect2.x = tmp_event.xexpose.x;
+ rect2.y = tmp_event.xexpose.y;
+ rect2.width = tmp_event.xexpose.width;
+ rect2.height = tmp_event.xexpose.height;
+
+ nrects++;
+ }
+ else
+ {
+ tmp_rect.x = tmp_event.xexpose.x;
+ tmp_rect.y = tmp_event.xexpose.y;
+ tmp_rect.width = tmp_event.xexpose.width;
+ tmp_rect.height = tmp_event.xexpose.height;
+
+ gdk_add_rect_to_rects (&rect1, &rect2, &tmp_rect);
+ }
+
+ count = tmp_event.xexpose.count;
+ }
+
+ if (nrects == 2)
+ {
+ gdk_rectangle_union (&rect1, &rect2, &tmp_rect);
+
+ if ((tmp_rect.width * tmp_rect.height) <
+ 2 * (rect1.height * rect1.width +
+ rect2.height * rect2.width))
+ {
+ rect1 = tmp_rect;
+ nrects = 1;
+ }
+ }
+
+ if (nrects == 2)
+ {
+ event.expose.type = GDK_EXPOSE;
+ event.expose.window = window;
+ event.expose.area.x = rect2.x;
+ event.expose.area.y = rect2.y;
+ event.expose.area.width = rect2.width;
+ event.expose.area.height = rect2.height;
+ event.expose.count = 0;
+
+ gdk_event_put (&event);
+ }
+
+ xevent->xexpose.count = nrects - 1;
+ xevent->xexpose.x = rect1.x;
+ xevent->xexpose.y = rect1.y;
+ xevent->xexpose.width = rect1.width;
+ xevent->xexpose.height = rect1.height;
+}
+
/*
*--------------------------------------------------------------
* gdk_event_get
@@ -834,6 +1018,7 @@ gdk_event_get (void)
#else
XNextEvent (gdk_display, &xevent);
#endif
+
event = gdk_event_new ();
event->any.type = GDK_NOTHING;
@@ -2005,6 +2190,13 @@ gdk_event_translate (GdkEvent *event,
case KeyRelease:
/* Lookup the string corresponding to the given keysym.
*/
+#ifdef USE_XIM
+ if (buf_len == 0)
+ {
+ buf_len = 128;
+ buf = g_new (gchar, buf_len);
+ }
+#endif
keysym = GDK_VoidSymbol;
charcount = XLookupString (&xevent->xkey, buf, 16,
&keysym, &compose);
@@ -2031,8 +2223,7 @@ gdk_event_translate (GdkEvent *event,
/* Print debugging info.
*/
GDK_NOTE (EVENTS,
- g_message ("button press[%d]:\t\twindow: %ld x,y: %d %d button: %d",
- window_private?window_private->dnd_drag_enabled:0,
+ g_message ("button press:\t\twindow: %ld x,y: %d %d button: %d",
xevent->xbutton.window - base_id,
xevent->xbutton.x, xevent->xbutton.y,
xevent->xbutton.button));
@@ -2102,8 +2293,7 @@ gdk_event_translate (GdkEvent *event,
/* Print debugging info.
*/
GDK_NOTE (EVENTS,
- g_message ("button release[%d]:\twindow: %ld x,y: %d %d button: %d",
- window_private?window_private->dnd_drag_enabled:0,
+ g_message ("button release:\twindow: %ld x,y: %d %d button: %d",
xevent->xbutton.window - base_id,
xevent->xbutton.x, xevent->xbutton.y,
xevent->xbutton.button));
@@ -2178,6 +2368,7 @@ gdk_event_translate (GdkEvent *event,
/* Tell XInput stuff about it if appropriate */
if (window_private &&
+ !window_private->destroyed &&
(window_private->extension_events != 0) &&
gdk_input_vtable.enter_event)
gdk_input_vtable.enter_event (&xevent->xcrossing, window);
@@ -2357,6 +2548,7 @@ gdk_event_translate (GdkEvent *event,
xevent->xexpose.window - base_id, xevent->xexpose.count,
xevent->xexpose.x, xevent->xexpose.y,
xevent->xexpose.width, xevent->xexpose.height));
+ gdk_compress_exposures (xevent, window);
event->expose.type = GDK_EXPOSE;
event->expose.window = window;
@@ -2539,10 +2731,11 @@ gdk_event_translate (GdkEvent *event,
xevent->xconfigure.above - base_id,
xevent->xconfigure.override_redirect));
- if ((window_private->extension_events != 0) &&
+ if (!window_private->destroyed &&
+ (window_private->extension_events != 0) &&
gdk_input_vtable.configure_event)
gdk_input_vtable.configure_event (&xevent->xconfigure, window);
-
+
if (window_private->window_type == GDK_WINDOW_CHILD)
return_val = FALSE;
else
@@ -2714,6 +2907,7 @@ gdk_event_translate (GdkEvent *event,
/* something else - (e.g., a Xinput event) */
if (window_private &&
+ !window_private->destroyed &&
(window_private->extension_events != 0) &&
gdk_input_vtable.other_event)
return_val = gdk_input_vtable.other_event(event, xevent, window);
@@ -3638,61 +3832,6 @@ _g_mbtowc (wchar_t *wstr, const char *str, size_t len)
#endif /* X_LOCALE */
-/*
- * used for debugging only
- */
-#ifdef DEBUG_DND
-static void
-gdk_print_atom (GdkAtom anatom)
-{
- gchar *tmpstr = NULL;
- tmpstr = (anatom!=None)?gdk_atom_name(anatom):"(none)";
- g_message("Atom %lu has name %s", anatom, tmpstr);
- if(tmpstr)
- g_free(tmpstr);
-}
-#endif
-
-#ifdef WE_HAVE_MOTIF_DROPS_DONE
-static GdkWindow *
-gdk_drop_get_real_window (GdkWindow *w,
- guint16 *x,
- guint16 *y)
-{
- GdkWindow *retval = w;
- GdkWindowPrivate *awin;
- GList *children;
- gint16 myx = *x, myy = *y;
-
- g_return_val_if_fail (w != NULL && x != NULL && y != NULL, NULL);
-
- myx = *x;
- myy = *y;
-
- descend:
- for (children = gdk_window_get_children(retval);
- children && children->next;
- children = children->next)
- {
- awin = (GdkWindowPrivate *) children->data;
- if ((myx >= awin->x) && (myy >= awin->y)
- && (myx < (awin->x + awin->width))
- && (myy < (awin->y + awin->height)))
- {
- retval = (GdkWindow *) awin;
- myx -= awin->x;
- myy -= awin->y;
- goto descend;
- }
- }
-
- *x = myx;
- *y = myy;
-
- return retval;
-}
-#endif
-
/* Sends a ClientMessage to all toplevel client windows */
gboolean
gdk_event_send_client_message (GdkEvent *event, guint32 xid)
@@ -3716,7 +3855,7 @@ gdk_event_send_client_message (GdkEvent *event, guint32 xid)
gboolean
gdk_event_send_client_message_to_all_recurse (XEvent *xev,
guint32 xid,
- gboolean send_anyways)
+ guint level)
{
static GdkAtom wm_state_atom = GDK_NONE;
@@ -3729,7 +3868,7 @@ gdk_event_send_client_message_to_all_recurse (XEvent *xev,
unsigned int ret_nchildren;
int i;
- gboolean send = TRUE;
+ gboolean send = FALSE;
gboolean found = FALSE;
if (!wm_state_atom)
@@ -3761,13 +3900,13 @@ gdk_event_send_client_message_to_all_recurse (XEvent *xev,
return FALSE;
for(i = 0; i < ret_nchildren; i++)
- if (gdk_event_send_client_message_to_all_recurse(xev, ret_children[i], FALSE))
+ if (gdk_event_send_client_message_to_all_recurse(xev, ret_children[i], level + 1))
found = TRUE;
XFree(ret_children);
}
- if (send || (!found && send_anyways))
+ if (send || (!found && (level == 1)))
{
xev->xclient.window = xid;
gdk_send_xevent (xid, False, NoEventMask, xev);
@@ -3791,7 +3930,7 @@ gdk_event_send_clientmessage_toall (GdkEvent *event)
memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
sev.xclient.message_type = event->client.message_type;
- gdk_event_send_client_message_to_all_recurse(&sev, gdk_root_window, TRUE);
+ gdk_event_send_client_message_to_all_recurse(&sev, gdk_root_window, 0);
gdk_error_warnings = old_warnings;
}
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
index 3df6ac8ac1..002696b872 100644
--- a/gdk/x11/gdkwindow-x11.c
+++ b/gdk/x11/gdkwindow-x11.c
@@ -58,6 +58,7 @@ int event_mask_table[20] =
SubstructureNotifyMask
};
+static gboolean gdk_window_have_shape_ext (void);
/* internal function created for and used by gdk_window_xid_at_coords */
Window
@@ -285,14 +286,6 @@ gdk_window_new (GdkWindow *parent,
private->height = (attributes->height > 1) ? (attributes->height) : (1);
private->window_type = attributes->window_type;
private->extension_events = FALSE;
- private->dnd_drag_data_type = None;
- private->dnd_drag_data_typesavail =
- private->dnd_drop_data_typesavail = NULL;
- private->dnd_drop_enabled = private->dnd_drag_enabled =
- private->dnd_drag_accepted = private->dnd_drag_datashow =
- private->dnd_drop_data_numtypesavail =
- private->dnd_drag_data_numtypesavail = 0;
- private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;
private->filters = NULL;
private->children = NULL;
@@ -506,15 +499,6 @@ gdk_window_foreign_new (guint32 anid)
private->colormap = NULL;
- private->dnd_drag_data_type = None;
- private->dnd_drag_data_typesavail =
- private->dnd_drop_data_typesavail = NULL;
- private->dnd_drop_enabled = private->dnd_drag_enabled =
- private->dnd_drag_accepted = private->dnd_drag_datashow =
- private->dnd_drop_data_numtypesavail =
- private->dnd_drag_data_numtypesavail = 0;
- private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;
-
private->filters = NULL;
private->children = NULL;
@@ -584,17 +568,6 @@ gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy,
if (private->extension_events != 0)
gdk_input_window_destroy (window);
- if(private->dnd_drag_data_numtypesavail > 0)
- {
- g_free (private->dnd_drag_data_typesavail);
- private->dnd_drag_data_typesavail = NULL;
- }
- if(private->dnd_drop_data_numtypesavail > 0)
- {
- g_free (private->dnd_drop_data_typesavail);
- private->dnd_drop_data_typesavail = NULL;
- }
-
if (private->filters)
{
tmp = private->filters;
@@ -1629,6 +1602,24 @@ gdk_window_add_colormap_windows (GdkWindow *window)
XFree (old_windows);
}
+static gboolean
+gdk_window_have_shape_ext (void)
+{
+ enum { UNKNOWN, NO, YES };
+ static gint have_shape = UNKNOWN;
+
+ if (have_shape == UNKNOWN)
+ {
+ int ignore;
+ if (XQueryExtension(gdk_display, "SHAPE", &ignore, &ignore, &ignore))
+ have_shape = YES;
+ else
+ have_shape = NO;
+ }
+
+ return (have_shape == YES);
+}
+
/*
* This needs the X11 shape extension.
* If not available, shaped windows will look
@@ -1639,31 +1630,18 @@ gdk_window_shape_combine_mask (GdkWindow *window,
GdkBitmap *mask,
gint x, gint y)
{
- enum { UNKNOWN, NO, YES };
-
- static gint have_shape = UNKNOWN;
-
GdkWindowPrivate *window_private;
Pixmap pixmap;
g_return_if_fail (window != NULL);
#ifdef HAVE_SHAPE_EXT
- if (have_shape == UNKNOWN)
- {
- int ignore;
- if (XQueryExtension(gdk_display, "SHAPE", &ignore, &ignore, &ignore))
- have_shape = YES;
- else
- have_shape = NO;
- }
-
- if (have_shape == YES)
+ window_private = (GdkWindowPrivate*) window;
+ if (window_private->destroyed)
+ return;
+
+ if (gdk_window_have_shape_ext())
{
- window_private = (GdkWindowPrivate*) window;
- if (window_private->destroyed)
- return;
-
if (mask)
{
GdkWindowPrivate *pixmap_private;
@@ -1960,6 +1938,344 @@ gdk_window_get_toplevels (void)
return new_list;
}
+/*
+ * propagate the shapes from all child windows of a GDK window to the parent
+ * window. Shamelessly ripped from Enlightenment's code
+ *
+ * - Raster
+ */
+
+struct _gdk_span
+{
+ gint start;
+ gint end;
+ struct _gdk_span *next;
+};
+
+static void
+gdk_add_to_span(struct _gdk_span **s, int x, int xx)
+{
+ struct _gdk_span *ptr1, *ptr2, *noo, *ss;
+ gchar spanning;
+
+ ptr2 = NULL;
+ ptr1 = *s;
+ spanning = 0;
+ ss = NULL;
+ /* scan the spans for this line */
+ while (ptr1)
+ {
+ /* -- -> new span */
+ /* == -> existing span */
+ /* ## -> spans intersect */
+ /* if we are in the middle of spanning the span into the line */
+ if (spanning)
+ {
+ /* case: ---- ==== */
+ if (xx < ptr1->start - 1)
+ {
+ /* ends before next span - extend to here */
+ ss->end = xx;
+ return;
+ }
+ /* case: ----##=== */
+ else if (xx <= ptr1->end)
+ {
+ /* crosses into next span - delete next span and append */
+ ss->end = ptr1->end;
+ ss->next = ptr1->next;
+ g_free(ptr1);
+ return;
+ }
+ /* case: ---###--- */
+ else
+ {
+ /* overlaps next span - delete and keep checking */
+ ss->next = ptr1->next;
+ g_free(ptr1);
+ ptr1 = ss;
+ }
+ }
+ /* otherwise havent started spanning it in yet */
+ else
+ {
+ /* case: ---- ==== */
+ if (xx < ptr1->start - 1)
+ {
+ /* insert span here in list */
+ noo = g_malloc(sizeof(struct _gdk_span));
+
+ if (noo)
+ {
+ noo->start = x;
+ noo->end = xx;
+ noo->next = ptr1;
+ if (ptr2)
+ ptr2->next = noo;
+ else
+ *s = noo;
+ }
+ return;
+ }
+ /* case: ----##=== */
+ else if ((x < ptr1->start) && (xx <= ptr1->end))
+ {
+ /* expand this span to the left point of the new one */
+ ptr1->start = x;
+ return;
+ }
+ /* case: ===###=== */
+ else if ((x >= ptr1->start) && (xx <= ptr1->end))
+ {
+ /* throw the span away */
+ return;
+ }
+ /* case: ---###--- */
+ else if ((x < ptr1->start) && (xx > ptr1->end))
+ {
+ ss = ptr1;
+ spanning = 1;
+ ptr1->start = x;
+ ptr1->end = xx;
+ }
+ /* case: ===##---- */
+ else if ((x >= ptr1->start) && (x <= ptr1->end + 1) && (xx > ptr1->end))
+ {
+ ss = ptr1;
+ spanning = 1;
+ ptr1->end = xx;
+ }
+ /* case: ==== ---- */
+ /* case handled by next loop iteration - first case */
+ }
+ ptr2 = ptr1;
+ ptr1 = ptr1->next;
+ }
+ /* it started in the middle but spans beyond your current list */
+ if (spanning)
+ {
+ ptr2->end = xx;
+ return;
+ }
+ /* it does not start inside a span or in the middle, so add it to the end */
+ noo = g_malloc(sizeof(struct _gdk_span));
+
+ if (noo)
+ {
+ noo->start = x;
+ noo->end = xx;
+ if (ptr2)
+ {
+ noo->next = ptr2->next;
+ ptr2->next = noo;
+ }
+ else
+ {
+ noo->next = NULL;
+ *s = noo;
+ }
+ }
+ return;
+}
+
+static void
+gdk_add_rectangles (Display *disp, Window win, struct _gdk_span **spans,
+ gint basew, gint baseh, gint x, gint y)
+{
+ gint a, k;
+ gint x1, y1, x2, y2;
+ gint rn, ord;
+ XRectangle *rl;
+
+ rl = XShapeGetRectangles(disp, win, ShapeBounding, &rn, &ord);
+ if (rl)
+ {
+ /* go through all clip rects in this window's shape */
+ for (k = 0; k < rn; k++)
+ {
+ /* for each clip rect, add it to each line's spans */
+ x1 = x + rl[k].x;
+ x2 = x + rl[k].x + (rl[k].width - 1);
+ y1 = y + rl[k].y;
+ y2 = y + rl[k].y + (rl[k].height - 1);
+ if (x1 < 0)
+ x1 = 0;
+ if (y1 < 0)
+ y1 = 0;
+ if (x2 >= basew)
+ x2 = basew - 1;
+ if (y2 >= baseh)
+ y2 = baseh - 1;
+ for (a = y1; a <= y2; a++)
+ {
+ if ((x2 - x1) >= 0)
+ gdk_add_to_span(&spans[a], x1, x2);
+ }
+ }
+ XFree(rl);
+ }
+}
+
+static void
+gdk_propagate_shapes(Display *disp, Window win, gboolean merge)
+{
+ Window rt, par, *list = NULL;
+ gint i, j, num = 0, num_rects = 0;
+ gint x, y, contig;
+ guint w, h, d;
+ gint baseh, basew;
+ XRectangle *rects = NULL;
+ struct _gdk_span **spans = NULL, *ptr1, *ptr2, *ptr3;
+ XWindowAttributes xatt;
+
+ XGetGeometry(disp, win, &rt, &x, &y, &w, &h, &d, &d);
+ if (h <= 0)
+ return;
+ basew = w;
+ baseh = h;
+ spans = g_malloc(sizeof(struct _gdk_span *) * h);
+
+ for (i = 0; i < h; i++)
+ spans[i] = NULL;
+ XQueryTree(disp, win, &rt, &par, &list, (unsigned int *)&num);
+ if (list)
+ {
+ /* go through all child windows and create/insert spans */
+ for (i = 0; i < num; i++)
+ {
+ if (XGetWindowAttributes(disp, list[i], &xatt) && (xatt.map_state != IsUnmapped))
+ if (XGetGeometry(disp, list[i], &rt, &x, &y, &w, &h, &d, &d))
+ gdk_add_rectangles (disp, list[i], spans, basew, baseh, x, y);
+ }
+ if (merge)
+ gdk_add_rectangles (disp, win, spans, basew, baseh, x, y);
+
+ /* go through the spans list and build a list of rects */
+ rects = g_malloc(sizeof(XRectangle) * 256);
+ num_rects = 0;
+ for (i = 0; i < baseh; i++)
+ {
+ ptr1 = spans[i];
+ /* go through the line for all spans */
+ while (ptr1)
+ {
+ rects[num_rects].x = ptr1->start;
+ rects[num_rects].y = i;
+ rects[num_rects].width = ptr1->end - ptr1->start + 1;
+ rects[num_rects].height = 1;
+ j = i + 1;
+ /* if there are more lines */
+ contig = 1;
+ /* while contigous rects (same start/end coords) exist */
+ while ((contig) && (j < baseh))
+ {
+ /* search next line for spans matching this one */
+ contig = 0;
+ ptr2 = spans[j];
+ ptr3 = NULL;
+ while (ptr2)
+ {
+ /* if we have an exact span match set contig */
+ if ((ptr2->start == ptr1->start) &&
+ (ptr2->end == ptr1->end))
+ {
+ contig = 1;
+ /* remove the span - not needed */
+ if (ptr3)
+ {
+ ptr3->next = ptr2->next;
+ g_free(ptr2);
+ ptr2 = NULL;
+ }
+ else
+ {
+ spans[j] = ptr2->next;
+ g_free(ptr2);
+ ptr2 = NULL;
+ }
+ break;
+ }
+ /* gone past the span point no point looking */
+ else if (ptr2->start < ptr1->start)
+ break;
+ if (ptr2)
+ {
+ ptr3 = ptr2;
+ ptr2 = ptr2->next;
+ }
+ }
+ /* if a contiguous span was found increase the rect h */
+ if (contig)
+ {
+ rects[num_rects].height++;
+ j++;
+ }
+ }
+ /* up the rect count */
+ num_rects++;
+ /* every 256 new rects increase the rect array */
+ if ((num_rects % 256) == 0)
+ rects = g_realloc(rects, sizeof(XRectangle) * (num_rects + 256));
+ ptr1 = ptr1->next;
+ }
+ }
+ /* set the rects as the shape mask */
+ if (rects)
+ {
+ XShapeCombineRectangles(disp, win, ShapeBounding, 0, 0, rects, num_rects,
+ ShapeSet, YXSorted);
+ g_free(rects);
+ }
+ XFree(list);
+ }
+ /* free up all the spans we made */
+ for (i = 0; i < baseh; i++)
+ {
+ ptr1 = spans[i];
+ while (ptr1)
+ {
+ ptr2 = ptr1;
+ ptr1 = ptr1->next;
+ g_free(ptr2);
+ }
+ }
+ g_free(spans);
+}
+
+void
+gdk_window_set_child_shapes (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+#ifdef HAVE_SHAPE_EXT
+ private = (GdkWindowPrivate*) window;
+ if (private->destroyed)
+ return;
+
+ if (gdk_window_have_shape_ext())
+ gdk_propagate_shapes (private->xdisplay, private->xwindow, FALSE);
+#endif
+}
+
+void
+gdk_window_merge_child_shapes (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+#ifdef HAVE_SHAPE_EXT
+ private = (GdkWindowPrivate*) window;
+ if (private->destroyed)
+ return;
+
+ if (gdk_window_have_shape_ext())
+ gdk_propagate_shapes (private->xdisplay, private->xwindow, TRUE);
+#endif
+}
+
void
gdk_drawable_set_data (GdkDrawable *drawable,
const gchar *key,