From 8098546227671a5d082fdf8f4811ee3ffca7f6d8 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Tue, 28 Mar 2000 01:24:44 +0000 Subject: Merge no-flicker branch into HEAD --- gtk/gtklayout.c | 530 ++------------------------------------------------------ 1 file changed, 12 insertions(+), 518 deletions(-) (limited to 'gtk/gtklayout.c') diff --git a/gtk/gtklayout.c b/gtk/gtklayout.c index bd21eead61..a57e52df1d 100644 --- a/gtk/gtklayout.c +++ b/gtk/gtklayout.c @@ -30,33 +30,18 @@ #include "gdkconfig.h" -#if defined (GDK_WINDOWING_X11) -#include "x11/gdkx.h" -#elif defined (GDK_WINDOWING_WIN32) -#include "win32/gdkwin32.h" -#endif - #include "gtklayout.h" #include "gtksignal.h" #include "gtkprivate.h" -typedef struct _GtkLayoutAdjData GtkLayoutAdjData; typedef struct _GtkLayoutChild GtkLayoutChild; -struct _GtkLayoutAdjData { - gint dx; - gint dy; -}; - struct _GtkLayoutChild { GtkWidget *widget; gint x; gint y; }; -#define IS_ONSCREEN(x,y) ((x >= G_MINSHORT) && (x <= G_MAXSHORT) && \ - (y >= G_MINSHORT) && (y <= G_MAXSHORT)) - static void gtk_layout_class_init (GtkLayoutClass *class); static void gtk_layout_init (GtkLayout *layout); @@ -83,33 +68,14 @@ static void gtk_layout_set_adjustments (GtkLayout *layout, GtkAdjustment *hadj, GtkAdjustment *vadj); -static void gtk_layout_position_child (GtkLayout *layout, - GtkLayoutChild *child); static void gtk_layout_allocate_child (GtkLayout *layout, GtkLayoutChild *child); -static void gtk_layout_position_children (GtkLayout *layout); - -static void gtk_layout_adjust_allocations_recurse (GtkWidget *widget, - gpointer cb_data); -static void gtk_layout_adjust_allocations (GtkLayout *layout, - gint dx, - gint dy); - -static void gtk_layout_expose_area (GtkLayout *layout, - gint x, - gint y, - gint width, - gint height); static void gtk_layout_adjustment_changed (GtkAdjustment *adjustment, GtkLayout *layout); -static GdkFilterReturn gtk_layout_main_filter (GdkXEvent *gdk_xevent, - GdkEvent *event, - gpointer data); static GtkWidgetClass *parent_class = NULL; -static gboolean gravity_works; /* Public interface */ @@ -261,9 +227,6 @@ gtk_layout_put (GtkLayout *layout, if (GTK_WIDGET_REALIZED (layout)) gtk_widget_set_parent_window (child->widget, layout->bin_window); - if (!IS_ONSCREEN (x, y)) - GTK_PRIVATE_SET_FLAG (child_widget, GTK_IS_OFFSCREEN); - if (GTK_WIDGET_REALIZED (layout)) gtk_widget_realize (child_widget); @@ -323,6 +286,9 @@ gtk_layout_set_size (GtkLayout *layout, layout->vadjustment->upper = layout->height; gtk_signal_emit_by_name (GTK_OBJECT (layout->vadjustment), "changed"); + + if (GTK_WIDGET_REALIZED (layout)) + gdk_window_resize (layout->bin_window, width, height); } void @@ -342,10 +308,7 @@ gtk_layout_thaw (GtkLayout *layout) if (layout->freeze_count) if (!(--layout->freeze_count)) - { - gtk_layout_position_children (layout); - gtk_widget_draw (GTK_WIDGET (layout), NULL); - } + gtk_widget_draw (GTK_WIDGET (layout), NULL); } /* Basic Object handling procedures @@ -467,7 +430,9 @@ gtk_layout_realize (GtkWidget *widget) attributes.x = 0; attributes.y = 0; - attributes.event_mask = GDK_EXPOSURE_MASK | GDK_SCROLL_MASK | + attributes.width = layout->width; + attributes.height = layout->height; + attributes.event_mask = GDK_EXPOSURE_MASK | GDK_SCROLL_MASK | gtk_widget_get_events (widget); layout->bin_window = gdk_window_new (widget->window, @@ -478,15 +443,6 @@ gtk_layout_realize (GtkWidget *widget) gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); gtk_style_set_background (widget->style, layout->bin_window, GTK_STATE_NORMAL); - gdk_window_add_filter (widget->window, gtk_layout_main_filter, layout); - /* gdk_window_add_filter (layout->bin_window, gtk_layout_filter, layout);*/ - - /* XXX: If we ever get multiple displays for GTK+, then gravity_works - * will have to become a widget member. Right now we just - * keep it as a global - */ - gravity_works = gdk_window_set_static_gravities (layout->bin_window, TRUE); - tmp_list = layout->children; while (tmp_list) { @@ -595,7 +551,6 @@ gtk_layout_size_allocate (GtkWidget *widget, GtkLayoutChild *child = tmp_list->data; tmp_list = tmp_list->next; - gtk_layout_position_child (layout, child); gtk_layout_allocate_child (layout, child); } @@ -604,9 +559,6 @@ gtk_layout_size_allocate (GtkWidget *widget, gdk_window_move_resize (widget->window, allocation->x, allocation->y, allocation->width, allocation->height); - gdk_window_move_resize (GTK_LAYOUT(widget)->bin_window, - 0, 0, - allocation->width, allocation->height); } layout->hadjustment->page_size = allocation->width; @@ -748,38 +700,6 @@ gtk_layout_forall (GtkContainer *container, /* Operations on children */ -static void -gtk_layout_position_child (GtkLayout *layout, - GtkLayoutChild *child) -{ - gint x; - gint y; - - x = child->x - layout->xoffset; - y = child->y - layout->yoffset; - - if (IS_ONSCREEN (x,y)) - { - if (GTK_WIDGET_MAPPED (layout) && - GTK_WIDGET_VISIBLE (child->widget)) - { - if (!GTK_WIDGET_MAPPED (child->widget)) - gtk_widget_map (child->widget); - } - - if (GTK_WIDGET_IS_OFFSCREEN (child->widget)) - GTK_PRIVATE_UNSET_FLAG (child->widget, GTK_IS_OFFSCREEN); - } - else - { - if (!GTK_WIDGET_IS_OFFSCREEN (child->widget)) - GTK_PRIVATE_SET_FLAG (child->widget, GTK_IS_OFFSCREEN); - - if (GTK_WIDGET_MAPPED (child->widget)) - gtk_widget_unmap (child->widget); - } -} - static void gtk_layout_allocate_child (GtkLayout *layout, GtkLayoutChild *child) @@ -796,451 +716,25 @@ gtk_layout_allocate_child (GtkLayout *layout, gtk_widget_size_allocate (child->widget, &allocation); } -static void -gtk_layout_position_children (GtkLayout *layout) -{ - GList *tmp_list; - - tmp_list = layout->children; - while (tmp_list) - { - GtkLayoutChild *child = tmp_list->data; - tmp_list = tmp_list->next; - - gtk_layout_position_child (layout, child); - } -} - -static void -gtk_layout_adjust_allocations_recurse (GtkWidget *widget, - gpointer cb_data) -{ - GtkLayoutAdjData *data = cb_data; - - widget->allocation.x += data->dx; - widget->allocation.y += data->dy; - - if (GTK_WIDGET_NO_WINDOW (widget) && - GTK_IS_CONTAINER (widget)) - gtk_container_forall (GTK_CONTAINER (widget), - gtk_layout_adjust_allocations_recurse, - cb_data); -} - -static void -gtk_layout_adjust_allocations (GtkLayout *layout, - gint dx, - gint dy) -{ - GList *tmp_list; - GtkLayoutAdjData data; - - data.dx = dx; - data.dy = dy; - - tmp_list = layout->children; - while (tmp_list) - { - GtkLayoutChild *child = tmp_list->data; - tmp_list = tmp_list->next; - - child->widget->allocation.x += dx; - child->widget->allocation.y += dy; - - if (GTK_WIDGET_NO_WINDOW (child->widget) && - GTK_IS_CONTAINER (child->widget)) - gtk_container_forall (GTK_CONTAINER (child->widget), - gtk_layout_adjust_allocations_recurse, - &data); - } -} - /* Callbacks */ -/* Send a synthetic expose event to the widget - */ -static void -gtk_layout_expose_area (GtkLayout *layout, - gint x, gint y, gint width, gint height) -{ - if (layout->visibility == GDK_VISIBILITY_UNOBSCURED) - { - GdkEventExpose event; - - event.type = GDK_EXPOSE; - event.send_event = TRUE; - event.window = layout->bin_window; - event.count = 0; - - event.area.x = x; - event.area.y = y; - event.area.width = width; - event.area.height = height; - - gdk_window_ref (event.window); - gtk_widget_event (GTK_WIDGET (layout), (GdkEvent *)&event); - gdk_window_unref (event.window); - } -} - -#ifdef GDK_WINDOWING_X11 - -/* This function is used to find events to process while scrolling - */ - -static Bool -gtk_layout_expose_predicate (Display *display, - XEvent *xevent, - XPointer arg) -{ - if ((xevent->type == Expose) || - ((xevent->xany.window == *(Window *)arg) && - (xevent->type == ConfigureNotify))) - return True; - else - return False; -} - -#endif /* X11 */ - -/* This is the main routine to do the scrolling. Scrolling is - * done by "Guffaw" scrolling, as in the Mozilla XFE, with - * a few modifications. - * - * The main improvement is that we keep track of whether we - * are obscured or not. If not, we ignore the generated expose - * events and instead do the exposes ourself, without having - * to wait for a roundtrip to the server. This also provides - * a limited form of expose-event compression, since we do - * the affected area as one big chunk. - * - * Real expose event compression, as in the XFE, could be added - * here. It would help opaque drags over the region, and the - * obscured case. - * - * Code needs to be added here to do the scrolling on machines - * that don't have working WindowGravity. That could be done - * - * - XCopyArea and move the windows, and accept trailing the - * background color. (Since it is only a fallback method) - * - XmHTML style. As above, but turn off expose events when - * not obscured and do the exposures ourself. - * - gzilla-style. Move the window continuously, and reset - * every 32768 pixels - */ - static void gtk_layout_adjustment_changed (GtkAdjustment *adjustment, GtkLayout *layout) { GtkWidget *widget; -#ifdef GDK_WINDOWING_X11 - XEvent xevent; -#endif - gint dx, dy; widget = GTK_WIDGET (layout); - dx = (gint)layout->hadjustment->value - layout->xoffset; - dy = (gint)layout->vadjustment->value - layout->yoffset; - - layout->xoffset = (gint)layout->hadjustment->value; - layout->yoffset = (gint)layout->vadjustment->value; - if (layout->freeze_count) return; - if (!GTK_WIDGET_MAPPED (layout)) - { - gtk_layout_position_children (layout); - return; - } - - gtk_layout_adjust_allocations (layout, -dx, -dy); - - if (dx > 0) - { - if (gravity_works) - { - gdk_window_resize (layout->bin_window, - widget->allocation.width + dx, - widget->allocation.height); - gdk_window_move (layout->bin_window, -dx, 0); - gdk_window_move_resize (layout->bin_window, - 0, 0, - widget->allocation.width, - widget->allocation.height); - } - else - { - /* FIXME */ - } - - gtk_layout_expose_area (layout, - MAX ((gint)widget->allocation.width - dx, 0), - 0, - MIN (dx, widget->allocation.width), - widget->allocation.height); - } - else if (dx < 0) - { - if (gravity_works) - { - gdk_window_move_resize (layout->bin_window, - dx, 0, - widget->allocation.width - dx, - widget->allocation.height); - gdk_window_move (layout->bin_window, 0, 0); - gdk_window_resize (layout->bin_window, - widget->allocation.width, - widget->allocation.height); - } - else - { - /* FIXME */ - } - - gtk_layout_expose_area (layout, - 0, - 0, - MIN (-dx, widget->allocation.width), - widget->allocation.height); - } - - if (dy > 0) - { - if (gravity_works) - { - gdk_window_resize (layout->bin_window, - widget->allocation.width, - widget->allocation.height + dy); - gdk_window_move (layout->bin_window, 0, -dy); - gdk_window_move_resize (layout->bin_window, - 0, 0, - widget->allocation.width, - widget->allocation.height); - } - else - { - /* FIXME */ - } - - gtk_layout_expose_area (layout, - 0, - MAX ((gint)widget->allocation.height - dy, 0), - widget->allocation.width, - MIN (dy, widget->allocation.height)); - } - else if (dy < 0) - { - if (gravity_works) - { - gdk_window_move_resize (layout->bin_window, - 0, dy, - widget->allocation.width, - widget->allocation.height - dy); - gdk_window_move (layout->bin_window, 0, 0); - gdk_window_resize (layout->bin_window, - widget->allocation.width, - widget->allocation.height); - } - else - { - /* FIXME */ - } - gtk_layout_expose_area (layout, - 0, - 0, - widget->allocation.width, - MIN (-dy, (gint)widget->allocation.height)); - } - - gtk_layout_position_children (layout); - - /* We have to make sure that all exposes from this scroll get - * processed before we scroll again, or the expose events will - * have invalid coordinates. - * - * We also do expose events for other windows, since otherwise - * their updating will fall behind the scrolling - * - * This also avoids a problem in pre-1.0 GTK where filters don't - * have access to configure events that were compressed. - */ - - gdk_flush(); - -#ifdef GDK_WINDOWING_X11 - while (XCheckIfEvent(GDK_WINDOW_XDISPLAY (layout->bin_window), - &xevent, - gtk_layout_expose_predicate, - (XPointer)&GDK_WINDOW_XWINDOW (layout->bin_window))) - { - GdkEvent event; - GtkWidget *event_widget; - - switch (xevent.type) - { - case Expose: - - if (xevent.xany.window == GDK_WINDOW_XWINDOW (layout->bin_window)) - { - /* If the window is unobscured, then we've exposed the - * regions with the following serials already, so we - * can throw out the expose events. - */ - if (layout->visibility == GDK_VISIBILITY_UNOBSCURED && - (((dx > 0 || dy > 0) && - xevent.xexpose.serial == layout->configure_serial) || - ((dx < 0 || dy < 0) && - xevent.xexpose.serial == layout->configure_serial + 1))) - continue; - /* The following expose was generated while the origin was - * different from the current origin, so we need to offset it. - */ - else if (xevent.xexpose.serial == layout->configure_serial) - { - xevent.xexpose.x += layout->scroll_x; - xevent.xexpose.y += layout->scroll_y; - } - event.expose.window = layout->bin_window; - event_widget = widget; - } - else - { - event.expose.window = gdk_window_lookup (xevent.xany.window); - gdk_window_get_user_data (event.expose.window, - (gpointer *)&event_widget); - } - - if (event_widget) - { - event.expose.type = GDK_EXPOSE; - event.expose.area.x = xevent.xexpose.x; - event.expose.area.y = xevent.xexpose.y; - event.expose.area.width = xevent.xexpose.width; - event.expose.area.height = xevent.xexpose.height; - event.expose.count = xevent.xexpose.count; - - gdk_window_ref (event.expose.window); - gtk_widget_event (event_widget, &event); - gdk_window_unref (event.expose.window); - } - break; - - case ConfigureNotify: - if (xevent.xany.window == GDK_WINDOW_XWINDOW (layout->bin_window) && - (xevent.xconfigure.x != 0 || xevent.xconfigure.y != 0)) - { - layout->configure_serial = xevent.xconfigure.serial; - layout->scroll_x = xevent.xconfigure.x; - layout->scroll_y = xevent.xconfigure.y; - } - break; - } - } -#elif defined (GDK_WINDOWING_WIN32) - /* XXX Not implemented */ -#endif -} - -#if 0 -/* The main event filter. Actually, we probably don't really need - * this filter at all, since we are calling it directly above in the - * expose-handling hack. But in case scrollbars - * are fixed up in some manner... - * - * This routine identifies expose events that are generated when - * we've temporarily moved the bin_window_origin, and translates - * them or discards them, depending on whether we are obscured - * or not. - */ -static GdkFilterReturn -gtk_layout_filter (GdkXEvent *gdk_xevent, - GdkEvent *event, - gpointer data) -{ -#ifdef GDK_WINDOWING_X11 - - XEvent *xevent; - GtkLayout *layout; - - xevent = (XEvent *)gdk_xevent; - layout = GTK_LAYOUT (data); - - switch (xevent->type) + if (GTK_WIDGET_REALIZED (layout)) { - case Expose: - if (xevent->xexpose.serial == layout->configure_serial) - { - if (layout->visibility == GDK_VISIBILITY_UNOBSCURED) - return GDK_FILTER_REMOVE; - else - { - xevent->xexpose.x += layout->scroll_x; - xevent->xexpose.y += layout->scroll_y; - - break; - } - } - break; + gdk_window_move (layout->bin_window, + - layout->hadjustment->value, + - layout->vadjustment->value); - case ConfigureNotify: - if ((xevent->xconfigure.x != 0) || (xevent->xconfigure.y != 0)) - { - layout->configure_serial = xevent->xconfigure.serial; - layout->scroll_x = xevent->xconfigure.x; - layout->scroll_y = xevent->xconfigure.y; - } - break; - } -#elif defined (GDK_WINDOWING_WIN32) - /* XXX Not implemented */ -#endif - - return GDK_FILTER_CONTINUE; -} -#endif 0 - -/* Although GDK does have a GDK_VISIBILITY_NOTIFY event, - * there is no corresponding event in GTK, so we have - * to get the events from a filter - */ -static GdkFilterReturn -gtk_layout_main_filter (GdkXEvent *gdk_xevent, - GdkEvent *event, - gpointer data) -{ -#ifdef GDK_WINDOWING_X11 - XEvent *xevent; - GtkLayout *layout; - - xevent = (XEvent *)gdk_xevent; - layout = GTK_LAYOUT (data); - - if (xevent->type == VisibilityNotify) - { - switch (xevent->xvisibility.state) - { - case VisibilityFullyObscured: - layout->visibility = GDK_VISIBILITY_FULLY_OBSCURED; - break; - - case VisibilityPartiallyObscured: - layout->visibility = GDK_VISIBILITY_PARTIAL; - break; - - case VisibilityUnobscured: - layout->visibility = GDK_VISIBILITY_UNOBSCURED; - break; - } - - return GDK_FILTER_REMOVE; + gdk_window_process_updates (layout->bin_window, TRUE); } -#elif defined (GDK_WINDOWING_WIN32) - /* XXX Not implemented */ -#endif - - return GDK_FILTER_CONTINUE; } - -- cgit v1.2.1