gdk_window_compute_position (impl, &parent_pos, &impl->position_info);
}
+static void
+gdk_window_copy_area_scroll (GdkWindow *window,
+ GdkRectangle *dest_rect,
+ gint dx,
+ gint dy)
+{
+ GdkWindowObject *obj = GDK_WINDOW_OBJECT (window);
+ GList *tmp_list;
+
+ if (dest_rect->width > 0 && dest_rect->height > 0)
+ {
+ GC gc;
+ XGCValues values;
+
+ values.graphics_exposures = True;
+ gc = XCreateGC (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ GCGraphicsExposures, &values);
+
+ gdk_window_queue_translation (window, dx, dy);
+
+ XCopyArea (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ GDK_WINDOW_XID (window),
+ gc,
+ dest_rect->x - dx, dest_rect->y - dy,
+ dest_rect->width, dest_rect->height,
+ dest_rect->x, dest_rect->y);
+
+ XFreeGC (GDK_WINDOW_XDISPLAY (window), gc);
+ }
+
+ tmp_list = obj->children;
+ while (tmp_list)
+ {
+ GdkWindow *child = GDK_WINDOW (tmp_list->data);
+ GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
+
+ gdk_window_move (child, child_obj->x + dx, child_obj->y + dy);
+
+ tmp_list = tmp_list->next;
+ }
+}
+
+static void
+compute_intermediate_position (GdkXPositionInfo *position_info,
+ GdkXPositionInfo *new_info,
+ gint d_xoffset,
+ gint d_yoffset,
+ GdkRectangle *new_position)
+{
+ gint new_x0, new_x1, new_y0, new_y1;
+
+ /* Wrap d_xoffset, d_yoffset into [-32768,32767] range. For the
+ * purposes of subwindow movement, it doesn't matter if we are
+ * off by a factor of 65536, and if we don't do this range
+ * reduction, we'll end up with invalid widths.
+ */
+ d_xoffset = (gint16)d_xoffset;
+ d_yoffset = (gint16)d_yoffset;
+
+ if (d_xoffset < 0)
+ {
+ new_x0 = position_info->x + d_xoffset;
+ new_x1 = position_info->x + position_info->width;
+ }
+ else
+ {
+ new_x0 = position_info->x;
+ new_x1 = position_info->x + new_info->width + d_xoffset;
+ }
+
+ new_position->x = new_x0;
+ new_position->width = new_x1 - new_x0;
+
+ if (d_yoffset < 0)
+ {
+ new_y0 = position_info->y + d_yoffset;
+ new_y1 = position_info->y + position_info->height;
+ }
+ else
+ {
+ new_y0 = position_info->y;
+ new_y1 = position_info->y + new_info->height + d_yoffset;
+ }
+
+ new_position->y = new_y0;
+ new_position->height = new_y1 - new_y0;
+}
+
+static void
+gdk_window_guffaw_scroll (GdkWindow *window,
+ gint dx,
+ gint dy)
+{
+ GdkWindowObject *obj = GDK_WINDOW_OBJECT (window);
+ GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (obj->impl);
+
+ gint d_xoffset = -dx;
+ gint d_yoffset = -dy;
+ GdkRectangle new_position;
+ GdkXPositionInfo new_info;
+ GdkWindowParentPos parent_pos;
+ GList *tmp_list;
+
+ gdk_window_compute_parent_pos (impl, &parent_pos);
+ gdk_window_compute_position (impl, &parent_pos, &new_info);
+
+ parent_pos.x += obj->x;
+ parent_pos.y += obj->y;
+ parent_pos.x11_x += new_info.x;
+ parent_pos.x11_y += new_info.y;
+ parent_pos.clip_rect = new_info.clip_rect;
+
+ gdk_window_tmp_unset_bg (window);
+
+ if (d_xoffset < 0 || d_yoffset < 0)
+ gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
+
+ gdk_window_set_static_gravities (window, TRUE);
+
+ compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
+ &new_position);
+
+ XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ new_position.x, new_position.y, new_position.width, new_position.height);
+
+ tmp_list = obj->children;
+ while (tmp_list)
+ {
+ GDK_WINDOW_OBJECT(tmp_list->data)->x -= d_xoffset;
+ GDK_WINDOW_OBJECT(tmp_list->data)->y -= d_yoffset;
+
+ gdk_window_premove (tmp_list->data, &parent_pos);
+ tmp_list = tmp_list->next;
+ }
+
+ XMoveWindow (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ new_position.x - d_xoffset, new_position.y - d_yoffset);
+
+ if (d_xoffset > 0 || d_yoffset > 0)
+ gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
+
+ XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ impl->position_info.x, impl->position_info.y,
+ impl->position_info.width, impl->position_info.height);
+
+ if (impl->position_info.no_bg)
+ gdk_window_tmp_reset_bg (window);
+
+ impl->position_info = new_info;
+
+ tmp_list = obj->children;
+ while (tmp_list)
+ {
+ gdk_window_postmove (tmp_list->data, &parent_pos);
+ tmp_list = tmp_list->next;
+ }
+}
+
/**
* gdk_window_scroll:
* @window: a #GdkWindow
gint dy)
{
gboolean can_guffaw_scroll = FALSE;
+ GdkRegion *invalidate_region;
GdkWindowImplX11 *impl;
GdkWindowObject *obj;
+ GdkRectangle dest_rect;
g_return_if_fail (GDK_IS_WINDOW (window));
- obj = GDK_WINDOW_OBJECT (window);
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+ obj = GDK_WINDOW_OBJECT (window);
impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
- if (GDK_WINDOW_DESTROYED (window))
+
+ if (dx == 0 && dy == 0)
return;
/* Move the current invalid region */
if (obj->update_area)
gdk_region_offset (obj->update_area, dx, dy);
+ invalidate_region = gdk_region_rectangle (&impl->position_info.clip_rect);
+
+ dest_rect = impl->position_info.clip_rect;
+ dest_rect.x += dx;
+ dest_rect.y += dy;
+ gdk_rectangle_intersect (&dest_rect, &impl->position_info.clip_rect, &dest_rect);
+
+ if (dest_rect.width > 0 && dest_rect.height > 0)
+ {
+ GdkRegion *tmp_region;
+
+ tmp_region = gdk_region_rectangle (&dest_rect);
+ gdk_region_subtract (invalidate_region, tmp_region);
+ gdk_region_destroy (tmp_region);
+ }
+
+ gdk_window_invalidate_region (window, invalidate_region, TRUE);
+ gdk_region_destroy (invalidate_region);
+
/* We can guffaw scroll if we are a child window, and the parent
- * does not extend beyond our edges.
+ * does not extend beyond our edges. Otherwise, we use XCopyArea, then
+ * move any children later
*/
-
if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
{
GdkWindowImplX11 *parent_impl = GDK_WINDOW_IMPL_X11 (obj->parent->impl);
- can_guffaw_scroll = (obj->x <= 0 &&
- obj->y <= 0 &&
- obj->x + impl->width >= parent_impl->width &&
- obj->y + impl->height >= parent_impl->height);
+ can_guffaw_scroll = ((dx == 0 || (obj->x <= 0 && obj->x + impl->width >= parent_impl->width)) &&
+ (dy == 0 || (obj->y <= 0 && obj->y + impl->height >= parent_impl->height)));
}
if (!obj->children || !can_guffaw_scroll)
- {
- /* Use XCopyArea, then move any children later
- */
- GList *tmp_list;
- GdkRegion *invalidate_region;
- GdkRectangle dest_rect;
-
- invalidate_region = gdk_region_rectangle (&impl->position_info.clip_rect);
-
- dest_rect = impl->position_info.clip_rect;
- dest_rect.x += dx;
- dest_rect.y += dy;
- gdk_rectangle_intersect (&dest_rect, &impl->position_info.clip_rect, &dest_rect);
-
- if (dest_rect.width > 0 && dest_rect.height > 0)
- {
- GC gc;
- XGCValues values;
- GdkRegion *tmp_region;
-
- tmp_region = gdk_region_rectangle (&dest_rect);
- gdk_region_subtract (invalidate_region, tmp_region);
- gdk_region_destroy (tmp_region);
-
- gdk_window_queue_translation (window, dx, dy);
-
- values.graphics_exposures = True;
- gc = XCreateGC (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- GCGraphicsExposures, &values);
-
- XCopyArea (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- GDK_WINDOW_XID (window),
- gc,
- dest_rect.x - dx, dest_rect.y - dy,
- dest_rect.width, dest_rect.height,
- dest_rect.x, dest_rect.y);
-
- XFreeGC (GDK_WINDOW_XDISPLAY (window), gc);
- }
-
- gdk_window_invalidate_region (window, invalidate_region, TRUE);
- gdk_region_destroy (invalidate_region);
-
- tmp_list = obj->children;
- while (tmp_list)
- {
- GdkWindow * child = GDK_WINDOW (tmp_list->data);
-
- gdk_window_move (child, obj->x + dx, obj->y + dy);
-
- tmp_list = tmp_list->next;
- }
- }
+ gdk_window_copy_area_scroll (window, &dest_rect, dx, dy);
else
- {
- /* Guffaw scroll
- */
- g_warning ("gdk_window_scroll(): guffaw scrolling not yet implemented");
- }
+ gdk_window_guffaw_scroll (window, dx, dy);
}
void
if (d_xoffset != 0 || d_yoffset != 0)
{
- gint new_x0, new_y0, new_x1, new_y1;
+ GdkRectangle new_position;
gdk_window_set_static_gravities (window, TRUE);
if (d_xoffset < 0 || d_yoffset < 0)
gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
-
- if (d_xoffset < 0)
- {
- new_x0 = impl->position_info.x + d_xoffset;
- new_x1 = impl->position_info.x + impl->position_info.width;
- }
- else
- {
- new_x0 = impl->position_info.x;
- new_x1 = impl->position_info.x + new_info.width + d_xoffset;
- }
- if (d_yoffset < 0)
- {
- new_y0 = impl->position_info.y + d_yoffset;
- new_y1 = impl->position_info.y + impl->position_info.height;
- }
- else
- {
- new_y0 = impl->position_info.y;
- new_y1 = impl->position_info.y + new_info.height + d_yoffset;
- }
+ compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
+ &new_position);
XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
- new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0);
+ new_position.x, new_position.y, new_position.width, new_position.height);
tmp_list = obj->children;
while (tmp_list)
XMoveWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
- new_x0 + dx, new_y0 + dy);
+ new_position.x + dx, new_position.y + dy);
if (d_xoffset > 0 || d_yoffset > 0)
gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
info->big = FALSE;
- if (window->width <= 32768)
+ if (window->width <= 32767)
{
info->width = window->width;
info->x = parent_pos->x + wrapper->x - parent_pos->x11_x;
else
{
info->big = TRUE;
- info->width = 32768;
+ info->width = 32767;
if (parent_pos->x + wrapper->x < -16384)
{
if (parent_pos->x + wrapper->x + window->width < 16384)
- info->x = parent_pos->x + wrapper->x + window->width - 32768 - parent_pos->x11_x;
+ info->x = parent_pos->x + wrapper->x + window->width - info->width - parent_pos->x11_x;
else
info->x = -16384 - parent_pos->x11_y;
}
info->x = parent_pos->x + wrapper->x - parent_pos->x11_x;
}
- if (window->height <= 32768)
+ if (window->height <= 32767)
{
info->height = window->height;
info->y = parent_pos->y + wrapper->y - parent_pos->x11_y;
else
{
info->big = TRUE;
- info->height = 32768;
+ info->height = 32767;
if (parent_pos->y + wrapper->y < -16384)
{
if (parent_pos->y + wrapper->y + window->height < 16384)
- info->y = parent_pos->y + wrapper->y + window->height - 32768 - parent_pos->x11_y;
+ info->y = parent_pos->y + wrapper->y + window->height - info->height - parent_pos->x11_y;
else
info->y = -16384 - parent_pos->x11_y;
}
if (d_xoffset != 0 || d_yoffset != 0)
{
- gint new_x0, new_y0, new_x1, new_y1;
+ GdkRectangle new_position;
if (d_xoffset < 0 || d_yoffset < 0)
gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
-
- if (d_xoffset < 0)
- {
- new_x0 = impl->position_info.x + d_xoffset;
- new_x1 = impl->position_info.x + impl->position_info.width;
- }
- else
- {
- new_x0 = impl->position_info.x;
- new_x1 = impl->position_info.x + new_info.width + d_xoffset;
- }
- if (d_yoffset < 0)
- {
- new_y0 = impl->position_info.y + d_yoffset;
- new_y1 = impl->position_info.y + impl->position_info.height;
- }
- else
- {
- new_y0 = impl->position_info.y;
- new_y1 = impl->position_info.y + new_info.height + d_yoffset;
- }
+ compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
+ &new_position);
XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window),
- new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0);
+ new_position.x, new_position.y, new_position.width, new_position.height);
}
tmp_list = obj->children;
old_clip_region = gdk_region_rectangle (old_clip);
new_clip_region = gdk_region_rectangle (new_clip);
+ /* We need to update this here because gdk_window_invalidate_region makes
+ * use if it (through gdk_drawable_get_visible_region
+ */
+ impl->position_info.clip_rect = *new_clip;
+
/* Trim invalid region of window to new clip rectangle
*/
if (obj->update_area)
gdk_region_destroy (new_clip_region);
gdk_region_destroy (old_clip_region);
}
-
*window = NULL;
}
+
+/*
+ * Big windows and guffaw scrolling
+ */
+
+static gboolean
+pattern_expose (GtkWidget *widget,
+ GdkEventExpose *event,
+ gpointer data)
+{
+ GdkColor *color;
+ GdkWindow *window = event->window;
+
+ color = g_object_get_data (G_OBJECT (window), "pattern-color");
+ if (color)
+ {
+ GdkGC *tmp_gc = gdk_gc_new (window);
+ gdk_gc_set_rgb_fg_color (tmp_gc, color);
+
+ gdk_draw_rectangle (window, tmp_gc, TRUE,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+ g_object_unref (G_OBJECT (tmp_gc));
+ }
+
+ return FALSE;
+}
+
+static void
+pattern_set_bg (GtkWidget *widget,
+ GdkWindow *child,
+ gint level)
+{
+ static const GdkColor colors[] = {
+ { 0, 0x4444, 0x4444, 0xffff },
+ { 0, 0x8888, 0x8888, 0xffff },
+ { 0, 0xaaaa, 0xaaaa, 0xffff }
+ };
+
+ g_object_set_data (G_OBJECT (child), "pattern-color", (gpointer)&colors[level]);
+ gdk_window_set_user_data (child, widget);
+}
+
+static void
+create_pattern (GtkWidget *widget,
+ GdkWindow *parent,
+ gint level,
+ gint width,
+ gint height)
+{
+ gint h = 1;
+ gint i = 0;
+
+ GdkWindow *child;
+
+ while (2 * h <= height)
+ {
+ gint w = 1;
+ gint j = 0;
+
+ while (2 * w <= width)
+ {
+ if ((i + j) % 2 == 0)
+ {
+ gint x = w - 1;
+ gint y = h - 1;
+
+ GdkWindowAttr attributes;
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = x;
+ attributes.y = y;
+ attributes.width = w;
+ attributes.height = h;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.event_mask = GDK_EXPOSURE_MASK;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+
+ child = gdk_window_new (parent, &attributes,
+ GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP);
+
+ pattern_set_bg (widget, child, level);
+
+ if (level < 2)
+ create_pattern (widget, child, level + 1, w, h);
+
+ gdk_window_show (child);
+ }
+ j++;
+ w *= 2;
+ }
+ i++;
+ h *= 2;
+ }
+}
+
+#define PATTERN_SIZE (1 << 18)
+
+static void
+pattern_hadj_changed (GtkAdjustment *adj,
+ GtkWidget *darea)
+{
+ gint *old_value = g_object_get_data (G_OBJECT (adj), "old-value");
+ gint new_value = adj->value;
+
+ if (GTK_WIDGET_REALIZED (darea))
+ {
+ gdk_window_scroll (darea->window, *old_value - new_value, 0);
+ *old_value = new_value;
+ }
+}
+
+static void
+pattern_vadj_changed (GtkAdjustment *adj,
+ GtkWidget *darea)
+{
+ gint *old_value = g_object_get_data (G_OBJECT (adj), "old-value");
+ gint new_value = adj->value;
+
+ if (GTK_WIDGET_REALIZED (darea))
+ {
+ gdk_window_scroll (darea->window, 0, *old_value - new_value);
+ *old_value = new_value;
+ }
+}
+
+static void
+pattern_realize (GtkWidget *widget,
+ gpointer data)
+{
+ pattern_set_bg (widget, widget->window, 0);
+ create_pattern (widget, widget->window, 1, PATTERN_SIZE, PATTERN_SIZE);
+}
+
+static void
+create_big_windows (void)
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *darea, *table, *scrollbar;
+ GtkWidget *eventbox;
+ GtkAdjustment *hadj;
+ GtkAdjustment *vadj;
+ static gint current_x;
+ static gint current_y;
+
+ if (!window)
+ {
+ current_x = 0;
+ current_y = 0;
+
+ window = gtk_dialog_new_with_buttons ("Big Windows",
+ NULL, 0,
+ GTK_STOCK_CLOSE,
+ GTK_RESPONSE_NONE,
+ NULL);
+
+ gtk_window_set_default_size (GTK_WINDOW (window), 200, 300);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+ &window);
+
+ gtk_signal_connect (GTK_OBJECT (window), "response",
+ GTK_SIGNAL_FUNC (gtk_widget_destroy),
+ NULL);
+
+ table = gtk_table_new (2, 2, FALSE);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
+ table, TRUE, TRUE, 0);
+
+ darea = gtk_drawing_area_new ();
+
+ hadj = (GtkAdjustment *)gtk_adjustment_new (0, 0, PATTERN_SIZE, 10, 100, 100);
+ gtk_signal_connect (GTK_OBJECT (hadj), "value_changed",
+ GTK_SIGNAL_FUNC (pattern_hadj_changed), darea);
+ g_object_set_data (G_OBJECT (hadj), "old-value", ¤t_x);
+
+ vadj = (GtkAdjustment *)gtk_adjustment_new (0, 0, PATTERN_SIZE, 10, 100, 100);
+ gtk_signal_connect (GTK_OBJECT (vadj), "value_changed",
+ GTK_SIGNAL_FUNC (pattern_vadj_changed), darea);
+ g_object_set_data (G_OBJECT (vadj), "old-value", ¤t_y);
+
+ gtk_signal_connect (GTK_OBJECT (darea), "realize",
+ GTK_SIGNAL_FUNC (pattern_realize),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (darea), "expose_event",
+ GTK_SIGNAL_FUNC (pattern_expose),
+ NULL);
+
+ eventbox = gtk_event_box_new ();
+ gtk_table_attach (GTK_TABLE (table), eventbox,
+ 0, 1, 0, 1,
+ GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND,
+ 0, 0);
+
+ gtk_container_add (GTK_CONTAINER (eventbox), darea);
+
+ scrollbar = gtk_hscrollbar_new (hadj);
+ gtk_table_attach (GTK_TABLE (table), scrollbar,
+ 0, 1, 1, 2,
+ GTK_FILL | GTK_EXPAND, GTK_FILL,
+ 0, 0);
+
+ scrollbar = gtk_vscrollbar_new (vadj);
+ gtk_table_attach (GTK_TABLE (table), scrollbar,
+ 1, 2, 0, 1,
+ GTK_FILL, GTK_EXPAND | GTK_FILL,
+ 0, 0);
+
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show_all (window);
+ else
+ gtk_widget_hide (window);
+}
+
/*
* GtkButton
*/
gboolean do_not_benchmark;
} buttons[] =
{
+ { "big windows", create_big_windows },
{ "button box", create_button_box },
{ "buttons", create_buttons },
{ "check buttons", create_check_buttons },