1/* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
3 * Josh MacDonald, Ryan Lortie
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
21 * file for a list of people on the GTK+ Team. See the ChangeLog
22 * files for a list of changes. These files are distributed with
23 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
24 */
25
26#include "config.h"
27
28#include <cairo-gobject.h>
29
30#include "gdkwindow.h"
31
32#include "gdkrectangle.h"
33#include "gdkinternals.h"
34#include "gdkintl.h"
35#include "gdkscreenprivate.h"
36#include "gdkdisplayprivate.h"
37#include "gdkdeviceprivate.h"
38#include "gdkvisualprivate.h"
39#include "gdkmarshalers.h"
40#include "gdkframeclockidle.h"
41#include "gdkwindowimpl.h"
42#include "gdkglcontextprivate.h"
43#include "gdkdrawingcontextprivate.h"
44#include "gdk-private.h"
45
46#include <math.h>
47
48#include <epoxy/gl.h>
49
50/* for the use of round() */
51#include "fallback-c89.c"
52
53#ifdef GDK_WINDOWING_WAYLAND
54#include "wayland/gdkwayland.h"
55#endif
56
57#undef DEBUG_WINDOW_PRINTING
58
59
60/**
61 * SECTION:windows
62 * @Short_description: Onscreen display areas in the target window system
63 * @Title: Windows
64 *
65 * A #GdkWindow is a (usually) rectangular region on the screen.
66 * It’s a low-level object, used to implement high-level objects such as
67 * #GtkWidget and #GtkWindow on the GTK+ level. A #GtkWindow is a toplevel
68 * window, the thing a user might think of as a “window” with a titlebar
69 * and so on; a #GtkWindow may contain many #GdkWindows. For example,
70 * each #GtkButton has a #GdkWindow associated with it.
71 *
72 * # Composited Windows # {#COMPOSITED-WINDOWS}
73 *
74 * Normally, the windowing system takes care of rendering the contents
75 * of a child window onto its parent window. This mechanism can be
76 * intercepted by calling gdk_window_set_composited() on the child
77 * window. For a “composited” window it is the
78 * responsibility of the application to render the window contents at
79 * the right spot.
80 *
81 * # Offscreen Windows # {#OFFSCREEN-WINDOWS}
82 *
83 * Offscreen windows are more general than composited windows, since
84 * they allow not only to modify the rendering of the child window onto
85 * its parent, but also to apply coordinate transformations.
86 *
87 * To integrate an offscreen window into a window hierarchy, one has
88 * to call gdk_offscreen_window_set_embedder() and handle a number of
89 * signals. The #GdkWindow::pick-embedded-child signal on the embedder
90 * window is used to select an offscreen child at given coordinates,
91 * and the #GdkWindow::to-embedder and #GdkWindow::from-embedder signals
92 * on the offscreen window are used to translate coordinates between
93 * the embedder and the offscreen window.
94 *
95 * For rendering an offscreen window onto its embedder, the contents
96 * of the offscreen window are available as a surface, via
97 * gdk_offscreen_window_get_surface().
98 */
99
100
101/* Historically a GdkWindow always matches a platform native window,
102 * be it a toplevel window or a child window. In this setup the
103 * GdkWindow (and other GdkDrawables) were platform independent classes,
104 * and the actual platform specific implementation was in a delegate
105 * object available as “impl” in the window object.
106 *
107 * With the addition of client side windows and offscreen windows this
108 * changes a bit. The application-visible GdkWindow object behaves as
109 * it did before, but not all such windows now have a corresponding native
110 * window. Instead windows that are “client side” are emulated by the gdk
111 * code such that clipping, drawing, moving, events etc work as expected.
112 *
113 * For GdkWindows that have a native window the “impl” object is the
114 * same as before. However, for all client side windows the impl object
115 * is shared with its parent (i.e. all client windows descendants of one
116 * native window has the same impl.
117 *
118 * Additionally there is a new type of platform independent impl object,
119 * GdkOffscreenWindow. All windows of type GDK_WINDOW_OFFSCREEN get an impl
120 * of this type (while their children are generally GDK_WINDOW_CHILD virtual
121 * windows). Such windows work by allocating a #cairo_surface_t as the backing
122 * store for drawing operations, which is resized with the window.
123 *
124 * GdkWindows have a pointer to the “impl window” they are in, i.e.
125 * the topmost GdkWindow which have the same “impl” value. This is stored
126 * in impl_window, which is different from the window itself only for client
127 * side windows.
128 * All GdkWindows (native or not) track the position of the window in the parent
129 * (x, y), the size of the window (width, height), the position of the window
130 * with respect to the impl window (abs_x, abs_y). We also track the clip
131 * region of the window wrt parent windows, in window-relative coordinates (clip_region).
132 *
133 * All toplevel windows are native windows, but also child windows can be
134 * native (although not children of offscreens). We always listen to
135 * a basic set of events (see get_native_event_mask) for these windows
136 * so that we can emulate events for any client side children.
137 *
138 * For native windows we apply the calculated clip region as a window shape
139 * so that eg. client side siblings that overlap the native child properly
140 * draws over the native child window.
141 */
142
143/* This adds a local value to the GdkVisibilityState enum */
144#define GDK_VISIBILITY_NOT_VIEWABLE 3
145
146enum {
147 PICK_EMBEDDED_CHILD, /* only called if children are embedded */
148 TO_EMBEDDER,
149 FROM_EMBEDDER,
150 CREATE_SURFACE,
151 LAST_SIGNAL
152};
153
154enum {
155 PROP_0,
156 PROP_CURSOR,
157 LAST_PROP
158};
159
160/* Global info */
161
162static void gdk_window_finalize (GObject *object);
163
164static void gdk_window_set_property (GObject *object,
165 guint prop_id,
166 const GValue *value,
167 GParamSpec *pspec);
168static void gdk_window_get_property (GObject *object,
169 guint prop_id,
170 GValue *value,
171 GParamSpec *pspec);
172
173static void gdk_window_clear_backing_region (GdkWindow *window);
174
175static void recompute_visible_regions (GdkWindow *private,
176 gboolean recalculate_children);
177static void gdk_window_invalidate_in_parent (GdkWindow *private);
178static void move_native_children (GdkWindow *private);
179static void update_cursor (GdkDisplay *display,
180 GdkDevice *device);
181static void impl_window_add_update_area (GdkWindow *impl_window,
182 cairo_region_t *region);
183static void gdk_window_invalidate_region_full (GdkWindow *window,
184 const cairo_region_t *region,
185 gboolean invalidate_children);
186static void gdk_window_invalidate_rect_full (GdkWindow *window,
187 const GdkRectangle *rect,
188 gboolean invalidate_children);
189static cairo_surface_t *gdk_window_ref_impl_surface (GdkWindow *window);
190
191static void gdk_window_set_frame_clock (GdkWindow *window,
192 GdkFrameClock *clock);
193
194static void draw_ugly_color (GdkWindow *window,
195 const cairo_region_t *region,
196 int color);
197
198
199static guint signals[LAST_SIGNAL] = { 0 };
200static GParamSpec *properties[LAST_PROP] = { NULL, };
201
202G_DEFINE_ABSTRACT_TYPE (GdkWindow, gdk_window, G_TYPE_OBJECT)
203
204#ifdef DEBUG_WINDOW_PRINTING
205char *
206print_region (cairo_region_t *region)
207{
208 GString *s = g_string_new ("{");
209 if (cairo_region_is_empty (region))
210 {
211 g_string_append (s, "empty");
212 }
213 else
214 {
215 int num = cairo_region_num_rectangles (region);
216 cairo_rectangle_int_t r;
217
218 if (num == 1)
219 {
220 cairo_region_get_rectangle (region, 0, &r);
221 g_string_append_printf (s, "%dx%d @%d,%d", r.width, r.height, r.x, r.y);
222 }
223 else
224 {
225 int i;
226 cairo_region_get_extents (region, &r);
227 g_string_append_printf (s, "extent: %dx%d @%d,%d, details: ", r.width, r.height, r.x, r.y);
228 for (i = 0; i < num; i++)
229 {
230 cairo_region_get_rectangle (region, i, &r);
231 g_string_append_printf (s, "[%dx%d @%d,%d]", r.width, r.height, r.x, r.y);
232 if (i != num -1)
233 g_string_append (s, ", ");
234 }
235 }
236 }
237 g_string_append (s, "}");
238 return g_string_free (s, FALSE);
239}
240#endif
241
242static GList *
243list_insert_link_before (GList *list,
244 GList *sibling,
245 GList *link)
246{
247 if (list == NULL || sibling == list)
248 {
249 link->prev = NULL;
250 link->next = list;
251 if (list)
252 list->prev = link;
253 return link;
254 }
255 else if (sibling == NULL)
256 {
257 GList *last = g_list_last (list);
258
259 last->next = link;
260 link->prev = last;
261 link->next = NULL;
262
263 return list;
264 }
265 else
266 {
267 link->next = sibling;
268 link->prev = sibling->prev;
269 sibling->prev = link;
270
271 if (link->prev)
272 link->prev->next = link;
273
274 return list;
275 }
276}
277
278static void
279gdk_window_init (GdkWindow *window)
280{
281 /* 0-initialization is good for all other fields. */
282
283 window->window_type = GDK_WINDOW_CHILD;
284
285 window->state = GDK_WINDOW_STATE_WITHDRAWN;
286 window->fullscreen_mode = GDK_FULLSCREEN_ON_CURRENT_MONITOR;
287 window->width = 1;
288 window->height = 1;
289 window->toplevel_window_type = -1;
290 /* starts hidden */
291 window->effective_visibility = GDK_VISIBILITY_NOT_VIEWABLE;
292 window->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
293 /* Default to unobscured since some backends don't send visibility events */
294 window->native_visibility = GDK_VISIBILITY_UNOBSCURED;
295 window->children_list_node.data = window;
296
297 window->device_cursor = g_hash_table_new_full (NULL, NULL,
298 NULL, g_object_unref);
299}
300
301/* Stop and return on the first non-NULL parent */
302static gboolean
303accumulate_get_window (GSignalInvocationHint *ihint,
304 GValue *return_accu,
305 const GValue *handler_return,
306 gpointer data)
307{
308 g_value_copy (handler_return, return_accu);
309 /* Continue while returning NULL */
310 return g_value_get_object (handler_return) == NULL;
311}
312
313static gboolean
314create_surface_accumulator (GSignalInvocationHint *ihint,
315 GValue *return_accu,
316 const GValue *handler_return,
317 gpointer data)
318{
319 g_value_copy (handler_return, return_accu);
320
321 /* Stop on the first non-NULL return value */
322 return g_value_get_boxed (handler_return) == NULL;
323}
324
325static GQuark quark_pointer_window = 0;
326
327static void
328gdk_window_class_init (GdkWindowClass *klass)
329{
330 GObjectClass *object_class = G_OBJECT_CLASS (klass);
331
332 object_class->finalize = gdk_window_finalize;
333 object_class->set_property = gdk_window_set_property;
334 object_class->get_property = gdk_window_get_property;
335
336 klass->create_surface = _gdk_offscreen_window_create_surface;
337
338 quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
339
340
341 /* Properties */
342
343 /**
344 * GdkWindow:cursor:
345 *
346 * The mouse pointer for a #GdkWindow. See gdk_window_set_cursor() and
347 * gdk_window_get_cursor() for details.
348 *
349 * Since: 2.18
350 */
351 properties[PROP_CURSOR] =
352 g_param_spec_object ("cursor",
353 P_("Cursor"),
354 P_("Cursor"),
355 GDK_TYPE_CURSOR,
356 G_PARAM_READWRITE);
357 g_object_class_install_properties (object_class, LAST_PROP, properties);
358
359 /**
360 * GdkWindow::pick-embedded-child:
361 * @window: the window on which the signal is emitted
362 * @x: x coordinate in the window
363 * @y: y coordinate in the window
364 *
365 * The ::pick-embedded-child signal is emitted to find an embedded
366 * child at the given position.
367 *
368 * Returns: (nullable) (transfer none): the #GdkWindow of the
369 * embedded child at @x, @y, or %NULL
370 *
371 * Since: 2.18
372 */
373 signals[PICK_EMBEDDED_CHILD] =
374 g_signal_new (g_intern_static_string ("pick-embedded-child"),
375 G_OBJECT_CLASS_TYPE (object_class),
376 G_SIGNAL_RUN_LAST,
377 G_STRUCT_OFFSET (GdkWindowClass, pick_embedded_child),
378 accumulate_get_window, NULL,
379 _gdk_marshal_OBJECT__DOUBLE_DOUBLE,
380 GDK_TYPE_WINDOW,
381 2,
382 G_TYPE_DOUBLE,
383 G_TYPE_DOUBLE);
384
385 /**
386 * GdkWindow::to-embedder:
387 * @window: the offscreen window on which the signal is emitted
388 * @offscreen_x: x coordinate in the offscreen window
389 * @offscreen_y: y coordinate in the offscreen window
390 * @embedder_x: (out) (type double): return location for the x
391 * coordinate in the embedder window
392 * @embedder_y: (out) (type double): return location for the y
393 * coordinate in the embedder window
394 *
395 * The ::to-embedder signal is emitted to translate coordinates
396 * in an offscreen window to its embedder.
397 *
398 * See also #GdkWindow::from-embedder.
399 *
400 * Since: 2.18
401 */
402 signals[TO_EMBEDDER] =
403 g_signal_new (g_intern_static_string ("to-embedder"),
404 G_OBJECT_CLASS_TYPE (object_class),
405 G_SIGNAL_RUN_LAST,
406 G_STRUCT_OFFSET (GdkWindowClass, to_embedder),
407 NULL, NULL,
408 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
409 G_TYPE_NONE,
410 4,
411 G_TYPE_DOUBLE,
412 G_TYPE_DOUBLE,
413 G_TYPE_POINTER,
414 G_TYPE_POINTER);
415
416 /**
417 * GdkWindow::from-embedder:
418 * @window: the offscreen window on which the signal is emitted
419 * @embedder_x: x coordinate in the embedder window
420 * @embedder_y: y coordinate in the embedder window
421 * @offscreen_x: (out) (type double): return location for the x
422 * coordinate in the offscreen window
423 * @offscreen_y: (out) (type double): return location for the y
424 * coordinate in the offscreen window
425 *
426 * The ::from-embedder signal is emitted to translate coordinates
427 * in the embedder of an offscreen window to the offscreen window.
428 *
429 * See also #GdkWindow::to-embedder.
430 *
431 * Since: 2.18
432 */
433 signals[FROM_EMBEDDER] =
434 g_signal_new (g_intern_static_string ("from-embedder"),
435 G_OBJECT_CLASS_TYPE (object_class),
436 G_SIGNAL_RUN_LAST,
437 G_STRUCT_OFFSET (GdkWindowClass, from_embedder),
438 NULL, NULL,
439 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
440 G_TYPE_NONE,
441 4,
442 G_TYPE_DOUBLE,
443 G_TYPE_DOUBLE,
444 G_TYPE_POINTER,
445 G_TYPE_POINTER);
446
447 /**
448 * GdkWindow::create-surface:
449 * @window: the offscreen window on which the signal is emitted
450 * @width: the width of the offscreen surface to create
451 * @height: the height of the offscreen surface to create
452 *
453 * The ::create-surface signal is emitted when an offscreen window
454 * needs its surface (re)created, which happens either when the
455 * window is first drawn to, or when the window is being
456 * resized. The first signal handler that returns a non-%NULL
457 * surface will stop any further signal emission, and its surface
458 * will be used.
459 *
460 * Note that it is not possible to access the window's previous
461 * surface from within any callback of this signal. Calling
462 * gdk_offscreen_window_get_surface() will lead to a crash.
463 *
464 * Returns: the newly created #cairo_surface_t for the offscreen window
465 *
466 * Since: 3.0
467 */
468 signals[CREATE_SURFACE] =
469 g_signal_new (g_intern_static_string ("create-surface"),
470 G_OBJECT_CLASS_TYPE (object_class),
471 G_SIGNAL_RUN_LAST,
472 G_STRUCT_OFFSET (GdkWindowClass, create_surface),
473 create_surface_accumulator, NULL,
474 _gdk_marshal_BOXED__INT_INT,
475 CAIRO_GOBJECT_TYPE_SURFACE,
476 2,
477 G_TYPE_INT,
478 G_TYPE_INT);
479}
480
481static void
482seat_removed_cb (GdkDisplay *display,
483 GdkSeat *seat,
484 GdkWindow *window)
485{
486 GdkDevice *device = gdk_seat_get_pointer (seat);
487
488 window->devices_inside = g_list_remove (window->devices_inside, device);
489 g_hash_table_remove (window->device_cursor, device);
490
491 if (window->device_events)
492 g_hash_table_remove (window->device_events, device);
493}
494
495static void
496gdk_window_finalize (GObject *object)
497{
498 GdkWindow *window = GDK_WINDOW (object);
499
500 g_signal_handlers_disconnect_by_func (gdk_window_get_display (window),
501 seat_removed_cb, window);
502
503 if (!GDK_WINDOW_DESTROYED (window))
504 {
505 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
506 {
507 g_warning ("losing last reference to undestroyed window");
508 _gdk_window_destroy (window, FALSE);
509 }
510 else
511 /* We use TRUE here, to keep us from actually calling
512 * XDestroyWindow() on the window
513 */
514 _gdk_window_destroy (window, TRUE);
515 }
516
517 if (window->impl)
518 {
519 g_object_unref (window->impl);
520 window->impl = NULL;
521 }
522
523 if (window->impl_window != window)
524 {
525 g_object_unref (window->impl_window);
526 window->impl_window = NULL;
527 }
528
529 if (window->shape)
530 cairo_region_destroy (window->shape);
531
532 if (window->input_shape)
533 cairo_region_destroy (window->input_shape);
534
535 if (window->cursor)
536 g_object_unref (window->cursor);
537
538 if (window->device_cursor)
539 g_hash_table_destroy (window->device_cursor);
540
541 if (window->device_events)
542 g_hash_table_destroy (window->device_events);
543
544 if (window->source_event_masks)
545 g_hash_table_destroy (window->source_event_masks);
546
547 if (window->devices_inside)
548 g_list_free (window->devices_inside);
549
550 G_OBJECT_CLASS (gdk_window_parent_class)->finalize (object);
551}
552
553static void
554gdk_window_set_property (GObject *object,
555 guint prop_id,
556 const GValue *value,
557 GParamSpec *pspec)
558{
559 GdkWindow *window = (GdkWindow *)object;
560
561 switch (prop_id)
562 {
563 case PROP_CURSOR:
564 gdk_window_set_cursor (window, g_value_get_object (value));
565 break;
566
567 default:
568 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
569 break;
570 }
571}
572
573static void
574gdk_window_get_property (GObject *object,
575 guint prop_id,
576 GValue *value,
577 GParamSpec *pspec)
578{
579 GdkWindow *window = (GdkWindow *) object;
580
581 switch (prop_id)
582 {
583 case PROP_CURSOR:
584 g_value_set_object (value, gdk_window_get_cursor (window));
585 break;
586
587 default:
588 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
589 break;
590 }
591}
592
593static gboolean
594gdk_window_is_offscreen (GdkWindow *window)
595{
596 return window->window_type == GDK_WINDOW_OFFSCREEN;
597}
598
599static GdkWindow *
600gdk_window_get_impl_window (GdkWindow *window)
601{
602 return window->impl_window;
603}
604
605GdkWindow *
606_gdk_window_get_impl_window (GdkWindow *window)
607{
608 return gdk_window_get_impl_window (window);
609}
610
611static gboolean
612gdk_window_has_impl (GdkWindow *window)
613{
614 return window->impl_window == window;
615}
616
617static gboolean
618gdk_window_is_toplevel (GdkWindow *window)
619{
620 return
621 window->parent == NULL ||
622 window->parent->window_type == GDK_WINDOW_ROOT;
623}
624
625gboolean
626_gdk_window_has_impl (GdkWindow *window)
627{
628 return gdk_window_has_impl (window);
629}
630
631static gboolean
632gdk_window_has_no_impl (GdkWindow *window)
633{
634 return window->impl_window != window;
635}
636
637static void
638remove_sibling_overlapped_area (GdkWindow *window,
639 cairo_region_t *region)
640{
641 GdkWindow *parent;
642 GdkWindow *sibling;
643 cairo_region_t *child_region;
644 GdkRectangle r;
645 GList *l;
646 cairo_region_t *shape;
647
648 parent = window->parent;
649
650 if (gdk_window_is_toplevel (window))
651 return;
652
653 /* Convert from from window coords to parent coords */
654 cairo_region_translate (region, window->x, window->y);
655
656 for (l = parent->children; l; l = l->next)
657 {
658 sibling = l->data;
659
660 if (sibling == window)
661 break;
662
663 if (!GDK_WINDOW_IS_MAPPED (sibling) || sibling->input_only || sibling->composited)
664 continue;
665
666 /* Ignore offscreen children, as they don't draw in their parent and
667 * don't take part in the clipping */
668 if (gdk_window_is_offscreen (sibling))
669 continue;
670
671 r.x = sibling->x;
672 r.y = sibling->y;
673 r.width = sibling->width;
674 r.height = sibling->height;
675
676 child_region = cairo_region_create_rectangle (&r);
677
678 if (sibling->shape)
679 {
680 /* Adjust shape region to parent window coords */
681 cairo_region_translate (sibling->shape, sibling->x, sibling->y);
682 cairo_region_intersect (child_region, sibling->shape);
683 cairo_region_translate (sibling->shape, -sibling->x, -sibling->y);
684 }
685 else if (window->window_type == GDK_WINDOW_FOREIGN)
686 {
687 shape = GDK_WINDOW_IMPL_GET_CLASS (sibling)->get_shape (sibling);
688 if (shape)
689 {
690 cairo_region_intersect (child_region, shape);
691 cairo_region_destroy (shape);
692 }
693 }
694
695 cairo_region_subtract (region, child_region);
696 cairo_region_destroy (child_region);
697 }
698
699 remove_sibling_overlapped_area (parent, region);
700
701 /* Convert back to window coords */
702 cairo_region_translate (region, -window->x, -window->y);
703}
704
705static void
706remove_child_area (GdkWindow *window,
707 gboolean for_input,
708 cairo_region_t *region)
709{
710 GdkWindow *child;
711 cairo_region_t *child_region;
712 GdkRectangle r;
713 GList *l;
714 cairo_region_t *shape;
715
716 for (l = window->children; l; l = l->next)
717 {
718 child = l->data;
719
720 /* If region is empty already, no need to do
721 anything potentially costly */
722 if (cairo_region_is_empty (region))
723 break;
724
725 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
726 continue;
727
728 /* Ignore offscreen children, as they don't draw in their parent and
729 * don't take part in the clipping */
730 if (gdk_window_is_offscreen (child))
731 continue;
732
733 r.x = child->x;
734 r.y = child->y;
735 r.width = child->width;
736 r.height = child->height;
737
738 /* Bail early if child totally outside region */
739 if (cairo_region_contains_rectangle (region, &r) == CAIRO_REGION_OVERLAP_OUT)
740 continue;
741
742 child_region = cairo_region_create_rectangle (&r);
743
744 if (child->shape)
745 {
746 /* Adjust shape region to parent window coords */
747 cairo_region_translate (child->shape, child->x, child->y);
748 cairo_region_intersect (child_region, child->shape);
749 cairo_region_translate (child->shape, -child->x, -child->y);
750 }
751 else if (window->window_type == GDK_WINDOW_FOREIGN)
752 {
753 shape = GDK_WINDOW_IMPL_GET_CLASS (child)->get_shape (child);
754 if (shape)
755 {
756 cairo_region_intersect (child_region, shape);
757 cairo_region_destroy (shape);
758 }
759 }
760
761 if (for_input)
762 {
763 if (child->input_shape)
764 cairo_region_intersect (child_region, child->input_shape);
765 else if (window->window_type == GDK_WINDOW_FOREIGN)
766 {
767 shape = GDK_WINDOW_IMPL_GET_CLASS (child)->get_input_shape (child);
768 if (shape)
769 {
770 cairo_region_intersect (child_region, shape);
771 cairo_region_destroy (shape);
772 }
773 }
774 }
775
776 cairo_region_subtract (region, child_region);
777 cairo_region_destroy (child_region);
778 }
779}
780
781static GdkVisibilityState
782effective_visibility (GdkWindow *window)
783{
784 GdkVisibilityState native;
785
786 if (!gdk_window_is_viewable (window))
787 return GDK_VISIBILITY_NOT_VIEWABLE;
788
789 native = window->impl_window->native_visibility;
790
791 if (native == GDK_VISIBILITY_FULLY_OBSCURED ||
792 window->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
793 return GDK_VISIBILITY_FULLY_OBSCURED;
794 else if (native == GDK_VISIBILITY_UNOBSCURED)
795 return window->visibility;
796 else /* native PARTIAL, private partial or unobscured */
797 return GDK_VISIBILITY_PARTIAL;
798}
799
800static void
801gdk_window_update_visibility (GdkWindow *window)
802{
803 GdkVisibilityState new_visibility;
804 GdkEvent *event;
805
806 new_visibility = effective_visibility (window);
807
808 if (new_visibility != window->effective_visibility)
809 {
810 window->effective_visibility = new_visibility;
811
812 if (new_visibility != GDK_VISIBILITY_NOT_VIEWABLE &&
813 window->event_mask & GDK_VISIBILITY_NOTIFY_MASK)
814 {
815 event = _gdk_make_event (window, GDK_VISIBILITY_NOTIFY,
816 NULL, FALSE);
817 event->visibility.state = new_visibility;
818 }
819 }
820}
821
822static void
823gdk_window_update_visibility_recursively (GdkWindow *window,
824 GdkWindow *only_for_impl)
825{
826 GdkWindow *child;
827 GList *l;
828
829 gdk_window_update_visibility (window);
830 for (l = window->children; l != NULL; l = l->next)
831 {
832 child = l->data;
833 if ((only_for_impl == NULL) ||
834 (only_for_impl == child->impl_window))
835 gdk_window_update_visibility_recursively (child, only_for_impl);
836 }
837}
838
839static gboolean
840should_apply_clip_as_shape (GdkWindow *window)
841{
842 return
843 gdk_window_has_impl (window) &&
844 /* Not for offscreens */
845 !gdk_window_is_offscreen (window) &&
846 /* or for non-shaped toplevels */
847 (!gdk_window_is_toplevel (window) ||
848 window->shape != NULL || window->applied_shape) &&
849 /* or for foreign windows */
850 window->window_type != GDK_WINDOW_FOREIGN &&
851 /* or for the root window */
852 window->window_type != GDK_WINDOW_ROOT;
853}
854
855static void
856apply_shape (GdkWindow *window,
857 cairo_region_t *region)
858{
859 GdkWindowImplClass *impl_class;
860
861 /* We trash whether we applied a shape so that
862 we can avoid unsetting it many times, which
863 could happen in e.g. apply_clip_as_shape as
864 windows get resized */
865 impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
866 if (region)
867 impl_class->shape_combine_region (window,
868 region, 0, 0);
869 else if (window->applied_shape)
870 impl_class->shape_combine_region (window,
871 NULL, 0, 0);
872
873 window->applied_shape = region != NULL;
874}
875
876static gboolean
877region_rect_equal (const cairo_region_t *region,
878 const GdkRectangle *rect)
879{
880 GdkRectangle extents;
881
882 if (cairo_region_num_rectangles (region) != 1)
883 return FALSE;
884
885 cairo_region_get_extents (region, &extents);
886
887 return extents.x == rect->x &&
888 extents.y == rect->y &&
889 extents.width == rect->width &&
890 extents.height == rect->height;
891}
892
893static void
894apply_clip_as_shape (GdkWindow *window)
895{
896 GdkRectangle r;
897 cairo_region_t *region;
898
899 r.x = r.y = 0;
900 r.width = window->width;
901 r.height = window->height;
902
903 region = cairo_region_copy (window->clip_region);
904 remove_sibling_overlapped_area (window, region);
905
906 /* We only apply the clip region if would differ
907 from the actual clip region implied by the size
908 of the window. This is to avoid unneccessarily
909 adding meaningless shapes to all native subwindows */
910 if (!region_rect_equal (region, &r))
911 apply_shape (window, region);
912 else
913 apply_shape (window, NULL);
914
915 cairo_region_destroy (region);
916}
917
918static void
919recompute_visible_regions_internal (GdkWindow *private,
920 gboolean recalculate_clip,
921 gboolean recalculate_children)
922{
923 GdkRectangle r;
924 GList *l;
925 GdkWindow *child;
926 cairo_region_t *new_clip;
927 gboolean clip_region_changed;
928 gboolean abs_pos_changed;
929 int old_abs_x, old_abs_y;
930
931 old_abs_x = private->abs_x;
932 old_abs_y = private->abs_y;
933
934 /* Update absolute position */
935 if (gdk_window_has_impl (private))
936 {
937 /* Native window starts here */
938 private->abs_x = 0;
939 private->abs_y = 0;
940 }
941 else
942 {
943 private->abs_x = private->parent->abs_x + private->x;
944 private->abs_y = private->parent->abs_y + private->y;
945 }
946
947 abs_pos_changed =
948 private->abs_x != old_abs_x ||
949 private->abs_y != old_abs_y;
950
951 /* Update clip region based on:
952 * parent clip
953 * window size/position
954 */
955 clip_region_changed = FALSE;
956 if (recalculate_clip)
957 {
958 if (private->viewable)
959 {
960 /* Calculate visible region (sans children) in parent window coords */
961 r.x = private->x;
962 r.y = private->y;
963 r.width = private->width;
964 r.height = private->height;
965 new_clip = cairo_region_create_rectangle (&r);
966
967 if (!gdk_window_is_toplevel (private))
968 cairo_region_intersect (new_clip, private->parent->clip_region);
969
970 /* Convert from parent coords to window coords */
971 cairo_region_translate (new_clip, -private->x, -private->y);
972
973 if (should_apply_clip_as_shape (private) && private->shape)
974 cairo_region_intersect (new_clip, private->shape);
975 }
976 else
977 new_clip = cairo_region_create ();
978
979 if (private->clip_region == NULL ||
980 !cairo_region_equal (private->clip_region, new_clip))
981 clip_region_changed = TRUE;
982
983 if (private->clip_region)
984 cairo_region_destroy (private->clip_region);
985 private->clip_region = new_clip;
986 }
987
988 if (clip_region_changed)
989 {
990 GdkVisibilityState visibility;
991 gboolean fully_visible;
992
993 if (cairo_region_is_empty (private->clip_region))
994 visibility = GDK_VISIBILITY_FULLY_OBSCURED;
995 else
996 {
997 if (private->shape)
998 {
999 fully_visible = cairo_region_equal (private->clip_region,
1000 private->shape);
1001 }
1002 else
1003 {
1004 r.x = 0;
1005 r.y = 0;
1006 r.width = private->width;
1007 r.height = private->height;
1008 fully_visible = region_rect_equal (private->clip_region, &r);
1009 }
1010
1011 if (fully_visible)
1012 visibility = GDK_VISIBILITY_UNOBSCURED;
1013 else
1014 visibility = GDK_VISIBILITY_PARTIAL;
1015 }
1016
1017 if (private->visibility != visibility)
1018 {
1019 private->visibility = visibility;
1020 gdk_window_update_visibility (private);
1021 }
1022 }
1023
1024 /* Update all children, recursively (except for root, where children are not exact). */
1025 if ((abs_pos_changed || clip_region_changed || recalculate_children) &&
1026 private->window_type != GDK_WINDOW_ROOT)
1027 {
1028 for (l = private->children; l; l = l->next)
1029 {
1030 child = l->data;
1031 /* Only recalculate clip if the the clip region changed, otherwise
1032 * there is no way the child clip region could change (its has not e.g. moved)
1033 * Except if recalculate_children is set to force child updates
1034 */
1035 recompute_visible_regions_internal (child,
1036 recalculate_clip && (clip_region_changed || recalculate_children),
1037 FALSE);
1038 }
1039 }
1040}
1041
1042/* Call this when private has changed in one or more of these ways:
1043 * size changed
1044 * window moved
1045 * new window added
1046 * stacking order of window changed
1047 * child deleted
1048 *
1049 * It will recalculate abs_x/y and the clip regions
1050 *
1051 * Unless the window didn’t change stacking order or size/pos, pass in TRUE
1052 * for recalculate_siblings. (Mostly used internally for the recursion)
1053 *
1054 * If a child window was removed (and you can’t use that child for
1055 * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
1056 */
1057static void
1058recompute_visible_regions (GdkWindow *private,
1059 gboolean recalculate_children)
1060{
1061 GdkWindow *toplevel;
1062
1063 toplevel = gdk_window_get_toplevel (private);
1064 toplevel->geometry_dirty = TRUE;
1065
1066 recompute_visible_regions_internal (private,
1067 TRUE,
1068 recalculate_children);
1069}
1070
1071static void
1072gdk_window_clear_old_updated_area (GdkWindow *window)
1073{
1074 int i;
1075
1076 for (i = 0; i < 2; i++)
1077 {
1078 if (window->old_updated_area[i])
1079 {
1080 cairo_region_destroy (window->old_updated_area[i]);
1081 window->old_updated_area[i] = NULL;
1082 }
1083 }
1084}
1085
1086static void
1087gdk_window_append_old_updated_area (GdkWindow *window,
1088 cairo_region_t *region)
1089{
1090 if (window->old_updated_area[1])
1091 cairo_region_destroy (window->old_updated_area[1]);
1092 window->old_updated_area[1] = window->old_updated_area[0];
1093 window->old_updated_area[0] = cairo_region_reference (region);
1094}
1095
1096void
1097_gdk_window_update_size (GdkWindow *window)
1098{
1099 gdk_window_clear_old_updated_area (window);
1100 recompute_visible_regions (window, FALSE);
1101}
1102
1103/* Find the native window that would be just above "child"
1104 * in the native stacking order if “child” was a native window
1105 * (it doesn’t have to be native). If there is no such native
1106 * window inside this native parent then NULL is returned.
1107 * If child is NULL, find lowest native window in parent.
1108 */
1109static GdkWindow *
1110find_native_sibling_above_helper (GdkWindow *parent,
1111 GdkWindow *child)
1112{
1113 GdkWindow *w;
1114 GList *l;
1115
1116 if (child)
1117 {
1118 l = g_list_find (parent->children, child);
1119 g_assert (l != NULL); /* Better be a child of its parent... */
1120 l = l->prev; /* Start looking at the one above the child */
1121 }
1122 else
1123 l = g_list_last (parent->children);
1124
1125 for (; l != NULL; l = l->prev)
1126 {
1127 w = l->data;
1128
1129 if (gdk_window_has_impl (w))
1130 return w;
1131
1132 g_assert (parent != w);
1133 w = find_native_sibling_above_helper (w, NULL);
1134 if (w)
1135 return w;
1136 }
1137
1138 return NULL;
1139}
1140
1141
1142static GdkWindow *
1143find_native_sibling_above (GdkWindow *parent,
1144 GdkWindow *child)
1145{
1146 GdkWindow *w;
1147
1148 if (!parent)
1149 return NULL;
1150
1151 w = find_native_sibling_above_helper (parent, child);
1152 if (w)
1153 return w;
1154
1155 if (gdk_window_has_impl (parent))
1156 return NULL;
1157 else
1158 return find_native_sibling_above (parent->parent, parent);
1159}
1160
1161static GdkEventMask
1162get_native_device_event_mask (GdkWindow *private,
1163 GdkDevice *device)
1164{
1165 GdkEventMask event_mask;
1166
1167 if (device)
1168 event_mask = GPOINTER_TO_INT (g_hash_table_lookup (private->device_events, device));
1169 else
1170 event_mask = private->event_mask;
1171
1172 if (private->window_type == GDK_WINDOW_ROOT ||
1173 private->window_type == GDK_WINDOW_FOREIGN)
1174 return event_mask;
1175 else
1176 {
1177 GdkEventMask mask;
1178
1179 /* Do whatever the app asks to, since the app
1180 * may be asking for weird things for native windows,
1181 * but don't use motion hints as that may affect non-native
1182 * child windows that don't want it. Also, we need to
1183 * set all the app-specified masks since they will be picked
1184 * up by any implicit grabs (i.e. if they were not set as
1185 * native we would not get the events we need). */
1186 mask = private->event_mask & ~GDK_POINTER_MOTION_HINT_MASK;
1187
1188 /* We need thse for all native windows so we can
1189 emulate events on children: */
1190 mask |=
1191 GDK_EXPOSURE_MASK |
1192 GDK_VISIBILITY_NOTIFY_MASK |
1193 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK;
1194
1195 /* Additionally we select for pointer and button events
1196 * for toplevels as we need to get these to emulate
1197 * them for non-native subwindows. Even though we don't
1198 * select on them for all native windows we will get them
1199 * as the events are propagated out to the first window
1200 * that select for them.
1201 * Not selecting for button press on all windows is an
1202 * important thing, because in X only one client can do
1203 * so, and we don't want to unexpectedly prevent another
1204 * client from doing it.
1205 *
1206 * We also need to do the same if the app selects for button presses
1207 * because then we will get implicit grabs for this window, and the
1208 * event mask used for that grab is based on the rest of the mask
1209 * for the window, but we might need more events than this window
1210 * lists due to some non-native child window.
1211 */
1212 if (gdk_window_is_toplevel (private) ||
1213 mask & GDK_BUTTON_PRESS_MASK)
1214 mask |=
1215 GDK_TOUCH_MASK |
1216 GDK_POINTER_MOTION_MASK |
1217 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1218 GDK_SCROLL_MASK;
1219
1220 return mask;
1221 }
1222}
1223
1224static GdkEventMask
1225get_native_grab_event_mask (GdkEventMask grab_mask)
1226{
1227 /* Similar to the above but for pointer events only */
1228 return
1229 GDK_POINTER_MOTION_MASK |
1230 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1231 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
1232 GDK_SCROLL_MASK |
1233 (grab_mask &
1234 ~GDK_POINTER_MOTION_HINT_MASK);
1235}
1236
1237static GdkEventMask
1238get_native_event_mask (GdkWindow *private)
1239{
1240 return get_native_device_event_mask (private, NULL);
1241}
1242
1243/* Puts the native window in the right order wrt the other native windows
1244 * in the hierarchy, given the position it has in the client side data.
1245 * This is useful if some operation changed the stacking order.
1246 * This calls assumes the native window is now topmost in its native parent.
1247 */
1248static void
1249sync_native_window_stack_position (GdkWindow *window)
1250{
1251 GdkWindow *above;
1252 GdkWindowImplClass *impl_class;
1253 GList listhead = {0};
1254
1255 impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
1256
1257 above = find_native_sibling_above (window->parent, window);
1258 if (above)
1259 {
1260 listhead.data = window;
1261 impl_class->restack_under (above, &listhead);
1262 }
1263}
1264
1265/**
1266 * gdk_window_new: (constructor)
1267 * @parent: (allow-none): a #GdkWindow, or %NULL to create the window as a child of
1268 * the default root window for the default display.
1269 * @attributes: attributes of the new window
1270 * @attributes_mask: (type GdkWindowAttributesType): mask indicating which
1271 * fields in @attributes are valid
1272 *
1273 * Creates a new #GdkWindow using the attributes from
1274 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
1275 * more details. Note: to use this on displays other than the default
1276 * display, @parent must be specified.
1277 *
1278 * Returns: (transfer full): the new #GdkWindow
1279 **/
1280GdkWindow*
1281gdk_window_new (GdkWindow *parent,
1282 GdkWindowAttr *attributes,
1283 gint attributes_mask)
1284{
1285 GdkWindow *window;
1286 GdkScreen *screen;
1287 GdkDisplay *display;
1288 int x, y;
1289 gboolean native;
1290 GdkEventMask event_mask;
1291 GdkWindow *real_parent;
1292
1293 g_return_val_if_fail (attributes != NULL, NULL);
1294
1295 if (!parent)
1296 {
1297 screen = gdk_screen_get_default ();
1298 parent = gdk_screen_get_root_window (screen);
1299 }
1300 else
1301 screen = gdk_window_get_screen (parent);
1302
1303 g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
1304
1305 if (GDK_WINDOW_DESTROYED (parent))
1306 {
1307 g_warning ("gdk_window_new(): parent is destroyed");
1308 return NULL;
1309 }
1310
1311 if (attributes_mask & GDK_WA_VISUAL)
1312 {
1313 g_return_val_if_fail (gdk_visual_get_screen (attributes->visual) == screen, NULL);
1314 }
1315
1316 display = gdk_screen_get_display (screen);
1317
1318 window = _gdk_display_create_window (display);
1319
1320 /* Windows with a foreign parent are treated as if they are children
1321 * of the root window, except for actual creation.
1322 */
1323 real_parent = parent;
1324 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
1325 parent = gdk_screen_get_root_window (screen);
1326
1327 window->parent = parent;
1328
1329 window->accept_focus = TRUE;
1330 window->focus_on_map = TRUE;
1331 window->event_compression = TRUE;
1332
1333 if (attributes_mask & GDK_WA_X)
1334 x = attributes->x;
1335 else
1336 x = 0;
1337
1338 if (attributes_mask & GDK_WA_Y)
1339 y = attributes->y;
1340 else
1341 y = 0;
1342
1343 window->x = x;
1344 window->y = y;
1345 window->width = (attributes->width > 1) ? (attributes->width) : (1);
1346 window->height = (attributes->height > 1) ? (attributes->height) : (1);
1347 window->alpha = 255;
1348
1349 if (attributes->wclass == GDK_INPUT_ONLY)
1350 {
1351 /* Backwards compatiblity - we've always ignored
1352 * attributes->window_type for input-only windows
1353 * before
1354 */
1355 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
1356 window->window_type = GDK_WINDOW_TEMP;
1357 else
1358 window->window_type = GDK_WINDOW_CHILD;
1359 }
1360 else
1361 window->window_type = attributes->window_type;
1362
1363 /* Sanity checks */
1364 switch (window->window_type)
1365 {
1366 case GDK_WINDOW_TOPLEVEL:
1367 case GDK_WINDOW_TEMP:
1368 case GDK_WINDOW_OFFSCREEN:
1369 if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
1370 g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
1371 "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
1372 break;
1373 case GDK_WINDOW_SUBSURFACE:
1374#ifdef GDK_WINDOWING_WAYLAND
1375 if (!GDK_IS_WAYLAND_DISPLAY (display))
1376 {
1377 g_warning (G_STRLOC "Subsurface windows can only be used on Wayland");
1378 return NULL;
1379 }
1380#endif
1381 break;
1382 case GDK_WINDOW_CHILD:
1383 break;
1384 default:
1385 g_warning (G_STRLOC "cannot make windows of type %d", window->window_type);
1386 return NULL;
1387 }
1388
1389 if (attributes_mask & GDK_WA_VISUAL)
1390 window->visual = attributes->visual;
1391 else
1392 window->visual = gdk_screen_get_system_visual (screen);
1393
1394 window->event_mask = attributes->event_mask;
1395
1396 if (attributes->wclass == GDK_INPUT_OUTPUT)
1397 {
1398 window->input_only = FALSE;
1399 window->depth = window->visual->depth;
1400
1401 /* XXX: Cache this somehow? */
1402 window->background = cairo_pattern_create_rgba (0, 0, 0, 0);
1403 }
1404 else
1405 {
1406 window->depth = 0;
1407 window->input_only = TRUE;
1408 }
1409
1410 window->parent->children = g_list_concat (&window->children_list_node, window->parent->children);
1411
1412 if (window->parent->window_type == GDK_WINDOW_ROOT)
1413 {
1414 GdkFrameClock *frame_clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL);
1415 gdk_window_set_frame_clock (window, frame_clock);
1416 g_object_unref (frame_clock);
1417 }
1418
1419 native = FALSE;
1420 if (window->parent->window_type == GDK_WINDOW_ROOT)
1421 native = TRUE; /* Always use native windows for toplevels */
1422
1423 if (gdk_window_is_offscreen (window))
1424 {
1425 _gdk_offscreen_window_new (window, attributes, attributes_mask);
1426 window->impl_window = window;
1427 }
1428 else if (native)
1429 {
1430 event_mask = get_native_event_mask (window);
1431
1432 /* Create the impl */
1433 _gdk_display_create_window_impl (display, window, real_parent, screen, event_mask, attributes, attributes_mask);
1434 window->impl_window = window;
1435
1436 parent->impl_window->native_children = g_list_prepend (parent->impl_window->native_children, window);
1437
1438 /* This will put the native window topmost in the native parent, which may
1439 * be wrong wrt other native windows in the non-native hierarchy, so restack */
1440 if (!_gdk_window_has_impl (real_parent))
1441 sync_native_window_stack_position (window);
1442 }
1443 else
1444 {
1445 window->impl_window = g_object_ref (window->parent->impl_window);
1446 window->impl = g_object_ref (window->impl_window->impl);
1447 }
1448
1449 recompute_visible_regions (window, FALSE);
1450
1451 gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
1452 (attributes->cursor) :
1453 NULL));
1454
1455 g_signal_connect (gdk_window_get_display (parent), "seat-removed",
1456 G_CALLBACK (seat_removed_cb), window);
1457
1458 if ((_gdk_gl_flags & (GDK_GL_ALWAYS | GDK_GL_DISABLE)) == GDK_GL_ALWAYS)
1459 {
1460 GError *error = NULL;
1461
1462 if (gdk_window_get_paint_gl_context (window, &error) == NULL)
1463 {
1464 g_warning ("Unable to force GL enabled: %s", error->message);
1465 g_error_free (error);
1466 }
1467 }
1468
1469 return window;
1470}
1471
1472static gboolean
1473is_parent_of (GdkWindow *parent,
1474 GdkWindow *child)
1475{
1476 GdkWindow *w;
1477
1478 w = child;
1479 while (w != NULL)
1480 {
1481 if (w == parent)
1482 return TRUE;
1483
1484 w = gdk_window_get_parent (w);
1485 }
1486
1487 return FALSE;
1488}
1489
1490static void
1491change_impl (GdkWindow *private,
1492 GdkWindow *impl_window,
1493 GdkWindowImpl *new)
1494{
1495 GList *l;
1496 GdkWindow *child;
1497 GdkWindowImpl *old_impl;
1498 GdkWindow *old_impl_window;
1499
1500 old_impl = private->impl;
1501 old_impl_window = private->impl_window;
1502 if (private != impl_window)
1503 private->impl_window = g_object_ref (impl_window);
1504 else
1505 private->impl_window = private;
1506 private->impl = g_object_ref (new);
1507 if (old_impl_window != private)
1508 g_object_unref (old_impl_window);
1509 g_object_unref (old_impl);
1510
1511 for (l = private->children; l != NULL; l = l->next)
1512 {
1513 child = l->data;
1514
1515 if (child->impl == old_impl)
1516 change_impl (child, impl_window, new);
1517 else
1518 {
1519 /* The child is a native, update native_children */
1520 old_impl_window->native_children =
1521 g_list_remove (old_impl_window->native_children, child);
1522 impl_window->native_children =
1523 g_list_prepend (impl_window->native_children, child);
1524 }
1525 }
1526}
1527
1528static void
1529reparent_to_impl (GdkWindow *private)
1530{
1531 GList *l;
1532 GdkWindow *child;
1533 gboolean show;
1534 GdkWindowImplClass *impl_class;
1535
1536 impl_class = GDK_WINDOW_IMPL_GET_CLASS (private->impl);
1537
1538 /* Enumerate in reverse order so we get the right order for the native
1539 windows (first in childrens list is topmost, and reparent places on top) */
1540 for (l = g_list_last (private->children); l != NULL; l = l->prev)
1541 {
1542 child = l->data;
1543
1544 if (child->impl == private->impl)
1545 reparent_to_impl (child);
1546 else
1547 {
1548 show = impl_class->reparent ((GdkWindow *)child,
1549 (GdkWindow *)private,
1550 child->x, child->y);
1551 if (show)
1552 gdk_window_show_unraised ((GdkWindow *)child);
1553 }
1554 }
1555}
1556
1557
1558/**
1559 * gdk_window_reparent:
1560 * @window: a #GdkWindow
1561 * @new_parent: new parent to move @window into
1562 * @x: X location inside the new parent
1563 * @y: Y location inside the new parent
1564 *
1565 * Reparents @window into the given @new_parent. The window being
1566 * reparented will be unmapped as a side effect.
1567 *
1568 **/
1569void
1570gdk_window_reparent (GdkWindow *window,
1571 GdkWindow *new_parent,
1572 gint x,
1573 gint y)
1574{
1575 GdkWindow *old_parent;
1576 GdkScreen *screen;
1577 gboolean show, was_mapped;
1578 gboolean do_reparent_to_impl;
1579 GdkEventMask old_native_event_mask;
1580 GdkWindowImplClass *impl_class;
1581
1582 g_return_if_fail (GDK_IS_WINDOW (window));
1583 g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
1584 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
1585
1586 if (GDK_WINDOW_DESTROYED (window) ||
1587 (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
1588 return;
1589
1590 screen = gdk_window_get_screen (window);
1591 if (!new_parent)
1592 new_parent = gdk_screen_get_root_window (screen);
1593
1594 /* No input-output children of input-only windows */
1595 if (new_parent->input_only && !window->input_only)
1596 return;
1597
1598 /* Don't create loops in hierarchy */
1599 if (is_parent_of (window, new_parent))
1600 return;
1601
1602 impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
1603 old_parent = window->parent;
1604
1605 was_mapped = GDK_WINDOW_IS_MAPPED (window);
1606
1607 /* Reparenting to toplevel. Ensure we have a native window so this can work */
1608 if (new_parent->window_type == GDK_WINDOW_ROOT ||
1609 new_parent->window_type == GDK_WINDOW_FOREIGN)
1610 gdk_window_ensure_native (window);
1611
1612 old_native_event_mask = 0;
1613 do_reparent_to_impl = FALSE;
1614 if (gdk_window_has_impl (window))
1615 {
1616 old_native_event_mask = get_native_event_mask (window);
1617 /* Native window */
1618 show = impl_class->reparent (window, new_parent, x, y);
1619 }
1620 else
1621 {
1622 /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
1623 g_assert (new_parent->window_type != GDK_WINDOW_ROOT &&
1624 new_parent->window_type != GDK_WINDOW_FOREIGN);
1625
1626 show = was_mapped;
1627 gdk_window_hide (window);
1628
1629 do_reparent_to_impl = TRUE;
1630 change_impl (window,
1631 new_parent->impl_window,
1632 new_parent->impl);
1633 }
1634
1635 /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1636 * the root window
1637 */
1638 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1639 {
1640 new_parent = gdk_screen_get_root_window (screen);
1641 }
1642
1643 if (old_parent)
1644 {
1645 old_parent->children = g_list_remove_link (old_parent->children, &window->children_list_node);
1646
1647 if (gdk_window_has_impl (window))
1648 old_parent->impl_window->native_children =
1649 g_list_remove (old_parent->impl_window->native_children, window);
1650 }
1651
1652 window->parent = new_parent;
1653 window->x = x;
1654 window->y = y;
1655
1656 new_parent->children = g_list_concat (&window->children_list_node, new_parent->children);
1657
1658 if (gdk_window_has_impl (window))
1659 new_parent->impl_window->native_children = g_list_prepend (new_parent->impl_window->native_children, window);
1660
1661 /* Switch the window type as appropriate */
1662
1663 switch (GDK_WINDOW_TYPE (new_parent))
1664 {
1665 case GDK_WINDOW_ROOT:
1666 case GDK_WINDOW_FOREIGN:
1667 if (window->toplevel_window_type != -1)
1668 GDK_WINDOW_TYPE (window) = window->toplevel_window_type;
1669 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1670 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1671 break;
1672 case GDK_WINDOW_OFFSCREEN:
1673 case GDK_WINDOW_TOPLEVEL:
1674 case GDK_WINDOW_CHILD:
1675 case GDK_WINDOW_TEMP:
1676 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
1677 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
1678 {
1679 /* Save the original window type so we can restore it if the
1680 * window is reparented back to be a toplevel
1681 */
1682 window->toplevel_window_type = GDK_WINDOW_TYPE (window);
1683 GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1684 }
1685 }
1686
1687 /* If we changed the window type, we might have to set or
1688 * unset the frame clock on the window
1689 */
1690 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_ROOT &&
1691 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
1692 {
1693 if (window->frame_clock == NULL)
1694 {
1695 GdkFrameClock *frame_clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL);
1696 gdk_window_set_frame_clock (window, frame_clock);
1697 g_object_unref (frame_clock);
1698 }
1699 }
1700 else
1701 {
1702 if (window->frame_clock != NULL)
1703 {
1704 g_object_run_dispose (G_OBJECT (window->frame_clock));
1705 gdk_window_set_frame_clock (window, NULL);
1706 }
1707 }
1708
1709 /* We might have changed window type for a native windows, so we
1710 need to change the event mask too. */
1711 if (gdk_window_has_impl (window))
1712 {
1713 GdkEventMask native_event_mask = get_native_event_mask (window);
1714
1715 if (native_event_mask != old_native_event_mask)
1716 impl_class->set_events (window, native_event_mask);
1717 }
1718
1719 _gdk_window_update_viewable (window);
1720
1721 recompute_visible_regions (window, FALSE);
1722
1723 if (do_reparent_to_impl)
1724 reparent_to_impl (window);
1725 else
1726 {
1727 /* The reparent will have put the native window topmost in the native parent,
1728 * which may be wrong wrt other native windows in the non-native hierarchy,
1729 * so restack */
1730 if (!gdk_window_has_impl (new_parent))
1731 sync_native_window_stack_position (window);
1732 }
1733
1734 if (show)
1735 gdk_window_show_unraised (window);
1736 else
1737 _gdk_synthesize_crossing_events_for_geometry_change (window);
1738}
1739
1740/**
1741 * gdk_window_ensure_native:
1742 * @window: a #GdkWindow
1743 *
1744 * Tries to ensure that there is a window-system native window for this
1745 * GdkWindow. This may fail in some situations, returning %FALSE.
1746 *
1747 * Offscreen window and children of them can never have native windows.
1748 *
1749 * Some backends may not support native child windows.
1750 *
1751 * Returns: %TRUE if the window has a native window, %FALSE otherwise
1752 *
1753 * Since: 2.18
1754 */
1755gboolean
1756gdk_window_ensure_native (GdkWindow *window)
1757{
1758 GdkWindow *impl_window;
1759 GdkWindowImpl *new_impl, *old_impl;
1760 GdkDisplay *display;
1761 GdkScreen *screen;
1762 GdkWindow *above, *parent;
1763 GList listhead;
1764 GdkWindowImplClass *impl_class;
1765
1766 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1767
1768 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
1769 GDK_WINDOW_DESTROYED (window))
1770 return FALSE;
1771
1772 impl_window = gdk_window_get_impl_window (window);
1773
1774 if (gdk_window_is_offscreen (impl_window))
1775 return FALSE; /* native in offscreens not supported */
1776
1777 if (impl_window == window)
1778 /* Already has an impl, and its not offscreen . */
1779 return TRUE;
1780
1781 /* Need to create a native window */
1782
1783 screen = gdk_window_get_screen (window);
1784 display = gdk_screen_get_display (screen);
1785 parent = window->parent;
1786
1787 old_impl = window->impl;
1788 _gdk_display_create_window_impl (display,
1789 window, parent,
1790 screen,
1791 get_native_event_mask (window),
1792 NULL, 0);
1793 new_impl = window->impl;
1794
1795 parent->impl_window->native_children =
1796 g_list_prepend (parent->impl_window->native_children, window);
1797
1798 window->impl = old_impl;
1799 change_impl (window, window, new_impl);
1800
1801 impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
1802
1803 /* Native window creation will put the native window topmost in the
1804 * native parent, which may be wrong wrt the position of the previous
1805 * non-native window wrt to the other non-native children, so correct this.
1806 */
1807 above = find_native_sibling_above (parent, window);
1808 if (above)
1809 {
1810 listhead.data = window;
1811 listhead.prev = NULL;
1812 listhead.next = NULL;
1813 impl_class->restack_under ((GdkWindow *)above, &listhead);
1814 }
1815
1816 recompute_visible_regions (window, FALSE);
1817
1818 reparent_to_impl (window);
1819
1820 if (!window->input_only)
1821 impl_class->set_background (window, window->background);
1822
1823 impl_class->input_shape_combine_region (window,
1824 window->input_shape,
1825 0, 0);
1826
1827 if (gdk_window_is_viewable (window))
1828 impl_class->show (window, FALSE);
1829
1830 gdk_window_invalidate_in_parent (window);
1831
1832 return TRUE;
1833}
1834
1835/**
1836 * _gdk_event_filter_unref:
1837 * @window: (allow-none): A #GdkWindow, or %NULL to be the global window
1838 * @filter: A window filter
1839 *
1840 * Release a reference to @filter. Note this function may
1841 * mutate the list storage, so you need to handle this
1842 * if iterating over a list of filters.
1843 */
1844void
1845_gdk_event_filter_unref (GdkWindow *window,
1846 GdkEventFilter *filter)
1847{
1848 GList **filters;
1849 GList *tmp_list;
1850
1851 if (window == NULL)
1852 filters = &_gdk_default_filters;
1853 else
1854 filters = &window->filters;
1855
1856 tmp_list = *filters;
1857 while (tmp_list)
1858 {
1859 GdkEventFilter *iter_filter = tmp_list->data;
1860 GList *node;
1861
1862 node = tmp_list;
1863 tmp_list = tmp_list->next;
1864
1865 if (iter_filter != filter)
1866 continue;
1867
1868 g_assert (iter_filter->ref_count > 0);
1869
1870 filter->ref_count--;
1871 if (filter->ref_count != 0)
1872 continue;
1873
1874 *filters = g_list_remove_link (*filters, node);
1875 g_free (filter);
1876 g_list_free_1 (node);
1877 }
1878}
1879
1880static void
1881window_remove_filters (GdkWindow *window)
1882{
1883 while (window->filters)
1884 _gdk_event_filter_unref (window, window->filters->data);
1885}
1886
1887static void
1888update_pointer_info_foreach (GdkDisplay *display,
1889 GdkDevice *device,
1890 GdkPointerWindowInfo *pointer_info,
1891 gpointer user_data)
1892{
1893 GdkWindow *window = user_data;
1894
1895 if (pointer_info->toplevel_under_pointer == window)
1896 {
1897 g_object_unref (pointer_info->toplevel_under_pointer);
1898 pointer_info->toplevel_under_pointer = NULL;
1899 }
1900}
1901
1902static void
1903window_remove_from_pointer_info (GdkWindow *window,
1904 GdkDisplay *display)
1905{
1906 _gdk_display_pointer_info_foreach (display,
1907 update_pointer_info_foreach,
1908 window);
1909}
1910
1911static void
1912gdk_window_free_current_paint (GdkWindow *window)
1913{
1914 cairo_surface_destroy (window->current_paint.surface);
1915 window->current_paint.surface = NULL;
1916
1917 cairo_region_destroy (window->current_paint.region);
1918 window->current_paint.region = NULL;
1919
1920 cairo_region_destroy (window->current_paint.flushed_region);
1921 window->current_paint.flushed_region = NULL;
1922
1923 cairo_region_destroy (window->current_paint.need_blend_region);
1924 window->current_paint.need_blend_region = NULL;
1925
1926 window->current_paint.surface_needs_composite = FALSE;
1927}
1928
1929/**
1930 * _gdk_window_destroy_hierarchy:
1931 * @window: a #GdkWindow
1932 * @recursing: If %TRUE, then this is being called because a parent
1933 * was destroyed.
1934 * @recursing_native: If %TRUE, then this is being called because a native parent
1935 * was destroyed. This generally means that the call to the
1936 * windowing system to destroy the window can be omitted, since
1937 * it will be destroyed as a result of the parent being destroyed.
1938 * Unless @foreign_destroy.
1939 * @foreign_destroy: If %TRUE, the window or a parent was destroyed by some
1940 * external agency. The window has already been destroyed and no
1941 * windowing system calls should be made. (This may never happen
1942 * for some windowing systems.)
1943 *
1944 * Internal function to destroy a window. Like gdk_window_destroy(),
1945 * but does not drop the reference count created by gdk_window_new().
1946 **/
1947static void
1948_gdk_window_destroy_hierarchy (GdkWindow *window,
1949 gboolean recursing,
1950 gboolean recursing_native,
1951 gboolean foreign_destroy)
1952{
1953 GdkWindowImplClass *impl_class;
1954 GdkWindow *temp_window;
1955 GdkScreen *screen;
1956 GdkDisplay *display;
1957 GList *tmp;
1958
1959 g_return_if_fail (GDK_IS_WINDOW (window));
1960
1961 if (GDK_WINDOW_DESTROYED (window))
1962 return;
1963
1964 display = gdk_window_get_display (window);
1965 screen = gdk_window_get_screen (window);
1966 temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
1967 if (temp_window == window)
1968 g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
1969
1970 switch (window->window_type)
1971 {
1972 case GDK_WINDOW_ROOT:
1973 if (!screen->closed)
1974 {
1975 g_error ("attempted to destroy root window");
1976 break;
1977 }
1978 /* else fall thru */
1979 case GDK_WINDOW_TOPLEVEL:
1980 case GDK_WINDOW_CHILD:
1981 case GDK_WINDOW_TEMP:
1982 case GDK_WINDOW_FOREIGN:
1983 case GDK_WINDOW_OFFSCREEN:
1984 if (window->window_type == GDK_WINDOW_FOREIGN && !foreign_destroy)
1985 {
1986 /* Logically, it probably makes more sense to send
1987 * a "destroy yourself" message to the foreign window
1988 * whether or not it's in our hierarchy; but for historical
1989 * reasons, we only send "destroy yourself" messages to
1990 * foreign windows in our hierarchy.
1991 */
1992 if (window->parent)
1993 {
1994 impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
1995
1996 if (gdk_window_has_impl (window))
1997 impl_class->destroy_foreign (window);
1998 }
1999
2000 /* Also for historical reasons, we remove any filters
2001 * on a foreign window when it or a parent is destroyed;
2002 * this likely causes problems if two separate portions
2003 * of code are maintaining filter lists on a foreign window.
2004 */
2005 window_remove_filters (window);
2006 }
2007 else
2008 {
2009 if (window->parent)
2010 {
2011 if (window->parent->children)
2012 window->parent->children = g_list_remove_link (window->parent->children, &window->children_list_node);
2013
2014 if (gdk_window_has_impl (window))
2015 window->parent->impl_window->native_children =
2016 g_list_remove (window->parent->impl_window->native_children, window);
2017
2018 if (!recursing &&
2019 GDK_WINDOW_IS_MAPPED (window))
2020 {
2021 recompute_visible_regions (window, FALSE);
2022 gdk_window_invalidate_in_parent (window);
2023 }
2024 }
2025
2026 if (window->gl_paint_context)
2027 {
2028 /* Make sure to destroy if current */
2029 g_object_run_dispose (G_OBJECT (window->gl_paint_context));
2030 g_object_unref (window->gl_paint_context);
2031 window->gl_paint_context = NULL;
2032 }
2033
2034 if (window->frame_clock)
2035 {
2036 g_object_run_dispose (G_OBJECT (window->frame_clock));
2037 gdk_window_set_frame_clock (window, NULL);
2038 }
2039
2040 gdk_window_free_current_paint (window);
2041
2042 if (window->background)
2043 {
2044 cairo_pattern_destroy (window->background);
2045 window->background = NULL;
2046 }
2047
2048 if (window->window_type == GDK_WINDOW_FOREIGN)
2049 g_assert (window->children == NULL);
2050 else
2051 {
2052 tmp = window->children;
2053 window->children = NULL;
2054 /* No need to free children list, its all made up of in-struct nodes */
2055
2056 while (tmp)
2057 {
2058 temp_window = tmp->data;
2059 tmp = tmp->next;
2060
2061 if (temp_window)
2062 _gdk_window_destroy_hierarchy (temp_window,
2063 TRUE,
2064 recursing_native || gdk_window_has_impl (window),
2065 foreign_destroy);
2066 }
2067
2068
2069 if (gdk_window_has_impl (window))
2070 g_assert (window->native_children == NULL);
2071 }
2072
2073 _gdk_window_clear_update_area (window);
2074
2075 impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
2076
2077 if (gdk_window_has_impl (window))
2078 impl_class->destroy (window, recursing_native, foreign_destroy);
2079 else
2080 {
2081 /* hide to make sure we repaint and break grabs */
2082 gdk_window_hide (window);
2083 }
2084
2085 window->state |= GDK_WINDOW_STATE_WITHDRAWN;
2086 window->parent = NULL;
2087 window->destroyed = TRUE;
2088
2089 window_remove_filters (window);
2090
2091 window_remove_from_pointer_info (window, display);
2092
2093 if (window->clip_region)
2094 {
2095 cairo_region_destroy (window->clip_region);
2096 window->clip_region = NULL;
2097 }
2098 }
2099 break;
2100 }
2101}
2102
2103/**
2104 * _gdk_window_destroy:
2105 * @window: a #GdkWindow
2106 * @foreign_destroy: If %TRUE, the window or a parent was destroyed by some
2107 * external agency. The window has already been destroyed and no
2108 * windowing system calls should be made. (This may never happen
2109 * for some windowing systems.)
2110 *
2111 * Internal function to destroy a window. Like gdk_window_destroy(),
2112 * but does not drop the reference count created by gdk_window_new().
2113 **/
2114void
2115_gdk_window_destroy (GdkWindow *window,
2116 gboolean foreign_destroy)
2117{
2118 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
2119}
2120
2121/**
2122 * gdk_window_destroy:
2123 * @window: a #GdkWindow
2124 *
2125 * Destroys the window system resources associated with @window and decrements @window's
2126 * reference count. The window system resources for all children of @window are also
2127 * destroyed, but the children’s reference counts are not decremented.
2128 *
2129 * Note that a window will not be destroyed automatically when its reference count
2130 * reaches zero. You must call this function yourself before that happens.
2131 *
2132 **/
2133void
2134gdk_window_destroy (GdkWindow *window)
2135{
2136 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, FALSE);
2137 g_object_unref (window);
2138}
2139
2140/**
2141 * gdk_window_set_user_data:
2142 * @window: a #GdkWindow
2143 * @user_data: (allow-none) (type GObject.Object): user data
2144 *
2145 * For most purposes this function is deprecated in favor of
2146 * g_object_set_data(). However, for historical reasons GTK+ stores
2147 * the #GtkWidget that owns a #GdkWindow as user data on the
2148 * #GdkWindow. So, custom widget implementations should use
2149 * this function for that. If GTK+ receives an event for a #GdkWindow,
2150 * and the user data for the window is non-%NULL, GTK+ will assume the
2151 * user data is a #GtkWidget, and forward the event to that widget.
2152 *
2153 **/
2154void
2155gdk_window_set_user_data (GdkWindow *window,
2156 gpointer user_data)
2157{
2158 g_return_if_fail (GDK_IS_WINDOW (window));
2159
2160 window->user_data = user_data;
2161}
2162
2163/**
2164 * gdk_window_get_user_data:
2165 * @window: a #GdkWindow
2166 * @data: (out): return location for user data
2167 *
2168 * Retrieves the user data for @window, which is normally the widget
2169 * that @window belongs to. See gdk_window_set_user_data().
2170 *
2171 **/
2172void
2173gdk_window_get_user_data (GdkWindow *window,
2174 gpointer *data)
2175{
2176 *data = window->user_data;
2177}
2178
2179/**
2180 * gdk_window_get_window_type:
2181 * @window: a #GdkWindow
2182 *
2183 * Gets the type of the window. See #GdkWindowType.
2184 *
2185 * Returns: type of window
2186 **/
2187GdkWindowType
2188gdk_window_get_window_type (GdkWindow *window)
2189{
2190 g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
2191
2192 return GDK_WINDOW_TYPE (window);
2193}
2194
2195/**
2196 * gdk_window_get_visual:
2197 * @window: a #GdkWindow
2198 *
2199 * Gets the #GdkVisual describing the pixel format of @window.
2200 *
2201 * Returns: (transfer none): a #GdkVisual
2202 *
2203 * Since: 2.24
2204 **/
2205GdkVisual*
2206gdk_window_get_visual (GdkWindow *window)
2207{
2208 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2209
2210 return window->visual;
2211}
2212
2213/**
2214 * gdk_window_get_screen:
2215 * @window: a #GdkWindow
2216 *
2217 * Gets the #GdkScreen associated with a #GdkWindow.
2218 *
2219 * Returns: (transfer none): the #GdkScreen associated with @window
2220 *
2221 * Since: 2.24
2222 **/
2223GdkScreen*
2224gdk_window_get_screen (GdkWindow *window)
2225{
2226 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2227
2228 return gdk_visual_get_screen (window->visual);
2229}
2230
2231/**
2232 * gdk_window_get_display:
2233 * @window: a #GdkWindow
2234 *
2235 * Gets the #GdkDisplay associated with a #GdkWindow.
2236 *
2237 * Returns: (transfer none): the #GdkDisplay associated with @window
2238 *
2239 * Since: 2.24
2240 **/
2241GdkDisplay *
2242gdk_window_get_display (GdkWindow *window)
2243{
2244 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2245
2246 return gdk_screen_get_display (gdk_visual_get_screen (window->visual));
2247}
2248/**
2249 * gdk_window_is_destroyed:
2250 * @window: a #GdkWindow
2251 *
2252 * Check to see if a window is destroyed..
2253 *
2254 * Returns: %TRUE if the window is destroyed
2255 *
2256 * Since: 2.18
2257 **/
2258gboolean
2259gdk_window_is_destroyed (GdkWindow *window)
2260{
2261 return GDK_WINDOW_DESTROYED (window);
2262}
2263
2264static void
2265to_embedder (GdkWindow *window,
2266 gdouble offscreen_x,
2267 gdouble offscreen_y,
2268 gdouble *embedder_x,
2269 gdouble *embedder_y)
2270{
2271 g_signal_emit (window, signals[TO_EMBEDDER], 0,
2272 offscreen_x, offscreen_y,
2273 embedder_x, embedder_y);
2274}
2275
2276static void
2277from_embedder (GdkWindow *window,
2278 gdouble embedder_x,
2279 gdouble embedder_y,
2280 gdouble *offscreen_x,
2281 gdouble *offscreen_y)
2282{
2283 g_signal_emit (window, signals[FROM_EMBEDDER], 0,
2284 embedder_x, embedder_y,
2285 offscreen_x, offscreen_y);
2286}
2287
2288/**
2289 * gdk_window_has_native:
2290 * @window: a #GdkWindow
2291 *
2292 * Checks whether the window has a native window or not. Note that
2293 * you can use gdk_window_ensure_native() if a native window is needed.
2294 *
2295 * Returns: %TRUE if the @window has a native window, %FALSE otherwise.
2296 *
2297 * Since: 2.22
2298 */
2299gboolean
2300gdk_window_has_native (GdkWindow *window)
2301{
2302 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2303
2304 return window->parent == NULL || window->parent->impl != window->impl;
2305}
2306
2307/**
2308 * gdk_window_get_position:
2309 * @window: a #GdkWindow
2310 * @x: (out) (allow-none): X coordinate of window
2311 * @y: (out) (allow-none): Y coordinate of window
2312 *
2313 * Obtains the position of the window as reported in the
2314 * most-recently-processed #GdkEventConfigure. Contrast with
2315 * gdk_window_get_geometry() which queries the X server for the
2316 * current window position, regardless of which events have been
2317 * received or processed.
2318 *
2319 * The position coordinates are relative to the window’s parent window.
2320 *
2321 **/
2322void
2323gdk_window_get_position (GdkWindow *window,
2324 gint *x,
2325 gint *y)
2326{
2327 g_return_if_fail (GDK_IS_WINDOW (window));
2328
2329 if (x)
2330 *x = window->x;
2331 if (y)
2332 *y = window->y;
2333}
2334
2335/**
2336 * gdk_window_get_parent:
2337 * @window: a #GdkWindow
2338 *
2339 * Obtains the parent of @window, as known to GDK. Does not query the
2340 * X server; thus this returns the parent as passed to gdk_window_new(),
2341 * not the actual parent. This should never matter unless you’re using
2342 * Xlib calls mixed with GDK calls on the X11 platform. It may also
2343 * matter for toplevel windows, because the window manager may choose
2344 * to reparent them.
2345 *
2346 * Note that you should use gdk_window_get_effective_parent() when
2347 * writing generic code that walks up a window hierarchy, because
2348 * gdk_window_get_parent() will most likely not do what you expect if
2349 * there are offscreen windows in the hierarchy.
2350 *
2351 * Returns: (transfer none): parent of @window
2352 **/
2353GdkWindow*
2354gdk_window_get_parent (GdkWindow *window)
2355{
2356 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2357
2358 return window->parent;
2359}
2360
2361/**
2362 * gdk_window_get_effective_parent:
2363 * @window: a #GdkWindow
2364 *
2365 * Obtains the parent of @window, as known to GDK. Works like
2366 * gdk_window_get_parent() for normal windows, but returns the
2367 * window’s embedder for offscreen windows.
2368 *
2369 * See also: gdk_offscreen_window_get_embedder()
2370 *
2371 * Returns: (transfer none): effective parent of @window
2372 *
2373 * Since: 2.22
2374 **/
2375GdkWindow *
2376gdk_window_get_effective_parent (GdkWindow *window)
2377{
2378 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2379
2380 if (gdk_window_is_offscreen (window))
2381 return gdk_offscreen_window_get_embedder (window);
2382 else
2383 return window->parent;
2384}
2385
2386/**
2387 * gdk_window_get_toplevel:
2388 * @window: a #GdkWindow
2389 *
2390 * Gets the toplevel window that’s an ancestor of @window.
2391 *
2392 * Any window type but %GDK_WINDOW_CHILD is considered a
2393 * toplevel window, as is a %GDK_WINDOW_CHILD window that
2394 * has a root window as parent.
2395 *
2396 * Note that you should use gdk_window_get_effective_toplevel() when
2397 * you want to get to a window’s toplevel as seen on screen, because
2398 * gdk_window_get_toplevel() will most likely not do what you expect
2399 * if there are offscreen windows in the hierarchy.
2400 *
2401 * Returns: (transfer none): the toplevel window containing @window
2402 **/
2403GdkWindow *
2404gdk_window_get_toplevel (GdkWindow *window)
2405{
2406 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2407
2408 while (window->window_type == GDK_WINDOW_CHILD)
2409 {
2410 if (gdk_window_is_toplevel (window))
2411 break;
2412 window = window->parent;
2413 }
2414
2415 return window;
2416}
2417
2418/**
2419 * gdk_window_get_effective_toplevel:
2420 * @window: a #GdkWindow
2421 *
2422 * Gets the toplevel window that’s an ancestor of @window.
2423 *
2424 * Works like gdk_window_get_toplevel(), but treats an offscreen window's
2425 * embedder as its parent, using gdk_window_get_effective_parent().
2426 *
2427 * See also: gdk_offscreen_window_get_embedder()
2428 *
2429 * Returns: (transfer none): the effective toplevel window containing @window
2430 *
2431 * Since: 2.22
2432 **/
2433GdkWindow *
2434gdk_window_get_effective_toplevel (GdkWindow *window)
2435{
2436 GdkWindow *parent;
2437
2438 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2439
2440 while ((parent = gdk_window_get_effective_parent (window)) != NULL &&
2441 (gdk_window_get_window_type (parent) != GDK_WINDOW_ROOT))
2442 window = parent;
2443
2444 return window;
2445}
2446
2447/**
2448 * gdk_window_get_children:
2449 * @window: a #GdkWindow
2450 *
2451 * Gets the list of children of @window known to GDK.
2452 * This function only returns children created via GDK,
2453 * so for example it’s useless when used with the root window;
2454 * it only returns windows an application created itself.
2455 *
2456 * The returned list must be freed, but the elements in the
2457 * list need not be.
2458 *
2459 * Returns: (transfer container) (element-type GdkWindow):
2460 * list of child windows inside @window
2461 **/
2462GList*
2463gdk_window_get_children (GdkWindow *window)
2464{
2465 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2466
2467 if (GDK_WINDOW_DESTROYED (window))
2468 return NULL;
2469
2470 return g_list_copy (window->children);
2471}
2472
2473/**
2474 * gdk_window_peek_children:
2475 * @window: a #GdkWindow
2476 *
2477 * Like gdk_window_get_children(), but does not copy the list of
2478 * children, so the list does not need to be freed.
2479 *
2480 * Returns: (transfer none) (element-type GdkWindow):
2481 * a reference to the list of child windows in @window
2482 **/
2483GList *
2484gdk_window_peek_children (GdkWindow *window)
2485{
2486 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2487
2488 if (GDK_WINDOW_DESTROYED (window))
2489 return NULL;
2490
2491 return window->children;
2492}
2493
2494
2495/**
2496 * gdk_window_get_children_with_user_data:
2497 * @window: a #GdkWindow
2498 * @user_data: user data to look for
2499 *
2500 * Gets the list of children of @window known to GDK with a
2501 * particular @user_data set on it.
2502 *
2503 * The returned list must be freed, but the elements in the
2504 * list need not be.
2505 *
2506 * The list is returned in (relative) stacking order, i.e. the
2507 * lowest window is first.
2508 *
2509 * Returns: (transfer container) (element-type GdkWindow):
2510 * list of child windows inside @window
2511 *
2512 * Since: 3.10
2513 **/
2514GList *
2515gdk_window_get_children_with_user_data (GdkWindow *window,
2516 gpointer user_data)
2517{
2518 GdkWindow *child;
2519 GList *res, *l;
2520
2521 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2522
2523 if (GDK_WINDOW_DESTROYED (window))
2524 return NULL;
2525
2526 res = NULL;
2527 for (l = window->children; l != NULL; l = l->next)
2528 {
2529 child = l->data;
2530
2531 if (child->user_data == user_data)
2532 res = g_list_prepend (res, child);
2533 }
2534
2535 return res;
2536}
2537
2538
2539/**
2540 * gdk_window_add_filter: (skip)
2541 * @window: (allow-none): a #GdkWindow
2542 * @function: filter callback
2543 * @data: data to pass to filter callback
2544 *
2545 * Adds an event filter to @window, allowing you to intercept events
2546 * before they reach GDK. This is a low-level operation and makes it
2547 * easy to break GDK and/or GTK+, so you have to know what you're
2548 * doing. Pass %NULL for @window to get all events for all windows,
2549 * instead of events for a specific window.
2550 *
2551 * If you are interested in X GenericEvents, bear in mind that
2552 * XGetEventData() has been already called on the event, and
2553 * XFreeEventData() must not be called within @function.
2554 **/
2555void
2556gdk_window_add_filter (GdkWindow *window,
2557 GdkFilterFunc function,
2558 gpointer data)
2559{
2560 GList *tmp_list;
2561 GdkEventFilter *filter;
2562
2563 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2564
2565 if (window && GDK_WINDOW_DESTROYED (window))
2566 return;
2567
2568 /* Filters are for the native events on the native window, so
2569 ensure there is a native window. */
2570 if (window)
2571 gdk_window_ensure_native (window);
2572
2573 if (window)
2574 tmp_list = window->filters;
2575 else
2576 tmp_list = _gdk_default_filters;
2577
2578 while (tmp_list)
2579 {
2580 filter = (GdkEventFilter *)tmp_list->data;
2581 if ((filter->function == function) && (filter->data == data))
2582 {
2583 filter->ref_count++;
2584 return;
2585 }
2586 tmp_list = tmp_list->next;
2587 }
2588
2589 filter = g_new (GdkEventFilter, 1);
2590 filter->function = function;
2591 filter->data = data;
2592 filter->ref_count = 1;
2593 filter->flags = 0;
2594
2595 if (window)
2596 window->filters = g_list_append (window->filters, filter);
2597 else
2598 _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
2599}
2600
2601/**
2602 * gdk_window_remove_filter: (skip)
2603 * @window: a #GdkWindow
2604 * @function: previously-added filter function
2605 * @data: user data for previously-added filter function
2606 *
2607 * Remove a filter previously added with gdk_window_add_filter().
2608 */
2609void
2610gdk_window_remove_filter (GdkWindow *window,
2611 GdkFilterFunc function,
2612 gpointer data)
2613{
2614 GList *tmp_list;
2615 GdkEventFilter *filter;
2616
2617 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2618
2619 if (window)
2620 tmp_list = window->filters;
2621 else
2622 tmp_list = _gdk_default_filters;
2623
2624 while (tmp_list)
2625 {
2626 filter = (GdkEventFilter *)tmp_list->data;
2627 tmp_list = tmp_list->next;
2628
2629 if ((filter->function == function) && (filter->data == data))
2630 {
2631 filter->flags |= GDK_EVENT_FILTER_REMOVED;
2632
2633 _gdk_event_filter_unref (window, filter);
2634
2635 return;
2636 }
2637 }
2638}
2639
2640/**
2641 * gdk_screen_get_toplevel_windows:
2642 * @screen: The #GdkScreen where the toplevels are located.
2643 *
2644 * Obtains a list of all toplevel windows known to GDK on the screen @screen.
2645 * A toplevel window is a child of the root window (see
2646 * gdk_get_default_root_window()).
2647 *
2648 * The returned list should be freed with g_list_free(), but
2649 * its elements need not be freed.
2650 *
2651 * Returns: (transfer container) (element-type GdkWindow):
2652 * list of toplevel windows, free with g_list_free()
2653 *
2654 * Since: 2.2
2655 **/
2656GList *
2657gdk_screen_get_toplevel_windows (GdkScreen *screen)
2658{
2659 GdkWindow * root_window;
2660 GList *new_list = NULL;
2661 GList *tmp_list;
2662
2663 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
2664
2665 root_window = gdk_screen_get_root_window (screen);
2666
2667 tmp_list = root_window->children;
2668 while (tmp_list)
2669 {
2670 GdkWindow *w = tmp_list->data;
2671
2672 if (w->window_type != GDK_WINDOW_FOREIGN)
2673 new_list = g_list_prepend (new_list, w);
2674 tmp_list = tmp_list->next;
2675 }
2676
2677 return new_list;
2678}
2679
2680/**
2681 * gdk_window_is_visible:
2682 * @window: a #GdkWindow
2683 *
2684 * Checks whether the window has been mapped (with gdk_window_show() or
2685 * gdk_window_show_unraised()).
2686 *
2687 * Returns: %TRUE if the window is mapped
2688 **/
2689gboolean
2690gdk_window_is_visible (GdkWindow *window)
2691{
2692 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2693
2694 return GDK_WINDOW_IS_MAPPED (window);
2695}
2696
2697/**
2698 * gdk_window_is_viewable:
2699 * @window: a #GdkWindow
2700 *
2701 * Check if the window and all ancestors of the window are
2702 * mapped. (This is not necessarily "viewable" in the X sense, since
2703 * we only check as far as we have GDK window parents, not to the root
2704 * window.)
2705 *
2706 * Returns: %TRUE if the window is viewable
2707 **/
2708gboolean
2709gdk_window_is_viewable (GdkWindow *window)
2710{
2711 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2712
2713 if (window->destroyed)
2714 return FALSE;
2715
2716 return window->viewable;
2717}
2718
2719/**
2720 * gdk_window_get_state:
2721 * @window: a #GdkWindow
2722 *
2723 * Gets the bitwise OR of the currently active window state flags,
2724 * from the #GdkWindowState enumeration.
2725 *
2726 * Returns: window state bitfield
2727 **/
2728GdkWindowState
2729gdk_window_get_state (GdkWindow *window)
2730{
2731 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2732
2733 return window->state;
2734}
2735
2736static cairo_content_t
2737gdk_window_get_content (GdkWindow *window)
2738{
2739 cairo_surface_t *surface;
2740 cairo_content_t content;
2741
2742 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
2743
2744 surface = gdk_window_ref_impl_surface (window);
2745 content = cairo_surface_get_content (surface);
2746 cairo_surface_destroy (surface);
2747
2748 return content;
2749}
2750
2751static cairo_surface_t *
2752gdk_window_ref_impl_surface (GdkWindow *window)
2753{
2754 return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->ref_cairo_surface (gdk_window_get_impl_window (window));
2755}
2756
2757GdkGLContext *
2758gdk_window_get_paint_gl_context (GdkWindow *window,
2759 GError **error)
2760{
2761 GError *internal_error = NULL;
2762
2763 if (_gdk_gl_flags & GDK_GL_DISABLE)
2764 {
2765 g_set_error_literal (error, GDK_GL_ERROR,
2766 GDK_GL_ERROR_NOT_AVAILABLE,
2767 _("GL support disabled via GDK_DEBUG"));
2768 return NULL;
2769 }
2770
2771 if (window->impl_window->gl_paint_context == NULL)
2772 {
2773 GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
2774
2775 if (impl_class->create_gl_context == NULL)
2776 {
2777 g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
2778 _("The current backend does not support OpenGL"));
2779 return NULL;
2780 }
2781
2782 window->impl_window->gl_paint_context =
2783 impl_class->create_gl_context (window->impl_window,
2784 TRUE,
2785 NULL,
2786 &internal_error);
2787 }
2788
2789 if (internal_error != NULL)
2790 {
2791 g_propagate_error (error, internal_error);
2792 g_clear_object (&(window->impl_window->gl_paint_context));
2793 return NULL;
2794 }
2795
2796 gdk_gl_context_realize (window->impl_window->gl_paint_context, &internal_error);
2797 if (internal_error != NULL)
2798 {
2799 g_propagate_error (error, internal_error);
2800 g_clear_object (&(window->impl_window->gl_paint_context));
2801 return NULL;
2802 }
2803
2804 return window->impl_window->gl_paint_context;
2805}
2806
2807/**
2808 * gdk_window_create_gl_context:
2809 * @window: a #GdkWindow
2810 * @error: return location for an error
2811 *
2812 * Creates a new #GdkGLContext matching the
2813 * framebuffer format to the visual of the #GdkWindow. The context
2814 * is disconnected from any particular window or surface.
2815 *
2816 * If the creation of the #GdkGLContext failed, @error will be set.
2817 *
2818 * Before using the returned #GdkGLContext, you will need to
2819 * call gdk_gl_context_make_current() or gdk_gl_context_realize().
2820 *
2821 * Returns: (transfer full): the newly created #GdkGLContext, or
2822 * %NULL on error
2823 *
2824 * Since: 3.16
2825 **/
2826GdkGLContext *
2827gdk_window_create_gl_context (GdkWindow *window,
2828 GError **error)
2829{
2830 GdkGLContext *paint_context;
2831
2832 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2833 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2834
2835 paint_context = gdk_window_get_paint_gl_context (window, error);
2836 if (paint_context == NULL)
2837 return NULL;
2838
2839 return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->create_gl_context (window->impl_window,
2840 FALSE,
2841 paint_context,
2842 error);
2843}
2844
2845static void
2846gdk_window_begin_paint_internal (GdkWindow *window,
2847 const cairo_region_t *region)
2848{
2849 GdkRectangle clip_box;
2850 GdkWindowImplClass *impl_class;
2851 double sx, sy;
2852 gboolean needs_surface;
2853 cairo_content_t surface_content;
2854
2855 if (GDK_WINDOW_DESTROYED (window) ||
2856 !gdk_window_has_impl (window))
2857 return;
2858
2859 if (window->current_paint.surface != NULL)
2860 {
2861 g_warning ("A paint operation on the window is alredy in progress. "
2862 "This is not allowed.");
2863 return;
2864 }
2865
2866 impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
2867
2868 needs_surface = TRUE;
2869 if (impl_class->begin_paint)
2870 needs_surface = impl_class->begin_paint (window);
2871
2872 window->current_paint.region = cairo_region_copy (region);
2873 cairo_region_intersect (window->current_paint.region, window->clip_region);
2874 cairo_region_get_extents (window->current_paint.region, &clip_box);
2875
2876 window->current_paint.flushed_region = cairo_region_create ();
2877 window->current_paint.need_blend_region = cairo_region_create ();
2878
2879 surface_content = gdk_window_get_content (window);
2880
2881 window->current_paint.use_gl = window->impl_window->gl_paint_context != NULL;
2882
2883 if (window->current_paint.use_gl)
2884 {
2885 GdkGLContext *context;
2886
2887 int ww = gdk_window_get_width (window) * gdk_window_get_scale_factor (window);
2888 int wh = gdk_window_get_height (window) * gdk_window_get_scale_factor (window);
2889
2890 context = gdk_window_get_paint_gl_context (window, NULL);
2891 if (context == NULL)
2892 {
2893 g_warning ("gl rendering failed, context: %p", context);
2894 window->current_paint.use_gl = FALSE;
2895 }
2896 else
2897 {
2898 gdk_gl_context_make_current (context);
2899 /* With gl we always need a surface to combine the gl
2900 drawing with the native drawing. */
2901 needs_surface = TRUE;
2902 /* Also, we need the surface to include alpha */
2903 surface_content = CAIRO_CONTENT_COLOR_ALPHA;
2904
2905 /* Initial setup */
2906 glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
2907 glDisable (GL_DEPTH_TEST);
2908 glDisable(GL_BLEND);
2909 glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
2910
2911 glViewport (0, 0, ww, wh);
2912 }
2913 }
2914
2915 if (needs_surface)
2916 {
2917 window->current_paint.surface = gdk_window_create_similar_surface (window,
2918 surface_content,
2919 MAX (clip_box.width, 1),
2920 MAX (clip_box.height, 1));
2921 sx = sy = 1;
2922 cairo_surface_get_device_scale (window->current_paint.surface, &sx, &sy);
2923 cairo_surface_set_device_offset (window->current_paint.surface, -clip_box.x*sx, -clip_box.y*sy);
2924 gdk_cairo_surface_mark_as_direct (window->current_paint.surface, window);
2925
2926 window->current_paint.surface_needs_composite = TRUE;
2927 }
2928 else
2929 {
2930 window->current_paint.surface = gdk_window_ref_impl_surface (window);
2931 window->current_paint.surface_needs_composite = FALSE;
2932 }
2933
2934 if (!cairo_region_is_empty (window->current_paint.region))
2935 gdk_window_clear_backing_region (window);
2936}
2937
2938static void
2939gdk_window_end_paint_internal (GdkWindow *window)
2940{
2941 GdkWindow *composited;
2942 GdkWindowImplClass *impl_class;
2943 GdkRectangle clip_box = { 0, };
2944 cairo_t *cr;
2945
2946 if (GDK_WINDOW_DESTROYED (window) ||
2947 !gdk_window_has_impl (window))
2948 return;
2949
2950 if (window->current_paint.surface == NULL)
2951 {
2952 g_warning (G_STRLOC": no preceding call to gdk_window_begin_draw_frame(), see documentation");
2953 return;
2954 }
2955
2956 impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
2957
2958 if (impl_class->end_paint)
2959 impl_class->end_paint (window);
2960
2961 if (window->current_paint.surface_needs_composite)
2962 {
2963 cairo_surface_t *surface;
2964
2965 cairo_region_get_extents (window->current_paint.region, &clip_box);
2966
2967 if (window->current_paint.use_gl)
2968 {
2969 cairo_region_t *opaque_region = cairo_region_copy (window->current_paint.region);
2970 cairo_region_subtract (opaque_region, window->current_paint.flushed_region);
2971 cairo_region_subtract (opaque_region, window->current_paint.need_blend_region);
2972
2973 gdk_gl_context_make_current (window->gl_paint_context);
2974
2975 if (!cairo_region_is_empty (opaque_region))
2976 gdk_gl_texture_from_surface (window->current_paint.surface,
2977 opaque_region);
2978 if (!cairo_region_is_empty (window->current_paint.need_blend_region))
2979 {
2980 glEnable(GL_BLEND);
2981 gdk_gl_texture_from_surface (window->current_paint.surface,
2982 window->current_paint.need_blend_region);
2983 glDisable(GL_BLEND);
2984 }
2985
2986 cairo_region_destroy (opaque_region);
2987
2988 gdk_gl_context_end_frame (window->gl_paint_context,
2989 window->current_paint.region,
2990 window->active_update_area);
2991 }
2992 else
2993 {
2994 surface = gdk_window_ref_impl_surface (window);
2995 cr = cairo_create (surface);
2996
2997 cairo_set_source_surface (cr, window->current_paint.surface, 0, 0);
2998 gdk_cairo_region (cr, window->current_paint.region);
2999 cairo_clip (cr);
3000
3001 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3002 cairo_paint (cr);
3003
3004 cairo_destroy (cr);
3005
3006 cairo_surface_flush (surface);
3007 cairo_surface_destroy (surface);
3008 }
3009 }
3010
3011 gdk_window_free_current_paint (window);
3012
3013 /* find a composited window in our hierarchy to signal its
3014 * parent to redraw, calculating the clip box as we go...
3015 *
3016 * stop if parent becomes NULL since then we'd have nowhere
3017 * to draw (ie: 'composited' will always be non-NULL here).
3018 */
3019 for (composited = window;
3020 composited->parent;
3021 composited = composited->parent)
3022 {
3023 clip_box.x += composited->x;
3024 clip_box.y += composited->y;
3025 clip_box.width = MIN (clip_box.width, composited->parent->width - clip_box.x);
3026 clip_box.height = MIN (clip_box.height, composited->parent->height - clip_box.y);
3027
3028 if (composited->composited)
3029 {
3030 gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
3031 &clip_box, FALSE);
3032 break;
3033 }
3034 }
3035}
3036
3037/**
3038 * gdk_window_begin_paint_rect:
3039 * @window: a #GdkWindow
3040 * @rectangle: rectangle you intend to draw to
3041 *
3042 * A convenience wrapper around gdk_window_begin_paint_region() which
3043 * creates a rectangular region for you. See
3044 * gdk_window_begin_paint_region() for details.
3045 *
3046 * Deprecated: 3.22: Use gdk_window_begin_draw_frame() instead
3047 */
3048void
3049gdk_window_begin_paint_rect (GdkWindow *window,
3050 const GdkRectangle *rectangle)
3051{
3052 cairo_region_t *region;
3053
3054 g_return_if_fail (GDK_IS_WINDOW (window));
3055
3056 region = cairo_region_create_rectangle (rectangle);
3057 gdk_window_begin_paint_internal (window, region);
3058 cairo_region_destroy (region);
3059}
3060
3061/**
3062 * gdk_window_begin_paint_region:
3063 * @window: a #GdkWindow
3064 * @region: region you intend to draw to
3065 *
3066 * Indicates that you are beginning the process of redrawing @region.
3067 * A backing store (offscreen buffer) large enough to contain @region
3068 * will be created. The backing store will be initialized with the
3069 * background color or background surface for @window. Then, all
3070 * drawing operations performed on @window will be diverted to the
3071 * backing store. When you call gdk_window_end_paint(), the backing
3072 * store will be copied to @window, making it visible onscreen. Only
3073 * the part of @window contained in @region will be modified; that is,
3074 * drawing operations are clipped to @region.
3075 *
3076 * The net result of all this is to remove flicker, because the user
3077 * sees the finished product appear all at once when you call
3078 * gdk_window_end_paint(). If you draw to @window directly without
3079 * calling gdk_window_begin_paint_region(), the user may see flicker
3080 * as individual drawing operations are performed in sequence. The
3081 * clipping and background-initializing features of
3082 * gdk_window_begin_paint_region() are conveniences for the
3083 * programmer, so you can avoid doing that work yourself.
3084 *
3085 * When using GTK+, the widget system automatically places calls to
3086 * gdk_window_begin_paint_region() and gdk_window_end_paint() around
3087 * emissions of the expose_event signal. That is, if you’re writing an
3088 * expose event handler, you can assume that the exposed area in
3089 * #GdkEventExpose has already been cleared to the window background,
3090 * is already set as the clip region, and already has a backing store.
3091 * Therefore in most cases, application code need not call
3092 * gdk_window_begin_paint_region(). (You can disable the automatic
3093 * calls around expose events on a widget-by-widget basis by calling
3094 * gtk_widget_set_double_buffered().)
3095 *
3096 * If you call this function multiple times before calling the
3097 * matching gdk_window_end_paint(), the backing stores are pushed onto
3098 * a stack. gdk_window_end_paint() copies the topmost backing store
3099 * onscreen, subtracts the topmost region from all other regions in
3100 * the stack, and pops the stack. All drawing operations affect only
3101 * the topmost backing store in the stack. One matching call to
3102 * gdk_window_end_paint() is required for each call to
3103 * gdk_window_begin_paint_region().
3104 *
3105 * Deprecated: 3.22: Use gdk_window_begin_draw_frame() instead
3106 */
3107void
3108gdk_window_begin_paint_region (GdkWindow *window,
3109 const cairo_region_t *region)
3110{
3111 g_return_if_fail (GDK_IS_WINDOW (window));
3112
3113 gdk_window_begin_paint_internal (window, region);
3114}
3115
3116/**
3117 * gdk_window_begin_draw_frame:
3118 * @window: a #GdkWindow
3119 * @region: a Cairo region
3120 *
3121 * Indicates that you are beginning the process of redrawing @region
3122 * on @window, and provides you with a #GdkDrawingContext.
3123 *
3124 * If @window is a top level #GdkWindow, backed by a native window
3125 * implementation, a backing store (offscreen buffer) large enough to
3126 * contain @region will be created. The backing store will be initialized
3127 * with the background color or background surface for @window. Then, all
3128 * drawing operations performed on @window will be diverted to the
3129 * backing store. When you call gdk_window_end_frame(), the contents of
3130 * the backing store will be copied to @window, making it visible
3131 * on screen. Only the part of @window contained in @region will be
3132 * modified; that is, drawing operations are clipped to @region.
3133 *
3134 * The net result of all this is to remove flicker, because the user
3135 * sees the finished product appear all at once when you call
3136 * gdk_window_end_draw_frame(). If you draw to @window directly without
3137 * calling gdk_window_begin_draw_frame(), the user may see flicker
3138 * as individual drawing operations are performed in sequence.
3139 *
3140 * When using GTK+, the widget system automatically places calls to
3141 * gdk_window_begin_draw_frame() and gdk_window_end_draw_frame() around
3142 * emissions of the `GtkWidget::draw` signal. That is, if you’re
3143 * drawing the contents of the widget yourself, you can assume that the
3144 * widget has a cleared background, is already set as the clip region,
3145 * and already has a backing store. Therefore in most cases, application
3146 * code in GTK does not need to call gdk_window_begin_draw_frame()
3147 * explicitly.
3148 *
3149 * Returns: (transfer none): a #GdkDrawingContext context that should be
3150 * used to draw the contents of the window; the returned context is owned
3151 * by GDK.
3152 *
3153 * Since: 3.22
3154 */
3155GdkDrawingContext *
3156gdk_window_begin_draw_frame (GdkWindow *window,
3157 const cairo_region_t *region)
3158{
3159 GdkDrawingContext *context;
3160 GdkWindowImplClass *impl_class;
3161
3162 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
3163
3164 if (window->drawing_context != NULL)
3165 {
3166 g_critical ("The window %p already has a drawing context. You cannot "
3167 "call gdk_window_begin_draw_frame() without calling "
3168 "gdk_window_end_draw_frame() first.", window);
3169 return NULL;
3170 }
3171
3172 if (gdk_window_has_native (window) && gdk_window_is_toplevel (window))
3173 gdk_window_begin_paint_internal (window, region);
3174
3175 impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
3176 if (impl_class->create_draw_context != NULL)
3177 {
3178 context = impl_class->create_draw_context (window, region);
3179 }
3180 else
3181 {
3182 context = g_object_new (GDK_TYPE_DRAWING_CONTEXT,
3183 "window", window,
3184 "clip", region,
3185 NULL);
3186 }
3187
3188 /* Do not take a reference, to avoid creating cycles */
3189 window->drawing_context = context;
3190
3191 return context;
3192}
3193
3194/**
3195 * gdk_window_end_draw_frame:
3196 * @window: a #GdkWindow
3197 * @context: the #GdkDrawingContext created by gdk_window_begin_draw_frame()
3198 *
3199 * Indicates that the drawing of the contents of @window started with
3200 * gdk_window_begin_frame() has been completed.
3201 *
3202 * This function will take care of destroying the #GdkDrawingContext.
3203 *
3204 * It is an error to call this function without a matching
3205 * gdk_window_begin_frame() first.
3206 *
3207 * Since: 3.22
3208 */
3209void
3210gdk_window_end_draw_frame (GdkWindow *window,
3211 GdkDrawingContext *context)
3212{
3213 GdkWindowImplClass *impl_class;
3214
3215 g_return_if_fail (GDK_IS_WINDOW (window));
3216 g_return_if_fail (GDK_IS_DRAWING_CONTEXT (context));
3217
3218 if (window->drawing_context == NULL)
3219 {
3220 g_critical ("The window %p has no drawing context. You must call "
3221 "gdk_window_begin_draw_frame() before calling "
3222 "gdk_window_end_draw_frame().", window);
3223 return;
3224 }
3225
3226 if (gdk_window_has_native (window) && gdk_window_is_toplevel (window))
3227 gdk_window_end_paint_internal (window);
3228
3229 impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
3230 if (impl_class->destroy_draw_context != NULL)
3231 impl_class->destroy_draw_context (window, context);
3232 else
3233 g_object_unref (context);
3234
3235 window->drawing_context = NULL;
3236}
3237
3238/*< private >
3239 * gdk_window_get_current_paint_region:
3240 * @window: a #GdkWindow
3241 *
3242 * Retrieves a copy of the current paint region.
3243 *
3244 * Returns: (transfer full): a Cairo region
3245 */
3246cairo_region_t *
3247gdk_window_get_current_paint_region (GdkWindow *window)
3248{
3249 cairo_region_t *region;
3250
3251 if (window->impl_window->current_paint.region != NULL)
3252 {
3253 region = cairo_region_copy (window->impl_window->current_paint.region);
3254 cairo_region_translate (region, -window->abs_x, -window->abs_y);
3255 }
3256 else
3257 {
3258 region = cairo_region_copy (window->clip_region);
3259 }
3260
3261 return region;
3262}
3263
3264/*< private >
3265 * gdk_window_get_drawing_context:
3266 * @window: a #GdkWindow
3267 *
3268 * Retrieves the #GdkDrawingContext associated to @window by
3269 * gdk_window_begin_draw_frame().
3270 *
3271 * Returns: (transfer none) (nullable): a #GdkDrawingContext, if any is set
3272 */
3273GdkDrawingContext *
3274gdk_window_get_drawing_context (GdkWindow *window)
3275{
3276 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
3277
3278 if (GDK_WINDOW_DESTROYED (window))
3279 return NULL;
3280
3281 return window->drawing_context;
3282}
3283
3284/**
3285 * gdk_window_mark_paint_from_clip:
3286 * @window: a #GdkWindow
3287 * @cr: a #cairo_t
3288 *
3289 * If you call this during a paint (e.g. between gdk_window_begin_paint_region()
3290 * and gdk_window_end_paint() then GDK will mark the current clip region of the
3291 * window as being drawn. This is required when mixing GL rendering via
3292 * gdk_cairo_draw_from_gl() and cairo rendering, as otherwise GDK has no way
3293 * of knowing when something paints over the GL-drawn regions.
3294 *
3295 * This is typically called automatically by GTK+ and you don't need
3296 * to care about this.
3297 *
3298 * Since: 3.16
3299 **/
3300void
3301gdk_window_mark_paint_from_clip (GdkWindow *window,
3302 cairo_t *cr)
3303{
3304 cairo_region_t *clip_region;
3305 GdkWindow *impl_window = window->impl_window;
3306
3307 if (impl_window->current_paint.surface == NULL ||
3308 cairo_get_target (cr) != impl_window->current_paint.surface)
3309 return;
3310
3311 if (cairo_region_is_empty (impl_window->current_paint.flushed_region))
3312 return;
3313
3314 /* This here seems a bit weird, but basically, we're taking the current
3315 clip and applying also the flushed region, and the result is that the
3316 new clip is the intersection of these. This is the area where the newly
3317 drawn region overlaps a previosly flushed area, which is an area of the
3318 double buffer surface that need to be blended OVER the back buffer rather
3319 than SRCed. */
3320 cairo_save (cr);
3321 /* We set the identity matrix here so we get and apply regions in native
3322 window coordinates. */
3323 cairo_identity_matrix (cr);
3324 gdk_cairo_region (cr, impl_window->current_paint.flushed_region);
3325 cairo_clip (cr);
3326
3327 clip_region = gdk_cairo_region_from_clip (cr);
3328 if (clip_region == NULL)
3329 {
3330 /* Failed to represent clip as region, mark all as requiring
3331 blend */
3332 cairo_region_union (impl_window->current_paint.need_blend_region,
3333 impl_window->current_paint.flushed_region);
3334 cairo_region_destroy (impl_window->current_paint.flushed_region);
3335 impl_window->current_paint.flushed_region = cairo_region_create ();
3336 }
3337 else
3338 {
3339 cairo_region_subtract (impl_window->current_paint.flushed_region, clip_region);
3340 cairo_region_union (impl_window->current_paint.need_blend_region, clip_region);
3341 }
3342 cairo_region_destroy (clip_region);
3343
3344 /* Clear the area on the double buffer surface to transparent so we
3345 can start drawing from scratch the area "above" the flushed
3346 region */
3347 cairo_set_source_rgba (cr, 0, 0, 0, 0);
3348 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3349 cairo_paint (cr);
3350
3351 cairo_restore (cr);
3352}
3353
3354/**
3355 * gdk_window_end_paint:
3356 * @window: a #GdkWindow
3357 *
3358 * Indicates that the backing store created by the most recent call
3359 * to gdk_window_begin_paint_region() should be copied onscreen and
3360 * deleted, leaving the next-most-recent backing store or no backing
3361 * store at all as the active paint region. See
3362 * gdk_window_begin_paint_region() for full details.
3363 *
3364 * It is an error to call this function without a matching
3365 * gdk_window_begin_paint_region() first.
3366 **/
3367void
3368gdk_window_end_paint (GdkWindow *window)
3369{
3370 g_return_if_fail (GDK_IS_WINDOW (window));
3371
3372 gdk_window_end_paint_internal (window);
3373}
3374
3375/**
3376 * gdk_window_flush:
3377 * @window: a #GdkWindow
3378 *
3379 * This function does nothing.
3380 *
3381 * Since: 2.18
3382 *
3383 * Deprecated: 3.14
3384 **/
3385void
3386gdk_window_flush (GdkWindow *window)
3387{
3388}
3389
3390/**
3391 * gdk_window_get_clip_region:
3392 * @window: a #GdkWindow
3393 *
3394 * Computes the region of a window that potentially can be written
3395 * to by drawing primitives. This region may not take into account
3396 * other factors such as if the window is obscured by other windows,
3397 * but no area outside of this region will be affected by drawing
3398 * primitives.
3399 *
3400 * Returns: a #cairo_region_t. This must be freed with cairo_region_destroy()
3401 * when you are done.
3402 **/
3403cairo_region_t*
3404gdk_window_get_clip_region (GdkWindow *window)
3405{
3406 cairo_region_t *result;
3407
3408 g_return_val_if_fail (GDK_WINDOW (window), NULL);
3409
3410 result = cairo_region_copy (window->clip_region);
3411
3412 if (window->current_paint.region != NULL)
3413 cairo_region_intersect (result, window->current_paint.region);
3414
3415 return result;
3416}
3417
3418/**
3419 * gdk_window_get_visible_region:
3420 * @window: a #GdkWindow
3421 *
3422 * Computes the region of the @window that is potentially visible.
3423 * This does not necessarily take into account if the window is
3424 * obscured by other windows, but no area outside of this region
3425 * is visible.
3426 *
3427 * Returns: a #cairo_region_t. This must be freed with cairo_region_destroy()
3428 * when you are done.
3429 **/
3430cairo_region_t *
3431gdk_window_get_visible_region (GdkWindow *window)
3432{
3433 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
3434
3435 return cairo_region_copy (window->clip_region);
3436}
3437
3438static void
3439gdk_window_clear_backing_region (GdkWindow *window)
3440{
3441 GdkWindow *bg_window;
3442 cairo_pattern_t *pattern = NULL;
3443 int x_offset = 0, y_offset = 0;
3444 cairo_t *cr;
3445
3446 if (GDK_WINDOW_DESTROYED (window))
3447 return;
3448
3449 cr = cairo_create (window->current_paint.surface);
3450
3451 for (bg_window = window; bg_window; bg_window = bg_window->parent)
3452 {
3453 pattern = gdk_window_get_background_pattern (bg_window);
3454 if (pattern)
3455 break;
3456
3457 x_offset += bg_window->x;
3458 y_offset += bg_window->y;
3459 }
3460
3461 if (pattern)
3462 {
3463 cairo_translate (cr, -x_offset, -y_offset);
3464 cairo_set_source (cr, pattern);
3465 cairo_translate (cr, x_offset, y_offset);
3466 }
3467 else
3468 cairo_set_source_rgb (cr, 0, 0, 0);
3469
3470 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3471 gdk_cairo_region (cr, window->current_paint.region);
3472 cairo_fill (cr);
3473
3474 cairo_destroy (cr);
3475}
3476
3477/* This returns either the current working surface on the paint stack
3478 * or the actual impl surface of the window. This should not be used
3479 * from very many places: be careful! */
3480static cairo_surface_t *
3481ref_window_surface (GdkWindow *window)
3482{
3483 if (window->impl_window->current_paint.surface)
3484 return cairo_surface_reference (window->impl_window->current_paint.surface);
3485 else
3486 return gdk_window_ref_impl_surface (window);
3487}
3488
3489/* This is used in places like gdk_cairo_set_source_window and
3490 * other places to take "screenshots" of windows. Thus, we allow
3491 * it to be used outside of a begin_paint / end_paint. */
3492cairo_surface_t *
3493_gdk_window_ref_cairo_surface (GdkWindow *window)
3494{
3495 cairo_surface_t *surface;
3496
3497 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
3498
3499 surface = ref_window_surface (window);
3500
3501 if (gdk_window_has_impl (window))
3502 {
3503 return surface;
3504 }
3505 else
3506 {
3507 cairo_surface_t *subsurface;
3508 subsurface = cairo_surface_create_for_rectangle (surface,
3509 window->abs_x,
3510 window->abs_y,
3511 window->width,
3512 window->height);
3513 cairo_surface_destroy (surface);
3514 return subsurface;
3515 }
3516}
3517
3518/**
3519 * gdk_cairo_create:
3520 * @window: a #GdkWindow
3521 *
3522 * Creates a Cairo context for drawing to @window.
3523 *
3524 * Note that calling cairo_reset_clip() on the resulting #cairo_t will
3525 * produce undefined results, so avoid it at all costs.
3526 *
3527 * Typically, this function is used to draw on a #GdkWindow out of the paint
3528 * cycle of the toolkit; this should be avoided, as it breaks various assumptions
3529 * and optimizations.
3530 *
3531 * If you are drawing on a native #GdkWindow in response to a %GDK_EXPOSE event
3532 * you should use gdk_window_begin_draw_frame() and gdk_drawing_context_get_cairo_context()
3533 * instead. GTK will automatically do this for you when drawing a widget.
3534 *
3535 * Returns: A newly created Cairo context. Free with
3536 * cairo_destroy() when you are done drawing.
3537 *
3538 * Since: 2.8
3539 *
3540 * Deprecated: 3.22: Use gdk_window_begin_draw_frame() and
3541 * gdk_drawing_context_get_cairo_context() instead
3542 **/
3543cairo_t *
3544gdk_cairo_create (GdkWindow *window)
3545{
3546 cairo_region_t *region;
3547 cairo_surface_t *surface;
3548 cairo_t *cr;
3549
3550 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
3551
3552 surface = _gdk_window_ref_cairo_surface (window);
3553
3554 cr = cairo_create (surface);
3555
3556 region = gdk_window_get_current_paint_region (window);
3557 gdk_cairo_region (cr, region);
3558 cairo_region_destroy (region);
3559 cairo_clip (cr);
3560
3561 /* Assign a drawing context, if one is set; if gdk_cairo_create()
3562 * is called outside of a frame drawing then this is going to be
3563 * NULL.
3564 */
3565 gdk_cairo_set_drawing_context (cr, window->drawing_context);
3566
3567 cairo_surface_destroy (surface);
3568
3569 return cr;
3570}
3571
3572/* Code for dirty-region queueing
3573 */
3574static GSList *update_windows = NULL;
3575gboolean _gdk_debug_updates = FALSE;
3576
3577static inline gboolean
3578gdk_window_is_ancestor (GdkWindow *window,
3579 GdkWindow *ancestor)
3580{
3581 while (window)
3582 {
3583 GdkWindow *parent = window->parent;
3584
3585 if (parent == ancestor)
3586 return TRUE;
3587
3588 window = parent;
3589 }
3590
3591 return FALSE;
3592}
3593
3594static void
3595gdk_window_add_update_window (GdkWindow *window)
3596{
3597 GSList *tmp;
3598 GSList *prev = NULL;
3599 gboolean has_ancestor_in_list = FALSE;
3600
3601 /* Check whether "window" is already in "update_windows" list.
3602 * It could be added during execution of gtk_widget_destroy() when
3603 * setting focus widget to NULL and redrawing old focus widget.
3604 * See bug 711552.
3605 */
3606 tmp = g_slist_find (update_windows, window);
3607 if (tmp != NULL)
3608 return;
3609
3610 for (tmp = update_windows; tmp; tmp = tmp->next)
3611 {
3612 GdkWindow *parent = window->parent;
3613
3614 /* check if tmp is an ancestor of "window"; if it is, set a
3615 * flag indicating that all following windows are either
3616 * children of "window" or from a differen hierarchy
3617 */
3618 if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
3619 has_ancestor_in_list = TRUE;
3620
3621 /* insert in reverse stacking order when adding around siblings,
3622 * so processing updates properly paints over lower stacked windows
3623 */
3624 if (parent == GDK_WINDOW (tmp->data)->parent)
3625 {
3626 gint index = g_list_index (parent->children, window);
3627 for (; tmp && parent == GDK_WINDOW (tmp->data)->parent; tmp = tmp->next)
3628 {
3629 gint sibling_index = g_list_index (parent->children, tmp->data);
3630 if (index > sibling_index)
3631 break;
3632 prev = tmp;
3633 }
3634 /* here, tmp got advanced past all lower stacked siblings */
3635 tmp = g_slist_prepend (tmp, g_object_ref (window));
3636 if (prev)
3637 prev->next = tmp;
3638 else
3639 update_windows = tmp;
3640 return;
3641 }
3642
3643 /* if "window" has an ancestor in the list and tmp is one of
3644 * "window's" children, insert "window" before tmp
3645 */
3646 if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
3647 {
3648 tmp = g_slist_prepend (tmp, g_object_ref (window));
3649
3650 if (prev)
3651 prev->next = tmp;
3652 else
3653 update_windows = tmp;
3654 return;
3655 }
3656
3657 /* if we're at the end of the list and had an ancestor it it,
3658 * append to the list
3659 */
3660 if (! tmp->next && has_ancestor_in_list)
3661 {
3662 tmp = g_slist_append (tmp, g_object_ref (window));
3663 return;
3664 }
3665
3666 prev = tmp;
3667 }
3668
3669 /* if all above checks failed ("window" is from a different
3670 * hierarchy than what is already in the list) or the list is
3671 * empty, prepend
3672 */
3673 update_windows = g_slist_prepend (update_windows, g_object_ref (window));
3674}
3675
3676static void
3677gdk_window_remove_update_window (GdkWindow *window)
3678{
3679 GSList *link;
3680
3681 link = g_slist_find (update_windows, window);
3682 if (link != NULL)
3683 {
3684 update_windows = g_slist_delete_link (update_windows, link);
3685 g_object_unref (window);
3686 }
3687}
3688
3689static gboolean
3690gdk_window_is_toplevel_frozen (GdkWindow *window)
3691{
3692 GdkWindow *toplevel;
3693
3694 toplevel = gdk_window_get_toplevel (window);
3695
3696 return toplevel->update_and_descendants_freeze_count > 0;
3697}
3698
3699static void
3700gdk_window_schedule_update (GdkWindow *window)
3701{
3702 GdkFrameClock *frame_clock;
3703
3704 if (window &&
3705 (window->update_freeze_count ||
3706 gdk_window_is_toplevel_frozen (window)))
3707 return;
3708
3709 /* If there's no frame clock (a foreign window), then the invalid
3710 * region will just stick around unless gdk_window_process_updates()
3711 * is called. */
3712 frame_clock = gdk_window_get_frame_clock (window);
3713 if (frame_clock)
3714 gdk_frame_clock_request_phase (gdk_window_get_frame_clock (window),
3715 GDK_FRAME_CLOCK_PHASE_PAINT);
3716}
3717
3718static void
3719gdk_window_add_damage (GdkWindow *toplevel,
3720 cairo_region_t *damaged_region)
3721{
3722 GdkDisplay *display;
3723 GdkEvent event = { 0, };
3724
3725 /* This function only makes sense for offscreen windows. */
3726 g_assert (gdk_window_is_offscreen (toplevel));
3727
3728 event.expose.type = GDK_DAMAGE;
3729 event.expose.window = toplevel;
3730 event.expose.send_event = FALSE;
3731 event.expose.region = damaged_region;
3732 cairo_region_get_extents (event.expose.region, &event.expose.area);
3733
3734 display = gdk_window_get_display (event.expose.window);
3735 _gdk_event_queue_append (display, gdk_event_copy (&event));
3736}
3737
3738static void
3739_gdk_window_process_updates_recurse_helper (GdkWindow *window,
3740 cairo_region_t *expose_region)
3741{
3742 GdkWindow *child;
3743 cairo_region_t *clipped_expose_region;
3744 GdkWindow **children;
3745 GdkWindow **free_children = NULL;
3746 int i, n_children;
3747 GList *l;
3748 GList *last_link;
3749
3750 if (window->destroyed)
3751 return;
3752
3753 if (window->alpha == 0 && !gdk_window_has_impl (window))
3754 return;
3755
3756 clipped_expose_region = cairo_region_copy (expose_region);
3757
3758 if (!gdk_window_has_impl (window))
3759 cairo_region_translate (clipped_expose_region, -window->x, -window->y);
3760
3761 cairo_region_intersect (clipped_expose_region, window->clip_region);
3762
3763 if (cairo_region_is_empty (clipped_expose_region))
3764 goto out;
3765
3766 if (gdk_window_is_offscreen (window))
3767 gdk_window_add_damage (window, clipped_expose_region);
3768
3769 /* Paint the window before the children, clipped to the window region */
3770
3771 /* While gtk+ no longer handles exposes on anything but native
3772 window we still have to send them to all windows that have the
3773 event mask set for backwards compat. We also need to send
3774 it to all native windows, even if they don't specify the
3775 expose mask, because they may have non-native children that do. */
3776 if (gdk_window_has_impl (window) ||
3777 window->event_mask & GDK_EXPOSURE_MASK)
3778 {
3779 GdkEvent event;
3780
3781 event.expose.type = GDK_EXPOSE;
3782 event.expose.window = window; /* we already hold a ref */
3783 event.expose.send_event = FALSE;
3784 event.expose.count = 0;
3785 event.expose.region = clipped_expose_region;
3786 cairo_region_get_extents (clipped_expose_region, &event.expose.area);
3787
3788 _gdk_event_emit (&event);
3789 }
3790
3791 n_children = 0;
3792 last_link = NULL;
3793 /* Count n_children and fetch bottommost at same time */
3794 for (l = window->children; l != NULL; l = l->next)
3795 {
3796 last_link = l;
3797 n_children++;
3798 }
3799
3800 children = g_newa (GdkWindow *, n_children);
3801 if (children == NULL)
3802 children = free_children = g_new (GdkWindow *, n_children);
3803
3804 n_children = 0;
3805 /* Iterate over children, starting at bottommost */
3806 for (l = last_link; l != NULL; l = l->prev)
3807 {
3808 child = l->data;
3809
3810 if (child->destroyed || !GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
3811 continue;
3812
3813 /* Ignore offscreen children, as they don't draw in their parent and
3814 * don't take part in the clipping */
3815 if (gdk_window_is_offscreen (child))
3816 continue;
3817
3818 /* Client side child, expose */
3819 if (child->impl == window->impl)
3820 {
3821 /* ref the child to make this reentrancy safe for expose
3822 handlers freeing other windows */
3823 children[n_children++] = g_object_ref (child);
3824 }
3825 }
3826
3827 for (i = 0; i < n_children; i++)
3828 {
3829 _gdk_window_process_updates_recurse_helper ((GdkWindow *)children[i],
3830 clipped_expose_region);
3831 g_object_unref (children[i]);
3832 }
3833
3834
3835 g_free (free_children);
3836
3837 out:
3838 cairo_region_destroy (clipped_expose_region);
3839}
3840
3841void
3842_gdk_window_process_updates_recurse (GdkWindow *window,
3843 cairo_region_t *expose_region)
3844{
3845 _gdk_window_process_updates_recurse_helper (window, expose_region);
3846}
3847
3848
3849static void
3850gdk_window_update_native_shapes (GdkWindow *window)
3851{
3852 GdkWindow *child;
3853 GList *l;
3854
3855 if (should_apply_clip_as_shape (window))
3856 apply_clip_as_shape (window);
3857
3858 for (l = window->native_children; l != NULL; l = l->next)
3859 {
3860 child = l->data;
3861
3862 gdk_window_update_native_shapes (child);
3863 }
3864}
3865
3866/* Process and remove any invalid area on the native window by creating
3867 * expose events for the window and all non-native descendants.
3868 */
3869static void
3870gdk_window_process_updates_internal (GdkWindow *window)
3871{
3872 GdkWindowImplClass *impl_class;
3873 GdkWindow *toplevel;
3874 GdkDisplay *display;
3875
3876 display = gdk_window_get_display (window);
3877 toplevel = gdk_window_get_toplevel (window);
3878 if (toplevel->geometry_dirty)
3879 {
3880 gdk_window_update_native_shapes (toplevel);
3881 toplevel->geometry_dirty = FALSE;
3882 }
3883
3884 /* Ensure the window lives while updating it */
3885 g_object_ref (window);
3886
3887 window->in_update = TRUE;
3888
3889 /* If an update got queued during update processing, we can get a
3890 * window in the update queue that has an empty update_area.
3891 * just ignore it.
3892 */
3893 if (window->update_area)
3894 {
3895 g_assert (window->active_update_area == NULL); /* No reentrancy */
3896
3897 window->active_update_area = window->update_area;
3898 window->update_area = NULL;
3899
3900 if (gdk_window_is_viewable (window))
3901 {
3902 cairo_region_t *expose_region;
3903
3904 expose_region = cairo_region_copy (window->active_update_area);
3905
3906 impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
3907
3908 /* Sometimes we can't just paint only the new area, as the windowing system
3909 * requires more to be repainted. For instance, with OpenGL you typically
3910 * repaint all of each frame each time and then swap the buffer, although
3911 * there are extensions that allow us to reuse part of an old frame.
3912 */
3913 if (impl_class->invalidate_for_new_frame)
3914 impl_class->invalidate_for_new_frame (window, expose_region);
3915
3916 /* Clip to part visible in impl window */
3917 cairo_region_intersect (expose_region, window->clip_region);
3918
3919 if (gdk_display_get_debug_updates (display))
3920 {
3921 cairo_region_t *swap_region = cairo_region_copy (expose_region);
3922 cairo_region_subtract (swap_region, window->active_update_area);
3923 draw_ugly_color (window, swap_region, 1);
3924 cairo_region_destroy (swap_region);
3925
3926 /* Make sure we see the red invalid area before redrawing. */
3927 gdk_display_sync (gdk_window_get_display (window));
3928 g_usleep (70000);
3929 }
3930
3931 if (impl_class->queue_antiexpose)
3932 impl_class->queue_antiexpose (window, expose_region);
3933
3934 impl_class->process_updates_recurse (window, expose_region);
3935
3936 gdk_window_append_old_updated_area (window, window->active_update_area);
3937
3938 cairo_region_destroy (expose_region);
3939 }
3940
3941 cairo_region_destroy (window->active_update_area);
3942 window->active_update_area = NULL;
3943 }
3944
3945 window->in_update = FALSE;
3946
3947 g_object_unref (window);
3948}
3949
3950static void
3951flush_all_displays (void)
3952{
3953 GSList *displays, *l;
3954
3955 displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
3956 for (l = displays; l; l = l->next)
3957 gdk_display_flush (l->data);
3958
3959 g_slist_free (displays);
3960}
3961
3962static void
3963before_process_all_updates (void)
3964{
3965 GSList *displays, *l;
3966 GdkDisplayClass *display_class;
3967
3968 displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
3969 display_class = GDK_DISPLAY_GET_CLASS (displays->data);
3970 for (l = displays; l; l = l->next)
3971 display_class->before_process_all_updates (l->data);
3972
3973 g_slist_free (displays);
3974}
3975
3976static void
3977after_process_all_updates (void)
3978{
3979 GSList *displays, *l;
3980 GdkDisplayClass *display_class;
3981
3982 displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
3983 display_class = GDK_DISPLAY_GET_CLASS (displays->data);
3984 for (l = displays; l; l = l->next)
3985 display_class->after_process_all_updates (l->data);
3986
3987 g_slist_free (displays);
3988}
3989
3990/* Currently it is not possible to override
3991 * gdk_window_process_all_updates in the same manner as
3992 * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
3993 * by implementing the GdkPaintable interface. If in the future a
3994 * backend would need this, the right solution would be to add a
3995 * method to GdkDisplay that can be optionally
3996 * NULL. gdk_window_process_all_updates can then walk the list of open
3997 * displays and call the mehod.
3998 */
3999
4000/**
4001 * gdk_window_process_all_updates:
4002 *
4003 * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
4004 * in the application.
4005 *
4006 **/
4007void
4008gdk_window_process_all_updates (void)
4009{
4010 GSList *old_update_windows = update_windows;
4011 GSList *tmp_list = update_windows;
4012 static gboolean in_process_all_updates = FALSE;
4013 static gboolean got_recursive_update = FALSE;
4014
4015 if (in_process_all_updates)
4016 {
4017 /* We can't do this now since that would recurse, so
4018 delay it until after the recursion is done. */
4019 got_recursive_update = TRUE;
4020 return;
4021 }
4022
4023 in_process_all_updates = TRUE;
4024 got_recursive_update = FALSE;
4025
4026 update_windows = NULL;
4027
4028 before_process_all_updates ();
4029
4030 while (tmp_list)
4031 {
4032 GdkWindow *window = tmp_list->data;
4033
4034 if (!GDK_WINDOW_DESTROYED (window))
4035 {
4036 if (window->update_freeze_count ||
4037 gdk_window_is_toplevel_frozen (window))
4038 gdk_window_add_update_window (window);
4039 else
4040 gdk_window_process_updates_internal (window);
4041 }
4042
4043 g_object_unref (window);
4044 tmp_list = tmp_list->next;
4045 }
4046
4047 g_slist_free (old_update_windows);
4048
4049 flush_all_displays ();
4050
4051 after_process_all_updates ();
4052
4053 in_process_all_updates = FALSE;
4054
4055 /* If we ignored a recursive call, schedule a
4056 redraw now so that it eventually happens,
4057 otherwise we could miss an update if nothing
4058 else schedules an update. */
4059 if (got_recursive_update)
4060 gdk_window_schedule_update (NULL);
4061}
4062
4063
4064enum {
4065 PROCESS_UPDATES_NO_RECURSE,
4066 PROCESS_UPDATES_WITH_ALL_CHILDREN,
4067 PROCESS_UPDATES_WITH_SAME_CLOCK_CHILDREN
4068};
4069
4070static void
4071find_impl_windows_to_update (GPtrArray *list,
4072 GdkWindow *window,
4073 gint recurse_mode)
4074{
4075 GList *node;
4076
4077 /* Recurse first, so that we process updates in reverse stacking
4078 * order so composition or painting over achieves the desired effect
4079 * for offscreen windows
4080 */
4081 if (recurse_mode != PROCESS_UPDATES_NO_RECURSE)
4082 {
4083 for (node = window->children; node; node = node->next)
4084 {
4085 GdkWindow *child = node->data;
4086
4087 if (!GDK_WINDOW_DESTROYED (child) &&
4088 (recurse_mode == PROCESS_UPDATES_WITH_ALL_CHILDREN ||
4089 (recurse_mode == PROCESS_UPDATES_WITH_SAME_CLOCK_CHILDREN &&
4090 child->frame_clock == NULL)))
4091 {
4092 find_impl_windows_to_update (list, child, recurse_mode);
4093 }
4094 }
4095 }
4096
4097 /* add reference count so the window cannot be deleted in a callback */
4098 if (window->impl_window == window)
4099 g_ptr_array_add (list, g_object_ref (window));
4100}
4101
4102static void
4103gdk_window_process_updates_with_mode (GdkWindow *window,
4104 int recurse_mode)
4105{
4106 GPtrArray *list = g_ptr_array_new_with_free_func (g_object_unref);
4107 int i;
4108
4109 g_return_if_fail (GDK_IS_WINDOW (window));
4110
4111 if (GDK_WINDOW_DESTROYED (window))
4112 return;
4113
4114 find_impl_windows_to_update (list, window, recurse_mode);
4115
4116 if (window->impl_window != window)
4117 g_ptr_array_add (list, g_object_ref (window->impl_window));
4118
4119 for (i = (int)list->len - 1; i >= 0; i --)
4120 {
4121 GdkWindow *impl_window = g_ptr_array_index (list, i);
4122
4123 if (impl_window->update_area &&
4124 !impl_window->update_freeze_count &&
4125 !gdk_window_is_toplevel_frozen (impl_window) &&
4126
4127 /* Don't recurse into process_updates_internal, we'll
4128 * do the update later when idle instead. */
4129 !impl_window->in_update)
4130 {
4131 gdk_window_process_updates_internal (impl_window);
4132 gdk_window_remove_update_window (impl_window);
4133 }
4134 }
4135
4136 g_ptr_array_free (list, TRUE);
4137}
4138
4139/**
4140 * gdk_window_process_updates:
4141 * @window: a #GdkWindow
4142 * @update_children: whether to also process updates for child windows
4143 *
4144 * Sends one or more expose events to @window. The areas in each
4145 * expose event will cover the entire update area for the window (see
4146 * gdk_window_invalidate_region() for details). Normally GDK calls
4147 * gdk_window_process_all_updates() on your behalf, so there’s no
4148 * need to call this function unless you want to force expose events
4149 * to be delivered immediately and synchronously (vs. the usual
4150 * case, where GDK delivers them in an idle handler). Occasionally
4151 * this is useful to produce nicer scrolling behavior, for example.
4152 *
4153 **/
4154void
4155gdk_window_process_updates (GdkWindow *window,
4156 gboolean update_children)
4157{
4158 g_return_if_fail (GDK_IS_WINDOW (window));
4159
4160 gdk_window_process_updates_with_mode (window,
4161 update_children ?
4162 PROCESS_UPDATES_WITH_ALL_CHILDREN :
4163 PROCESS_UPDATES_NO_RECURSE);
4164}
4165
4166static void
4167gdk_window_invalidate_rect_full (GdkWindow *window,
4168 const GdkRectangle *rect,
4169 gboolean invalidate_children)
4170{
4171 GdkRectangle window_rect;
4172 cairo_region_t *region;
4173
4174 g_return_if_fail (GDK_IS_WINDOW (window));
4175
4176 if (GDK_WINDOW_DESTROYED (window))
4177 return;
4178
4179 if (window->input_only || !window->viewable)
4180 return;
4181
4182 if (!rect)
4183 {
4184 window_rect.x = 0;
4185 window_rect.y = 0;
4186 window_rect.width = window->width;
4187 window_rect.height = window->height;
4188 rect = &window_rect;
4189 }
4190
4191 region = cairo_region_create_rectangle (rect);
4192 gdk_window_invalidate_region_full (window, region, invalidate_children);
4193 cairo_region_destroy (region);
4194}
4195
4196/**
4197 * gdk_window_invalidate_rect:
4198 * @window: a #GdkWindow
4199 * @rect: (allow-none): rectangle to invalidate or %NULL to invalidate the whole
4200 * window
4201 * @invalidate_children: whether to also invalidate child windows
4202 *
4203 * A convenience wrapper around gdk_window_invalidate_region() which
4204 * invalidates a rectangular region. See
4205 * gdk_window_invalidate_region() for details.
4206 **/
4207void
4208gdk_window_invalidate_rect (GdkWindow *window,
4209 const GdkRectangle *rect,
4210 gboolean invalidate_children)
4211{
4212 gdk_window_invalidate_rect_full (window, rect, invalidate_children);
4213}
4214
4215/**
4216 * gdk_window_set_invalidate_handler: (skip)
4217 * @window: a #GdkWindow
4218 * @handler: a #GdkWindowInvalidateHandlerFunc callback function
4219 *
4220 * Registers an invalidate handler for a specific window. This
4221 * will get called whenever a region in the window or its children
4222 * is invalidated.
4223 *
4224 * This can be used to record the invalidated region, which is
4225 * useful if you are keeping an offscreen copy of some region
4226 * and want to keep it up to date. You can also modify the
4227 * invalidated region in case you’re doing some effect where
4228 * e.g. a child widget appears in multiple places.
4229 *
4230 * Since: 3.10
4231 **/
4232void
4233gdk_window_set_invalidate_handler (GdkWindow *window,
4234 GdkWindowInvalidateHandlerFunc handler)
4235{
4236 window->invalidate_handler = handler;
4237}
4238
4239static void
4240draw_ugly_color (GdkWindow *window,
4241 const cairo_region_t *region,
4242 int color)
4243{
4244 cairo_t *cr;
4245
4246G_GNUC_BEGIN_IGNORE_DEPRECATIONS
4247 cr = gdk_cairo_create (window);
4248G_GNUC_END_IGNORE_DEPRECATIONS
4249
4250 /* Draw ugly color all over the newly-invalid region */
4251 if (color == 0)
4252 cairo_set_source_rgb (cr, 50000/65535., 10000/65535., 10000/65535.);
4253 else
4254 cairo_set_source_rgb (cr, 10000/65535., 50000/65535., 10000/65535.);
4255
4256 gdk_cairo_region (cr, region);
4257 cairo_fill (cr);
4258
4259 cairo_destroy (cr);
4260}
4261
4262static void
4263impl_window_add_update_area (GdkWindow *impl_window,
4264 cairo_region_t *region)
4265{
4266 if (impl_window->update_area)
4267 cairo_region_union (impl_window->update_area, region);
4268 else
4269 {
4270 gdk_window_add_update_window (impl_window);
4271 impl_window->update_area = cairo_region_copy (region);
4272 gdk_window_schedule_update (impl_window);
4273 }
4274}
4275
4276static void
4277gdk_window_invalidate_maybe_recurse_full (GdkWindow *window,
4278 const cairo_region_t *region,
4279 GdkWindowChildFunc child_func,
4280 gpointer user_data);
4281
4282/* Returns true if window is a decendant of parent, but stops looking
4283 * at the first native window. Also ensures that all parents match
4284 * child_func if non-null..
4285 *
4286 * This is useful in combination with
4287 * window->impl_window->native_children as it lets you find all native
4288 * decendants in an efficient way (assuming few children are native).
4289 */
4290static gboolean
4291has_visible_ancestor_in_impl (GdkWindow *window,
4292 GdkWindow *ancestor,
4293 GdkWindowChildFunc child_func,
4294 gpointer user_data)
4295{
4296 GdkWindow *p;
4297 GdkWindow *stop_at;
4298
4299 p = window->parent;
4300 stop_at = p->impl_window;
4301 while (p != NULL)
4302 {
4303 if (!p->viewable)
4304 return FALSE;
4305 if (child_func &&
4306 !(*child_func) ((GdkWindow *)p, user_data))
4307 return FALSE;
4308 if (p == ancestor)
4309 return TRUE;
4310 if (p == stop_at)
4311 return FALSE;
4312 p = p->parent;
4313 }
4314 return FALSE;
4315}
4316
4317static void
4318invalidate_impl_subwindows (GdkWindow *window,
4319 const cairo_region_t *region,
4320 GdkWindowChildFunc child_func,
4321 gpointer user_data)
4322{
4323 GList *l;
4324
4325 /* Iterate over all native children of the native window
4326 that window is in. */
4327 for (l = window->impl_window->native_children;
4328 l != NULL;
4329 l = l->next)
4330 {
4331 GdkWindow *native_child = l->data;
4332 cairo_region_t *tmp;
4333 int dx, dy;
4334
4335 if (native_child->input_only)
4336 continue;
4337
4338 /* Then skip any that does not have window as an ancestor,
4339 * also checking that the ancestors are visible and pass child_func
4340 * This is fast if we assume native children are rare */
4341 if (!has_visible_ancestor_in_impl (native_child, window,
4342 child_func, user_data))
4343 continue;
4344
4345 dx = native_child->parent->abs_x + native_child->x - window->abs_x;
4346 dy = native_child->parent->abs_y + native_child->y - window->abs_y;
4347
4348 tmp = cairo_region_copy (region);
4349 cairo_region_translate (tmp, -dx, -dy);
4350 gdk_window_invalidate_maybe_recurse_full (native_child,
4351 tmp, child_func, user_data);
4352 cairo_region_destroy (tmp);
4353 }
4354}
4355
4356static void
4357gdk_window_invalidate_maybe_recurse_full (GdkWindow *window,
4358 const cairo_region_t *region,
4359 GdkWindowChildFunc child_func,
4360 gpointer user_data)
4361{
4362 cairo_region_t *visible_region;
4363 cairo_rectangle_int_t r;
4364 GdkDisplay *display;
4365
4366 g_return_if_fail (GDK_IS_WINDOW (window));
4367
4368 if (GDK_WINDOW_DESTROYED (window))
4369 return;
4370
4371 if (window->input_only ||
4372 !window->viewable ||
4373 cairo_region_is_empty (region) ||
4374 window->window_type == GDK_WINDOW_ROOT)
4375 return;
4376
4377 r.x = 0;
4378 r.y = 0;
4379
4380 visible_region = cairo_region_copy (region);
4381
4382 if (child_func)
4383 invalidate_impl_subwindows (window, region, child_func, user_data);
4384
4385 display = gdk_window_get_display (window);
4386 if (gdk_display_get_debug_updates (display))
4387 draw_ugly_color (window, visible_region, 0);
4388
4389 while (window != NULL &&
4390 !cairo_region_is_empty (visible_region))
4391 {
4392 if (window->invalidate_handler)
4393 window->invalidate_handler (window, visible_region);
4394
4395 r.width = window->width;
4396 r.height = window->height;
4397 cairo_region_intersect_rectangle (visible_region, &r);
4398
4399 if (gdk_window_has_impl (window))
4400 {
4401 impl_window_add_update_area (window, visible_region);
4402 break;
4403 }
4404 else
4405 {
4406 cairo_region_translate (visible_region,
4407 window->x, window->y);
4408 window = window->parent;
4409 }
4410 }
4411
4412 cairo_region_destroy (visible_region);
4413}
4414
4415/**
4416 * gdk_window_invalidate_maybe_recurse:
4417 * @window: a #GdkWindow
4418 * @region: a #cairo_region_t
4419 * @child_func: (scope call) (allow-none): function to use to decide if to
4420 * recurse to a child, %NULL means never recurse.
4421 * @user_data: data passed to @child_func
4422 *
4423 * Adds @region to the update area for @window. The update area is the
4424 * region that needs to be redrawn, or “dirty region.” The call
4425 * gdk_window_process_updates() sends one or more expose events to the
4426 * window, which together cover the entire update area. An
4427 * application would normally redraw the contents of @window in
4428 * response to those expose events.
4429 *
4430 * GDK will call gdk_window_process_all_updates() on your behalf
4431 * whenever your program returns to the main loop and becomes idle, so
4432 * normally there’s no need to do that manually, you just need to
4433 * invalidate regions that you know should be redrawn.
4434 *
4435 * The @child_func parameter controls whether the region of
4436 * each child window that intersects @region will also be invalidated.
4437 * Only children for which @child_func returns #TRUE will have the area
4438 * invalidated.
4439 **/
4440void
4441gdk_window_invalidate_maybe_recurse (GdkWindow *window,
4442 const cairo_region_t *region,
4443 GdkWindowChildFunc child_func,
4444 gpointer user_data)
4445{
4446 gdk_window_invalidate_maybe_recurse_full (window, region,
4447 child_func, user_data);
4448}
4449
4450static gboolean
4451true_predicate (GdkWindow *window,
4452 gpointer user_data)
4453{
4454 return TRUE;
4455}
4456
4457static void
4458gdk_window_invalidate_region_full (GdkWindow *window,
4459 const cairo_region_t *region,
4460 gboolean invalidate_children)
4461{
4462 gdk_window_invalidate_maybe_recurse_full (window, region,
4463 invalidate_children ?
4464 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
4465 NULL);
4466}
4467
4468/**
4469 * gdk_window_invalidate_region:
4470 * @window: a #GdkWindow
4471 * @region: a #cairo_region_t
4472 * @invalidate_children: %TRUE to also invalidate child windows
4473 *
4474 * Adds @region to the update area for @window. The update area is the
4475 * region that needs to be redrawn, or “dirty region.” The call
4476 * gdk_window_process_updates() sends one or more expose events to the
4477 * window, which together cover the entire update area. An
4478 * application would normally redraw the contents of @window in
4479 * response to those expose events.
4480 *
4481 * GDK will call gdk_window_process_all_updates() on your behalf
4482 * whenever your program returns to the main loop and becomes idle, so
4483 * normally there’s no need to do that manually, you just need to
4484 * invalidate regions that you know should be redrawn.
4485 *
4486 * The @invalidate_children parameter controls whether the region of
4487 * each child window that intersects @region will also be invalidated.
4488 * If %FALSE, then the update area for child windows will remain
4489 * unaffected. See gdk_window_invalidate_maybe_recurse if you need
4490 * fine grained control over which children are invalidated.
4491 **/
4492void
4493gdk_window_invalidate_region (GdkWindow *window,
4494 const cairo_region_t *region,
4495 gboolean invalidate_children)
4496{
4497 gdk_window_invalidate_maybe_recurse (window, region,
4498 invalidate_children ?
4499 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
4500 NULL);
4501}
4502
4503/**
4504 * _gdk_window_invalidate_for_expose:
4505 * @window: a #GdkWindow
4506 * @region: a #cairo_region_t
4507 *
4508 * Adds @region to the update area for @window. The update area is the
4509 * region that needs to be redrawn, or “dirty region.” The call
4510 * gdk_window_process_updates() sends one or more expose events to the
4511 * window, which together cover the entire update area. An
4512 * application would normally redraw the contents of @window in
4513 * response to those expose events.
4514 *
4515 * GDK will call gdk_window_process_all_updates() on your behalf
4516 * whenever your program returns to the main loop and becomes idle, so
4517 * normally there’s no need to do that manually, you just need to
4518 * invalidate regions that you know should be redrawn.
4519 *
4520 * This version of invalidation is used when you recieve expose events
4521 * from the native window system. It exposes the native window, plus
4522 * any non-native child windows (but not native child windows, as those would
4523 * have gotten their own expose events).
4524 **/
4525void
4526_gdk_window_invalidate_for_expose (GdkWindow *window,
4527 cairo_region_t *region)
4528{
4529 gdk_window_invalidate_maybe_recurse_full (window, region,
4530 (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
4531 NULL);
4532}
4533
4534
4535/**
4536 * gdk_window_get_update_area:
4537 * @window: a #GdkWindow
4538 *
4539 * Transfers ownership of the update area from @window to the caller
4540 * of the function. That is, after calling this function, @window will
4541 * no longer have an invalid/dirty region; the update area is removed
4542 * from @window and handed to you. If a window has no update area,
4543 * gdk_window_get_update_area() returns %NULL. You are responsible for
4544 * calling cairo_region_destroy() on the returned region if it’s non-%NULL.
4545 *
4546 * Returns: the update area for @window
4547 **/
4548cairo_region_t *
4549gdk_window_get_update_area (GdkWindow *window)
4550{
4551 GdkWindow *impl_window;
4552 cairo_region_t *tmp_region, *to_remove;
4553
4554 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
4555
4556 impl_window = gdk_window_get_impl_window (window);
4557
4558 if (impl_window->update_area)
4559 {
4560 tmp_region = cairo_region_copy (window->clip_region);
4561 /* Convert to impl coords */
4562 cairo_region_translate (tmp_region, window->abs_x, window->abs_y);
4563 cairo_region_intersect (tmp_region, impl_window->update_area);
4564
4565 if (cairo_region_is_empty (tmp_region))
4566 {
4567 cairo_region_destroy (tmp_region);
4568 return NULL;
4569 }
4570 else
4571 {
4572 /* Convert from impl coords */
4573 cairo_region_translate (tmp_region, -window->abs_x, -window->abs_y);
4574
4575 /* Don't remove any update area that is overlapped by sibling windows
4576 or child windows as these really need to be repainted independently of this window. */
4577 to_remove = cairo_region_copy (tmp_region);
4578
4579 remove_child_area (window, FALSE, to_remove);
4580 remove_sibling_overlapped_area (window, to_remove);
4581
4582 /* Remove from update_area */
4583 cairo_region_translate (to_remove, window->abs_x, window->abs_y);
4584 cairo_region_subtract (impl_window->update_area, to_remove);
4585
4586 cairo_region_destroy (to_remove);
4587
4588 if (cairo_region_is_empty (impl_window->update_area))
4589 {
4590 cairo_region_destroy (impl_window->update_area);
4591 impl_window->update_area = NULL;
4592
4593 gdk_window_remove_update_window ((GdkWindow *)impl_window);
4594 }
4595
4596 return tmp_region;
4597 }
4598 }
4599 else
4600 return NULL;
4601}
4602
4603/**
4604 * _gdk_window_clear_update_area:
4605 * @window: a #GdkWindow.
4606 *
4607 * Internal function to clear the update area for a window. This
4608 * is called when the window is hidden or destroyed.
4609 **/
4610void
4611_gdk_window_clear_update_area (GdkWindow *window)
4612{
4613 g_return_if_fail (GDK_IS_WINDOW (window));
4614
4615 if (window->update_area)
4616 {
4617 gdk_window_remove_update_window (window);
4618
4619 cairo_region_destroy (window->update_area);
4620 window->update_area = NULL;
4621 }
4622}
4623
4624/**
4625 * gdk_window_freeze_updates:
4626 * @window: a #GdkWindow
4627 *
4628 * Temporarily freezes a window such that it won’t receive expose
4629 * events. The window will begin receiving expose events again when
4630 * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
4631 * has been called more than once, gdk_window_thaw_updates() must be called
4632 * an equal number of times to begin processing exposes.
4633 **/
4634void
4635gdk_window_freeze_updates (GdkWindow *window)
4636{
4637 GdkWindow *impl_window;
4638
4639 g_return_if_fail (GDK_IS_WINDOW (window));
4640
4641 impl_window = gdk_window_get_impl_window (window);
4642 impl_window->update_freeze_count++;
4643}
4644
4645/**
4646 * gdk_window_thaw_updates:
4647 * @window: a #GdkWindow
4648 *
4649 * Thaws a window frozen with gdk_window_freeze_updates().
4650 **/
4651void
4652gdk_window_thaw_updates (GdkWindow *window)
4653{
4654 GdkWindow *impl_window;
4655
4656 g_return_if_fail (GDK_IS_WINDOW (window));
4657
4658 impl_window = gdk_window_get_impl_window (window);
4659
4660 g_return_if_fail (impl_window->update_freeze_count > 0);
4661
4662 if (--impl_window->update_freeze_count == 0)
4663 gdk_window_schedule_update (GDK_WINDOW (impl_window));
4664}
4665
4666/**
4667 * gdk_window_freeze_toplevel_updates_libgtk_only:
4668 * @window: a #GdkWindow
4669 *
4670 * Temporarily freezes a window and all its descendants such that it won't
4671 * receive expose events. The window will begin receiving expose events
4672 * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
4673 * gdk_window_freeze_toplevel_updates_libgtk_only()
4674 * has been called more than once,
4675 * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
4676 * an equal number of times to begin processing exposes.
4677 *
4678 * This function is not part of the GDK public API and is only
4679 * for use by GTK+.
4680 *
4681 * Deprecated: 3.16: This symbol was never meant to be used outside of GTK+
4682 */
4683void
4684gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
4685{
4686 gdk_window_freeze_toplevel_updates (window);
4687}
4688
4689void
4690gdk_window_freeze_toplevel_updates (GdkWindow *window)
4691{
4692 g_return_if_fail (GDK_IS_WINDOW (window));
4693 g_return_if_fail (window->window_type != GDK_WINDOW_CHILD);
4694
4695 window->update_and_descendants_freeze_count++;
4696 _gdk_frame_clock_freeze (gdk_window_get_frame_clock (window));
4697}
4698
4699/**
4700 * gdk_window_thaw_toplevel_updates_libgtk_only:
4701 * @window: a #GdkWindow
4702 *
4703 * Thaws a window frozen with
4704 * gdk_window_freeze_toplevel_updates_libgtk_only().
4705 *
4706 * This function is not part of the GDK public API and is only
4707 * for use by GTK+.
4708 *
4709 * Deprecated: 3.16: This symbol was never meant to be used outside of GTK+
4710 */
4711void
4712gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
4713{
4714 gdk_window_thaw_toplevel_updates (window);
4715}
4716
4717void
4718gdk_window_thaw_toplevel_updates (GdkWindow *window)
4719{
4720 g_return_if_fail (GDK_IS_WINDOW (window));
4721 g_return_if_fail (window->window_type != GDK_WINDOW_CHILD);
4722 g_return_if_fail (window->update_and_descendants_freeze_count > 0);
4723
4724 window->update_and_descendants_freeze_count--;
4725 _gdk_frame_clock_thaw (gdk_window_get_frame_clock (window));
4726
4727 gdk_window_schedule_update (window);
4728}
4729
4730/**
4731 * gdk_window_set_debug_updates:
4732 * @setting: %TRUE to turn on update debugging
4733 *
4734 * With update debugging enabled, calls to
4735 * gdk_window_invalidate_region() clear the invalidated region of the
4736 * screen to a noticeable color, and GDK pauses for a short time
4737 * before sending exposes to windows during
4738 * gdk_window_process_updates(). The net effect is that you can see
4739 * the invalid region for each window and watch redraws as they
4740 * occur. This allows you to diagnose inefficiencies in your application.
4741 *
4742 * In essence, because the GDK rendering model prevents all flicker,
4743 * if you are redrawing the same region 400 times you may never
4744 * notice, aside from noticing a speed problem. Enabling update
4745 * debugging causes GTK to flicker slowly and noticeably, so you can
4746 * see exactly what’s being redrawn when, in what order.
4747 *
4748 * The --gtk-debug=updates command line option passed to GTK+ programs
4749 * enables this debug option at application startup time. That's
4750 * usually more useful than calling gdk_window_set_debug_updates()
4751 * yourself, though you might want to use this function to enable
4752 * updates sometime after application startup time.
4753 *
4754 **/
4755void
4756gdk_window_set_debug_updates (gboolean setting)
4757{
4758 _gdk_debug_updates = setting;
4759}
4760
4761/**
4762 * gdk_window_constrain_size:
4763 * @geometry: a #GdkGeometry structure
4764 * @flags: a mask indicating what portions of @geometry are set
4765 * @width: desired width of window
4766 * @height: desired height of the window
4767 * @new_width: (out): location to store resulting width
4768 * @new_height: (out): location to store resulting height
4769 *
4770 * Constrains a desired width and height according to a
4771 * set of geometry hints (such as minimum and maximum size).
4772 */
4773void
4774gdk_window_constrain_size (GdkGeometry *geometry,
4775 GdkWindowHints flags,
4776 gint width,
4777 gint height,
4778 gint *new_width,
4779 gint *new_height)
4780{
4781 /* This routine is partially borrowed from fvwm.
4782 *
4783 * Copyright 1993, Robert Nation
4784 * You may use this code for any purpose, as long as the original
4785 * copyright remains in the source code and all documentation
4786 *
4787 * which in turn borrows parts of the algorithm from uwm
4788 */
4789 gint min_width = 0;
4790 gint min_height = 0;
4791 gint base_width = 0;
4792 gint base_height = 0;
4793 gint xinc = 1;
4794 gint yinc = 1;
4795 gint max_width = G_MAXINT;
4796 gint max_height = G_MAXINT;
4797
4798#define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
4799
4800 if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
4801 {
4802 base_width = geometry->base_width;
4803 base_height = geometry->base_height;
4804 min_width = geometry->min_width;
4805 min_height = geometry->min_height;
4806 }
4807 else if (flags & GDK_HINT_BASE_SIZE)
4808 {
4809 base_width = geometry->base_width;
4810 base_height = geometry->base_height;
4811 min_width = geometry->base_width;
4812 min_height = geometry->base_height;
4813 }
4814 else if (flags & GDK_HINT_MIN_SIZE)
4815 {
4816 base_width = geometry->min_width;
4817 base_height = geometry->min_height;
4818 min_width = geometry->min_width;
4819 min_height = geometry->min_height;
4820 }
4821
4822 if (flags & GDK_HINT_MAX_SIZE)
4823 {
4824 max_width = geometry->max_width ;
4825 max_height = geometry->max_height;
4826 }
4827
4828 if (flags & GDK_HINT_RESIZE_INC)
4829 {
4830 xinc = MAX (xinc, geometry->width_inc);
4831 yinc = MAX (yinc, geometry->height_inc);
4832 }
4833
4834 /* clamp width and height to min and max values
4835 */
4836 width = CLAMP (width, min_width, max_width);
4837 height = CLAMP (height, min_height, max_height);
4838
4839 /* shrink to base + N * inc
4840 */
4841 width = base_width + FLOOR (width - base_width, xinc);
4842 height = base_height + FLOOR (height - base_height, yinc);
4843
4844 /* constrain aspect ratio, according to:
4845 *
4846 * width
4847 * min_aspect <= -------- <= max_aspect
4848 * height
4849 */
4850
4851 if (flags & GDK_HINT_ASPECT &&
4852 geometry->min_aspect > 0 &&
4853 geometry->max_aspect > 0)
4854 {
4855 gint delta;
4856
4857 if (geometry->min_aspect * height > width)
4858 {
4859 delta = FLOOR (height - width / geometry->min_aspect, yinc);
4860 if (height - delta >= min_height)
4861 height -= delta;
4862 else
4863 {
4864 delta = FLOOR (height * geometry->min_aspect - width, xinc);
4865 if (width + delta <= max_width)
4866 width += delta;
4867 }
4868 }
4869
4870 if (geometry->max_aspect * height < width)
4871 {
4872 delta = FLOOR (width - height * geometry->max_aspect, xinc);
4873 if (width - delta >= min_width)
4874 width -= delta;
4875 else
4876 {
4877 delta = FLOOR (width / geometry->max_aspect - height, yinc);
4878 if (height + delta <= max_height)
4879 height += delta;
4880 }
4881 }
4882 }
4883
4884#undef FLOOR
4885
4886 *new_width = width;
4887 *new_height = height;
4888}
4889
4890/**
4891 * gdk_window_get_pointer:
4892 * @window: a #GdkWindow
4893 * @x: (out) (allow-none): return location for X coordinate of pointer or %NULL to not
4894 * return the X coordinate
4895 * @y: (out) (allow-none): return location for Y coordinate of pointer or %NULL to not
4896 * return the Y coordinate
4897