diff --git a/ChangeLog b/ChangeLog index ce969aac75..fc6aa9e30a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +Wed Jul 29 16:56:07 1998 Owen Taylor + + * gdk/gdk.c: Fairly implementation of expose compression. + (No GraphicsExpose compression yet, always compress + with the equivalent of XtCompressMultiple - no compression + of Expose events across non-Expose events) + + * gdk/gdk.h gdk/gdkrectangle.c: gdk_rectangle_union() + Find rectangle bounding two rectangles. + + * gtk/gtkstyle.c: Set clip rects for a few extra GC's + in gdk_default_draw_shadow() + Wed Jul 29 16:03:20 EDT 1998 The Rasterman * Fixed drawing functions to handle switching themes on the fly gracefully and look decent. diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index ce969aac75..fc6aa9e30a 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,16 @@ +Wed Jul 29 16:56:07 1998 Owen Taylor + + * gdk/gdk.c: Fairly implementation of expose compression. + (No GraphicsExpose compression yet, always compress + with the equivalent of XtCompressMultiple - no compression + of Expose events across non-Expose events) + + * gdk/gdk.h gdk/gdkrectangle.c: gdk_rectangle_union() + Find rectangle bounding two rectangles. + + * gtk/gtkstyle.c: Set clip rects for a few extra GC's + in gdk_default_draw_shadow() + Wed Jul 29 16:03:20 EDT 1998 The Rasterman * Fixed drawing functions to handle switching themes on the fly gracefully and look decent. diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index ce969aac75..fc6aa9e30a 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,16 @@ +Wed Jul 29 16:56:07 1998 Owen Taylor + + * gdk/gdk.c: Fairly implementation of expose compression. + (No GraphicsExpose compression yet, always compress + with the equivalent of XtCompressMultiple - no compression + of Expose events across non-Expose events) + + * gdk/gdk.h gdk/gdkrectangle.c: gdk_rectangle_union() + Find rectangle bounding two rectangles. + + * gtk/gtkstyle.c: Set clip rects for a few extra GC's + in gdk_default_draw_shadow() + Wed Jul 29 16:03:20 EDT 1998 The Rasterman * Fixed drawing functions to handle switching themes on the fly gracefully and look decent. diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index ce969aac75..fc6aa9e30a 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,16 @@ +Wed Jul 29 16:56:07 1998 Owen Taylor + + * gdk/gdk.c: Fairly implementation of expose compression. + (No GraphicsExpose compression yet, always compress + with the equivalent of XtCompressMultiple - no compression + of Expose events across non-Expose events) + + * gdk/gdk.h gdk/gdkrectangle.c: gdk_rectangle_union() + Find rectangle bounding two rectangles. + + * gtk/gtkstyle.c: Set clip rects for a few extra GC's + in gdk_default_draw_shadow() + Wed Jul 29 16:03:20 EDT 1998 The Rasterman * Fixed drawing functions to handle switching themes on the fly gracefully and look decent. diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index ce969aac75..fc6aa9e30a 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,16 @@ +Wed Jul 29 16:56:07 1998 Owen Taylor + + * gdk/gdk.c: Fairly implementation of expose compression. + (No GraphicsExpose compression yet, always compress + with the equivalent of XtCompressMultiple - no compression + of Expose events across non-Expose events) + + * gdk/gdk.h gdk/gdkrectangle.c: gdk_rectangle_union() + Find rectangle bounding two rectangles. + + * gtk/gtkstyle.c: Set clip rects for a few extra GC's + in gdk_default_draw_shadow() + Wed Jul 29 16:03:20 EDT 1998 The Rasterman * Fixed drawing functions to handle switching themes on the fly gracefully and look decent. diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index ce969aac75..fc6aa9e30a 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,16 @@ +Wed Jul 29 16:56:07 1998 Owen Taylor + + * gdk/gdk.c: Fairly implementation of expose compression. + (No GraphicsExpose compression yet, always compress + with the equivalent of XtCompressMultiple - no compression + of Expose events across non-Expose events) + + * gdk/gdk.h gdk/gdkrectangle.c: gdk_rectangle_union() + Find rectangle bounding two rectangles. + + * gtk/gtkstyle.c: Set clip rects for a few extra GC's + in gdk_default_draw_shadow() + Wed Jul 29 16:03:20 EDT 1998 The Rasterman * Fixed drawing functions to handle switching themes on the fly gracefully and look decent. diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index ce969aac75..fc6aa9e30a 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,16 @@ +Wed Jul 29 16:56:07 1998 Owen Taylor + + * gdk/gdk.c: Fairly implementation of expose compression. + (No GraphicsExpose compression yet, always compress + with the equivalent of XtCompressMultiple - no compression + of Expose events across non-Expose events) + + * gdk/gdk.h gdk/gdkrectangle.c: gdk_rectangle_union() + Find rectangle bounding two rectangles. + + * gtk/gtkstyle.c: Set clip rects for a few extra GC's + in gdk_default_draw_shadow() + Wed Jul 29 16:03:20 EDT 1998 The Rasterman * Fixed drawing functions to handle switching themes on the fly gracefully and look decent. diff --git a/gdk/gdk.c b/gdk/gdk.c index 603a77819c..597ab043a8 100644 --- a/gdk/gdk.c +++ b/gdk/gdk.c @@ -749,6 +749,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 @@ -840,6 +1028,7 @@ gdk_event_get (void) #else XNextEvent (gdk_display, &xevent); #endif + event = gdk_event_new (); event->any.type = GDK_NOTHING; @@ -2532,6 +2721,8 @@ gdk_event_translate (GdkEvent *event, 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; event->expose.area.x = xevent->xexpose.x; diff --git a/gdk/gdk.h b/gdk/gdk.h index 1b20af7590..9a39d990ae 100644 --- a/gdk/gdk.h +++ b/gdk/gdk.h @@ -684,6 +684,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 */ 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/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c index 603a77819c..597ab043a8 100644 --- a/gdk/x11/gdkmain-x11.c +++ b/gdk/x11/gdkmain-x11.c @@ -749,6 +749,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 @@ -840,6 +1028,7 @@ gdk_event_get (void) #else XNextEvent (gdk_display, &xevent); #endif + event = gdk_event_new (); event->any.type = GDK_NOTHING; @@ -2532,6 +2721,8 @@ gdk_event_translate (GdkEvent *event, 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; event->expose.area.x = xevent->xexpose.x; diff --git a/gtk/gtkstyle.c b/gtk/gtkstyle.c index b9ee03b999..6076c9d6f0 100644 --- a/gtk/gtkstyle.c +++ b/gtk/gtkstyle.c @@ -1207,6 +1207,12 @@ gtk_default_draw_shadow (GtkStyle *style, { gdk_gc_set_clip_rectangle (gc1, area); gdk_gc_set_clip_rectangle (gc2, area); + if ((shadow_type == GTK_SHADOW_IN) || + (shadow_type == GTK_SHADOW_OUT)) + { + gdk_gc_set_clip_rectangle (style->black_gc, area); + gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area); + } } switch (shadow_type) { @@ -1317,6 +1323,12 @@ gtk_default_draw_shadow (GtkStyle *style, { gdk_gc_set_clip_rectangle (gc1, NULL); gdk_gc_set_clip_rectangle (gc2, NULL); + if ((shadow_type == GTK_SHADOW_IN) || + (shadow_type == GTK_SHADOW_OUT)) + { + gdk_gc_set_clip_rectangle (style->black_gc, NULL); + gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL); + } } }