1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 #include "gdk.h" /* For gdk_rectangle_intersect */
22 #include "gdkprivate-x11.h"
24 #include "gdkregion.h"
25 #include "gdkinternals.h"
26 #include "gdkscreen-x11.h"
27 #include "gdkdisplay-x11.h"
28 #include "gdkwindow-x11.h"
31 typedef struct _GdkWindowQueueItem GdkWindowQueueItem;
32 typedef struct _GdkWindowParentPos GdkWindowParentPos;
35 GDK_WINDOW_QUEUE_TRANSLATE,
36 GDK_WINDOW_QUEUE_ANTIEXPOSE
39 struct _GdkWindowQueueItem
43 GdkWindowQueueType type;
57 _gdk_window_move_resize_child (GdkWindow *window,
65 g_return_if_fail (window != NULL);
66 g_return_if_fail (GDK_IS_WINDOW (window));
68 obj = GDK_WINDOW_OBJECT (window);
73 g_warning ("Native children wider or taller than 65535 pixels are not supported");
86 /* We don't really care about origin overflow, because on overflow
87 the window won't be visible anyway and thus it will be shaped
90 _gdk_x11_window_tmp_unset_parent_bg (window);
91 _gdk_x11_window_tmp_unset_bg (window, TRUE);
92 XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
93 GDK_WINDOW_XID (window),
94 obj->x + obj->parent->abs_x,
95 obj->y + obj->parent->abs_y,
97 _gdk_x11_window_tmp_reset_parent_bg (window);
98 _gdk_x11_window_tmp_reset_bg (window, TRUE);
102 expose_serial_predicate (Display *xdisplay,
106 gulong *serial = (gulong *)arg;
108 if (xev->xany.type == Expose || xev->xany.type == GraphicsExpose)
109 *serial = MIN (*serial, xev->xany.serial);
114 /* Find oldest possible serial for an outstanding expose event
117 find_current_serial (Display *xdisplay)
120 gulong serial = NextRequest (xdisplay);
122 XSync (xdisplay, False);
124 XCheckIfEvent (xdisplay, &xev, expose_serial_predicate, (XPointer)&serial);
130 queue_delete_link (GQueue *queue,
133 if (queue->tail == link)
134 queue->tail = link->prev;
136 queue->head = g_list_remove_link (queue->head, link);
137 g_list_free_1 (link);
142 queue_item_free (GdkWindowQueueItem *item)
146 g_object_remove_weak_pointer (G_OBJECT (item->window),
147 (gpointer *)&(item->window));
150 if (item->type == GDK_WINDOW_QUEUE_ANTIEXPOSE)
151 gdk_region_destroy (item->u.antiexpose.area);
154 if (item->u.translate.area)
155 gdk_region_destroy (item->u.translate.area);
162 gdk_window_queue (GdkWindow *window,
163 GdkWindowQueueItem *item)
165 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
167 if (!display_x11->translate_queue)
168 display_x11->translate_queue = g_queue_new ();
170 /* Keep length of queue finite by, if it grows too long,
171 * figuring out the latest relevant serial and discarding
172 * irrelevant queue items.
174 if (display_x11->translate_queue->length >= 64)
176 gulong serial = find_current_serial (GDK_WINDOW_XDISPLAY (window));
177 GList *tmp_list = display_x11->translate_queue->head;
181 GdkWindowQueueItem *item = tmp_list->data;
182 GList *next = tmp_list->next;
184 /* an overflow-safe (item->serial < serial) */
185 if (item->serial - serial > (gulong) G_MAXLONG)
187 queue_delete_link (display_x11->translate_queue, tmp_list);
188 queue_item_free (item);
195 /* Catch the case where someone isn't processing events and there
196 * is an event stuck in the event queue with an old serial:
197 * If we can't reduce the queue length by the above method,
198 * discard anti-expose items. (We can't discard translate
201 if (display_x11->translate_queue->length >= 64)
203 GList *tmp_list = display_x11->translate_queue->head;
207 GdkWindowQueueItem *item = tmp_list->data;
208 GList *next = tmp_list->next;
210 if (item->type == GDK_WINDOW_QUEUE_ANTIEXPOSE)
212 queue_delete_link (display_x11->translate_queue, tmp_list);
213 queue_item_free (item);
220 item->window = window;
221 item->serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
223 g_object_add_weak_pointer (G_OBJECT (window),
224 (gpointer *)&(item->window));
226 g_queue_push_tail (display_x11->translate_queue, item);
230 _gdk_x11_window_queue_translation (GdkWindow *window,
236 GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
237 item->type = GDK_WINDOW_QUEUE_TRANSLATE;
238 item->u.translate.area = area ? gdk_region_copy (area) : NULL;
239 item->u.translate.dx = dx;
240 item->u.translate.dy = dy;
242 /* Ensure that the gc is flushed so that we get the right
243 serial from NextRequest in gdk_window_queue, i.e. the
244 the serial for the XCopyArea, not the ones from flushing
246 _gdk_x11_gc_flush (gc);
247 gdk_window_queue (window, item);
251 _gdk_x11_window_queue_antiexpose (GdkWindow *window,
254 GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
255 item->type = GDK_WINDOW_QUEUE_ANTIEXPOSE;
256 item->u.antiexpose.area = area;
258 gdk_window_queue (window, item);
264 _gdk_window_process_expose (GdkWindow *window,
268 GdkRegion *invalidate_region = gdk_region_rectangle (area);
269 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
271 if (display_x11->translate_queue)
273 GList *tmp_list = display_x11->translate_queue->head;
277 GdkWindowQueueItem *item = tmp_list->data;
278 GList *next = tmp_list->next;
280 /* an overflow-safe (serial < item->serial) */
281 if (serial - item->serial > (gulong) G_MAXLONG)
283 if (item->window == window)
285 if (item->type == GDK_WINDOW_QUEUE_TRANSLATE)
287 if (item->u.translate.area)
289 GdkRegion *intersection;
291 intersection = gdk_region_copy (invalidate_region);
292 gdk_region_intersect (intersection, item->u.translate.area);
293 gdk_region_subtract (invalidate_region, intersection);
294 gdk_region_offset (intersection, item->u.translate.dx, item->u.translate.dy);
295 gdk_region_union (invalidate_region, intersection);
296 gdk_region_destroy (intersection);
299 gdk_region_offset (invalidate_region, item->u.translate.dx, item->u.translate.dy);
301 else /* anti-expose */
303 gdk_region_subtract (invalidate_region, item->u.antiexpose.area);
309 queue_delete_link (display_x11->translate_queue, tmp_list);
310 queue_item_free (item);
316 if (!gdk_region_empty (invalidate_region))
317 _gdk_window_invalidate_for_expose (window, invalidate_region);
319 gdk_region_destroy (invalidate_region);
322 #define __GDK_GEOMETRY_X11_C__
323 #include "gdkaliasdef.c"