summaryrefslogtreecommitdiff
path: root/gtk/gtklayout.c
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@src.gnome.org>2000-03-28 01:24:44 +0000
committerOwen Taylor <otaylor@src.gnome.org>2000-03-28 01:24:44 +0000
commit8098546227671a5d082fdf8f4811ee3ffca7f6d8 (patch)
treed1857c89ee73451cbb04bbf595c0dc8bade55987 /gtk/gtklayout.c
parent4238d406e928d1afd95ab0c6ae51b6a37f9780ea (diff)
downloadgtk+-8098546227671a5d082fdf8f4811ee3ffca7f6d8.tar.gz
Merge no-flicker branch into HEAD
Diffstat (limited to 'gtk/gtklayout.c')
-rw-r--r--gtk/gtklayout.c530
1 files changed, 12 insertions, 518 deletions
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;
@@ -749,38 +701,6 @@ gtk_layout_forall (GtkContainer *container,
*/
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;
}
-