diff options
author | Owen Taylor <otaylor@src.gnome.org> | 1998-11-06 22:05:02 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 1998-11-06 22:05:02 +0000 |
commit | e2a521922085c8010028e227f61bba59ea6b8242 (patch) | |
tree | 2500d6aa6f63aab4b58c17546532ecce8fdcca37 /gdk | |
parent | 3c0df19a588bd96f328bda975db8eb9fa7f79e81 (diff) | |
download | gtk+-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.am | 17 | ||||
-rw-r--r-- | gdk/gdk.c | 283 | ||||
-rw-r--r-- | gdk/gdk.h | 22 | ||||
-rw-r--r-- | gdk/gdkcursors.h | 18 | ||||
-rw-r--r-- | gdk/gdkdnd.c | 89 | ||||
-rw-r--r-- | gdk/gdkgc.c | 2 | ||||
-rw-r--r-- | gdk/gdkimage.c | 3 | ||||
-rw-r--r-- | gdk/gdkinputxfree.h | 2 | ||||
-rw-r--r-- | gdk/gdkprivate.h | 16 | ||||
-rw-r--r-- | gdk/gdkrectangle.c | 14 | ||||
-rw-r--r-- | gdk/gdkrgb.c | 18 | ||||
-rw-r--r-- | gdk/gdkwindow.c | 408 | ||||
-rwxr-xr-x | gdk/makecursors.awk | 4 | ||||
-rwxr-xr-x | gdk/makekeysyms.awk | 5 | ||||
-rw-r--r-- | gdk/x11/gdkdnd-x11.c | 89 | ||||
-rw-r--r-- | gdk/x11/gdkimage-x11.c | 3 | ||||
-rw-r--r-- | gdk/x11/gdkinput-xfree.c | 2 | ||||
-rw-r--r-- | gdk/x11/gdkmain-x11.c | 283 | ||||
-rw-r--r-- | gdk/x11/gdkwindow-x11.c | 408 |
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 @@ -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; } @@ -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, |