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.
20 /* gdkgeometry-win32.c: emulation of 32 bit coordinates within the
21 * limits of Win32 GDI. Just a copy of the X11 version, more or less.
22 * Probably totally bogus in functionality. Just a quick hack, to
23 * get the thing to build. Need to write some test code for it.
24 * Well, need to find out what it is supposed to do first ;-)
26 * The X11 version by Owen Taylor <otaylor@redhat.com>
27 * Copyright Red Hat, Inc. 2000
28 * Win32 hack by Tor Lillqvist <tml@iki.fi>
29 * and Hans Breuer <hans@breuer.org>
32 #include "gdk.h" /* For gdk_rectangle_intersect */
33 #include "gdkregion.h"
34 #include "gdkregion-generic.h"
35 #include "gdkprivate-win32.h"
37 #define SIZE_LIMIT 32000
39 typedef struct _GdkWindowQueueItem GdkWindowQueueItem;
40 typedef struct _GdkWindowParentPos GdkWindowParentPos;
43 GDK_WINDOW_QUEUE_TRANSLATE,
44 GDK_WINDOW_QUEUE_ANTIEXPOSE
47 struct _GdkWindowQueueItem
51 GdkWindowQueueType type;
63 struct _GdkWindowParentPos
69 GdkRectangle clip_rect;
72 static void gdk_window_compute_position (GdkWindowImplWin32 *window,
73 GdkWindowParentPos *parent_pos,
74 GdkWin32PositionInfo *info);
75 static void gdk_window_compute_parent_pos (GdkWindowImplWin32 *window,
76 GdkWindowParentPos *parent_pos);
77 static void gdk_window_premove (GdkWindow *window,
78 GdkWindowParentPos *parent_pos);
79 static void gdk_window_postmove (GdkWindow *window,
80 GdkWindowParentPos *parent_pos);
81 static void gdk_window_queue_translation (GdkWindow *window,
84 static void gdk_window_tmp_unset_bg (GdkWindow *window);
85 static void gdk_window_tmp_reset_bg (GdkWindow *window);
86 static void gdk_window_clip_changed (GdkWindow *window,
87 GdkRectangle *old_clip,
88 GdkRectangle *new_clip);
90 static GSList *translate_queue = NULL;
93 _gdk_windowing_window_get_offsets (GdkWindow *window,
97 GdkWindowImplWin32 *impl =
98 GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
100 *x_offset = impl->position_info.x_offset;
101 *y_offset = impl->position_info.y_offset;
105 _gdk_window_init_position (GdkWindow *window)
107 GdkWindowParentPos parent_pos;
108 GdkWindowImplWin32 *impl;
110 g_return_if_fail (GDK_IS_WINDOW (window));
112 impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
114 gdk_window_compute_parent_pos (impl, &parent_pos);
115 gdk_window_compute_position (impl, &parent_pos, &impl->position_info);
119 gdk_window_copy_area_scroll (GdkWindow *window,
120 GdkRectangle *dest_rect,
124 GdkWindowObject *obj = GDK_WINDOW_OBJECT (window);
127 if (dest_rect->width > 0 && dest_rect->height > 0)
130 clipRect.left = dest_rect->x;
131 clipRect.top = dest_rect->y;
132 clipRect.right = clipRect.left + dest_rect->width;
133 clipRect.bottom = clipRect.top + dest_rect->height;
135 gdk_window_queue_translation (window, dx, dy);
137 if (!ScrollWindowEx (GDK_WINDOW_HWND (window),
138 dx, dy, /* in: scroll offsets */
139 NULL, /* in: scroll rect, NULL == entire client area */
140 &clipRect, /* in: restrict to */
141 NULL, /* out: update region */
142 NULL, /* out: update rect */
144 WIN32_API_FAILED ("ScrollWindowEx");
147 tmp_list = obj->children;
150 GdkWindow *child = GDK_WINDOW (tmp_list->data);
151 GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
153 gdk_window_move (child, child_obj->x + dx, child_obj->y + dy);
155 tmp_list = tmp_list->next;
160 compute_intermediate_position (GdkWin32PositionInfo *position_info,
161 GdkWin32PositionInfo *new_info,
164 GdkRectangle *new_position)
166 gint new_x0, new_x1, new_y0, new_y1;
168 /* Wrap d_xoffset, d_yoffset into [-32768,32767] range. For the
169 * purposes of subwindow movement, it doesn't matter if we are
170 * off by a factor of 65536, and if we don't do this range
171 * reduction, we'll end up with invalid widths.
173 d_xoffset = (gint16)d_xoffset;
174 d_yoffset = (gint16)d_yoffset;
178 new_x0 = position_info->x + d_xoffset;
179 new_x1 = position_info->x + position_info->width;
183 new_x0 = position_info->x;
184 new_x1 = position_info->x + new_info->width + d_xoffset;
187 new_position->x = new_x0;
188 new_position->width = new_x1 - new_x0;
192 new_y0 = position_info->y + d_yoffset;
193 new_y1 = position_info->y + position_info->height;
197 new_y0 = position_info->y;
198 new_y1 = position_info->y + new_info->height + d_yoffset;
201 new_position->y = new_y0;
202 new_position->height = new_y1 - new_y0;
206 gdk_window_guffaw_scroll (GdkWindow *window,
210 GdkWindowObject *obj = GDK_WINDOW_OBJECT (window);
211 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
213 gint d_xoffset = -dx;
214 gint d_yoffset = -dy;
215 GdkRectangle new_position;
216 GdkWin32PositionInfo new_info;
217 GdkWindowParentPos parent_pos;
220 gdk_window_compute_parent_pos (impl, &parent_pos);
221 gdk_window_compute_position (impl, &parent_pos, &new_info);
223 parent_pos.x += obj->x;
224 parent_pos.y += obj->y;
225 parent_pos.win32_x += new_info.x;
226 parent_pos.win32_y += new_info.y;
227 parent_pos.clip_rect = new_info.clip_rect;
229 gdk_window_tmp_unset_bg (window);
231 if (d_xoffset < 0 || d_yoffset < 0)
232 gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
234 gdk_window_set_static_gravities (window, TRUE);
236 compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
239 /* XXX: this is only translating the X11 code. Don't know why the
240 * window movement needs to be done in three steps there, and here ??
242 if (!SetWindowPos (GDK_WINDOW_HWND (window), NULL,
243 new_position.x, new_position.y,
244 new_position.width, new_position.height,
245 SWP_NOACTIVATE | SWP_NOZORDER))
246 WIN32_API_FAILED ("SetWindowPos");
248 tmp_list = obj->children;
251 GDK_WINDOW_OBJECT(tmp_list->data)->x -= d_xoffset;
252 GDK_WINDOW_OBJECT(tmp_list->data)->y -= d_yoffset;
254 gdk_window_premove (tmp_list->data, &parent_pos);
255 tmp_list = tmp_list->next;
258 if (!SetWindowPos (GDK_WINDOW_HWND (window), NULL,
259 new_position.x - d_xoffset, new_position.y - d_yoffset, 1, 1,
260 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE))
261 WIN32_API_FAILED ("SetWindowPos");
263 if (d_xoffset > 0 || d_yoffset > 0)
264 gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
266 if (!SetWindowPos (GDK_WINDOW_HWND (window), NULL,
267 impl->position_info.x, impl->position_info.y,
268 impl->position_info.width, impl->position_info.height,
269 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE))
270 WIN32_API_FAILED ("SetWindowPos");
272 if (impl->position_info.no_bg)
273 gdk_window_tmp_reset_bg (window);
275 impl->position_info = new_info;
277 tmp_list = obj->children;
280 gdk_window_postmove (tmp_list->data, &parent_pos);
281 tmp_list = tmp_list->next;
287 * @window: a #GdkWindow
288 * @dx: Amount to scroll in the X direction
289 * @dy: Amount to scroll in the Y direction
291 * Scroll the contents of @window, both pixels and children, by the given
292 * amount. @window itself does not move. Portions of the window that the scroll
293 * operation brings in from offscreen areas are invalidated. The invalidated
294 * region may be bigger than what would strictly be necessary. (For Win32, a
295 * minimum area will be invalidated if the window has no subwindows, or if the
296 * edges of the window's parent do not extend beyond the edges of the window. In
297 * other cases, a multi-step process is used to scroll the window which may
298 * produce temporary visual artifacts and unnecessary invalidations.)
301 gdk_window_scroll (GdkWindow *window,
305 gboolean can_guffaw_scroll = FALSE;
306 GdkRegion *invalidate_region;
307 GdkWindowImplWin32 *impl;
308 GdkWindowObject *obj;
309 GdkRectangle dest_rect;
311 g_return_if_fail (GDK_IS_WINDOW (window));
313 if (GDK_WINDOW_DESTROYED (window))
316 obj = GDK_WINDOW_OBJECT (window);
317 impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
319 if (dx == 0 && dy == 0)
322 /* Move the current invalid region */
323 if (obj->update_area)
324 gdk_region_offset (obj->update_area, dx, dy);
326 invalidate_region = gdk_region_rectangle (&impl->position_info.clip_rect);
328 dest_rect = impl->position_info.clip_rect;
331 gdk_rectangle_intersect (&dest_rect, &impl->position_info.clip_rect, &dest_rect);
333 if (dest_rect.width > 0 && dest_rect.height > 0)
335 GdkRegion *tmp_region;
337 tmp_region = gdk_region_rectangle (&dest_rect);
338 gdk_region_subtract (invalidate_region, tmp_region);
339 gdk_region_destroy (tmp_region);
342 gdk_window_invalidate_region (window, invalidate_region, TRUE);
343 gdk_region_destroy (invalidate_region);
345 /* We can guffaw scroll if we are a child window, and the parent
346 * does not extend beyond our edges. Otherwise, we use XCopyArea, then
347 * move any children later
349 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
351 GdkWindowImplWin32 *parent_impl = GDK_WINDOW_IMPL_WIN32 (obj->parent->impl);
352 can_guffaw_scroll = ((dx == 0 || (obj->x <= 0 && obj->x + impl->width >= parent_impl->width)) &&
353 (dy == 0 || (obj->y <= 0 && obj->y + impl->height >= parent_impl->height)));
356 if (!obj->children || !can_guffaw_scroll)
357 gdk_window_copy_area_scroll (window, &dest_rect, dx, dy);
359 gdk_window_guffaw_scroll (window, dx, dy);
363 _gdk_window_move_resize_child (GdkWindow *window,
369 GdkWindowImplWin32 *impl;
370 GdkWindowObject *obj;
371 GdkWin32PositionInfo new_info;
372 GdkWindowParentPos parent_pos;
374 gint d_xoffset, d_yoffset;
379 g_return_if_fail (window != NULL);
380 g_return_if_fail (GDK_IS_WINDOW (window));
382 obj = GDK_WINDOW_OBJECT (window);
383 impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
388 is_move = dx != 0 || dy != 0;
389 is_resize = impl->width != width || impl->height != height;
391 if (!is_move && !is_resize)
397 impl->height = height;
399 gdk_window_compute_parent_pos (impl, &parent_pos);
400 gdk_window_compute_position (impl, &parent_pos, &new_info);
402 gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
404 parent_pos.x += obj->x;
405 parent_pos.y += obj->y;
406 parent_pos.win32_x += new_info.x;
407 parent_pos.win32_y += new_info.y;
408 parent_pos.clip_rect = new_info.clip_rect;
410 d_xoffset = new_info.x_offset - impl->position_info.x_offset;
411 d_yoffset = new_info.y_offset - impl->position_info.y_offset;
413 if (d_xoffset != 0 || d_yoffset != 0)
415 GdkRectangle new_position;
417 gdk_window_set_static_gravities (window, TRUE);
419 if (d_xoffset < 0 || d_yoffset < 0)
420 gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
422 compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
425 if (!SetWindowPos (GDK_WINDOW_HWND (window), NULL,
426 new_position.x, new_position.y,
427 new_position.width, new_position.height,
428 SWP_NOACTIVATE | SWP_NOZORDER))
429 WIN32_API_FAILED ("SetWindowPos");
431 tmp_list = obj->children;
434 gdk_window_premove (tmp_list->data, &parent_pos);
435 tmp_list = tmp_list->next;
438 if (!SetWindowPos (GDK_WINDOW_HWND (window), NULL,
439 new_position.x + dx, new_position.y + dy, 0, 0,
440 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOREDRAW))
441 WIN32_API_FAILED ("SetWindowPos");
443 if (d_xoffset > 0 || d_yoffset > 0)
444 gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
446 if (!SetWindowPos (GDK_WINDOW_HWND (window), NULL,
447 new_info.x, new_info.y,
448 new_info.width, new_info.height,
449 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW))
450 WIN32_API_FAILED ("SetWindowPos");
452 if (impl->position_info.no_bg)
453 gdk_window_tmp_reset_bg (window);
455 if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
456 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
458 impl->position_info = new_info;
460 tmp_list = obj->children;
463 gdk_window_postmove (tmp_list->data, &parent_pos);
464 tmp_list = tmp_list->next;
469 if (is_move && is_resize)
470 gdk_window_set_static_gravities (window, FALSE);
472 if (impl->position_info.mapped && !new_info.mapped)
473 ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
475 tmp_list = obj->children;
478 gdk_window_premove (tmp_list->data, &parent_pos);
479 tmp_list = tmp_list->next;
482 if (!SetWindowPos (GDK_WINDOW_HWND (window), NULL,
483 new_info.x, new_info.y,
484 new_info.width, new_info.height,
485 SWP_NOACTIVATE | SWP_NOZORDER |
486 (is_resize ? 0 : SWP_NOSIZE)))
487 WIN32_API_FAILED ("SetWindowPos");
489 tmp_list = obj->children;
492 gdk_window_postmove (tmp_list->data, &parent_pos);
493 tmp_list = tmp_list->next;
496 if (impl->position_info.no_bg)
497 gdk_window_tmp_reset_bg (window);
499 if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
500 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
502 impl->position_info = new_info;
507 gdk_window_compute_position (GdkWindowImplWin32 *window,
508 GdkWindowParentPos *parent_pos,
509 GdkWin32PositionInfo *info)
511 GdkWindowObject *wrapper;
515 g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (window));
517 wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_WIN32 (window)->wrapper);
521 if (window->width <= SIZE_LIMIT)
523 info->width = window->width;
524 info->x = parent_pos->x + wrapper->x - parent_pos->win32_x;
529 info->width = SIZE_LIMIT;
530 if (parent_pos->x + wrapper->x < -(SIZE_LIMIT/2))
532 if (parent_pos->x + wrapper->x + window->width < (SIZE_LIMIT/2))
533 info->x = parent_pos->x + wrapper->x + window->width - SIZE_LIMIT - parent_pos->win32_x;
535 info->x = -(SIZE_LIMIT/2) - parent_pos->win32_y;
538 info->x = parent_pos->x + wrapper->x - parent_pos->win32_x;
541 if (window->height <= SIZE_LIMIT)
543 info->height = window->height;
544 info->y = parent_pos->y + wrapper->y - parent_pos->win32_y;
549 info->height = SIZE_LIMIT;
550 if (parent_pos->y + wrapper->y < -(SIZE_LIMIT/2))
552 if (parent_pos->y + wrapper->y + window->height < (SIZE_LIMIT/2))
553 info->y = parent_pos->y + wrapper->y + window->height - SIZE_LIMIT - parent_pos->win32_y;
555 info->y = -(SIZE_LIMIT/2) - parent_pos->win32_y;
558 info->y = parent_pos->y + wrapper->y - parent_pos->win32_y;
561 parent_x_offset = parent_pos->win32_x - parent_pos->x;
562 parent_y_offset = parent_pos->win32_y - parent_pos->y;
564 info->x_offset = parent_x_offset + info->x - wrapper->x;
565 info->y_offset = parent_y_offset + info->y - wrapper->y;
567 /* We don't considering the clipping of toplevel windows and their immediate children
568 * by their parents, and simply always map those windows.
570 if (parent_pos->clip_rect.width == G_MAXINT)
572 /* Check if the window would wrap around into the visible space in either direction */
573 else if (info->x + parent_x_offset < parent_pos->clip_rect.x + parent_pos->clip_rect.width - 65536 ||
574 info->x + info->width + parent_x_offset > parent_pos->clip_rect.x + 65536 ||
575 info->y + parent_y_offset < parent_pos->clip_rect.y + parent_pos->clip_rect.height - 65536 ||
576 info->y + info->height + parent_y_offset > parent_pos->clip_rect.y + 65536)
577 info->mapped = FALSE;
583 if (GDK_WINDOW_TYPE (wrapper) == GDK_WINDOW_CHILD)
585 info->clip_rect.x = wrapper->x;
586 info->clip_rect.y = wrapper->y;
587 info->clip_rect.width = window->width;
588 info->clip_rect.height = window->height;
590 gdk_rectangle_intersect (&info->clip_rect, &parent_pos->clip_rect, &info->clip_rect);
592 info->clip_rect.x -= wrapper->x;
593 info->clip_rect.y -= wrapper->y;
597 info->clip_rect.x = 0;
598 info->clip_rect.y = 0;
599 info->clip_rect.width = G_MAXINT;
600 info->clip_rect.height = G_MAXINT;
605 gdk_window_compute_parent_pos (GdkWindowImplWin32 *window,
606 GdkWindowParentPos *parent_pos)
608 GdkWindowObject *wrapper;
609 GdkWindowObject *parent;
610 GdkRectangle tmp_clip;
612 int clip_xoffset = 0;
613 int clip_yoffset = 0;
615 g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (window));
617 wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_WIN32 (window)->wrapper);
621 parent_pos->win32_x = 0;
622 parent_pos->win32_y = 0;
624 /* We take a simple approach here and simply consider toplevel
625 * windows not to clip their children on the right/bottom, since the
626 * size of toplevel windows is not directly under our
627 * control. Clipping only really matters when scrolling and
628 * generally we aren't going to be moving the immediate child of a
629 * toplevel beyond the bounds of that toplevel.
631 * We could go ahead and recompute the clips of toplevel windows and
632 * their descendents when we receive size notification, but it would
633 * probably not be an improvement in most cases.
635 parent_pos->clip_rect.x = 0;
636 parent_pos->clip_rect.y = 0;
637 parent_pos->clip_rect.width = G_MAXINT;
638 parent_pos->clip_rect.height = G_MAXINT;
640 parent = (GdkWindowObject *)wrapper->parent;
641 while (parent && parent->window_type == GDK_WINDOW_CHILD)
643 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (parent->impl);
645 tmp_clip.x = - clip_xoffset;
646 tmp_clip.y = - clip_yoffset;
647 tmp_clip.width = impl->width;
648 tmp_clip.height = impl->height;
650 gdk_rectangle_intersect (&parent_pos->clip_rect, &tmp_clip, &parent_pos->clip_rect);
652 parent_pos->x += parent->x;
653 parent_pos->y += parent->y;
654 parent_pos->win32_x += impl->position_info.x;
655 parent_pos->win32_y += impl->position_info.y;
657 clip_xoffset += parent->x;
658 clip_yoffset += parent->y;
660 parent = (GdkWindowObject *)parent->parent;
665 gdk_window_premove (GdkWindow *window,
666 GdkWindowParentPos *parent_pos)
668 GdkWindowImplWin32 *impl;
669 GdkWindowObject *obj;
670 GdkWin32PositionInfo new_info;
672 gint d_xoffset, d_yoffset;
673 GdkWindowParentPos this_pos;
675 obj = (GdkWindowObject *) window;
676 impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
678 gdk_window_compute_position (impl, parent_pos, &new_info);
680 gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
682 this_pos.x = parent_pos->x + obj->x;
683 this_pos.y = parent_pos->y + obj->y;
684 this_pos.win32_x = parent_pos->win32_x + new_info.x;
685 this_pos.win32_y = parent_pos->win32_y + new_info.y;
686 this_pos.clip_rect = new_info.clip_rect;
688 if (impl->position_info.mapped && !new_info.mapped)
689 ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
691 d_xoffset = new_info.x_offset - impl->position_info.x_offset;
692 d_yoffset = new_info.y_offset - impl->position_info.y_offset;
694 if (d_xoffset != 0 || d_yoffset != 0)
696 GdkRectangle new_position;
698 if (d_xoffset < 0 || d_yoffset < 0)
699 gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
701 compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
704 if (!SetWindowPos (GDK_WINDOW_HWND (window), NULL,
705 new_position.x, new_position.y,
706 new_position.width, new_position.height,
707 SWP_NOREDRAW | SWP_NOZORDER | SWP_NOACTIVATE))
708 WIN32_API_FAILED ("SetWindowPos");
711 tmp_list = obj->children;
714 gdk_window_premove (tmp_list->data, &this_pos);
715 tmp_list = tmp_list->next;
720 gdk_window_postmove (GdkWindow *window,
721 GdkWindowParentPos *parent_pos)
723 GdkWindowImplWin32 *impl;
724 GdkWindowObject *obj;
725 GdkWin32PositionInfo new_info;
727 gint d_xoffset, d_yoffset;
728 GdkWindowParentPos this_pos;
730 obj = (GdkWindowObject *) window;
731 impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
733 gdk_window_compute_position (impl, parent_pos, &new_info);
735 this_pos.x = parent_pos->x + obj->x;
736 this_pos.y = parent_pos->y + obj->y;
737 this_pos.win32_x = parent_pos->win32_x + new_info.x;
738 this_pos.win32_y = parent_pos->win32_y + new_info.y;
739 this_pos.clip_rect = new_info.clip_rect;
741 d_xoffset = new_info.x_offset - impl->position_info.x_offset;
742 d_yoffset = new_info.y_offset - impl->position_info.y_offset;
744 if (d_xoffset != 0 || d_yoffset != 0)
746 if (d_xoffset > 0 || d_yoffset > 0)
747 gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
749 if (!SetWindowPos (GDK_WINDOW_HWND (window), NULL,
750 new_info.x, new_info.y,
751 new_info.width, new_info.height,
752 SWP_NOREDRAW | SWP_NOZORDER | SWP_NOACTIVATE))
753 WIN32_API_FAILED ("SetWindowPos");
756 if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
757 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
759 if (impl->position_info.no_bg)
760 gdk_window_tmp_reset_bg (window);
762 impl->position_info = new_info;
764 tmp_list = obj->children;
767 gdk_window_postmove (tmp_list->data, &this_pos);
768 tmp_list = tmp_list->next;
773 gdk_window_queue_translation (GdkWindow *window,
777 GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
778 item->window = window;
779 item->serial = GetMessageTime ();
780 item->type = GDK_WINDOW_QUEUE_TRANSLATE;
781 item->u.translate.dx = dx;
782 item->u.translate.dy = dy;
784 GDK_NOTE (EVENTS, g_print ("gdk_window_queue_translation %#x %ld %d,%d\n",
785 (guint) GDK_WINDOW_HWND (window),
789 gdk_drawable_ref (window);
790 translate_queue = g_slist_append (translate_queue, item);
794 _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
798 GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
800 item->window = window;
801 item->serial = GetMessageTime ();
802 item->type = GDK_WINDOW_QUEUE_ANTIEXPOSE;
803 item->u.antiexpose.area = area;
805 GDK_NOTE (EVENTS, g_print ("_gdk_windowing_window_queue_antiexpose %#x %ld %dx%d@+%d+%d\n",
806 (guint) GDK_WINDOW_HWND (window),
808 area->extents.x2 - area->extents.x1,
809 area->extents.y2 - area->extents.y1,
810 area->extents.x1, area->extents.y1));
812 gdk_drawable_ref (window);
813 translate_queue = g_slist_append (translate_queue, item);
820 gdk_region_get_clipbox (area, &r);
821 hrgn = CreateRectRgn(r.x, r.y, r.width+1, r.height+1);
823 g_return_val_if_fail (area != NULL, FALSE);
825 GDK_NOTE (MISC, g_print ("_gdk_windowing_window_queue_antiexpose %#x\n",
826 (guint) GDK_WINDOW_HWND (window)));
828 /* HB: not quite sure if this is the right thing to do.
829 * (Region not to be proceesed by next WM_PAINT)
831 ValidateRgn(GDK_WINDOW_HWND (window), hrgn);
838 _gdk_window_process_expose (GdkWindow *window,
842 GdkWindowImplWin32 *impl;
843 GdkRegion *invalidate_region = gdk_region_rectangle (area);
844 GdkRegion *clip_region;
845 GSList *tmp_list = translate_queue;
847 impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
849 GDK_NOTE (EVENTS, g_print ("_gdk_window_process_expose %#x %ld %dx%d@+%d+%d\n",
850 (guint) GDK_WINDOW_HWND (window), serial,
851 area->width, area->height, area->x, area->y));
855 GdkWindowQueueItem *item = tmp_list->data;
856 tmp_list = tmp_list->next;
858 if (serial < item->serial)
860 if (item->window == window)
862 if (item->type == GDK_WINDOW_QUEUE_TRANSLATE)
863 gdk_region_offset (invalidate_region, - item->u.translate.dx, - item->u.translate.dy);
864 else /* anti-expose */
865 gdk_region_subtract (invalidate_region, item->u.antiexpose.area);
870 GSList *tmp_link = translate_queue;
872 translate_queue = g_slist_remove_link (translate_queue, translate_queue);
873 gdk_drawable_unref (item->window);
875 if (item->type == GDK_WINDOW_QUEUE_ANTIEXPOSE)
876 gdk_region_destroy (item->u.antiexpose.area);
879 g_slist_free_1 (tmp_link);
883 clip_region = gdk_region_rectangle (&impl->position_info.clip_rect);
884 gdk_region_intersect (invalidate_region, clip_region);
886 if (!gdk_region_empty (invalidate_region))
887 gdk_window_invalidate_region (window, invalidate_region, FALSE);
889 gdk_region_destroy (invalidate_region);
890 gdk_region_destroy (clip_region);
894 gdk_window_tmp_unset_bg (GdkWindow *window)
896 GdkWindowImplWin32 *impl;
897 GdkWindowObject *obj;
899 obj = (GdkWindowObject *) window;
900 impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
902 impl->position_info.no_bg = TRUE;
905 * The X version sets background = None to avoid updateing for a moment.
906 * Not sure if this could really emulate it.
908 if (obj->bg_pixmap != GDK_NO_BG)
909 /* handled in WM_ERASEBKGRND proceesing */;
913 gdk_window_tmp_reset_bg (GdkWindow *window)
915 GdkWindowImplWin32 *impl;
916 GdkWindowObject *obj;
918 obj = (GdkWindowObject *) window;
919 impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
921 impl->position_info.no_bg = FALSE;
923 if (obj->bg_pixmap == GDK_NO_BG)
937 gdk_window_clip_changed (GdkWindow *window, GdkRectangle *old_clip, GdkRectangle *new_clip)
939 GdkWindowImplWin32 *impl;
940 GdkWindowObject *obj;
941 GdkRegion *old_clip_region;
942 GdkRegion *new_clip_region;
944 if (((GdkWindowObject *)window)->input_only)
947 obj = (GdkWindowObject *) window;
948 impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
950 old_clip_region = gdk_region_rectangle (old_clip);
951 new_clip_region = gdk_region_rectangle (new_clip);
953 /* We need to update this here because gdk_window_invalidate_region makes
954 * use if it (through gdk_drawable_get_visible_region
956 impl->position_info.clip_rect = *new_clip;
958 /* Trim invalid region of window to new clip rectangle
960 if (obj->update_area)
961 gdk_region_intersect (obj->update_area, new_clip_region);
963 /* Invalidate newly exposed portion of window
965 gdk_region_subtract (new_clip_region, old_clip_region);
966 if (!gdk_region_empty (new_clip_region))
968 gdk_window_tmp_unset_bg (window);
969 gdk_window_invalidate_region (window, new_clip_region, FALSE);
972 gdk_region_destroy (new_clip_region);
973 gdk_region_destroy (old_clip_region);