Bug Summary

File:cdk/cdkwindow.c
Warning:line 1947, column 7
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cdkwindow.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/cdk -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Cdk" -D G_LOG_USE_STRUCTURED=1 -D CDK_COMPILATION -I .. -I ../cdk -I .. -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/cdk -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-09-19-172934-43638-1 -x c cdkwindow.c
1/* CDK - 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 CTK+ Team and others 1997-2000. See the AUTHORS
21 * file for a list of people on the CTK+ Team. See the ChangeLog
22 * files for a list of changes. These files are distributed with
23 * CTK+ at ftp://ftp.ctk.org/pub/ctk/.
24 */
25
26#include "config.h"
27
28#include <cairo-gobject.h>
29
30#include "cdkwindow.h"
31
32#include "cdkrectangle.h"
33#include "cdkinternals.h"
34#include "cdkintl.h"
35#include "cdkscreenprivate.h"
36#include "cdkdisplayprivate.h"
37#include "cdkdeviceprivate.h"
38#include "cdkvisualprivate.h"
39#include "cdkmarshalers.h"
40#include "cdkframeclockidle.h"
41#include "cdkwindowimpl.h"
42#include "cdkglcontextprivate.h"
43#include "cdkdrawingcontextprivate.h"
44#include "cdk-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 CDK_WINDOWING_WAYLAND
54#include "wayland/cdkwayland.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 #CdkWindow is a (usually) rectangular region on the screen.
66 * It’s a low-level object, used to implement high-level objects such as
67 * #CtkWidget and #CtkWindow on the CTK+ level. A #CtkWindow is a toplevel
68 * window, the thing a user might think of as a “window” with a titlebar
69 * and so on; a #CtkWindow may contain many #CdkWindows. For example,
70 * each #CtkButton has a #CdkWindow 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 cdk_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 cdk_offscreen_window_set_embedder() and handle a number of
89 * signals. The #CdkWindow::pick-embedded-child signal on the embedder
90 * window is used to select an offscreen child at given coordinates,
91 * and the #CdkWindow::to-embedder and #CdkWindow::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 * cdk_offscreen_window_get_surface().
98 */
99
100
101/* Historically a CdkWindow always matches a platform native window,
102 * be it a toplevel window or a child window. In this setup the
103 * CdkWindow (and other CdkDrawables) 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 CdkWindow 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 cdk
111 * code such that clipping, drawing, moving, events etc work as expected.
112 *
113 * For CdkWindows 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 * CdkOffscreenWindow. All windows of type CDK_WINDOW_OFFSCREEN get an impl
120 * of this type (while their children are generally CDK_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 * CdkWindows have a pointer to the “impl window” they are in, i.e.
125 * the topmost CdkWindow 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 CdkWindows (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 CdkVisibilityState enum */
144#define CDK_VISIBILITY_NOT_VIEWABLE3 3
145
146enum {
147 PICK_EMBEDDED_CHILD, /* only called if children are embedded */
148 TO_EMBEDDER,
149 FROM_EMBEDDER,
150 CREATE_SURFACE,
151 MOVED_TO_RECT,
152 LAST_SIGNAL
153};
154
155enum {
156 PROP_0,
157 PROP_CURSOR,
158 LAST_PROP
159};
160
161/* Global info */
162
163static void cdk_window_finalize (GObject *object);
164
165static void cdk_window_set_property (GObject *object,
166 guint prop_id,
167 const GValue *value,
168 GParamSpec *pspec);
169static void cdk_window_get_property (GObject *object,
170 guint prop_id,
171 GValue *value,
172 GParamSpec *pspec);
173
174static void cdk_window_clear_backing_region (CdkWindow *window);
175
176static void recompute_visible_regions (CdkWindow *private,
177 gboolean recalculate_children);
178static void cdk_window_invalidate_in_parent (CdkWindow *private);
179static void move_native_children (CdkWindow *private);
180static void update_cursor (CdkDisplay *display,
181 CdkDevice *device);
182static void impl_window_add_update_area (CdkWindow *impl_window,
183 cairo_region_t *region);
184static void cdk_window_invalidate_region_full (CdkWindow *window,
185 const cairo_region_t *region,
186 gboolean invalidate_children);
187static void cdk_window_invalidate_rect_full (CdkWindow *window,
188 const CdkRectangle *rect,
189 gboolean invalidate_children);
190static cairo_surface_t *cdk_window_ref_impl_surface (CdkWindow *window);
191
192static void cdk_window_set_frame_clock (CdkWindow *window,
193 CdkFrameClock *clock);
194
195static void draw_ugly_color (CdkWindow *window,
196 const cairo_region_t *region,
197 int color);
198
199
200static guint signals[LAST_SIGNAL] = { 0 };
201static GParamSpec *properties[LAST_PROP] = { NULL((void*)0), };
202
203G_DEFINE_ABSTRACT_TYPE (CdkWindow, cdk_window, G_TYPE_OBJECT)static void cdk_window_init (CdkWindow *self); static void cdk_window_class_init
(CdkWindowClass *klass); static GType cdk_window_get_type_once
(void); static gpointer cdk_window_parent_class = ((void*)0)
; static gint CdkWindow_private_offset; static void cdk_window_class_intern_init
(gpointer klass) { cdk_window_parent_class = g_type_class_peek_parent
(klass); if (CdkWindow_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CdkWindow_private_offset); cdk_window_class_init
((CdkWindowClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer cdk_window_get_instance_private (CdkWindow *
self) { return (((gpointer) ((guint8*) (self) + (glong) (CdkWindow_private_offset
)))); } GType cdk_window_get_type (void) { static GType static_g_define_type_id
= 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) * (&static_g_define_type_id) : ((void*)
0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= cdk_window_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType cdk_window_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CdkWindow"),
sizeof (CdkWindowClass), (GClassInitFunc)(void (*)(void)) cdk_window_class_intern_init
, sizeof (CdkWindow), (GInstanceInitFunc)(void (*)(void)) cdk_window_init
, (GTypeFlags) G_TYPE_FLAG_ABSTRACT); { {{};} } return g_define_type_id
; }
204
205#ifdef DEBUG_WINDOW_PRINTING
206char *
207print_region (cairo_region_t *region)
208{
209 GString *s = g_string_new ("{");
210 if (cairo_region_is_empty (region))
211 {
212 g_string_append (s, "empty")(__builtin_constant_p ("empty") ? __extension__ ({ const char
* const __val = ("empty"); g_string_append_len_inline (s, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (s, "empty"
, (gssize) -1))
;
213 }
214 else
215 {
216 int num = cairo_region_num_rectangles (region);
217 cairo_rectangle_int_t r;
218
219 if (num == 1)
220 {
221 cairo_region_get_rectangle (region, 0, &r);
222 g_string_append_printf (s, "%dx%d @%d,%d", r.width, r.height, r.x, r.y);
223 }
224 else
225 {
226 int i;
227 cairo_region_get_extents (region, &r);
228 g_string_append_printf (s, "extent: %dx%d @%d,%d, details: ", r.width, r.height, r.x, r.y);
229 for (i = 0; i < num; i++)
230 {
231 cairo_region_get_rectangle (region, i, &r);
232 g_string_append_printf (s, "[%dx%d @%d,%d]", r.width, r.height, r.x, r.y);
233 if (i != num -1)
234 g_string_append (s, ", ")(__builtin_constant_p (", ") ? __extension__ ({ const char * const
__val = (", "); g_string_append_len_inline (s, __val, (__val
!= ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (s, ", ", (gssize) -1)
)
;
235 }
236 }
237 }
238 g_string_append (s, "}")(__builtin_constant_p ("}") ? __extension__ ({ const char * const
__val = ("}"); g_string_append_len_inline (s, __val, (__val !=
((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (s, "}", (gssize) -1))
;
239 return g_string_free (s, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((s), (
(0))) : g_string_free_and_steal (s)) : (g_string_free) ((s), (
(0))))
;
240}
241#endif
242
243static GList *
244list_insert_link_before (GList *list,
245 GList *sibling,
246 GList *link)
247{
248 if (list == NULL((void*)0) || sibling == list)
249 {
250 link->prev = NULL((void*)0);
251 link->next = list;
252 if (list)
253 list->prev = link;
254 return link;
255 }
256 else if (sibling == NULL((void*)0))
257 {
258 GList *last = g_list_last (list);
259
260 last->next = link;
261 link->prev = last;
262 link->next = NULL((void*)0);
263
264 return list;
265 }
266 else
267 {
268 link->next = sibling;
269 link->prev = sibling->prev;
270 sibling->prev = link;
271
272 if (link->prev)
273 link->prev->next = link;
274
275 return list;
276 }
277}
278
279static void
280cdk_window_init (CdkWindow *window)
281{
282 /* 0-initialization is good for all other fields. */
283
284 window->window_type = CDK_WINDOW_CHILD;
285
286 window->state = CDK_WINDOW_STATE_WITHDRAWN;
287 window->fullscreen_mode = CDK_FULLSCREEN_ON_CURRENT_MONITOR;
288 window->width = 1;
289 window->height = 1;
290 window->toplevel_window_type = -1;
291 /* starts hidden */
292 window->effective_visibility = CDK_VISIBILITY_NOT_VIEWABLE3;
293 window->visibility = CDK_VISIBILITY_FULLY_OBSCURED;
294 /* Default to unobscured since some backends don't send visibility events */
295 window->native_visibility = CDK_VISIBILITY_UNOBSCURED;
296 window->children_list_node.data = window;
297
298 window->device_cursor = g_hash_table_new_full (NULL((void*)0), NULL((void*)0),
299 NULL((void*)0), g_object_unref);
300}
301
302/* Stop and return on the first non-NULL parent */
303static gboolean
304accumulate_get_window (GSignalInvocationHint *ihint G_GNUC_UNUSED__attribute__ ((__unused__)),
305 GValue *return_accu,
306 const GValue *handler_return,
307 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
308{
309 g_value_copy (handler_return, return_accu);
310 /* Continue while returning NULL */
311 return g_value_get_object (handler_return) == NULL((void*)0);
312}
313
314static gboolean
315create_surface_accumulator (GSignalInvocationHint *ihint G_GNUC_UNUSED__attribute__ ((__unused__)),
316 GValue *return_accu,
317 const GValue *handler_return,
318 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
319{
320 g_value_copy (handler_return, return_accu);
321
322 /* Stop on the first non-NULL return value */
323 return g_value_get_boxed (handler_return) == NULL((void*)0);
324}
325
326static GQuark quark_pointer_window = 0;
327
328static void
329cdk_window_class_init (CdkWindowClass *klass)
330{
331 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), (((GType) ((20) << (2))))))))
;
332
333 object_class->finalize = cdk_window_finalize;
334 object_class->set_property = cdk_window_set_property;
335 object_class->get_property = cdk_window_get_property;
336
337 klass->create_surface = _cdk_offscreen_window_create_surface;
338
339 quark_pointer_window = g_quark_from_static_string ("ctk-pointer-window");
340
341
342 /* Properties */
343
344 /**
345 * CdkWindow:cursor:
346 *
347 * The mouse pointer for a #CdkWindow. See cdk_window_set_cursor() and
348 * cdk_window_get_cursor() for details.
349 *
350 * Since: 2.18
351 */
352 properties[PROP_CURSOR] =
353 g_param_spec_object ("cursor",
354 P_("Cursor")dgettext("ctk30" "-properties","Cursor"),
355 P_("Cursor")dgettext("ctk30" "-properties","Cursor"),
356 CDK_TYPE_CURSOR(cdk_cursor_get_type ()),
357 G_PARAM_READWRITE);
358 g_object_class_install_properties (object_class, LAST_PROP, properties);
359
360 /**
361 * CdkWindow::pick-embedded-child:
362 * @window: the window on which the signal is emitted
363 * @x: x coordinate in the window
364 * @y: y coordinate in the window
365 *
366 * The ::pick-embedded-child signal is emitted to find an embedded
367 * child at the given position.
368 *
369 * Returns: (nullable) (transfer none): the #CdkWindow of the
370 * embedded child at @x, @y, or %NULL
371 *
372 * Since: 2.18
373 */
374 signals[PICK_EMBEDDED_CHILD] =
375 g_signal_new (g_intern_static_string ("pick-embedded-child"),
376 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
377 G_SIGNAL_RUN_LAST,
378 G_STRUCT_OFFSET (CdkWindowClass, pick_embedded_child)((glong) __builtin_offsetof(CdkWindowClass, pick_embedded_child
))
,
379 accumulate_get_window, NULL((void*)0),
380 _cdk_marshal_OBJECT__DOUBLE_DOUBLE,
381 CDK_TYPE_WINDOW(cdk_window_get_type ()),
382 2,
383 G_TYPE_DOUBLE((GType) ((15) << (2))),
384 G_TYPE_DOUBLE((GType) ((15) << (2))));
385 g_signal_set_va_marshaller (signals[PICK_EMBEDDED_CHILD],
386 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
387 _cdk_marshal_OBJECT__DOUBLE_DOUBLEv);
388
389 /**
390 * CdkWindow::to-embedder:
391 * @window: the offscreen window on which the signal is emitted
392 * @offscreen_x: x coordinate in the offscreen window
393 * @offscreen_y: y coordinate in the offscreen window
394 * @embedder_x: (out) (type double): return location for the x
395 * coordinate in the embedder window
396 * @embedder_y: (out) (type double): return location for the y
397 * coordinate in the embedder window
398 *
399 * The ::to-embedder signal is emitted to translate coordinates
400 * in an offscreen window to its embedder.
401 *
402 * See also #CdkWindow::from-embedder.
403 *
404 * Since: 2.18
405 */
406 signals[TO_EMBEDDER] =
407 g_signal_new (g_intern_static_string ("to-embedder"),
408 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
409 G_SIGNAL_RUN_LAST,
410 G_STRUCT_OFFSET (CdkWindowClass, to_embedder)((glong) __builtin_offsetof(CdkWindowClass, to_embedder)),
411 NULL((void*)0), NULL((void*)0),
412 _cdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
413 G_TYPE_NONE((GType) ((1) << (2))),
414 4,
415 G_TYPE_DOUBLE((GType) ((15) << (2))),
416 G_TYPE_DOUBLE((GType) ((15) << (2))),
417 G_TYPE_POINTER((GType) ((17) << (2))),
418 G_TYPE_POINTER((GType) ((17) << (2))));
419 g_signal_set_va_marshaller (signals[TO_EMBEDDER],
420 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
421 _cdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTERv);
422
423 /**
424 * CdkWindow::from-embedder:
425 * @window: the offscreen window on which the signal is emitted
426 * @embedder_x: x coordinate in the embedder window
427 * @embedder_y: y coordinate in the embedder window
428 * @offscreen_x: (out) (type double): return location for the x
429 * coordinate in the offscreen window
430 * @offscreen_y: (out) (type double): return location for the y
431 * coordinate in the offscreen window
432 *
433 * The ::from-embedder signal is emitted to translate coordinates
434 * in the embedder of an offscreen window to the offscreen window.
435 *
436 * See also #CdkWindow::to-embedder.
437 *
438 * Since: 2.18
439 */
440 signals[FROM_EMBEDDER] =
441 g_signal_new (g_intern_static_string ("from-embedder"),
442 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
443 G_SIGNAL_RUN_LAST,
444 G_STRUCT_OFFSET (CdkWindowClass, from_embedder)((glong) __builtin_offsetof(CdkWindowClass, from_embedder)),
445 NULL((void*)0), NULL((void*)0),
446 _cdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
447 G_TYPE_NONE((GType) ((1) << (2))),
448 4,
449 G_TYPE_DOUBLE((GType) ((15) << (2))),
450 G_TYPE_DOUBLE((GType) ((15) << (2))),
451 G_TYPE_POINTER((GType) ((17) << (2))),
452 G_TYPE_POINTER((GType) ((17) << (2))));
453 g_signal_set_va_marshaller (signals[FROM_EMBEDDER],
454 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
455 _cdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTERv);
456
457 /**
458 * CdkWindow::create-surface:
459 * @window: the offscreen window on which the signal is emitted
460 * @width: the width of the offscreen surface to create
461 * @height: the height of the offscreen surface to create
462 *
463 * The ::create-surface signal is emitted when an offscreen window
464 * needs its surface (re)created, which happens either when the
465 * window is first drawn to, or when the window is being
466 * resized. The first signal handler that returns a non-%NULL
467 * surface will stop any further signal emission, and its surface
468 * will be used.
469 *
470 * Note that it is not possible to access the window's previous
471 * surface from within any callback of this signal. Calling
472 * cdk_offscreen_window_get_surface() will lead to a crash.
473 *
474 * Returns: the newly created #cairo_surface_t for the offscreen window
475 *
476 * Since: 3.0
477 */
478 signals[CREATE_SURFACE] =
479 g_signal_new (g_intern_static_string ("create-surface"),
480 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
481 G_SIGNAL_RUN_LAST,
482 G_STRUCT_OFFSET (CdkWindowClass, create_surface)((glong) __builtin_offsetof(CdkWindowClass, create_surface)),
483 create_surface_accumulator, NULL((void*)0),
484 _cdk_marshal_BOXED__INT_INT,
485 CAIRO_GOBJECT_TYPE_SURFACEcairo_gobject_surface_get_type (),
486 2,
487 G_TYPE_INT((GType) ((6) << (2))),
488 G_TYPE_INT((GType) ((6) << (2))));
489 g_signal_set_va_marshaller (signals[CREATE_SURFACE],
490 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
491 _cdk_marshal_BOXED__INT_INTv);
492
493 /**
494 * CdkWindow::moved-to-rect:
495 * @window: the #CdkWindow that moved
496 * @flipped_rect: (nullable): the position of @window after any possible
497 * flipping or %NULL if the backend can't obtain it
498 * @final_rect: (nullable): the final position of @window or %NULL if the
499 * backend can't obtain it
500 * @flipped_x: %TRUE if the anchors were flipped horizontally
501 * @flipped_y: %TRUE if the anchors were flipped vertically
502 *
503 * Emitted when the position of @window is finalized after being moved to a
504 * destination rectangle.
505 *
506 * @window might be flipped over the destination rectangle in order to keep
507 * it on-screen, in which case @flipped_x and @flipped_y will be set to %TRUE
508 * accordingly.
509 *
510 * @flipped_rect is the ideal position of @window after any possible
511 * flipping, but before any possible sliding. @final_rect is @flipped_rect,
512 * but possibly translated in the case that flipping is still ineffective in
513 * keeping @window on-screen.
514 *
515 * Since: 3.22
516 * Stability: Private
517 */
518 signals[MOVED_TO_RECT] =
519 g_signal_new (g_intern_static_string ("moved-to-rect"),
520 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
521 G_SIGNAL_RUN_FIRST,
522 0,
523 NULL((void*)0),
524 NULL((void*)0),
525 _cdk_marshal_VOID__POINTER_POINTER_BOOLEAN_BOOLEAN,
526 G_TYPE_NONE((GType) ((1) << (2))),
527 4,
528 G_TYPE_POINTER((GType) ((17) << (2))),
529 G_TYPE_POINTER((GType) ((17) << (2))),
530 G_TYPE_BOOLEAN((GType) ((5) << (2))),
531 G_TYPE_BOOLEAN((GType) ((5) << (2))));
532 g_signal_set_va_marshaller (signals[MOVED_TO_RECT],
533 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
534 _cdk_marshal_VOID__POINTER_POINTER_BOOLEAN_BOOLEANv);
535}
536
537static void
538seat_removed_cb (CdkDisplay *display G_GNUC_UNUSED__attribute__ ((__unused__)),
539 CdkSeat *seat,
540 CdkWindow *window)
541{
542 CdkDevice *device = cdk_seat_get_pointer (seat);
543
544 window->devices_inside = g_list_remove (window->devices_inside, device);
545 g_hash_table_remove (window->device_cursor, device);
546
547 if (window->device_events)
548 g_hash_table_remove (window->device_events, device);
549}
550
551static void
552cdk_window_finalize (GObject *object)
553{
554 CdkWindow *window = CDK_WINDOW (object)((((CdkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((cdk_window_get_type ()))))))
;
555
556 g_signal_handlers_disconnect_by_func (cdk_window_get_display (window),g_signal_handlers_disconnect_matched ((cdk_window_get_display
(window)), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (seat_removed_cb), (window))
557 seat_removed_cb, window)g_signal_handlers_disconnect_matched ((cdk_window_get_display
(window)), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (seat_removed_cb), (window))
;
558
559 if (!CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
560 {
561 if (CDK_WINDOW_TYPE (window)((((CdkWindow *)(window)))->window_type) != CDK_WINDOW_FOREIGN)
562 {
563 g_warning ("losing last reference to undestroyed window");
564 _cdk_window_destroy (window, FALSE(0));
565 }
566 else
567 /* We use TRUE here, to keep us from actually calling
568 * XDestroyWindow() on the window
569 */
570 _cdk_window_destroy (window, TRUE(!(0)));
571 }
572
573 if (window->synthesized_crossing_event_id)
574 {
575 g_source_remove (window->synthesized_crossing_event_id);
576 window->synthesized_crossing_event_id = 0;
577 }
578
579 if (window->impl)
580 {
581 g_object_unref (window->impl);
582 window->impl = NULL((void*)0);
583 }
584
585 if (window->impl_window != window)
586 {
587 g_object_unref (window->impl_window);
588 window->impl_window = NULL((void*)0);
589 }
590
591 if (window->shape)
592 cairo_region_destroy (window->shape);
593
594 if (window->input_shape)
595 cairo_region_destroy (window->input_shape);
596
597 if (window->cursor)
598 g_object_unref (window->cursor);
599
600 if (window->device_cursor)
601 g_hash_table_destroy (window->device_cursor);
602
603 if (window->device_events)
604 g_hash_table_destroy (window->device_events);
605
606 if (window->source_event_masks)
607 g_hash_table_destroy (window->source_event_masks);
608
609 if (window->devices_inside)
610 g_list_free (window->devices_inside);
611
612 if (window->opaque_region)
613 cairo_region_destroy (window->opaque_region);
614
615 G_OBJECT_CLASS (cdk_window_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((cdk_window_parent_class)), (((GType) ((20) << (2))
))))))
->finalize (object);
616}
617
618static void
619cdk_window_set_property (GObject *object,
620 guint prop_id,
621 const GValue *value,
622 GParamSpec *pspec)
623{
624 CdkWindow *window = (CdkWindow *)object;
625
626 switch (prop_id)
627 {
628 case PROP_CURSOR:
629 cdk_window_set_cursor (window, g_value_get_object (value));
630 break;
631
632 default:
633 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "cdkwindow.c", 633, ("property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
634 break;
635 }
636}
637
638static void
639cdk_window_get_property (GObject *object,
640 guint prop_id,
641 GValue *value,
642 GParamSpec *pspec)
643{
644 CdkWindow *window = (CdkWindow *) object;
645
646 switch (prop_id)
647 {
648 case PROP_CURSOR:
649 g_value_set_object (value, cdk_window_get_cursor (window));
650 break;
651
652 default:
653 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "cdkwindow.c", 653, ("property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
654 break;
655 }
656}
657
658static gboolean
659cdk_window_is_offscreen (CdkWindow *window)
660{
661 return window->window_type == CDK_WINDOW_OFFSCREEN;
662}
663
664static gboolean
665cdk_window_is_subsurface (CdkWindow *window)
666{
667 return window->window_type == CDK_WINDOW_SUBSURFACE;
668}
669
670static CdkWindow *
671cdk_window_get_impl_window (CdkWindow *window)
672{
673 return window->impl_window;
674}
675
676CdkWindow *
677_cdk_window_get_impl_window (CdkWindow *window)
678{
679 return cdk_window_get_impl_window (window);
680}
681
682static gboolean
683cdk_window_has_impl (CdkWindow *window)
684{
685 return window->impl_window == window;
686}
687
688static gboolean
689cdk_window_is_toplevel (CdkWindow *window)
690{
691 return
692 window->parent == NULL((void*)0) ||
693 window->parent->window_type == CDK_WINDOW_ROOT;
694}
695
696gboolean
697_cdk_window_has_impl (CdkWindow *window)
698{
699 return cdk_window_has_impl (window);
700}
701
702static gboolean
703cdk_window_has_no_impl (CdkWindow *window)
704{
705 return window->impl_window != window;
706}
707
708static void
709remove_sibling_overlapped_area (CdkWindow *window,
710 cairo_region_t *region)
711{
712 CdkWindow *parent;
713 CdkWindow *sibling;
714 cairo_region_t *child_region;
715 CdkRectangle r;
716 GList *l;
717 cairo_region_t *shape;
718
719 parent = window->parent;
720
721 if (cdk_window_is_toplevel (window))
722 return;
723
724 /* Convert from from window coords to parent coords */
725 cairo_region_translate (region, window->x, window->y);
726
727 for (l = parent->children; l; l = l->next)
728 {
729 sibling = l->data;
730
731 if (sibling == window)
732 break;
733
734 if (!CDK_WINDOW_IS_MAPPED (sibling)(((sibling)->state & CDK_WINDOW_STATE_WITHDRAWN) == 0) || sibling->input_only || sibling->composited)
735 continue;
736
737 /* Ignore offscreen children, as they don't draw in their parent and
738 * don't take part in the clipping */
739 if (cdk_window_is_offscreen (sibling))
740 continue;
741
742 r.x = sibling->x;
743 r.y = sibling->y;
744 r.width = sibling->width;
745 r.height = sibling->height;
746
747 child_region = cairo_region_create_rectangle (&r);
748
749 if (sibling->shape)
750 {
751 /* Adjust shape region to parent window coords */
752 cairo_region_translate (sibling->shape, sibling->x, sibling->y);
753 cairo_region_intersect (child_region, sibling->shape);
754 cairo_region_translate (sibling->shape, -sibling->x, -sibling->y);
755 }
756 else if (window->window_type == CDK_WINDOW_FOREIGN)
757 {
758 shape = CDK_WINDOW_IMPL_GET_CLASS (sibling)((((CdkWindowImplClass*) (((GTypeInstance*) ((sibling)))->
g_class))))
->get_shape (sibling);
759 if (shape)
760 {
761 cairo_region_intersect (child_region, shape);
762 cairo_region_destroy (shape);
763 }
764 }
765
766 cairo_region_subtract (region, child_region);
767 cairo_region_destroy (child_region);
768 }
769
770 remove_sibling_overlapped_area (parent, region);
771
772 /* Convert back to window coords */
773 cairo_region_translate (region, -window->x, -window->y);
774}
775
776static void
777remove_child_area (CdkWindow *window,
778 gboolean for_input,
779 cairo_region_t *region)
780{
781 CdkWindow *child;
782 cairo_region_t *child_region;
783 CdkRectangle r;
784 GList *l;
785 cairo_region_t *shape;
786
787 for (l = window->children; l; l = l->next)
788 {
789 child = l->data;
790
791 /* If region is empty already, no need to do
792 anything potentially costly */
793 if (cairo_region_is_empty (region))
794 break;
795
796 if (!CDK_WINDOW_IS_MAPPED (child)(((child)->state & CDK_WINDOW_STATE_WITHDRAWN) == 0) || child->input_only || child->composited)
797 continue;
798
799 /* Ignore offscreen children, as they don't draw in their parent and
800 * don't take part in the clipping */
801 if (cdk_window_is_offscreen (child))
802 continue;
803
804 r.x = child->x;
805 r.y = child->y;
806 r.width = child->width;
807 r.height = child->height;
808
809 /* Bail early if child totally outside region */
810 if (cairo_region_contains_rectangle (region, &r) == CAIRO_REGION_OVERLAP_OUT)
811 continue;
812
813 child_region = cairo_region_create_rectangle (&r);
814
815 if (child->shape)
816 {
817 /* Adjust shape region to parent window coords */
818 cairo_region_translate (child->shape, child->x, child->y);
819 cairo_region_intersect (child_region, child->shape);
820 cairo_region_translate (child->shape, -child->x, -child->y);
821 }
822 else if (window->window_type == CDK_WINDOW_FOREIGN)
823 {
824 shape = CDK_WINDOW_IMPL_GET_CLASS (child)((((CdkWindowImplClass*) (((GTypeInstance*) ((child)))->g_class
))))
->get_shape (child);
825 if (shape)
826 {
827 cairo_region_intersect (child_region, shape);
828 cairo_region_destroy (shape);
829 }
830 }
831
832 if (for_input)
833 {
834 if (child->input_shape)
835 cairo_region_intersect (child_region, child->input_shape);
836 else if (window->window_type == CDK_WINDOW_FOREIGN)
837 {
838 shape = CDK_WINDOW_IMPL_GET_CLASS (child)((((CdkWindowImplClass*) (((GTypeInstance*) ((child)))->g_class
))))
->get_input_shape (child);
839 if (shape)
840 {
841 cairo_region_intersect (child_region, shape);
842 cairo_region_destroy (shape);
843 }
844 }
845 }
846
847 cairo_region_subtract (region, child_region);
848 cairo_region_destroy (child_region);
849 }
850}
851
852static CdkVisibilityState
853effective_visibility (CdkWindow *window)
854{
855 CdkVisibilityState native;
856
857 if (!cdk_window_is_viewable (window))
858 return CDK_VISIBILITY_NOT_VIEWABLE3;
859
860 native = window->impl_window->native_visibility;
861
862 if (native == CDK_VISIBILITY_FULLY_OBSCURED ||
863 window->visibility == CDK_VISIBILITY_FULLY_OBSCURED)
864 return CDK_VISIBILITY_FULLY_OBSCURED;
865 else if (native == CDK_VISIBILITY_UNOBSCURED)
866 return window->visibility;
867 else /* native PARTIAL, private partial or unobscured */
868 return CDK_VISIBILITY_PARTIAL;
869}
870
871static void
872cdk_window_update_visibility (CdkWindow *window)
873{
874 CdkVisibilityState new_visibility;
875 CdkEvent *event;
876
877 new_visibility = effective_visibility (window);
878
879 if (new_visibility != window->effective_visibility)
880 {
881 window->effective_visibility = new_visibility;
882
883 if (new_visibility != CDK_VISIBILITY_NOT_VIEWABLE3 &&
884 window->event_mask & CDK_VISIBILITY_NOTIFY_MASK)
885 {
886 event = _cdk_make_event (window, CDK_VISIBILITY_NOTIFY,
887 NULL((void*)0), FALSE(0));
888 event->visibility.state = new_visibility;
889 }
890 }
891}
892
893static void
894cdk_window_update_visibility_recursively (CdkWindow *window,
895 CdkWindow *only_for_impl)
896{
897 CdkWindow *child;
898 GList *l;
899
900 cdk_window_update_visibility (window);
901 for (l = window->children; l != NULL((void*)0); l = l->next)
902 {
903 child = l->data;
904 if ((only_for_impl == NULL((void*)0)) ||
905 (only_for_impl == child->impl_window))
906 cdk_window_update_visibility_recursively (child, only_for_impl);
907 }
908}
909
910static gboolean
911should_apply_clip_as_shape (CdkWindow *window)
912{
913 return
914 cdk_window_has_impl (window) &&
915 /* Not for offscreens */
916 !cdk_window_is_offscreen (window) &&
917 /* or for non-shaped toplevels */
918 (!cdk_window_is_toplevel (window) ||
919 window->shape != NULL((void*)0) || window->applied_shape) &&
920 /* or for foreign windows */
921 window->window_type != CDK_WINDOW_FOREIGN &&
922 /* or for the root window */
923 window->window_type != CDK_WINDOW_ROOT;
924}
925
926static void
927apply_shape (CdkWindow *window,
928 cairo_region_t *region)
929{
930 CdkWindowImplClass *impl_class;
931
932 /* We trash whether we applied a shape so that
933 we can avoid unsetting it many times, which
934 could happen in e.g. apply_clip_as_shape as
935 windows get resized */
936 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
937 if (region)
938 impl_class->shape_combine_region (window,
939 region, 0, 0);
940 else if (window->applied_shape)
941 impl_class->shape_combine_region (window,
942 NULL((void*)0), 0, 0);
943
944 window->applied_shape = region != NULL((void*)0);
945}
946
947static gboolean
948region_rect_equal (const cairo_region_t *region,
949 const CdkRectangle *rect)
950{
951 CdkRectangle extents;
952
953 if (cairo_region_num_rectangles (region) != 1)
954 return FALSE(0);
955
956 cairo_region_get_extents (region, &extents);
957
958 return extents.x == rect->x &&
959 extents.y == rect->y &&
960 extents.width == rect->width &&
961 extents.height == rect->height;
962}
963
964static void
965apply_clip_as_shape (CdkWindow *window)
966{
967 CdkRectangle r;
968 cairo_region_t *region;
969
970 r.x = r.y = 0;
971 r.width = window->width;
972 r.height = window->height;
973
974 region = cairo_region_copy (window->clip_region);
975 remove_sibling_overlapped_area (window, region);
976
977 /* We only apply the clip region if would differ
978 from the actual clip region implied by the size
979 of the window. This is to avoid unneccessarily
980 adding meaningless shapes to all native subwindows */
981 if (!region_rect_equal (region, &r))
982 apply_shape (window, region);
983 else
984 apply_shape (window, NULL((void*)0));
985
986 cairo_region_destroy (region);
987}
988
989static void
990recompute_visible_regions_internal (CdkWindow *private,
991 gboolean recalculate_clip,
992 gboolean recalculate_children)
993{
994 CdkRectangle r;
995 GList *l;
996 CdkWindow *child;
997 cairo_region_t *new_clip;
998 gboolean clip_region_changed;
999 gboolean abs_pos_changed;
1000 int old_abs_x, old_abs_y;
1001
1002 old_abs_x = private->abs_x;
1003 old_abs_y = private->abs_y;
1004
1005 /* Update absolute position */
1006 if ((cdk_window_has_impl (private) &&
1007 private->window_type != CDK_WINDOW_SUBSURFACE) ||
1008 (cdk_window_is_toplevel (private) &&
1009 private->window_type == CDK_WINDOW_SUBSURFACE))
1010 {
1011 /* Native windows and toplevel subsurfaces start here */
1012 private->abs_x = 0;
1013 private->abs_y = 0;
1014 }
1015 else
1016 {
1017 private->abs_x = private->parent->abs_x + private->x;
1018 private->abs_y = private->parent->abs_y + private->y;
1019 }
1020
1021 abs_pos_changed =
1022 private->abs_x != old_abs_x ||
1023 private->abs_y != old_abs_y;
1024
1025 /* Update clip region based on:
1026 * parent clip
1027 * window size/position
1028 */
1029 clip_region_changed = FALSE(0);
1030 if (recalculate_clip)
1031 {
1032 if (private->viewable)
1033 {
1034 /* Calculate visible region (sans children) in parent window coords */
1035 r.x = private->x;
1036 r.y = private->y;
1037 r.width = private->width;
1038 r.height = private->height;
1039 new_clip = cairo_region_create_rectangle (&r);
1040
1041 if (!cdk_window_is_toplevel (private))
1042 cairo_region_intersect (new_clip, private->parent->clip_region);
1043
1044 /* Convert from parent coords to window coords */
1045 cairo_region_translate (new_clip, -private->x, -private->y);
1046
1047 if (should_apply_clip_as_shape (private) && private->shape)
1048 cairo_region_intersect (new_clip, private->shape);
1049 }
1050 else
1051 new_clip = cairo_region_create ();
1052
1053 if (private->clip_region == NULL((void*)0) ||
1054 !cairo_region_equal (private->clip_region, new_clip))
1055 clip_region_changed = TRUE(!(0));
1056
1057 if (private->clip_region)
1058 cairo_region_destroy (private->clip_region);
1059 private->clip_region = new_clip;
1060 }
1061
1062 if (clip_region_changed)
1063 {
1064 CdkVisibilityState visibility;
1065 gboolean fully_visible;
1066
1067 if (cairo_region_is_empty (private->clip_region))
1068 visibility = CDK_VISIBILITY_FULLY_OBSCURED;
1069 else
1070 {
1071 if (private->shape)
1072 {
1073 fully_visible = cairo_region_equal (private->clip_region,
1074 private->shape);
1075 }
1076 else
1077 {
1078 r.x = 0;
1079 r.y = 0;
1080 r.width = private->width;
1081 r.height = private->height;
1082 fully_visible = region_rect_equal (private->clip_region, &r);
1083 }
1084
1085 if (fully_visible)
1086 visibility = CDK_VISIBILITY_UNOBSCURED;
1087 else
1088 visibility = CDK_VISIBILITY_PARTIAL;
1089 }
1090
1091 if (private->visibility != visibility)
1092 {
1093 private->visibility = visibility;
1094 cdk_window_update_visibility (private);
1095 }
1096 }
1097
1098 /* Update all children, recursively (except for root, where children are not exact). */
1099 if ((abs_pos_changed || clip_region_changed || recalculate_children) &&
1100 private->window_type != CDK_WINDOW_ROOT)
1101 {
1102 for (l = private->children; l; l = l->next)
1103 {
1104 child = l->data;
1105 /* Only recalculate clip if the the clip region changed, otherwise
1106 * there is no way the child clip region could change (its has not e.g. moved)
1107 * Except if recalculate_children is set to force child updates
1108 */
1109 recompute_visible_regions_internal (child,
1110 recalculate_clip && (clip_region_changed || recalculate_children),
1111 FALSE(0));
1112 }
1113 }
1114}
1115
1116/* Call this when private has changed in one or more of these ways:
1117 * size changed
1118 * window moved
1119 * new window added
1120 * stacking order of window changed
1121 * child deleted
1122 *
1123 * It will recalculate abs_x/y and the clip regions
1124 *
1125 * Unless the window didn’t change stacking order or size/pos, pass in TRUE
1126 * for recalculate_siblings. (Mostly used internally for the recursion)
1127 *
1128 * If a child window was removed (and you can’t use that child for
1129 * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
1130 */
1131static void
1132recompute_visible_regions (CdkWindow *private,
1133 gboolean recalculate_children)
1134{
1135 CdkWindow *toplevel;
1136
1137 toplevel = cdk_window_get_toplevel (private);
1138 toplevel->geometry_dirty = TRUE(!(0));
1139
1140 recompute_visible_regions_internal (private,
1141 TRUE(!(0)),
1142 recalculate_children);
1143}
1144
1145static void
1146cdk_window_clear_old_updated_area (CdkWindow *window)
1147{
1148 int i;
1149
1150 for (i = 0; i < 2; i++)
1151 {
1152 if (window->old_updated_area[i])
1153 {
1154 cairo_region_destroy (window->old_updated_area[i]);
1155 window->old_updated_area[i] = NULL((void*)0);
1156 }
1157 }
1158}
1159
1160static void
1161cdk_window_append_old_updated_area (CdkWindow *window,
1162 cairo_region_t *region)
1163{
1164 if (window->old_updated_area[1])
1165 cairo_region_destroy (window->old_updated_area[1]);
1166 window->old_updated_area[1] = window->old_updated_area[0];
1167 window->old_updated_area[0] = cairo_region_reference (region);
1168}
1169
1170void
1171_cdk_window_update_size (CdkWindow *window)
1172{
1173 cdk_window_clear_old_updated_area (window);
1174 recompute_visible_regions (window, FALSE(0));
1175}
1176
1177/* Find the native window that would be just above "child"
1178 * in the native stacking order if “child” was a native window
1179 * (it doesn’t have to be native). If there is no such native
1180 * window inside this native parent then NULL is returned.
1181 * If child is NULL, find lowest native window in parent.
1182 */
1183static CdkWindow *
1184find_native_sibling_above_helper (CdkWindow *parent,
1185 CdkWindow *child)
1186{
1187 CdkWindow *w;
1188 GList *l;
1189
1190 if (child)
1191 {
1192 l = g_list_find (parent->children, child);
1193 g_assert (l != NULL)do { if (l != ((void*)0)) ; else g_assertion_message_expr ("Cdk"
, "cdkwindow.c", 1193, ((const char*) (__func__)), "l != NULL"
); } while (0)
; /* Better be a child of its parent... */
1194 l = l->prev; /* Start looking at the one above the child */
1195 }
1196 else
1197 l = g_list_last (parent->children);
1198
1199 for (; l != NULL((void*)0); l = l->prev)
1200 {
1201 w = l->data;
1202
1203 if (cdk_window_has_impl (w))
1204 return w;
1205
1206 g_assert (parent != w)do { if (parent != w) ; else g_assertion_message_expr ("Cdk",
"cdkwindow.c", 1206, ((const char*) (__func__)), "parent != w"
); } while (0)
;
1207 w = find_native_sibling_above_helper (w, NULL((void*)0));
1208 if (w)
1209 return w;
1210 }
1211
1212 return NULL((void*)0);
1213}
1214
1215
1216static CdkWindow *
1217find_native_sibling_above (CdkWindow *parent,
1218 CdkWindow *child)
1219{
1220 CdkWindow *w;
1221
1222 if (!parent)
1223 return NULL((void*)0);
1224
1225 w = find_native_sibling_above_helper (parent, child);
1226 if (w)
1227 return w;
1228
1229 if (cdk_window_has_impl (parent))
1230 return NULL((void*)0);
1231 else
1232 return find_native_sibling_above (parent->parent, parent);
1233}
1234
1235static CdkEventMask
1236get_native_device_event_mask (CdkWindow *private,
1237 CdkDevice *device)
1238{
1239 CdkEventMask event_mask;
1240
1241 if (device)
1242 event_mask = GPOINTER_TO_INT (g_hash_table_lookup (private->device_events, device))((gint) (glong) (g_hash_table_lookup (private->device_events
, device)))
;
1243 else
1244 event_mask = private->event_mask;
1245
1246 if (private->window_type == CDK_WINDOW_ROOT ||
1247 private->window_type == CDK_WINDOW_FOREIGN)
1248 return event_mask;
1249 else
1250 {
1251 CdkEventMask mask;
1252
1253 /* Do whatever the app asks to, since the app
1254 * may be asking for weird things for native windows,
1255 * but don't use motion hints as that may affect non-native
1256 * child windows that don't want it. Also, we need to
1257 * set all the app-specified masks since they will be picked
1258 * up by any implicit grabs (i.e. if they were not set as
1259 * native we would not get the events we need). */
1260 mask = private->event_mask & ~CDK_POINTER_MOTION_HINT_MASK;
1261
1262 /* We need thse for all native windows so we can
1263 emulate events on children: */
1264 mask |=
1265 CDK_EXPOSURE_MASK |
1266 CDK_VISIBILITY_NOTIFY_MASK |
1267 CDK_ENTER_NOTIFY_MASK | CDK_LEAVE_NOTIFY_MASK;
1268
1269 /* Additionally we select for pointer and button events
1270 * for toplevels as we need to get these to emulate
1271 * them for non-native subwindows. Even though we don't
1272 * select on them for all native windows we will get them
1273 * as the events are propagated out to the first window
1274 * that select for them.
1275 * Not selecting for button press on all windows is an
1276 * important thing, because in X only one client can do
1277 * so, and we don't want to unexpectedly prevent another
1278 * client from doing it.
1279 *
1280 * We also need to do the same if the app selects for button presses
1281 * because then we will get implicit grabs for this window, and the
1282 * event mask used for that grab is based on the rest of the mask
1283 * for the window, but we might need more events than this window
1284 * lists due to some non-native child window.
1285 */
1286 if (cdk_window_is_toplevel (private) ||
1287 mask & CDK_BUTTON_PRESS_MASK)
1288 mask |=
1289 CDK_TOUCH_MASK |
1290 CDK_POINTER_MOTION_MASK |
1291 CDK_BUTTON_PRESS_MASK | CDK_BUTTON_RELEASE_MASK |
1292 CDK_SCROLL_MASK;
1293
1294 return mask;
1295 }
1296}
1297
1298static CdkEventMask
1299get_native_grab_event_mask (CdkEventMask grab_mask)
1300{
1301 /* Similar to the above but for pointer events only */
1302 return
1303 CDK_POINTER_MOTION_MASK |
1304 CDK_BUTTON_PRESS_MASK | CDK_BUTTON_RELEASE_MASK |
1305 CDK_ENTER_NOTIFY_MASK | CDK_LEAVE_NOTIFY_MASK |
1306 CDK_SCROLL_MASK |
1307 (grab_mask &
1308 ~CDK_POINTER_MOTION_HINT_MASK);
1309}
1310
1311static CdkEventMask
1312get_native_event_mask (CdkWindow *private)
1313{
1314 return get_native_device_event_mask (private, NULL((void*)0));
1315}
1316
1317/* Puts the native window in the right order wrt the other native windows
1318 * in the hierarchy, given the position it has in the client side data.
1319 * This is useful if some operation changed the stacking order.
1320 * This calls assumes the native window is now topmost in its native parent.
1321 */
1322static void
1323sync_native_window_stack_position (CdkWindow *window)
1324{
1325 CdkWindow *above;
1326 CdkWindowImplClass *impl_class;
1327 GList listhead = {0};
1328
1329 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
1330
1331 above = find_native_sibling_above (window->parent, window);
1332 if (above)
1333 {
1334 listhead.data = window;
1335 impl_class->restack_under (above, &listhead);
1336 }
1337}
1338
1339/**
1340 * cdk_window_new: (constructor)
1341 * @parent: (allow-none): a #CdkWindow, or %NULL to create the window as a child of
1342 * the default root window for the default display.
1343 * @attributes: attributes of the new window
1344 * @attributes_mask: (type CdkWindowAttributesType): mask indicating which
1345 * fields in @attributes are valid
1346 *
1347 * Creates a new #CdkWindow using the attributes from
1348 * @attributes. See #CdkWindowAttr and #CdkWindowAttributesType for
1349 * more details. Note: to use this on displays other than the default
1350 * display, @parent must be specified.
1351 *
1352 * Returns: (transfer full): the new #CdkWindow
1353 **/
1354CdkWindow*
1355cdk_window_new (CdkWindow *parent,
1356 CdkWindowAttr *attributes,
1357 gint attributes_mask)
1358{
1359 CdkWindow *window;
1360 CdkScreen *screen;
1361 CdkDisplay *display;
1362 int x, y;
1363 gboolean native;
1364 CdkEventMask event_mask;
1365 CdkWindow *real_parent;
1366
1367 g_return_val_if_fail (attributes != NULL, NULL)do { if ((attributes != ((void*)0))) { } else { g_return_if_fail_warning
("Cdk", ((const char*) (__func__)), "attributes != NULL"); return
(((void*)0)); } } while (0)
;
1368
1369 if (!parent)
1370 {
1371 screen = cdk_screen_get_default ();
1372 parent = cdk_screen_get_root_window (screen);
1373 }
1374 else
1375 screen = cdk_window_get_screen (parent);
1376
1377 g_return_val_if_fail (CDK_IS_WINDOW (parent), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((parent)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (parent)"); return (((void*)0)); } } while
(0)
;
1378
1379 if (CDK_WINDOW_DESTROYED (parent)(((CdkWindow *)(parent))->destroyed))
1380 {
1381 g_warning ("cdk_window_new(): parent is destroyed");
1382 return NULL((void*)0);
1383 }
1384
1385 if (attributes_mask & CDK_WA_VISUAL)
1386 {
1387 g_return_val_if_fail (cdk_visual_get_screen (attributes->visual) == screen, NULL)do { if ((cdk_visual_get_screen (attributes->visual) == screen
)) { } else { g_return_if_fail_warning ("Cdk", ((const char*)
(__func__)), "cdk_visual_get_screen (attributes->visual) == screen"
); return (((void*)0)); } } while (0)
;
1388 }
1389
1390 display = cdk_screen_get_display (screen);
1391
1392 window = _cdk_display_create_window (display);
1393
1394 /* Windows with a foreign parent are treated as if they are children
1395 * of the root window, except for actual creation.
1396 */
1397 real_parent = parent;
1398 if (CDK_WINDOW_TYPE (parent)((((CdkWindow *)(parent)))->window_type) == CDK_WINDOW_FOREIGN)
1399 parent = cdk_screen_get_root_window (screen);
1400
1401 window->parent = parent;
1402
1403 window->accept_focus = TRUE(!(0));
1404 window->focus_on_map = TRUE(!(0));
1405 window->event_compression = TRUE(!(0));
1406
1407 if (attributes_mask & CDK_WA_X)
1408 x = attributes->x;
1409 else
1410 x = 0;
1411
1412 if (attributes_mask & CDK_WA_Y)
1413 y = attributes->y;
1414 else
1415 y = 0;
1416
1417 window->x = x;
1418 window->y = y;
1419 window->width = (attributes->width > 1) ? (attributes->width) : (1);
1420 window->height = (attributes->height > 1) ? (attributes->height) : (1);
1421 window->alpha = 255;
1422
1423 if (attributes->wclass == CDK_INPUT_ONLY)
1424 {
1425 /* Backwards compatiblity - we've always ignored
1426 * attributes->window_type for input-only windows
1427 * before
1428 */
1429 if (CDK_WINDOW_TYPE (parent)((((CdkWindow *)(parent)))->window_type) == CDK_WINDOW_ROOT)
1430 window->window_type = CDK_WINDOW_TEMP;
1431 else
1432 window->window_type = CDK_WINDOW_CHILD;
1433 }
1434 else
1435 window->window_type = attributes->window_type;
1436
1437 /* Sanity checks */
1438 switch (window->window_type)
1439 {
1440 case CDK_WINDOW_TOPLEVEL:
1441 case CDK_WINDOW_TEMP:
1442 case CDK_WINDOW_OFFSCREEN:
1443 if (CDK_WINDOW_TYPE (parent)((((CdkWindow *)(parent)))->window_type) != CDK_WINDOW_ROOT)
1444 g_warning (G_STRLOC"cdkwindow.c" ":" "1444" "Toplevel windows must be created as children of\n"
1445 "of a window of type CDK_WINDOW_ROOT or CDK_WINDOW_FOREIGN");
1446 break;
1447 case CDK_WINDOW_SUBSURFACE:
1448#ifdef CDK_WINDOWING_WAYLAND
1449 if (!CDK_IS_WAYLAND_DISPLAY (display)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(display)); GType __t = ((cdk_wayland_display_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
1450 {
1451 g_warning (G_STRLOC"cdkwindow.c" ":" "1451" "Subsurface windows can only be used on Wayland");
1452 return NULL((void*)0);
1453 }
1454#endif
1455 break;
1456 case CDK_WINDOW_CHILD:
1457 break;
1458 default:
1459 g_warning (G_STRLOC"cdkwindow.c" ":" "1459" "cannot make windows of type %d", window->window_type);
1460 return NULL((void*)0);
1461 }
1462
1463 if (attributes_mask & CDK_WA_VISUAL)
1464 window->visual = attributes->visual;
1465 else
1466 window->visual = cdk_screen_get_system_visual (screen);
1467
1468 window->event_mask = attributes->event_mask;
1469
1470 if (attributes->wclass == CDK_INPUT_OUTPUT)
1471 {
1472 window->input_only = FALSE(0);
1473 window->depth = window->visual->depth;
1474
1475 /* XXX: Cache this somehow? */
1476 window->background = cairo_pattern_create_rgba (0, 0, 0, 0);
1477 }
1478 else
1479 {
1480 window->depth = 0;
1481 window->input_only = TRUE(!(0));
1482 }
1483
1484 window->parent->children = g_list_concat (&window->children_list_node, window->parent->children);
1485
1486 if (window->parent->window_type == CDK_WINDOW_ROOT)
1487 {
1488 CdkFrameClock *frame_clock = g_object_new (CDK_TYPE_FRAME_CLOCK_IDLE(cdk_frame_clock_idle_get_type ()), NULL((void*)0));
1489 cdk_window_set_frame_clock (window, frame_clock);
1490 g_object_unref (frame_clock);
1491 }
1492
1493 native = FALSE(0);
1494 if (window->parent->window_type == CDK_WINDOW_ROOT)
1495 native = TRUE(!(0)); /* Always use native windows for toplevels */
1496
1497#ifdef CDK_WINDOWING_WAYLAND
1498 if (window->window_type == CDK_WINDOW_SUBSURFACE)
1499 native = TRUE(!(0)); /* Always use native windows for subsurfaces as well */
1500#endif
1501
1502 if (cdk_window_is_offscreen (window))
1503 {
1504 _cdk_offscreen_window_new (window, attributes, attributes_mask);
1505 window->impl_window = window;
1506 }
1507 else if (native)
1508 {
1509 event_mask = get_native_event_mask (window);
1510
1511 /* Create the impl */
1512 _cdk_display_create_window_impl (display, window, real_parent, screen, event_mask, attributes, attributes_mask);
1513 window->impl_window = window;
1514
1515 parent->impl_window->native_children = g_list_prepend (parent->impl_window->native_children, window);
1516
1517 /* This will put the native window topmost in the native parent, which may
1518 * be wrong wrt other native windows in the non-native hierarchy, so restack */
1519 if (!_cdk_window_has_impl (real_parent))
1520 sync_native_window_stack_position (window);
1521 }
1522 else
1523 {
1524 window->impl_window = g_object_ref (window->parent->impl_window)((__typeof__ (window->parent->impl_window)) (g_object_ref
) (window->parent->impl_window))
;
1525 window->impl = g_object_ref (window->impl_window->impl)((__typeof__ (window->impl_window->impl)) (g_object_ref
) (window->impl_window->impl))
;
1526 }
1527
1528 recompute_visible_regions (window, FALSE(0));
1529
1530 cdk_window_set_cursor (window, ((attributes_mask & CDK_WA_CURSOR) ?
1531 (attributes->cursor) :
1532 NULL((void*)0)));
1533
1534 g_signal_connect (cdk_window_get_display (parent), "seat-removed",g_signal_connect_data ((cdk_window_get_display (parent)), ("seat-removed"
), (((GCallback) (seat_removed_cb))), (window), ((void*)0), (
GConnectFlags) 0)
1535 G_CALLBACK (seat_removed_cb), window)g_signal_connect_data ((cdk_window_get_display (parent)), ("seat-removed"
), (((GCallback) (seat_removed_cb))), (window), ((void*)0), (
GConnectFlags) 0)
;
1536
1537 if ((_cdk_gl_flags & (CDK_GL_ALWAYS | CDK_GL_DISABLE)) == CDK_GL_ALWAYS)
1538 {
1539 GError *error = NULL((void*)0);
1540
1541 if (cdk_window_get_paint_gl_context (window, &error) == NULL((void*)0))
1542 {
1543 g_warning ("Unable to force GL enabled: %s", error->message);
1544 g_error_free (error);
1545 }
1546 }
1547
1548 return window;
1549}
1550
1551static gboolean
1552is_parent_of (CdkWindow *parent,
1553 CdkWindow *child)
1554{
1555 CdkWindow *w;
1556
1557 w = child;
1558 while (w != NULL((void*)0))
1559 {
1560 if (w == parent)
1561 return TRUE(!(0));
1562
1563 w = cdk_window_get_parent (w);
1564 }
1565
1566 return FALSE(0);
1567}
1568
1569static void
1570change_impl (CdkWindow *private,
1571 CdkWindow *impl_window,
1572 CdkWindowImpl *new)
1573{
1574 GList *l;
1575 CdkWindow *child;
1576 CdkWindowImpl *old_impl;
1577 CdkWindow *old_impl_window;
1578
1579 old_impl = private->impl;
1580 old_impl_window = private->impl_window;
1581 if (private != impl_window)
1582 private->impl_window = g_object_ref (impl_window)((__typeof__ (impl_window)) (g_object_ref) (impl_window));
1583 else
1584 private->impl_window = private;
1585 private->impl = g_object_ref (new)((__typeof__ (new)) (g_object_ref) (new));
1586 if (old_impl_window != private)
1587 g_object_unref (old_impl_window);
1588 g_object_unref (old_impl);
1589
1590 for (l = private->children; l != NULL((void*)0); l = l->next)
1591 {
1592 child = l->data;
1593
1594 if (child->impl == old_impl)
1595 change_impl (child, impl_window, new);
1596 else
1597 {
1598 /* The child is a native, update native_children */
1599 old_impl_window->native_children =
1600 g_list_remove (old_impl_window->native_children, child);
1601 impl_window->native_children =
1602 g_list_prepend (impl_window->native_children, child);
1603 }
1604 }
1605}
1606
1607static void
1608reparent_to_impl (CdkWindow *private)
1609{
1610 GList *l;
1611 CdkWindow *child;
1612 gboolean show;
1613 CdkWindowImplClass *impl_class;
1614
1615 impl_class = CDK_WINDOW_IMPL_GET_CLASS (private->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((private->impl
)))->g_class))))
;
1616
1617 /* Enumerate in reverse order so we get the right order for the native
1618 windows (first in childrens list is topmost, and reparent places on top) */
1619 for (l = g_list_last (private->children); l != NULL((void*)0); l = l->prev)
1620 {
1621 child = l->data;
1622
1623 if (child->impl == private->impl)
1624 reparent_to_impl (child);
1625 else
1626 {
1627 show = impl_class->reparent ((CdkWindow *)child,
1628 (CdkWindow *)private,
1629 child->x, child->y);
1630 if (show)
1631 cdk_window_show_unraised ((CdkWindow *)child);
1632 }
1633 }
1634}
1635
1636
1637/**
1638 * cdk_window_reparent:
1639 * @window: a #CdkWindow
1640 * @new_parent: new parent to move @window into
1641 * @x: X location inside the new parent
1642 * @y: Y location inside the new parent
1643 *
1644 * Reparents @window into the given @new_parent. The window being
1645 * reparented will be unmapped as a side effect.
1646 *
1647 **/
1648void
1649cdk_window_reparent (CdkWindow *window,
1650 CdkWindow *new_parent,
1651 gint x,
1652 gint y)
1653{
1654 CdkWindow *old_parent;
1655 CdkScreen *screen;
1656 gboolean show, was_mapped;
1657 gboolean do_reparent_to_impl;
1658 CdkEventMask old_native_event_mask;
1659 CdkWindowImplClass *impl_class;
1660
1661 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
1662 g_return_if_fail (new_parent == NULL || CDK_IS_WINDOW (new_parent))do { if ((new_parent == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((new_parent)); GType __t = ((cdk_window_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Cdk", ((const
char*) (__func__)), "new_parent == NULL || CDK_IS_WINDOW (new_parent)"
); return; } } while (0)
;
1663 g_return_if_fail (CDK_WINDOW_TYPE (window) != CDK_WINDOW_ROOT)do { if ((((((CdkWindow *)(window)))->window_type) != CDK_WINDOW_ROOT
)) { } else { g_return_if_fail_warning ("Cdk", ((const char*)
(__func__)), "CDK_WINDOW_TYPE (window) != CDK_WINDOW_ROOT");
return; } } while (0)
;
1664
1665 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed) ||
1666 (new_parent && CDK_WINDOW_DESTROYED (new_parent)(((CdkWindow *)(new_parent))->destroyed)))
1667 return;
1668
1669 screen = cdk_window_get_screen (window);
1670 if (!new_parent)
1671 new_parent = cdk_screen_get_root_window (screen);
1672
1673 /* No input-output children of input-only windows */
1674 if (new_parent->input_only && !window->input_only)
1675 return;
1676
1677 /* Don't create loops in hierarchy */
1678 if (is_parent_of (window, new_parent))
1679 return;
1680
1681 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
1682 old_parent = window->parent;
1683
1684 was_mapped = CDK_WINDOW_IS_MAPPED (window)(((window)->state & CDK_WINDOW_STATE_WITHDRAWN) == 0);
1685
1686 /* Reparenting to toplevel. Ensure we have a native window so this can work */
1687 if (new_parent->window_type == CDK_WINDOW_ROOT ||
1688 new_parent->window_type == CDK_WINDOW_FOREIGN)
1689 cdk_window_ensure_native (window);
1690
1691 old_native_event_mask = 0;
1692 do_reparent_to_impl = FALSE(0);
1693 if (cdk_window_has_impl (window))
1694 {
1695 old_native_event_mask = get_native_event_mask (window);
1696 /* Native window */
1697 show = impl_class->reparent (window, new_parent, x, y);
1698 }
1699 else
1700 {
1701 /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
1702 g_assert (new_parent->window_type != CDK_WINDOW_ROOT &&do { if (new_parent->window_type != CDK_WINDOW_ROOT &&
new_parent->window_type != CDK_WINDOW_FOREIGN) ; else g_assertion_message_expr
("Cdk", "cdkwindow.c", 1703, ((const char*) (__func__)), "new_parent->window_type != CDK_WINDOW_ROOT && new_parent->window_type != CDK_WINDOW_FOREIGN"
); } while (0)
1703 new_parent->window_type != CDK_WINDOW_FOREIGN)do { if (new_parent->window_type != CDK_WINDOW_ROOT &&
new_parent->window_type != CDK_WINDOW_FOREIGN) ; else g_assertion_message_expr
("Cdk", "cdkwindow.c", 1703, ((const char*) (__func__)), "new_parent->window_type != CDK_WINDOW_ROOT && new_parent->window_type != CDK_WINDOW_FOREIGN"
); } while (0)
;
1704
1705 show = was_mapped;
1706 cdk_window_hide (window);
1707
1708 do_reparent_to_impl = TRUE(!(0));
1709 change_impl (window,
1710 new_parent->impl_window,
1711 new_parent->impl);
1712 }
1713
1714 /* From here on, we treat parents of type CDK_WINDOW_FOREIGN like
1715 * the root window
1716 */
1717 if (CDK_WINDOW_TYPE (new_parent)((((CdkWindow *)(new_parent)))->window_type) == CDK_WINDOW_FOREIGN)
1718 {
1719 new_parent = cdk_screen_get_root_window (screen);
1720 }
1721
1722 if (old_parent)
1723 {
1724 old_parent->children = g_list_remove_link (old_parent->children, &window->children_list_node);
1725
1726 if (cdk_window_has_impl (window))
1727 old_parent->impl_window->native_children =
1728 g_list_remove (old_parent->impl_window->native_children, window);
1729 }
1730
1731 window->parent = new_parent;
1732 window->x = x;
1733 window->y = y;
1734
1735 new_parent->children = g_list_concat (&window->children_list_node, new_parent->children);
1736
1737 if (cdk_window_has_impl (window))
1738 new_parent->impl_window->native_children = g_list_prepend (new_parent->impl_window->native_children, window);
1739
1740 /* Switch the window type as appropriate */
1741
1742 switch (CDK_WINDOW_TYPE (new_parent)((((CdkWindow *)(new_parent)))->window_type))
1743 {
1744 case CDK_WINDOW_ROOT:
1745 case CDK_WINDOW_FOREIGN:
1746 if (window->toplevel_window_type != -1)
1747 CDK_WINDOW_TYPE (window)((((CdkWindow *)(window)))->window_type) = window->toplevel_window_type;
1748 else if (CDK_WINDOW_TYPE (window)((((CdkWindow *)(window)))->window_type) == CDK_WINDOW_CHILD)
1749 CDK_WINDOW_TYPE (window)((((CdkWindow *)(window)))->window_type) = CDK_WINDOW_TOPLEVEL;
1750 break;
1751 case CDK_WINDOW_OFFSCREEN:
1752 case CDK_WINDOW_TOPLEVEL:
1753 case CDK_WINDOW_CHILD:
1754 case CDK_WINDOW_TEMP:
1755 if (CDK_WINDOW_TYPE (window)((((CdkWindow *)(window)))->window_type) != CDK_WINDOW_CHILD && \
1756 CDK_WINDOW_TYPE (window)((((CdkWindow *)(window)))->window_type) != CDK_WINDOW_FOREIGN)
1757 {
1758 /* Save the original window type so we can restore it if the
1759 * window is reparented back to be a toplevel
1760 */
1761 window->toplevel_window_type = CDK_WINDOW_TYPE (window)((((CdkWindow *)(window)))->window_type);
1762 CDK_WINDOW_TYPE (window)((((CdkWindow *)(window)))->window_type) = CDK_WINDOW_CHILD;
1763 }
1764 }
1765
1766 /* If we changed the window type, we might have to set or
1767 * unset the frame clock on the window
1768 */
1769 if (CDK_WINDOW_TYPE (new_parent)((((CdkWindow *)(new_parent)))->window_type) == CDK_WINDOW_ROOT &&
1770 CDK_WINDOW_TYPE (window)((((CdkWindow *)(window)))->window_type) != CDK_WINDOW_FOREIGN)
1771 {
1772 if (window->frame_clock == NULL((void*)0))
1773 {
1774 CdkFrameClock *frame_clock = g_object_new (CDK_TYPE_FRAME_CLOCK_IDLE(cdk_frame_clock_idle_get_type ()), NULL((void*)0));
1775 cdk_window_set_frame_clock (window, frame_clock);
1776 g_object_unref (frame_clock);
1777 }
1778 }
1779 else
1780 {
1781 if (window->frame_clock != NULL((void*)0))
1782 {
1783 g_object_run_dispose (G_OBJECT (window->frame_clock)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->frame_clock)), (((GType) ((20) << (2)))
)))))
);
1784 cdk_window_set_frame_clock (window, NULL((void*)0));
1785 }
1786 }
1787
1788 /* We might have changed window type for a native windows, so we
1789 need to change the event mask too. */
1790 if (cdk_window_has_impl (window))
1791 {
1792 CdkEventMask native_event_mask = get_native_event_mask (window);
1793
1794 if (native_event_mask != old_native_event_mask)
1795 impl_class->set_events (window, native_event_mask);
1796 }
1797
1798 _cdk_window_update_viewable (window);
1799
1800 recompute_visible_regions (window, FALSE(0));
1801
1802 if (do_reparent_to_impl)
1803 reparent_to_impl (window);
1804 else
1805 {
1806 /* The reparent will have put the native window topmost in the native parent,
1807 * which may be wrong wrt other native windows in the non-native hierarchy,
1808 * so restack */
1809 if (!cdk_window_has_impl (new_parent))
1810 sync_native_window_stack_position (window);
1811 }
1812
1813 if (show)
1814 cdk_window_show_unraised (window);
1815 else
1816 _cdk_synthesize_crossing_events_for_geometry_change (window);
1817}
1818
1819/**
1820 * cdk_window_ensure_native:
1821 * @window: a #CdkWindow
1822 *
1823 * Tries to ensure that there is a window-system native window for this
1824 * CdkWindow. This may fail in some situations, returning %FALSE.
1825 *
1826 * Offscreen window and children of them can never have native windows.
1827 *
1828 * Some backends may not support native child windows.
1829 *
1830 * Returns: %TRUE if the window has a native window, %FALSE otherwise
1831 *
1832 * Since: 2.18
1833 */
1834gboolean
1835cdk_window_ensure_native (CdkWindow *window)
1836{
1837 CdkWindow *impl_window;
1838 CdkWindowImpl *new_impl, *old_impl;
1839 CdkDisplay *display;
1840 CdkScreen *screen;
1841 CdkWindow *above, *parent;
1842 GList listhead;
1843 CdkWindowImplClass *impl_class;
1844
1845 g_return_val_if_fail (CDK_IS_WINDOW (window), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return ((0)); } } while (0)
;
1846
1847 if (CDK_WINDOW_TYPE (window)((((CdkWindow *)(window)))->window_type) == CDK_WINDOW_ROOT ||
1848 CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
1849 return FALSE(0);
1850
1851 impl_window = cdk_window_get_impl_window (window);
1852
1853 if (cdk_window_is_offscreen (impl_window))
1854 return FALSE(0); /* native in offscreens not supported */
1855
1856 if (impl_window == window)
1857 /* Already has an impl, and its not offscreen . */
1858 return TRUE(!(0));
1859
1860 /* Need to create a native window */
1861
1862 screen = cdk_window_get_screen (window);
1863 display = cdk_screen_get_display (screen);
1864 parent = window->parent;
1865
1866 old_impl = window->impl;
1867 _cdk_display_create_window_impl (display,
1868 window, parent,
1869 screen,
1870 get_native_event_mask (window),
1871 NULL((void*)0), 0);
1872 new_impl = window->impl;
1873
1874 parent->impl_window->native_children =
1875 g_list_prepend (parent->impl_window->native_children, window);
1876
1877 window->impl = old_impl;
1878 change_impl (window, window, new_impl);
1879
1880 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
1881
1882 /* Native window creation will put the native window topmost in the
1883 * native parent, which may be wrong wrt the position of the previous
1884 * non-native window wrt to the other non-native children, so correct this.
1885 */
1886 above = find_native_sibling_above (parent, window);
1887 if (above)
1888 {
1889 listhead.data = window;
1890 listhead.prev = NULL((void*)0);
1891 listhead.next = NULL((void*)0);
1892 impl_class->restack_under ((CdkWindow *)above, &listhead);
1893 }
1894
1895 recompute_visible_regions (window, FALSE(0));
1896
1897 reparent_to_impl (window);
1898
1899 if (!window->input_only)
1900 impl_class->set_background (window, window->background);
1901
1902 impl_class->input_shape_combine_region (window,
1903 window->input_shape,
1904 0, 0);
1905
1906 if (cdk_window_is_viewable (window))
1907 impl_class->show (window, FALSE(0));
1908
1909 cdk_window_invalidate_in_parent (window);
1910
1911 return TRUE(!(0));
1912}
1913
1914/**
1915 * _cdk_event_filter_unref:
1916 * @window: (allow-none): A #CdkWindow, or %NULL to be the global window
1917 * @filter: A window filter
1918 *
1919 * Release a reference to @filter. Note this function may
1920 * mutate the list storage, so you need to handle this
1921 * if iterating over a list of filters.
1922 */
1923void
1924_cdk_event_filter_unref (CdkWindow *window,
1925 CdkEventFilter *filter)
1926{
1927 GList **filters;
1928 GList *tmp_list;
1929
1930 if (window
10.1
'window' is equal to NULL
== NULL((void*)0))
11
Taking true branch
1931 filters = &_cdk_default_filters;
1932 else
1933 filters = &window->filters;
1934
1935 tmp_list = *filters;
1936 while (tmp_list)
12
Loop condition is true. Entering loop body
21
Loop condition is true. Entering loop body
1937 {
1938 CdkEventFilter *iter_filter = tmp_list->data;
1939 GList *node;
1940
1941 node = tmp_list;
1942 tmp_list = tmp_list->next;
1943
1944 if (iter_filter
21.1
'iter_filter' is equal to 'filter'
!= filter
)
13
Assuming 'iter_filter' is equal to 'filter'
14
Taking false branch
22
Taking false branch
1945 continue;
1946
1947 g_assert (iter_filter->ref_count > 0)do { if (iter_filter->ref_count > 0) ; else g_assertion_message_expr
("Cdk", "cdkwindow.c", 1947, ((const char*) (__func__)), "iter_filter->ref_count > 0"
); } while (0)
;
15
Assuming field 'ref_count' is > 0
16
Taking true branch
17
Loop condition is false. Exiting loop
23
Use of memory after it is freed
1948
1949 filter->ref_count--;
1950 if (filter->ref_count != 0)
18
Assuming field 'ref_count' is equal to 0
19
Taking false branch
1951 continue;
1952
1953 *filters = g_list_remove_link (*filters, node);
1954 g_free (filter);
20
Memory is released
1955 g_list_free_1 (node);
1956 }
1957}
1958
1959static void
1960window_remove_filters (CdkWindow *window)
1961{
1962 while (window->filters)
1963 _cdk_event_filter_unref (window, window->filters->data);
1964}
1965
1966static void
1967update_pointer_info_foreach (CdkDisplay *display G_GNUC_UNUSED__attribute__ ((__unused__)),
1968 CdkDevice *device G_GNUC_UNUSED__attribute__ ((__unused__)),
1969 CdkPointerWindowInfo *pointer_info,
1970 gpointer user_data)
1971{
1972 CdkWindow *window = user_data;
1973
1974 if (pointer_info->toplevel_under_pointer == window)
1975 {
1976 g_object_unref (pointer_info->toplevel_under_pointer);
1977 pointer_info->toplevel_under_pointer = NULL((void*)0);
1978 }
1979}
1980
1981static void
1982window_remove_from_pointer_info (CdkWindow *window,
1983 CdkDisplay *display)
1984{
1985 _cdk_display_pointer_info_foreach (display,
1986 update_pointer_info_foreach,
1987 window);
1988}
1989
1990static void
1991cdk_window_free_current_paint (CdkWindow *window)
1992{
1993 cairo_surface_destroy (window->current_paint.surface);
1994 window->current_paint.surface = NULL((void*)0);
1995
1996 cairo_region_destroy (window->current_paint.region);
1997 window->current_paint.region = NULL((void*)0);
1998
1999 cairo_region_destroy (window->current_paint.flushed_region);
2000 window->current_paint.flushed_region = NULL((void*)0);
2001
2002 cairo_region_destroy (window->current_paint.need_blend_region);
2003 window->current_paint.need_blend_region = NULL((void*)0);
2004
2005 window->current_paint.surface_needs_composite = FALSE(0);
2006}
2007
2008/**
2009 * _cdk_window_destroy_hierarchy:
2010 * @window: a #CdkWindow
2011 * @recursing: If %TRUE, then this is being called because a parent
2012 * was destroyed.
2013 * @recursing_native: If %TRUE, then this is being called because a native parent
2014 * was destroyed. This generally means that the call to the
2015 * windowing system to destroy the window can be omitted, since
2016 * it will be destroyed as a result of the parent being destroyed.
2017 * Unless @foreign_destroy.
2018 * @foreign_destroy: If %TRUE, the window or a parent was destroyed by some
2019 * external agency. The window has already been destroyed and no
2020 * windowing system calls should be made. (This may never happen
2021 * for some windowing systems.)
2022 *
2023 * Internal function to destroy a window. Like cdk_window_destroy(),
2024 * but does not drop the reference count created by cdk_window_new().
2025 **/
2026static void
2027_cdk_window_destroy_hierarchy (CdkWindow *window,
2028 gboolean recursing,
2029 gboolean recursing_native,
2030 gboolean foreign_destroy)
2031{
2032 CdkWindowImplClass *impl_class;
2033 CdkWindow *temp_window;
2034 CdkScreen *screen;
2035 CdkDisplay *display;
2036 GList *tmp;
2037
2038 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
2039
2040 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
2041 return;
2042
2043 display = cdk_window_get_display (window);
2044 screen = cdk_window_get_screen (window);
2045 temp_window = g_object_get_qdata (G_OBJECT (screen)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), (((GType) ((20) << (2))))))))
, quark_pointer_window);
2046 if (temp_window == window)
2047 g_object_set_qdata (G_OBJECT (screen)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), (((GType) ((20) << (2))))))))
, quark_pointer_window, NULL((void*)0));
2048
2049 switch (window->window_type)
2050 {
2051 case CDK_WINDOW_ROOT:
2052 if (!screen->closed)
2053 {
2054 g_error ("attempted to destroy root window");
2055 break;
2056 }
2057 /* else fall thru */
2058 case CDK_WINDOW_TOPLEVEL:
2059 case CDK_WINDOW_CHILD:
2060 case CDK_WINDOW_TEMP:
2061 case CDK_WINDOW_FOREIGN:
2062 case CDK_WINDOW_OFFSCREEN:
2063 case CDK_WINDOW_SUBSURFACE:
2064 if (window->window_type == CDK_WINDOW_FOREIGN && !foreign_destroy)
2065 {
2066 /* Logically, it probably makes more sense to send
2067 * a "destroy yourself" message to the foreign window
2068 * whether or not it's in our hierarchy; but for historical
2069 * reasons, we only send "destroy yourself" messages to
2070 * foreign windows in our hierarchy.
2071 */
2072 if (window->parent)
2073 {
2074 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
2075
2076 if (cdk_window_has_impl (window))
2077 impl_class->destroy_foreign (window);
2078 }
2079
2080 /* Also for historical reasons, we remove any filters
2081 * on a foreign window when it or a parent is destroyed;
2082 * this likely causes problems if two separate portions
2083 * of code are maintaining filter lists on a foreign window.
2084 */
2085 window_remove_filters (window);
2086 }
2087 else
2088 {
2089 if (window->parent)
2090 {
2091 if (window->parent->children)
2092 window->parent->children = g_list_remove_link (window->parent->children, &window->children_list_node);
2093
2094 if (cdk_window_has_impl (window))
2095 window->parent->impl_window->native_children =
2096 g_list_remove (window->parent->impl_window->native_children, window);
2097
2098 if (!recursing &&
2099 CDK_WINDOW_IS_MAPPED (window)(((window)->state & CDK_WINDOW_STATE_WITHDRAWN) == 0))
2100 {
2101 recompute_visible_regions (window, FALSE(0));
2102 cdk_window_invalidate_in_parent (window);
2103 }
2104 }
2105
2106 if (window->gl_paint_context)
2107 {
2108 /* Make sure to destroy if current */
2109 g_object_run_dispose (G_OBJECT (window->gl_paint_context)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->gl_paint_context)), (((GType) ((20) << (
2))))))))
);
2110 g_object_unref (window->gl_paint_context);
2111 window->gl_paint_context = NULL((void*)0);
2112 }
2113
2114 if (window->frame_clock)
2115 {
2116 g_object_run_dispose (G_OBJECT (window->frame_clock)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->frame_clock)), (((GType) ((20) << (2)))
)))))
);
2117 cdk_window_set_frame_clock (window, NULL((void*)0));
2118 }
2119
2120 cdk_window_free_current_paint (window);
2121
2122 if (window->background)
2123 {
2124 cairo_pattern_destroy (window->background);
2125 window->background = NULL((void*)0);
2126 }
2127
2128 if (window->window_type == CDK_WINDOW_FOREIGN)
2129 g_assert (window->children == NULL)do { if (window->children == ((void*)0)) ; else g_assertion_message_expr
("Cdk", "cdkwindow.c", 2129, ((const char*) (__func__)), "window->children == NULL"
); } while (0)
;
2130 else
2131 {
2132 tmp = window->children;
2133 window->children = NULL((void*)0);
2134 /* No need to free children list, its all made up of in-struct nodes */
2135
2136 while (tmp)
2137 {
2138 temp_window = tmp->data;
2139 tmp = tmp->next;
2140
2141 if (temp_window)
2142 _cdk_window_destroy_hierarchy (temp_window,
2143 TRUE(!(0)),
2144 recursing_native || cdk_window_has_impl (window),
2145 foreign_destroy);
2146 }
2147
2148
2149 if (cdk_window_has_impl (window))
2150 g_assert (window->native_children == NULL)do { if (window->native_children == ((void*)0)) ; else g_assertion_message_expr
("Cdk", "cdkwindow.c", 2150, ((const char*) (__func__)), "window->native_children == NULL"
); } while (0)
;
2151 }
2152
2153 _cdk_window_clear_update_area (window);
2154
2155 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
2156
2157 if (cdk_window_has_impl (window))
2158 impl_class->destroy (window, recursing_native, foreign_destroy);
2159 else
2160 {
2161 /* hide to make sure we repaint and break grabs */
2162 cdk_window_hide (window);
2163 }
2164
2165 window->state |= CDK_WINDOW_STATE_WITHDRAWN;
2166 window->parent = NULL((void*)0);
2167 window->destroyed = TRUE(!(0));
2168
2169 window_remove_filters (window);
2170
2171 window_remove_from_pointer_info (window, display);
2172
2173 if (window->clip_region)
2174 {
2175 cairo_region_destroy (window->clip_region);
2176 window->clip_region = NULL((void*)0);
2177 }
2178 }
2179 break;
2180 }
2181}
2182
2183/**
2184 * _cdk_window_destroy:
2185 * @window: a #CdkWindow
2186 * @foreign_destroy: If %TRUE, the window or a parent was destroyed by some
2187 * external agency. The window has already been destroyed and no
2188 * windowing system calls should be made. (This may never happen
2189 * for some windowing systems.)
2190 *
2191 * Internal function to destroy a window. Like cdk_window_destroy(),
2192 * but does not drop the reference count created by cdk_window_new().
2193 **/
2194void
2195_cdk_window_destroy (CdkWindow *window,
2196 gboolean foreign_destroy)
2197{
2198 _cdk_window_destroy_hierarchy (window, FALSE(0), FALSE(0), foreign_destroy);
2199}
2200
2201/**
2202 * cdk_window_destroy:
2203 * @window: a #CdkWindow
2204 *
2205 * Destroys the window system resources associated with @window and decrements @window's
2206 * reference count. The window system resources for all children of @window are also
2207 * destroyed, but the children’s reference counts are not decremented.
2208 *
2209 * Note that a window will not be destroyed automatically when its reference count
2210 * reaches zero. You must call this function yourself before that happens.
2211 *
2212 **/
2213void
2214cdk_window_destroy (CdkWindow *window)
2215{
2216 _cdk_window_destroy_hierarchy (window, FALSE(0), FALSE(0), FALSE(0));
2217 g_object_unref (window);
2218}
2219
2220/**
2221 * cdk_window_set_user_data:
2222 * @window: a #CdkWindow
2223 * @user_data: (allow-none) (type GObject.Object): user data
2224 *
2225 * For most purposes this function is deprecated in favor of
2226 * g_object_set_data(). However, for historical reasons CTK+ stores
2227 * the #CtkWidget that owns a #CdkWindow as user data on the
2228 * #CdkWindow. So, custom widget implementations should use
2229 * this function for that. If CTK+ receives an event for a #CdkWindow,
2230 * and the user data for the window is non-%NULL, CTK+ will assume the
2231 * user data is a #CtkWidget, and forward the event to that widget.
2232 *
2233 **/
2234void
2235cdk_window_set_user_data (CdkWindow *window,
2236 gpointer user_data)
2237{
2238 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
2239
2240 window->user_data = user_data;
2241}
2242
2243/**
2244 * cdk_window_get_user_data:
2245 * @window: a #CdkWindow
2246 * @data: (out): return location for user data
2247 *
2248 * Retrieves the user data for @window, which is normally the widget
2249 * that @window belongs to. See cdk_window_set_user_data().
2250 *
2251 **/
2252void
2253cdk_window_get_user_data (CdkWindow *window,
2254 gpointer *data)
2255{
2256 *data = window->user_data;
2257}
2258
2259/**
2260 * cdk_window_get_window_type:
2261 * @window: a #CdkWindow
2262 *
2263 * Gets the type of the window. See #CdkWindowType.
2264 *
2265 * Returns: type of window
2266 **/
2267CdkWindowType
2268cdk_window_get_window_type (CdkWindow *window)
2269{
2270 g_return_val_if_fail (CDK_IS_WINDOW (window), (CdkWindowType) -1)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return ((CdkWindowType) -1); }
} while (0)
;
2271
2272 return CDK_WINDOW_TYPE (window)((((CdkWindow *)(window)))->window_type);
2273}
2274
2275/**
2276 * cdk_window_get_visual:
2277 * @window: a #CdkWindow
2278 *
2279 * Gets the #CdkVisual describing the pixel format of @window.
2280 *
2281 * Returns: (transfer none): a #CdkVisual
2282 *
2283 * Since: 2.24
2284 **/
2285CdkVisual*
2286cdk_window_get_visual (CdkWindow *window)
2287{
2288 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
2289
2290 return window->visual;
2291}
2292
2293/**
2294 * cdk_window_get_screen:
2295 * @window: a #CdkWindow
2296 *
2297 * Gets the #CdkScreen associated with a #CdkWindow.
2298 *
2299 * Returns: (transfer none): the #CdkScreen associated with @window
2300 *
2301 * Since: 2.24
2302 **/
2303CdkScreen*
2304cdk_window_get_screen (CdkWindow *window)
2305{
2306 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
2307
2308 return cdk_visual_get_screen (window->visual);
2309}
2310
2311/**
2312 * cdk_window_get_display:
2313 * @window: a #CdkWindow
2314 *
2315 * Gets the #CdkDisplay associated with a #CdkWindow.
2316 *
2317 * Returns: (transfer none): the #CdkDisplay associated with @window
2318 *
2319 * Since: 2.24
2320 **/
2321CdkDisplay *
2322cdk_window_get_display (CdkWindow *window)
2323{
2324 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
2325
2326 return cdk_screen_get_display (cdk_visual_get_screen (window->visual));
2327}
2328/**
2329 * cdk_window_is_destroyed:
2330 * @window: a #CdkWindow
2331 *
2332 * Check to see if a window is destroyed..
2333 *
2334 * Returns: %TRUE if the window is destroyed
2335 *
2336 * Since: 2.18
2337 **/
2338gboolean
2339cdk_window_is_destroyed (CdkWindow *window)
2340{
2341 return CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed);
2342}
2343
2344static void
2345to_embedder (CdkWindow *window,
2346 gdouble offscreen_x,
2347 gdouble offscreen_y,
2348 gdouble *embedder_x,
2349 gdouble *embedder_y)
2350{
2351 g_signal_emit (window, signals[TO_EMBEDDER], 0,
2352 offscreen_x, offscreen_y,
2353 embedder_x, embedder_y);
2354}
2355
2356static void
2357from_embedder (CdkWindow *window,
2358 gdouble embedder_x,
2359 gdouble embedder_y,
2360 gdouble *offscreen_x,
2361 gdouble *offscreen_y)
2362{
2363 g_signal_emit (window, signals[FROM_EMBEDDER], 0,
2364 embedder_x, embedder_y,
2365 offscreen_x, offscreen_y);
2366}
2367
2368/**
2369 * cdk_window_has_native:
2370 * @window: a #CdkWindow
2371 *
2372 * Checks whether the window has a native window or not. Note that
2373 * you can use cdk_window_ensure_native() if a native window is needed.
2374 *
2375 * Returns: %TRUE if the @window has a native window, %FALSE otherwise.
2376 *
2377 * Since: 2.22
2378 */
2379gboolean
2380cdk_window_has_native (CdkWindow *window)
2381{
2382 g_return_val_if_fail (CDK_IS_WINDOW (window), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return ((0)); } } while (0)
;
2383
2384 return window->parent == NULL((void*)0) || window->parent->impl != window->impl;
2385}
2386
2387/**
2388 * cdk_window_get_position:
2389 * @window: a #CdkWindow
2390 * @x: (out) (allow-none): X coordinate of window
2391 * @y: (out) (allow-none): Y coordinate of window
2392 *
2393 * Obtains the position of the window as reported in the
2394 * most-recently-processed #CdkEventConfigure. Contrast with
2395 * cdk_window_get_geometry() which queries the X server for the
2396 * current window position, regardless of which events have been
2397 * received or processed.
2398 *
2399 * The position coordinates are relative to the window’s parent window.
2400 *
2401 **/
2402void
2403cdk_window_get_position (CdkWindow *window,
2404 gint *x,
2405 gint *y)
2406{
2407 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
2408
2409 if (x)
2410 *x = window->x;
2411 if (y)
2412 *y = window->y;
2413}
2414
2415/**
2416 * cdk_window_get_parent:
2417 * @window: a #CdkWindow
2418 *
2419 * Obtains the parent of @window, as known to CDK. Does not query the
2420 * X server; thus this returns the parent as passed to cdk_window_new(),
2421 * not the actual parent. This should never matter unless you’re using
2422 * Xlib calls mixed with CDK calls on the X11 platform. It may also
2423 * matter for toplevel windows, because the window manager may choose
2424 * to reparent them.
2425 *
2426 * Note that you should use cdk_window_get_effective_parent() when
2427 * writing generic code that walks up a window hierarchy, because
2428 * cdk_window_get_parent() will most likely not do what you expect if
2429 * there are offscreen windows in the hierarchy.
2430 *
2431 * Returns: (transfer none): parent of @window
2432 **/
2433CdkWindow*
2434cdk_window_get_parent (CdkWindow *window)
2435{
2436 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
2437
2438 return window->parent;
2439}
2440
2441/**
2442 * cdk_window_get_effective_parent:
2443 * @window: a #CdkWindow
2444 *
2445 * Obtains the parent of @window, as known to CDK. Works like
2446 * cdk_window_get_parent() for normal windows, but returns the
2447 * window’s embedder for offscreen windows.
2448 *
2449 * See also: cdk_offscreen_window_get_embedder()
2450 *
2451 * Returns: (transfer none): effective parent of @window
2452 *
2453 * Since: 2.22
2454 **/
2455CdkWindow *
2456cdk_window_get_effective_parent (CdkWindow *window)
2457{
2458 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
2459
2460 if (cdk_window_is_offscreen (window))
2461 return cdk_offscreen_window_get_embedder (window);
2462 else if (cdk_window_is_subsurface (window))
2463 return window->transient_for;
2464 else
2465 return window->parent;
2466}
2467
2468/**
2469 * cdk_window_get_toplevel:
2470 * @window: a #CdkWindow
2471 *
2472 * Gets the toplevel window that’s an ancestor of @window.
2473 *
2474 * Any window type but %CDK_WINDOW_CHILD is considered a
2475 * toplevel window, as is a %CDK_WINDOW_CHILD window that
2476 * has a root window as parent.
2477 *
2478 * Note that you should use cdk_window_get_effective_toplevel() when
2479 * you want to get to a window’s toplevel as seen on screen, because
2480 * cdk_window_get_toplevel() will most likely not do what you expect
2481 * if there are offscreen windows in the hierarchy.
2482 *
2483 * Returns: (transfer none): the toplevel window containing @window
2484 **/
2485CdkWindow *
2486cdk_window_get_toplevel (CdkWindow *window)
2487{
2488 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
2489
2490 while (window->window_type == CDK_WINDOW_CHILD ||
2491 window->window_type == CDK_WINDOW_SUBSURFACE)
2492 {
2493 if (cdk_window_is_toplevel (window))
2494 break;
2495 window = window->parent;
2496 }
2497
2498 return window;
2499}
2500
2501/**
2502 * cdk_window_get_effective_toplevel:
2503 * @window: a #CdkWindow
2504 *
2505 * Gets the toplevel window that’s an ancestor of @window.
2506 *
2507 * Works like cdk_window_get_toplevel(), but treats an offscreen window's
2508 * embedder as its parent, using cdk_window_get_effective_parent().
2509 *
2510 * See also: cdk_offscreen_window_get_embedder()
2511 *
2512 * Returns: (transfer none): the effective toplevel window containing @window
2513 *
2514 * Since: 2.22
2515 **/
2516CdkWindow *
2517cdk_window_get_effective_toplevel (CdkWindow *window)
2518{
2519 CdkWindow *parent;
2520
2521 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
2522
2523 while ((parent = cdk_window_get_effective_parent (window)) != NULL((void*)0) &&
2524 (cdk_window_get_window_type (parent) != CDK_WINDOW_ROOT))
2525 window = parent;
2526
2527 return window;
2528}
2529
2530/**
2531 * cdk_window_get_children:
2532 * @window: a #CdkWindow
2533 *
2534 * Gets the list of children of @window known to CDK.
2535 * This function only returns children created via CDK,
2536 * so for example it’s useless when used with the root window;
2537 * it only returns windows an application created itself.
2538 *
2539 * The returned list must be freed, but the elements in the
2540 * list need not be.
2541 *
2542 * Returns: (transfer container) (element-type CdkWindow):
2543 * list of child windows inside @window
2544 **/
2545GList*
2546cdk_window_get_children (CdkWindow *window)
2547{
2548 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
2549
2550 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
2551 return NULL((void*)0);
2552
2553 return g_list_copy (window->children);
2554}
2555
2556/**
2557 * cdk_window_peek_children:
2558 * @window: a #CdkWindow
2559 *
2560 * Like cdk_window_get_children(), but does not copy the list of
2561 * children, so the list does not need to be freed.
2562 *
2563 * Returns: (transfer none) (element-type CdkWindow):
2564 * a reference to the list of child windows in @window
2565 **/
2566GList *
2567cdk_window_peek_children (CdkWindow *window)
2568{
2569 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
2570
2571 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
2572 return NULL((void*)0);
2573
2574 return window->children;
2575}
2576
2577
2578/**
2579 * cdk_window_get_children_with_user_data:
2580 * @window: a #CdkWindow
2581 * @user_data: user data to look for
2582 *
2583 * Gets the list of children of @window known to CDK with a
2584 * particular @user_data set on it.
2585 *
2586 * The returned list must be freed, but the elements in the
2587 * list need not be.
2588 *
2589 * The list is returned in (relative) stacking order, i.e. the
2590 * lowest window is first.
2591 *
2592 * Returns: (transfer container) (element-type CdkWindow):
2593 * list of child windows inside @window
2594 *
2595 * Since: 3.10
2596 **/
2597GList *
2598cdk_window_get_children_with_user_data (CdkWindow *window,
2599 gpointer user_data)
2600{
2601 CdkWindow *child;
2602 GList *res, *l;
2603
2604 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
2605
2606 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
2607 return NULL((void*)0);
2608
2609 res = NULL((void*)0);
2610 for (l = window->children; l != NULL((void*)0); l = l->next)
2611 {
2612 child = l->data;
2613
2614 if (child->user_data == user_data)
2615 res = g_list_prepend (res, child);
2616 }
2617
2618 return res;
2619}
2620
2621
2622/**
2623 * cdk_window_add_filter: (skip)
2624 * @window: (allow-none): a #CdkWindow
2625 * @function: filter callback
2626 * @data: data to pass to filter callback
2627 *
2628 * Adds an event filter to @window, allowing you to intercept events
2629 * before they reach CDK. This is a low-level operation and makes it
2630 * easy to break CDK and/or CTK+, so you have to know what you're
2631 * doing. Pass %NULL for @window to get all events for all windows,
2632 * instead of events for a specific window.
2633 *
2634 * If you are interested in X GenericEvents, bear in mind that
2635 * XGetEventData() has been already called on the event, and
2636 * XFreeEventData() must not be called within @function.
2637 **/
2638void
2639cdk_window_add_filter (CdkWindow *window,
2640 CdkFilterFunc function,
2641 gpointer data)
2642{
2643 GList *tmp_list;
2644 CdkEventFilter *filter;
2645
2646 g_return_if_fail (window == NULL || CDK_IS_WINDOW (window))do { if ((window == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((window)); GType __t = ((cdk_window_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Cdk", ((const
char*) (__func__)), "window == NULL || CDK_IS_WINDOW (window)"
); return; } } while (0)
;
2647
2648 if (window && CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
2649 return;
2650
2651 /* Filters are for the native events on the native window, so
2652 ensure there is a native window. */
2653 if (window)
2654 cdk_window_ensure_native (window);
2655
2656 if (window)
2657 tmp_list = window->filters;
2658 else
2659 tmp_list = _cdk_default_filters;
2660
2661 while (tmp_list)
2662 {
2663 filter = (CdkEventFilter *)tmp_list->data;
2664 if ((filter->function == function) && (filter->data == data))
2665 {
2666 filter->ref_count++;
2667 filter->flags = 0;
2668 return;
2669 }
2670 tmp_list = tmp_list->next;
2671 }
2672
2673 filter = g_new (CdkEventFilter, 1)((CdkEventFilter *) g_malloc_n ((1), sizeof (CdkEventFilter))
)
;
2674 filter->function = function;
2675 filter->data = data;
2676 filter->ref_count = 1;
2677 filter->flags = 0;
2678
2679 if (window)
2680 window->filters = g_list_append (window->filters, filter);
2681 else
2682 _cdk_default_filters = g_list_append (_cdk_default_filters, filter);
2683}
2684
2685/**
2686 * cdk_window_remove_filter: (skip)
2687 * @window: a #CdkWindow
2688 * @function: previously-added filter function
2689 * @data: user data for previously-added filter function
2690 *
2691 * Remove a filter previously added with cdk_window_add_filter().
2692 */
2693void
2694cdk_window_remove_filter (CdkWindow *window,
2695 CdkFilterFunc function,
2696 gpointer data)
2697{
2698 GList *tmp_list;
2699 CdkEventFilter *filter;
2700
2701 g_return_if_fail (window == NULL || CDK_IS_WINDOW (window))do { if ((window == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((window)); GType __t = ((cdk_window_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Cdk", ((const
char*) (__func__)), "window == NULL || CDK_IS_WINDOW (window)"
); return; } } while (0)
;
1
Assuming 'window' is equal to null
2
Loop condition is false. Exiting loop
2702
2703 if (window
2.1
'window' is null
)
3
Taking false branch
2704 tmp_list = window->filters;
2705 else
2706 tmp_list = _cdk_default_filters;
2707
2708 while (tmp_list)
4
Loop condition is true. Entering loop body
6
Loop condition is true. Entering loop body
2709 {
2710 filter = (CdkEventFilter *)tmp_list->data;
2711 tmp_list = tmp_list->next;
2712
2713 if ((filter->function == function) && (filter->data == data))
5
Assuming 'function' is not equal to field 'function'
7
Assuming 'function' is equal to field 'function'
8
Assuming 'data' is equal to field 'data'
9
Taking true branch
2714 {
2715 filter->flags |= CDK_EVENT_FILTER_REMOVED;
2716
2717 _cdk_event_filter_unref (window, filter);
10
Calling '_cdk_event_filter_unref'
2718
2719 return;
2720 }
2721 }
2722}
2723
2724/**
2725 * cdk_screen_get_toplevel_windows:
2726 * @screen: The #CdkScreen where the toplevels are located.
2727 *
2728 * Obtains a list of all toplevel windows known to CDK on the screen @screen.
2729 * A toplevel window is a child of the root window (see
2730 * cdk_get_default_root_window()).
2731 *
2732 * The returned list should be freed with g_list_free(), but
2733 * its elements need not be freed.
2734 *
2735 * Returns: (transfer container) (element-type CdkWindow):
2736 * list of toplevel windows, free with g_list_free()
2737 *
2738 * Since: 2.2
2739 **/
2740GList *
2741cdk_screen_get_toplevel_windows (CdkScreen *screen)
2742{
2743 CdkWindow * root_window;
2744 GList *new_list = NULL((void*)0);
2745 GList *tmp_list;
2746
2747 g_return_val_if_fail (CDK_IS_SCREEN (screen), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((screen)); GType __t = ((cdk_screen_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_SCREEN (screen)"); return (((void*)0)); } } while
(0)
;
2748
2749 root_window = cdk_screen_get_root_window (screen);
2750
2751 tmp_list = root_window->children;
2752 while (tmp_list)
2753 {
2754 CdkWindow *w = tmp_list->data;
2755
2756 if (w->window_type != CDK_WINDOW_FOREIGN)
2757 new_list = g_list_prepend (new_list, w);
2758 tmp_list = tmp_list->next;
2759 }
2760
2761 return new_list;
2762}
2763
2764/**
2765 * cdk_window_is_visible:
2766 * @window: a #CdkWindow
2767 *
2768 * Checks whether the window has been mapped (with cdk_window_show() or
2769 * cdk_window_show_unraised()).
2770 *
2771 * Returns: %TRUE if the window is mapped
2772 **/
2773gboolean
2774cdk_window_is_visible (CdkWindow *window)
2775{
2776 g_return_val_if_fail (CDK_IS_WINDOW (window), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return ((0)); } } while (0)
;
2777
2778 return CDK_WINDOW_IS_MAPPED (window)(((window)->state & CDK_WINDOW_STATE_WITHDRAWN) == 0);
2779}
2780
2781/**
2782 * cdk_window_is_viewable:
2783 * @window: a #CdkWindow
2784 *
2785 * Check if the window and all ancestors of the window are
2786 * mapped. (This is not necessarily "viewable" in the X sense, since
2787 * we only check as far as we have CDK window parents, not to the root
2788 * window.)
2789 *
2790 * Returns: %TRUE if the window is viewable
2791 **/
2792gboolean
2793cdk_window_is_viewable (CdkWindow *window)
2794{
2795 g_return_val_if_fail (CDK_IS_WINDOW (window), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return ((0)); } } while (0)
;
2796
2797 if (window->destroyed)
2798 return FALSE(0);
2799
2800 return window->viewable;
2801}
2802
2803/**
2804 * cdk_window_get_state:
2805 * @window: a #CdkWindow
2806 *
2807 * Gets the bitwise OR of the currently active window state flags,
2808 * from the #CdkWindowState enumeration.
2809 *
2810 * Returns: window state bitfield
2811 **/
2812CdkWindowState
2813cdk_window_get_state (CdkWindow *window)
2814{
2815 g_return_val_if_fail (CDK_IS_WINDOW (window), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return ((0)); } } while (0)
;
2816
2817 return window->state;
2818}
2819
2820static cairo_content_t
2821cdk_window_get_content (CdkWindow *window)
2822{
2823 cairo_surface_t *surface;
2824 cairo_content_t content;
2825
2826 g_return_val_if_fail (CDK_IS_WINDOW (window), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (0); } } while (0)
;
2827
2828 surface = cdk_window_ref_impl_surface (window);
2829 content = cairo_surface_get_content (surface);
2830 cairo_surface_destroy (surface);
2831
2832 return content;
2833}
2834
2835static cairo_surface_t *
2836cdk_window_ref_impl_surface (CdkWindow *window)
2837{
2838 return CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->ref_cairo_surface (cdk_window_get_impl_window (window));
2839}
2840
2841CdkGLContext *
2842cdk_window_get_paint_gl_context (CdkWindow *window,
2843 GError **error)
2844{
2845 GError *internal_error = NULL((void*)0);
2846
2847 if (_cdk_gl_flags & CDK_GL_DISABLE)
2848 {
2849 g_set_error_literal (error, CDK_GL_ERROR(cdk_gl_error_quark ()),
2850 CDK_GL_ERROR_NOT_AVAILABLE,
2851 _("GL support disabled via CDK_DEBUG")((char *) g_dgettext ("ctk30", "GL support disabled via CDK_DEBUG"
))
);
2852 return NULL((void*)0);
2853 }
2854
2855 if (window->impl_window->gl_paint_context == NULL((void*)0))
2856 {
2857 CdkWindowImplClass *impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
2858
2859 if (impl_class->create_gl_context == NULL((void*)0))
2860 {
2861 g_set_error_literal (error, CDK_GL_ERROR(cdk_gl_error_quark ()), CDK_GL_ERROR_NOT_AVAILABLE,
2862 _("The current backend does not support OpenGL")((char *) g_dgettext ("ctk30", "The current backend does not support OpenGL"
))
);
2863 return NULL((void*)0);
2864 }
2865
2866 window->impl_window->gl_paint_context =
2867 impl_class->create_gl_context (window->impl_window,
2868 TRUE(!(0)),
2869 NULL((void*)0),
2870 &internal_error);
2871 }
2872
2873 if (internal_error != NULL((void*)0))
2874 {
2875 g_propagate_error (error, internal_error);
2876 g_clear_object (&(window->impl_window->gl_paint_context))do { _Static_assert (sizeof *((&(window->impl_window->
gl_paint_context))) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (((&(window->impl_window->gl_paint_context
)))) _pp = ((&(window->impl_window->gl_paint_context
))); __typeof__ (*((&(window->impl_window->gl_paint_context
)))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
2877 return NULL((void*)0);
2878 }
2879
2880 cdk_gl_context_realize (window->impl_window->gl_paint_context, &internal_error);
2881 if (internal_error != NULL((void*)0))
2882 {
2883 g_propagate_error (error, internal_error);
2884 g_clear_object (&(window->impl_window->gl_paint_context))do { _Static_assert (sizeof *((&(window->impl_window->
gl_paint_context))) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (((&(window->impl_window->gl_paint_context
)))) _pp = ((&(window->impl_window->gl_paint_context
))); __typeof__ (*((&(window->impl_window->gl_paint_context
)))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
2885 return NULL((void*)0);
2886 }
2887
2888 return window->impl_window->gl_paint_context;
2889}
2890
2891/**
2892 * cdk_window_create_gl_context:
2893 * @window: a #CdkWindow
2894 * @error: return location for an error
2895 *
2896 * Creates a new #CdkGLContext matching the
2897 * framebuffer format to the visual of the #CdkWindow. The context
2898 * is disconnected from any particular window or surface.
2899 *
2900 * If the creation of the #CdkGLContext failed, @error will be set.
2901 *
2902 * Before using the returned #CdkGLContext, you will need to
2903 * call cdk_gl_context_make_current() or cdk_gl_context_realize().
2904 *
2905 * Returns: (transfer full): the newly created #CdkGLContext, or
2906 * %NULL on error
2907 *
2908 * Since: 3.16
2909 **/
2910CdkGLContext *
2911cdk_window_create_gl_context (CdkWindow *window,
2912 GError **error)
2913{
2914 CdkGLContext *paint_context;
2915
2916 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
2917 g_return_val_if_fail (error == NULL || *error == NULL, NULL)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else
{ g_return_if_fail_warning ("Cdk", ((const char*) (__func__)
), "error == NULL || *error == NULL"); return (((void*)0)); }
} while (0)
;
2918
2919 paint_context = cdk_window_get_paint_gl_context (window, error);
2920 if (paint_context == NULL((void*)0))
2921 return NULL((void*)0);
2922
2923 return CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->create_gl_context (window->impl_window,
2924 FALSE(0),
2925 paint_context,
2926 error);
2927}
2928
2929static void
2930cdk_window_begin_paint_internal (CdkWindow *window,
2931 const cairo_region_t *region)
2932{
2933 CdkRectangle clip_box;
2934 CdkWindowImplClass *impl_class;
2935 double sx, sy;
2936 gboolean needs_surface;
2937 cairo_content_t surface_content;
2938
2939 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed) ||
2940 !cdk_window_has_impl (window))
2941 return;
2942
2943 if (window->current_paint.surface != NULL((void*)0))
2944 {
2945 g_warning ("A paint operation on the window is alredy in progress. "
2946 "This is not allowed.");
2947 return;
2948 }
2949
2950 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
2951
2952 needs_surface = TRUE(!(0));
2953 if (impl_class->begin_paint)
2954 needs_surface = impl_class->begin_paint (window);
2955
2956 window->current_paint.region = cairo_region_copy (region);
2957 cairo_region_intersect (window->current_paint.region, window->clip_region);
2958 cairo_region_get_extents (window->current_paint.region, &clip_box);
2959
2960 window->current_paint.flushed_region = cairo_region_create ();
2961 window->current_paint.need_blend_region = cairo_region_create ();
2962
2963 surface_content = cdk_window_get_content (window);
2964
2965 window->current_paint.use_gl = window->impl_window->gl_paint_context != NULL((void*)0);
2966
2967 if (window->current_paint.use_gl)
2968 {
2969 CdkGLContext *context;
2970
2971 int ww = cdk_window_get_width (window) * cdk_window_get_scale_factor (window);
2972 int wh = cdk_window_get_height (window) * cdk_window_get_scale_factor (window);
2973
2974 context = cdk_window_get_paint_gl_context (window, NULL((void*)0));
2975 if (context == NULL((void*)0))
2976 {
2977 g_warning ("gl rendering failed, context: %p", context);
2978 window->current_paint.use_gl = FALSE(0);
2979 }
2980 else
2981 {
2982 cdk_gl_context_make_current (context);
2983 /* With gl we always need a surface to combine the gl
2984 drawing with the native drawing. */
2985 needs_surface = TRUE(!(0));
2986 /* Also, we need the surface to include alpha */
2987 surface_content = CAIRO_CONTENT_COLOR_ALPHA;
2988
2989 /* Initial setup */
2990 glClearColorepoxy_glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
2991 glDisableepoxy_glDisable (GL_DEPTH_TEST0x0B71);
2992 glDisableepoxy_glDisable(GL_BLEND0x0BE2);
2993 glBlendFuncepoxy_glBlendFunc (GL_ONE1, GL_ONE_MINUS_SRC_ALPHA0x0303);
2994
2995 glViewportepoxy_glViewport (0, 0, ww, wh);
2996 }
2997 }
2998
2999 if (needs_surface)
3000 {
3001 window->current_paint.surface = cdk_window_create_similar_surface (window,
3002 surface_content,
3003 MAX (clip_box.width, 1)(((clip_box.width) > (1)) ? (clip_box.width) : (1)),
3004 MAX (clip_box.height, 1)(((clip_box.height) > (1)) ? (clip_box.height) : (1)));
3005 sx = sy = 1;
3006 cairo_surface_get_device_scale (window->current_paint.surface, &sx, &sy);
3007 cairo_surface_set_device_offset (window->current_paint.surface, -clip_box.x*sx, -clip_box.y*sy);
3008 cdk_cairo_surface_mark_as_direct (window->current_paint.surface, window);
3009
3010 window->current_paint.surface_needs_composite = TRUE(!(0));
3011 }
3012 else
3013 {
3014 window->current_paint.surface = cdk_window_ref_impl_surface (window);
3015 window->current_paint.surface_needs_composite = FALSE(0);
3016 }
3017
3018 if (!cairo_region_is_empty (window->current_paint.region))
3019 cdk_window_clear_backing_region (window);
3020}
3021
3022static void
3023cdk_window_end_paint_internal (CdkWindow *window)
3024{
3025 CdkWindow *composited;
3026 CdkWindowImplClass *impl_class;
3027 CdkRectangle clip_box = { 0, };
3028 cairo_t *cr;
3029
3030 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed) ||
3031 !cdk_window_has_impl (window))
3032 return;
3033
3034 if (window->current_paint.surface == NULL((void*)0))
3035 {
3036 g_warning (G_STRLOC"cdkwindow.c" ":" "3036"": no preceding call to cdk_window_begin_draw_frame(), see documentation");
3037 return;
3038 }
3039
3040 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
3041
3042 if (impl_class->end_paint)
3043 impl_class->end_paint (window);
3044
3045 if (window->current_paint.surface_needs_composite)
3046 {
3047 cairo_surface_t *surface;
3048
3049 cairo_region_get_extents (window->current_paint.region, &clip_box);
3050
3051 if (window->current_paint.use_gl)
3052 {
3053 cairo_region_t *opaque_region = cairo_region_copy (window->current_paint.region);
3054 cairo_region_subtract (opaque_region, window->current_paint.flushed_region);
3055 cairo_region_subtract (opaque_region, window->current_paint.need_blend_region);
3056
3057 cdk_gl_context_make_current (window->gl_paint_context);
3058
3059 if (!cairo_region_is_empty (opaque_region))
3060 cdk_gl_texture_from_surface (window->current_paint.surface,
3061 opaque_region);
3062 if (!cairo_region_is_empty (window->current_paint.need_blend_region))
3063 {
3064 glEnableepoxy_glEnable(GL_BLEND0x0BE2);
3065 cdk_gl_texture_from_surface (window->current_paint.surface,
3066 window->current_paint.need_blend_region);
3067 glDisableepoxy_glDisable(GL_BLEND0x0BE2);
3068 }
3069
3070 cairo_region_destroy (opaque_region);
3071
3072 cdk_gl_context_end_frame (window->gl_paint_context,
3073 window->current_paint.region,
3074 window->active_update_area);
3075 }
3076 else
3077 {
3078 surface = cdk_window_ref_impl_surface (window);
3079 cr = cairo_create (surface);
3080
3081 cairo_set_source_surface (cr, window->current_paint.surface, 0, 0);
3082 cdk_cairo_region (cr, window->current_paint.region);
3083 cairo_clip (cr);
3084
3085 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3086 cairo_paint (cr);
3087
3088 cairo_destroy (cr);
3089
3090 cairo_surface_flush (surface);
3091 cairo_surface_destroy (surface);
3092 }
3093 }
3094
3095 cdk_window_free_current_paint (window);
3096
3097 /* find a composited window in our hierarchy to signal its
3098 * parent to redraw, calculating the clip box as we go...
3099 *
3100 * stop if parent becomes NULL since then we'd have nowhere
3101 * to draw (ie: 'composited' will always be non-NULL here).
3102 */
3103 for (composited = window;
3104 composited->parent;
3105 composited = composited->parent)
3106 {
3107 clip_box.x += composited->x;
3108 clip_box.y += composited->y;
3109 clip_box.width = MIN (clip_box.width, composited->parent->width - clip_box.x)(((clip_box.width) < (composited->parent->width - clip_box
.x)) ? (clip_box.width) : (composited->parent->width - clip_box
.x))
;
3110 clip_box.height = MIN (clip_box.height, composited->parent->height - clip_box.y)(((clip_box.height) < (composited->parent->height - clip_box
.y)) ? (clip_box.height) : (composited->parent->height -
clip_box.y))
;
3111
3112 if (composited->composited)
3113 {
3114 cdk_window_invalidate_rect (CDK_WINDOW (composited->parent)((((CdkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((composited->parent)), ((cdk_window_get_type ()))))))
,
3115 &clip_box, FALSE(0));
3116 break;
3117 }
3118 }
3119}
3120
3121/**
3122 * cdk_window_begin_paint_rect:
3123 * @window: a #CdkWindow
3124 * @rectangle: rectangle you intend to draw to
3125 *
3126 * A convenience wrapper around cdk_window_begin_paint_region() which
3127 * creates a rectangular region for you. See
3128 * cdk_window_begin_paint_region() for details.
3129 *
3130 * Deprecated: 3.22: Use cdk_window_begin_draw_frame() instead
3131 */
3132void
3133cdk_window_begin_paint_rect (CdkWindow *window,
3134 const CdkRectangle *rectangle)
3135{
3136 cairo_region_t *region;
3137
3138 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
3139
3140 region = cairo_region_create_rectangle (rectangle);
3141 cdk_window_begin_paint_internal (window, region);
3142 cairo_region_destroy (region);
3143}
3144
3145/**
3146 * cdk_window_begin_paint_region:
3147 * @window: a #CdkWindow
3148 * @region: region you intend to draw to
3149 *
3150 * Indicates that you are beginning the process of redrawing @region.
3151 * A backing store (offscreen buffer) large enough to contain @region
3152 * will be created. The backing store will be initialized with the
3153 * background color or background surface for @window. Then, all
3154 * drawing operations performed on @window will be diverted to the
3155 * backing store. When you call cdk_window_end_paint(), the backing
3156 * store will be copied to @window, making it visible onscreen. Only
3157 * the part of @window contained in @region will be modified; that is,
3158 * drawing operations are clipped to @region.
3159 *
3160 * The net result of all this is to remove flicker, because the user
3161 * sees the finished product appear all at once when you call
3162 * cdk_window_end_paint(). If you draw to @window directly without
3163 * calling cdk_window_begin_paint_region(), the user may see flicker
3164 * as individual drawing operations are performed in sequence. The
3165 * clipping and background-initializing features of
3166 * cdk_window_begin_paint_region() are conveniences for the
3167 * programmer, so you can avoid doing that work yourself.
3168 *
3169 * When using CTK+, the widget system automatically places calls to
3170 * cdk_window_begin_paint_region() and cdk_window_end_paint() around
3171 * emissions of the expose_event signal. That is, if you’re writing an
3172 * expose event handler, you can assume that the exposed area in
3173 * #CdkEventExpose has already been cleared to the window background,
3174 * is already set as the clip region, and already has a backing store.
3175 * Therefore in most cases, application code need not call
3176 * cdk_window_begin_paint_region(). (You can disable the automatic
3177 * calls around expose events on a widget-by-widget basis by calling
3178 * ctk_widget_set_double_buffered().)
3179 *
3180 * If you call this function multiple times before calling the
3181 * matching cdk_window_end_paint(), the backing stores are pushed onto
3182 * a stack. cdk_window_end_paint() copies the topmost backing store
3183 * onscreen, subtracts the topmost region from all other regions in
3184 * the stack, and pops the stack. All drawing operations affect only
3185 * the topmost backing store in the stack. One matching call to
3186 * cdk_window_end_paint() is required for each call to
3187 * cdk_window_begin_paint_region().
3188 *
3189 * Deprecated: 3.22: Use cdk_window_begin_draw_frame() instead
3190 */
3191void
3192cdk_window_begin_paint_region (CdkWindow *window,
3193 const cairo_region_t *region)
3194{
3195 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
3196
3197 cdk_window_begin_paint_internal (window, region);
3198}
3199
3200/**
3201 * cdk_window_begin_draw_frame:
3202 * @window: a #CdkWindow
3203 * @region: a Cairo region
3204 *
3205 * Indicates that you are beginning the process of redrawing @region
3206 * on @window, and provides you with a #CdkDrawingContext.
3207 *
3208 * If @window is a top level #CdkWindow, backed by a native window
3209 * implementation, a backing store (offscreen buffer) large enough to
3210 * contain @region will be created. The backing store will be initialized
3211 * with the background color or background surface for @window. Then, all
3212 * drawing operations performed on @window will be diverted to the
3213 * backing store. When you call cdk_window_end_frame(), the contents of
3214 * the backing store will be copied to @window, making it visible
3215 * on screen. Only the part of @window contained in @region will be
3216 * modified; that is, drawing operations are clipped to @region.
3217 *
3218 * The net result of all this is to remove flicker, because the user
3219 * sees the finished product appear all at once when you call
3220 * cdk_window_end_draw_frame(). If you draw to @window directly without
3221 * calling cdk_window_begin_draw_frame(), the user may see flicker
3222 * as individual drawing operations are performed in sequence.
3223 *
3224 * When using CTK+, the widget system automatically places calls to
3225 * cdk_window_begin_draw_frame() and cdk_window_end_draw_frame() around
3226 * emissions of the `CtkWidget::draw` signal. That is, if you’re
3227 * drawing the contents of the widget yourself, you can assume that the
3228 * widget has a cleared background, is already set as the clip region,
3229 * and already has a backing store. Therefore in most cases, application
3230 * code in CTK does not need to call cdk_window_begin_draw_frame()
3231 * explicitly.
3232 *
3233 * Returns: (transfer none): a #CdkDrawingContext context that should be
3234 * used to draw the contents of the window; the returned context is owned
3235 * by CDK.
3236 *
3237 * Since: 3.22
3238 */
3239CdkDrawingContext *
3240cdk_window_begin_draw_frame (CdkWindow *window,
3241 const cairo_region_t *region)
3242{
3243 CdkDrawingContext *context;
3244 CdkWindowImplClass *impl_class;
3245
3246 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
3247
3248 if (window->drawing_context != NULL((void*)0))
3249 {
3250 g_critical ("The window %p already has a drawing context. You cannot "
3251 "call cdk_window_begin_draw_frame() without calling "
3252 "cdk_window_end_draw_frame() first.", window);
3253 return NULL((void*)0);
3254 }
3255
3256 if (cdk_window_has_native (window) && cdk_window_is_toplevel (window))
3257 cdk_window_begin_paint_internal (window, region);
3258
3259 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
3260 if (impl_class->create_draw_context != NULL((void*)0))
3261 {
3262 context = impl_class->create_draw_context (window, region);
3263 }
3264 else
3265 {
3266 context = g_object_new (CDK_TYPE_DRAWING_CONTEXT(cdk_drawing_context_get_type ()),
3267 "window", window,
3268 "clip", region,
3269 NULL((void*)0));
3270 }
3271
3272 /* Do not take a reference, to avoid creating cycles */
3273 window->drawing_context = context;
3274
3275 return context;
3276}
3277
3278/**
3279 * cdk_window_end_draw_frame:
3280 * @window: a #CdkWindow
3281 * @context: the #CdkDrawingContext created by cdk_window_begin_draw_frame()
3282 *
3283 * Indicates that the drawing of the contents of @window started with
3284 * cdk_window_begin_frame() has been completed.
3285 *
3286 * This function will take care of destroying the #CdkDrawingContext.
3287 *
3288 * It is an error to call this function without a matching
3289 * cdk_window_begin_frame() first.
3290 *
3291 * Since: 3.22
3292 */
3293void
3294cdk_window_end_draw_frame (CdkWindow *window,
3295 CdkDrawingContext *context)
3296{
3297 CdkWindowImplClass *impl_class;
3298
3299 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
3300 g_return_if_fail (CDK_IS_DRAWING_CONTEXT (context))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((context)); GType __t = ((cdk_drawing_context_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Cdk", ((const
char*) (__func__)), "CDK_IS_DRAWING_CONTEXT (context)"); return
; } } while (0)
;
3301
3302 if (window->drawing_context == NULL((void*)0))
3303 {
3304 g_critical ("The window %p has no drawing context. You must call "
3305 "cdk_window_begin_draw_frame() before calling "
3306 "cdk_window_end_draw_frame().", window);
3307 return;
3308 }
3309
3310 if (cdk_window_has_native (window) && cdk_window_is_toplevel (window))
3311 cdk_window_end_paint_internal (window);
3312
3313 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
3314 if (impl_class->destroy_draw_context != NULL((void*)0))
3315 impl_class->destroy_draw_context (window, context);
3316 else
3317 g_object_unref (context);
3318
3319 window->drawing_context = NULL((void*)0);
3320}
3321
3322/*< private >
3323 * cdk_window_get_current_paint_region:
3324 * @window: a #CdkWindow
3325 *
3326 * Retrieves a copy of the current paint region.
3327 *
3328 * Returns: (transfer full): a Cairo region
3329 */
3330cairo_region_t *
3331cdk_window_get_current_paint_region (CdkWindow *window)
3332{
3333 cairo_region_t *region;
3334
3335 if (window->impl_window->current_paint.region != NULL((void*)0))
3336 {
3337 region = cairo_region_copy (window->impl_window->current_paint.region);
3338 cairo_region_translate (region, -window->abs_x, -window->abs_y);
3339 }
3340 else
3341 {
3342 region = cairo_region_copy (window->clip_region);
3343 }
3344
3345 return region;
3346}
3347
3348/*< private >
3349 * cdk_window_get_drawing_context:
3350 * @window: a #CdkWindow
3351 *
3352 * Retrieves the #CdkDrawingContext associated to @window by
3353 * cdk_window_begin_draw_frame().
3354 *
3355 * Returns: (transfer none) (nullable): a #CdkDrawingContext, if any is set
3356 */
3357CdkDrawingContext *
3358cdk_window_get_drawing_context (CdkWindow *window)
3359{
3360 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
3361
3362 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
3363 return NULL((void*)0);
3364
3365 return window->drawing_context;
3366}
3367
3368/**
3369 * cdk_window_mark_paint_from_clip:
3370 * @window: a #CdkWindow
3371 * @cr: a #cairo_t
3372 *
3373 * If you call this during a paint (e.g. between cdk_window_begin_paint_region()
3374 * and cdk_window_end_paint() then CDK will mark the current clip region of the
3375 * window as being drawn. This is required when mixing GL rendering via
3376 * cdk_cairo_draw_from_gl() and cairo rendering, as otherwise CDK has no way
3377 * of knowing when something paints over the GL-drawn regions.
3378 *
3379 * This is typically called automatically by CTK+ and you don't need
3380 * to care about this.
3381 *
3382 * Since: 3.16
3383 **/
3384void
3385cdk_window_mark_paint_from_clip (CdkWindow *window,
3386 cairo_t *cr)
3387{
3388 cairo_region_t *clip_region;
3389 CdkWindow *impl_window = window->impl_window;
3390
3391 if (impl_window->current_paint.surface == NULL((void*)0) ||
3392 cairo_get_target (cr) != impl_window->current_paint.surface)
3393 return;
3394
3395 if (cairo_region_is_empty (impl_window->current_paint.flushed_region))
3396 return;
3397
3398 /* This here seems a bit weird, but basically, we're taking the current
3399 clip and applying also the flushed region, and the result is that the
3400 new clip is the intersection of these. This is the area where the newly
3401 drawn region overlaps a previosly flushed area, which is an area of the
3402 double buffer surface that need to be blended OVER the back buffer rather
3403 than SRCed. */
3404 cairo_save (cr);
3405 /* We set the identity matrix here so we get and apply regions in native
3406 window coordinates. */
3407 cairo_identity_matrix (cr);
3408 cdk_cairo_region (cr, impl_window->current_paint.flushed_region);
3409 cairo_clip (cr);
3410
3411 clip_region = cdk_cairo_region_from_clip (cr);
3412 if (clip_region == NULL((void*)0))
3413 {
3414 /* Failed to represent clip as region, mark all as requiring
3415 blend */
3416 cairo_region_union (impl_window->current_paint.need_blend_region,
3417 impl_window->current_paint.flushed_region);
3418 cairo_region_destroy (impl_window->current_paint.flushed_region);
3419 impl_window->current_paint.flushed_region = cairo_region_create ();
3420 }
3421 else
3422 {
3423 cairo_region_subtract (impl_window->current_paint.flushed_region, clip_region);
3424 cairo_region_union (impl_window->current_paint.need_blend_region, clip_region);
3425 }
3426 cairo_region_destroy (clip_region);
3427
3428 /* Clear the area on the double buffer surface to transparent so we
3429 can start drawing from scratch the area "above" the flushed
3430 region */
3431 cairo_set_source_rgba (cr, 0, 0, 0, 0);
3432 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3433 cairo_paint (cr);
3434
3435 cairo_restore (cr);
3436}
3437
3438/**
3439 * cdk_window_end_paint:
3440 * @window: a #CdkWindow
3441 *
3442 * Indicates that the backing store created by the most recent call
3443 * to cdk_window_begin_paint_region() should be copied onscreen and
3444 * deleted, leaving the next-most-recent backing store or no backing
3445 * store at all as the active paint region. See
3446 * cdk_window_begin_paint_region() for full details.
3447 *
3448 * It is an error to call this function without a matching
3449 * cdk_window_begin_paint_region() first.
3450 **/
3451void
3452cdk_window_end_paint (CdkWindow *window)
3453{
3454 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
3455
3456 cdk_window_end_paint_internal (window);
3457}
3458
3459/**
3460 * cdk_window_flush:
3461 * @window: a #CdkWindow
3462 *
3463 * This function does nothing.
3464 *
3465 * Since: 2.18
3466 *
3467 * Deprecated: 3.14
3468 **/
3469void
3470cdk_window_flush (CdkWindow *window G_GNUC_UNUSED__attribute__ ((__unused__)))
3471{
3472}
3473
3474/**
3475 * cdk_window_get_clip_region:
3476 * @window: a #CdkWindow
3477 *
3478 * Computes the region of a window that potentially can be written
3479 * to by drawing primitives. This region may not take into account
3480 * other factors such as if the window is obscured by other windows,
3481 * but no area outside of this region will be affected by drawing
3482 * primitives.
3483 *
3484 * Returns: a #cairo_region_t. This must be freed with cairo_region_destroy()
3485 * when you are done.
3486 **/
3487cairo_region_t*
3488cdk_window_get_clip_region (CdkWindow *window)
3489{
3490 cairo_region_t *result;
3491
3492 g_return_val_if_fail (CDK_WINDOW (window), NULL)do { if ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((window)), ((cdk_window_get_type ()))))))
)) { } else { g_return_if_fail_warning ("Cdk", ((const char*)
(__func__)), "CDK_WINDOW (window)"); return (((void*)0)); } }
while (0)
;
3493
3494 result = cairo_region_copy (window->clip_region);
3495
3496 if (window->current_paint.region != NULL((void*)0))
3497 cairo_region_intersect (result, window->current_paint.region);
3498
3499 return result;
3500}
3501
3502/**
3503 * cdk_window_get_visible_region:
3504 * @window: a #CdkWindow
3505 *
3506 * Computes the region of the @window that is potentially visible.
3507 * This does not necessarily take into account if the window is
3508 * obscured by other windows, but no area outside of this region
3509 * is visible.
3510 *
3511 * Returns: a #cairo_region_t. This must be freed with cairo_region_destroy()
3512 * when you are done.
3513 **/
3514cairo_region_t *
3515cdk_window_get_visible_region (CdkWindow *window)
3516{
3517 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
3518
3519 return cairo_region_copy (window->clip_region);
3520}
3521
3522static void
3523cdk_window_clear_backing_region (CdkWindow *window)
3524{
3525 CdkWindow *bg_window;
3526 cairo_pattern_t *pattern = NULL((void*)0);
3527 int x_offset = 0, y_offset = 0;
3528 cairo_t *cr;
3529
3530 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
3531 return;
3532
3533 cr = cairo_create (window->current_paint.surface);
3534
3535 for (bg_window = window; bg_window; bg_window = bg_window->parent)
3536 {
3537 pattern = cdk_window_get_background_pattern (bg_window);
3538
3539 if (pattern)
3540 break;
3541
3542 x_offset += bg_window->x;
3543 y_offset += bg_window->y;
3544 }
3545
3546 if (pattern)
3547 {
3548 cairo_translate (cr, -x_offset, -y_offset);
3549 cairo_set_source (cr, pattern);
3550 cairo_translate (cr, x_offset, y_offset);
3551 }
3552 else
3553 cairo_set_source_rgb (cr, 0, 0, 0);
3554
3555 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3556 cdk_cairo_region (cr, window->current_paint.region);
3557 cairo_fill (cr);
3558
3559 cairo_destroy (cr);
3560}
3561
3562/* This returns either the current working surface on the paint stack
3563 * or the actual impl surface of the window. This should not be used
3564 * from very many places: be careful! */
3565static cairo_surface_t *
3566ref_window_surface (CdkWindow *window)
3567{
3568 if (window->impl_window->current_paint.surface)
3569 return cairo_surface_reference (window->impl_window->current_paint.surface);
3570 else
3571 return cdk_window_ref_impl_surface (window);
3572}
3573
3574/* This is used in places like cdk_cairo_set_source_window and
3575 * other places to take "screenshots" of windows. Thus, we allow
3576 * it to be used outside of a begin_paint / end_paint. */
3577cairo_surface_t *
3578_cdk_window_ref_cairo_surface (CdkWindow *window)
3579{
3580 cairo_surface_t *surface;
3581
3582 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
3583
3584 surface = ref_window_surface (window);
3585
3586 if (cdk_window_has_impl (window))
3587 {
3588 return surface;
3589 }
3590 else
3591 {
3592 cairo_surface_t *subsurface;
3593 subsurface = cairo_surface_create_for_rectangle (surface,
3594 window->abs_x,
3595 window->abs_y,
3596 window->width,
3597 window->height);
3598 cairo_surface_destroy (surface);
3599 return subsurface;
3600 }
3601}
3602
3603/**
3604 * cdk_cairo_create:
3605 * @window: a #CdkWindow
3606 *
3607 * Creates a Cairo context for drawing to @window.
3608 *
3609 * Note that calling cairo_reset_clip() on the resulting #cairo_t will
3610 * produce undefined results, so avoid it at all costs.
3611 *
3612 * Typically, this function is used to draw on a #CdkWindow out of the paint
3613 * cycle of the toolkit; this should be avoided, as it breaks various assumptions
3614 * and optimizations.
3615 *
3616 * If you are drawing on a native #CdkWindow in response to a %CDK_EXPOSE event
3617 * you should use cdk_window_begin_draw_frame() and cdk_drawing_context_get_cairo_context()
3618 * instead. CTK will automatically do this for you when drawing a widget.
3619 *
3620 * Returns: A newly created Cairo context. Free with
3621 * cairo_destroy() when you are done drawing.
3622 *
3623 * Since: 2.8
3624 **/
3625cairo_t *
3626cdk_cairo_create (CdkWindow *window)
3627{
3628 cairo_region_t *region;
3629 cairo_surface_t *surface;
3630 cairo_t *cr;
3631
3632 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
3633
3634 surface = _cdk_window_ref_cairo_surface (window);
3635
3636 cr = cairo_create (surface);
3637
3638 region = cdk_window_get_current_paint_region (window);
3639 cdk_cairo_region (cr, region);
3640 cairo_region_destroy (region);
3641 cairo_clip (cr);
3642
3643 /* Assign a drawing context, if one is set; if cdk_cairo_create()
3644 * is called outside of a frame drawing then this is going to be
3645 * NULL.
3646 */
3647 cdk_cairo_set_drawing_context (cr, window->drawing_context);
3648
3649 cairo_surface_destroy (surface);
3650
3651 return cr;
3652}
3653
3654/* Code for dirty-region queueing
3655 */
3656static GSList *update_windows = NULL((void*)0);
3657gboolean _cdk_debug_updates = FALSE(0);
3658
3659static inline gboolean
3660cdk_window_is_ancestor (CdkWindow *window,
3661 CdkWindow *ancestor)
3662{
3663 while (window)
3664 {
3665 CdkWindow *parent = window->parent;
3666
3667 if (parent == ancestor)
3668 return TRUE(!(0));
3669
3670 window = parent;
3671 }
3672
3673 return FALSE(0);
3674}
3675
3676static void
3677cdk_window_add_update_window (CdkWindow *window)
3678{
3679 GSList *tmp;
3680 GSList *prev = NULL((void*)0);
3681 gboolean has_ancestor_in_list = FALSE(0);
3682
3683 /* Check whether "window" is already in "update_windows" list.
3684 * It could be added during execution of ctk_widget_destroy() when
3685 * setting focus widget to NULL and redrawing old focus widget.
3686 * See bug 711552.
3687 */
3688 tmp = g_slist_find (update_windows, window);
3689 if (tmp != NULL((void*)0))
3690 return;
3691
3692 for (tmp = update_windows; tmp; tmp = tmp->next)
3693 {
3694 CdkWindow *parent = window->parent;
3695
3696 /* check if tmp is an ancestor of "window"; if it is, set a
3697 * flag indicating that all following windows are either
3698 * children of "window" or from a differen hierarchy
3699 */
3700 if (!has_ancestor_in_list && cdk_window_is_ancestor (window, tmp->data))
3701 has_ancestor_in_list = TRUE(!(0));
3702
3703 /* insert in reverse stacking order when adding around siblings,
3704 * so processing updates properly paints over lower stacked windows
3705 */
3706 if (parent == CDK_WINDOW (tmp->data)((((CdkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tmp->data)), ((cdk_window_get_type ()))))))
->parent)
3707 {
3708 gint index = g_list_index (parent->children, window);
3709 for (; tmp && parent == CDK_WINDOW (tmp->data)((((CdkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tmp->data)), ((cdk_window_get_type ()))))))
->parent; tmp = tmp->next)
3710 {
3711 gint sibling_index = g_list_index (parent->children, tmp->data);
3712 if (index > sibling_index)
3713 break;
3714 prev = tmp;
3715 }
3716 /* here, tmp got advanced past all lower stacked siblings */
3717 tmp = g_slist_prepend (tmp, g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window)));
3718 if (prev)
3719 prev->next = tmp;
3720 else
3721 update_windows = tmp;
3722 return;
3723 }
3724
3725 /* if "window" has an ancestor in the list and tmp is one of
3726 * "window's" children, insert "window" before tmp
3727 */
3728 if (has_ancestor_in_list && cdk_window_is_ancestor (tmp->data, window))
3729 {
3730 tmp = g_slist_prepend (tmp, g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window)));
3731
3732 if (prev)
3733 prev->next = tmp;
3734 else
3735 update_windows = tmp;
3736 return;
3737 }
3738
3739 /* if we're at the end of the list and had an ancestor it it,
3740 * append to the list
3741 */
3742 if (! tmp->next && has_ancestor_in_list)
3743 {
3744 tmp = g_slist_append (tmp, g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window)));
3745 return;
3746 }
3747
3748 prev = tmp;
3749 }
3750
3751 /* if all above checks failed ("window" is from a different
3752 * hierarchy than what is already in the list) or the list is
3753 * empty, prepend
3754 */
3755 update_windows = g_slist_prepend (update_windows, g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window)));
3756}
3757
3758static void
3759cdk_window_remove_update_window (CdkWindow *window)
3760{
3761 GSList *link;
3762
3763 link = g_slist_find (update_windows, window);
3764 if (link != NULL((void*)0))
3765 {
3766 update_windows = g_slist_delete_link (update_windows, link);
3767 g_object_unref (window);
3768 }
3769}
3770
3771static gboolean
3772cdk_window_is_toplevel_frozen (CdkWindow *window)
3773{
3774 CdkWindow *toplevel;
3775
3776 toplevel = cdk_window_get_toplevel (window);
3777
3778 return toplevel->update_and_descendants_freeze_count > 0;
3779}
3780
3781static void
3782cdk_window_schedule_update (CdkWindow *window)
3783{
3784 CdkFrameClock *frame_clock;
3785
3786 if (window &&
3787 (window->update_freeze_count ||
3788 cdk_window_is_toplevel_frozen (window)))
3789 return;
3790
3791 /* If there's no frame clock (a foreign window), then the invalid
3792 * region will just stick around unless cdk_window_process_updates()
3793 * is called. */
3794 frame_clock = cdk_window_get_frame_clock (window);
3795 if (frame_clock)
3796 cdk_frame_clock_request_phase (cdk_window_get_frame_clock (window),
3797 CDK_FRAME_CLOCK_PHASE_PAINT);
3798}
3799
3800static void
3801cdk_window_add_damage (CdkWindow *toplevel,
3802 cairo_region_t *damaged_region)
3803{
3804 CdkDisplay *display;
3805 CdkEvent event = { 0, };
3806
3807 /* This function only makes sense for offscreen windows. */
3808 g_assert (cdk_window_is_offscreen (toplevel))do { if (cdk_window_is_offscreen (toplevel)) ; else g_assertion_message_expr
("Cdk", "cdkwindow.c", 3808, ((const char*) (__func__)), "cdk_window_is_offscreen (toplevel)"
); } while (0)
;
3809
3810 event.expose.type = CDK_DAMAGE;
3811 event.expose.window = toplevel;
3812 event.expose.send_event = FALSE(0);
3813 event.expose.region = damaged_region;
3814 cairo_region_get_extents (event.expose.region, &event.expose.area);
3815
3816 display = cdk_window_get_display (event.expose.window);
3817 _cdk_event_queue_append (display, cdk_event_copy (&event));
3818}
3819
3820static void
3821_cdk_window_process_updates_recurse_helper (CdkWindow *window,
3822 cairo_region_t *expose_region)
3823{
3824 CdkWindow *child;
3825 cairo_region_t *clipped_expose_region;
3826 CdkWindow **children;
3827 CdkWindow **free_children = NULL((void*)0);
3828 int i, n_children;
3829 GList *l;
3830 GList *last_link;
3831
3832 if (window->destroyed)
3833 return;
3834
3835 if (window->alpha == 0 && !cdk_window_has_impl (window))
3836 return;
3837
3838 clipped_expose_region = cairo_region_copy (expose_region);
3839
3840 if (!cdk_window_has_impl (window))
3841 cairo_region_translate (clipped_expose_region, -window->x, -window->y);
3842
3843 cairo_region_intersect (clipped_expose_region, window->clip_region);
3844
3845 if (cairo_region_is_empty (clipped_expose_region))
3846 goto out;
3847
3848 if (cdk_window_is_offscreen (window))
3849 cdk_window_add_damage (window, clipped_expose_region);
3850
3851 /* Paint the window before the children, clipped to the window region */
3852
3853 /* While ctk+ no longer handles exposes on anything but native
3854 window we still have to send them to all windows that have the
3855 event mask set for backwards compat. We also need to send
3856 it to all native windows, even if they don't specify the
3857 expose mask, because they may have non-native children that do. */
3858 if (cdk_window_has_impl (window) ||
3859 window->event_mask & CDK_EXPOSURE_MASK)
3860 {
3861 CdkEvent event;
3862
3863 event.expose.type = CDK_EXPOSE;
3864 event.expose.window = window; /* we already hold a ref */
3865 event.expose.send_event = FALSE(0);
3866 event.expose.count = 0;
3867 event.expose.region = clipped_expose_region;
3868 cairo_region_get_extents (clipped_expose_region, &event.expose.area);
3869
3870 _cdk_event_emit (&event);
3871 }
3872
3873 n_children = 0;
3874 last_link = NULL((void*)0);
3875 /* Count n_children and fetch bottommost at same time */
3876 for (l = window->children; l != NULL((void*)0); l = l->next)
3877 {
3878 last_link = l;
3879 n_children++;
3880 }
3881
3882 children = g_newa (CdkWindow *, n_children)((CdkWindow **) __builtin_alloca (sizeof (CdkWindow *) * (gsize
) (n_children)))
;
3883 if (children == NULL((void*)0))
3884 children = free_children = g_new (CdkWindow *, n_children)((CdkWindow * *) g_malloc_n ((n_children), sizeof (CdkWindow *
)))
;
3885
3886 n_children = 0;
3887 /* Iterate over children, starting at bottommost */
3888 for (l = last_link; l != NULL((void*)0); l = l->prev)
3889 {
3890 child = l->data;
3891
3892 if (child->destroyed || !CDK_WINDOW_IS_MAPPED (child)(((child)->state & CDK_WINDOW_STATE_WITHDRAWN) == 0) || child->input_only || child->composited)
3893 continue;
3894
3895 /* Ignore offscreen children, as they don't draw in their parent and
3896 * don't take part in the clipping */
3897 if (cdk_window_is_offscreen (child))
3898 continue;
3899
3900 /* Client side child, expose */
3901 if (child->impl == window->impl)
3902 {
3903 /* ref the child to make this reentrancy safe for expose
3904 handlers freeing other windows */
3905 children[n_children++] = g_object_ref (child)((__typeof__ (child)) (g_object_ref) (child));
3906 }
3907 }
3908
3909 for (i = 0; i < n_children; i++)
3910 {
3911 _cdk_window_process_updates_recurse_helper ((CdkWindow *)children[i],
3912 clipped_expose_region);
3913 g_object_unref (children[i]);
3914 }
3915
3916
3917 g_free (free_children);
3918
3919 out:
3920 cairo_region_destroy (clipped_expose_region);
3921}
3922
3923void
3924_cdk_window_process_updates_recurse (CdkWindow *window,
3925 cairo_region_t *expose_region)
3926{
3927 _cdk_window_process_updates_recurse_helper (window, expose_region);
3928}
3929
3930
3931static void
3932cdk_window_update_native_shapes (CdkWindow *window)
3933{
3934 CdkWindow *child;
3935 GList *l;
3936
3937 if (should_apply_clip_as_shape (window))
3938 apply_clip_as_shape (window);
3939
3940 for (l = window->native_children; l != NULL((void*)0); l = l->next)
3941 {
3942 child = l->data;
3943
3944 cdk_window_update_native_shapes (child);
3945 }
3946}
3947
3948/* Process and remove any invalid area on the native window by creating
3949 * expose events for the window and all non-native descendants.
3950 */
3951static void
3952cdk_window_process_updates_internal (CdkWindow *window)
3953{
3954 CdkWindowImplClass *impl_class;
3955 CdkWindow *toplevel;
3956 CdkDisplay *display;
3957
3958 display = cdk_window_get_display (window);
3959 toplevel = cdk_window_get_toplevel (window);
3960 if (toplevel->geometry_dirty)
3961 {
3962 cdk_window_update_native_shapes (toplevel);
3963 toplevel->geometry_dirty = FALSE(0);
3964 }
3965
3966 /* Ensure the window lives while updating it */
3967 g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
3968
3969 window->in_update = TRUE(!(0));
3970
3971 /* If an update got queued during update processing, we can get a
3972 * window in the update queue that has an empty update_area.
3973 * just ignore it.
3974 */
3975 if (window->update_area)
3976 {
3977 g_assert (window->active_update_area == NULL)do { if (window->active_update_area == ((void*)0)) ; else g_assertion_message_expr
("Cdk", "cdkwindow.c", 3977, ((const char*) (__func__)), "window->active_update_area == NULL"
); } while (0)
; /* No reentrancy */
3978
3979 window->active_update_area = window->update_area;
3980 window->update_area = NULL((void*)0);
3981
3982 if (cdk_window_is_viewable (window))
3983 {
3984 cairo_region_t *expose_region;
3985
3986 expose_region = cairo_region_copy (window->active_update_area);
3987
3988 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
3989
3990 /* Sometimes we can't just paint only the new area, as the windowing system
3991 * requires more to be repainted. For instance, with OpenGL you typically
3992 * repaint all of each frame each time and then swap the buffer, although
3993 * there are extensions that allow us to reuse part of an old frame.
3994 */
3995 if (impl_class->invalidate_for_new_frame)
3996 impl_class->invalidate_for_new_frame (window, expose_region);
3997
3998 /* Clip to part visible in impl window */
3999 cairo_region_intersect (expose_region, window->clip_region);
4000
4001 if (cdk_display_get_debug_updates (display))
4002 {
4003 cairo_region_t *swap_region = cairo_region_copy (expose_region);
4004 cairo_region_subtract (swap_region, window->active_update_area);
4005 draw_ugly_color (window, swap_region, 1);
4006 cairo_region_destroy (swap_region);
4007
4008 /* Make sure we see the red invalid area before redrawing. */
4009 cdk_display_sync (cdk_window_get_display (window));
4010 g_usleep (70000);
4011 }
4012
4013 if (impl_class->queue_antiexpose)
4014 impl_class->queue_antiexpose (window, expose_region);
4015
4016 impl_class->process_updates_recurse (window, expose_region);
4017
4018 cdk_window_append_old_updated_area (window, window->active_update_area);
4019
4020 cairo_region_destroy (expose_region);
4021 }
4022
4023 cairo_region_destroy (window->active_update_area);
4024 window->active_update_area = NULL((void*)0);
4025 }
4026
4027 window->in_update = FALSE(0);
4028
4029 g_object_unref (window);
4030}
4031
4032static void
4033flush_all_displays (void)
4034{
4035 GSList *displays, *l;
4036
4037 displays = cdk_display_manager_list_displays (cdk_display_manager_get ());
4038 for (l = displays; l; l = l->next)
4039 cdk_display_flush (l->data);
4040
4041 g_slist_free (displays);
4042}
4043
4044static void
4045before_process_all_updates (void)
4046{
4047 GSList *displays, *l;
4048
4049 displays = cdk_display_manager_list_displays (cdk_display_manager_get ());
4050 for (l = displays; l; l = l->next)
4051 CDK_DISPLAY_GET_CLASS (l->data)((((CdkDisplayClass*) (((GTypeInstance*) ((l->data)))->
g_class))))
->before_process_all_updates (l->data);
4052
4053 g_slist_free (displays);
4054}
4055
4056static void
4057after_process_all_updates (void)
4058{
4059 GSList *displays, *l;
4060
4061 displays = cdk_display_manager_list_displays (cdk_display_manager_get ());
4062 for (l = displays; l; l = l->next)
4063 CDK_DISPLAY_GET_CLASS (l->data)((((CdkDisplayClass*) (((GTypeInstance*) ((l->data)))->
g_class))))
->after_process_all_updates (l->data);
4064
4065 g_slist_free (displays);
4066}
4067
4068/* Currently it is not possible to override
4069 * cdk_window_process_all_updates in the same manner as
4070 * cdk_window_process_updates and cdk_window_invalidate_maybe_recurse
4071 * by implementing the CdkPaintable interface. If in the future a
4072 * backend would need this, the right solution would be to add a
4073 * method to CdkDisplay that can be optionally
4074 * NULL. cdk_window_process_all_updates can then walk the list of open
4075 * displays and call the mehod.
4076 */
4077
4078/**
4079 * cdk_window_process_all_updates:
4080 *
4081 * Calls cdk_window_process_updates() for all windows (see #CdkWindow)
4082 * in the application.
4083 **/
4084void
4085cdk_window_process_all_updates (void)
4086{
4087 GSList *old_update_windows = update_windows;
4088 GSList *tmp_list = update_windows;
4089 static gboolean in_process_all_updates = FALSE(0);
4090 static gboolean got_recursive_update = FALSE(0);
4091
4092 if (in_process_all_updates)
4093 {
4094 /* We can't do this now since that would recurse, so
4095 delay it until after the recursion is done. */
4096 got_recursive_update = TRUE(!(0));
4097 return;
4098 }
4099
4100 in_process_all_updates = TRUE(!(0));
4101 got_recursive_update = FALSE(0);
4102
4103 update_windows = NULL((void*)0);
4104
4105 before_process_all_updates ();
4106
4107 while (tmp_list)
4108 {
4109 CdkWindow *window = tmp_list->data;
4110
4111 if (!CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
4112 {
4113 if (window->update_freeze_count ||
4114 cdk_window_is_toplevel_frozen (window))
4115 cdk_window_add_update_window (window);
4116 else
4117 cdk_window_process_updates_internal (window);
4118 }
4119
4120 g_object_unref (window);
4121 tmp_list = tmp_list->next;
4122 }
4123
4124 g_slist_free (old_update_windows);
4125
4126 flush_all_displays ();
4127
4128 after_process_all_updates ();
4129
4130 in_process_all_updates = FALSE(0);
4131
4132 /* If we ignored a recursive call, schedule a
4133 redraw now so that it eventually happens,
4134 otherwise we could miss an update if nothing
4135 else schedules an update. */
4136 if (got_recursive_update)
4137 cdk_window_schedule_update (NULL((void*)0));
4138}
4139
4140
4141enum {
4142 PROCESS_UPDATES_NO_RECURSE,
4143 PROCESS_UPDATES_WITH_ALL_CHILDREN,
4144 PROCESS_UPDATES_WITH_SAME_CLOCK_CHILDREN
4145};
4146
4147static void
4148find_impl_windows_to_update (GPtrArray *list,
4149 CdkWindow *window,
4150 gint recurse_mode)
4151{
4152 GList *node;
4153
4154 /* Recurse first, so that we process updates in reverse stacking
4155 * order so composition or painting over achieves the desired effect
4156 * for offscreen windows
4157 */
4158 if (recurse_mode != PROCESS_UPDATES_NO_RECURSE)
4159 {
4160 for (node = window->children; node; node = node->next)
4161 {
4162 CdkWindow *child = node->data;
4163
4164 if (!CDK_WINDOW_DESTROYED (child)(((CdkWindow *)(child))->destroyed) &&
4165 (recurse_mode == PROCESS_UPDATES_WITH_ALL_CHILDREN ||
4166 (recurse_mode == PROCESS_UPDATES_WITH_SAME_CLOCK_CHILDREN &&
4167 child->frame_clock == NULL((void*)0))))
4168 {
4169 find_impl_windows_to_update (list, child, recurse_mode);
4170 }
4171 }
4172 }
4173
4174 /* add reference count so the window cannot be deleted in a callback */
4175 if (window->impl_window == window)
4176 g_ptr_array_add (list, g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window)));
4177}
4178
4179static void
4180cdk_window_process_updates_with_mode (CdkWindow *window,
4181 int recurse_mode)
4182{
4183 GPtrArray *list;
4184 int i;
4185
4186 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
4187
4188 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
4189 return;
4190
4191 list = g_ptr_array_new_with_free_func (g_object_unref);
4192 find_impl_windows_to_update (list, window, recurse_mode);
4193
4194 if (window->impl_window != window)
4195 g_ptr_array_add (list, g_object_ref (window->impl_window)((__typeof__ (window->impl_window)) (g_object_ref) (window
->impl_window))
);
4196
4197 for (i = (int)list->len - 1; i >= 0; i --)
4198 {
4199 CdkWindow *impl_window = g_ptr_array_index (list, i)((list)->pdata)[i];
4200
4201 if (impl_window->update_area &&
4202 !impl_window->update_freeze_count &&
4203 !cdk_window_is_toplevel_frozen (impl_window) &&
4204
4205 /* Don't recurse into process_updates_internal, we'll
4206 * do the update later when idle instead. */
4207 !impl_window->in_update)
4208 {
4209 cdk_window_process_updates_internal (impl_window);
4210 cdk_window_remove_update_window (impl_window);
4211 }
4212 }
4213
4214 g_ptr_array_free (list, TRUE(!(0)));
4215}
4216
4217/**
4218 * cdk_window_process_updates:
4219 * @window: a #CdkWindow
4220 * @update_children: whether to also process updates for child windows
4221 *
4222 * Sends one or more expose events to @window. The areas in each
4223 * expose event will cover the entire update area for the window (see
4224 * cdk_window_invalidate_region() for details). Normally CDK calls
4225 * cdk_window_process_all_updates() on your behalf, so there’s no
4226 * need to call this function unless you want to force expose events
4227 * to be delivered immediately and synchronously (vs. the usual
4228 * case, where CDK delivers them in an idle handler). Occasionally
4229 * this is useful to produce nicer scrolling behavior, for example.
4230 **/
4231void
4232cdk_window_process_updates (CdkWindow *window,
4233 gboolean update_children)
4234{
4235 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
4236
4237 cdk_window_process_updates_with_mode (window,
4238 update_children ?
4239 PROCESS_UPDATES_WITH_ALL_CHILDREN :
4240 PROCESS_UPDATES_NO_RECURSE);
4241}
4242
4243static void
4244cdk_window_invalidate_rect_full (CdkWindow *window,
4245 const CdkRectangle *rect,
4246 gboolean invalidate_children)
4247{
4248 CdkRectangle window_rect;
4249 cairo_region_t *region;
4250
4251 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
4252
4253 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
4254 return;
4255
4256 if (window->input_only || !window->viewable)
4257 return;
4258
4259 if (!rect)
4260 {
4261 window_rect.x = 0;
4262 window_rect.y = 0;
4263 window_rect.width = window->width;
4264 window_rect.height = window->height;
4265 rect = &window_rect;
4266 }
4267
4268 region = cairo_region_create_rectangle (rect);
4269 cdk_window_invalidate_region_full (window, region, invalidate_children);
4270 cairo_region_destroy (region);
4271}
4272
4273/**
4274 * cdk_window_invalidate_rect:
4275 * @window: a #CdkWindow
4276 * @rect: (allow-none): rectangle to invalidate or %NULL to invalidate the whole
4277 * window
4278 * @invalidate_children: whether to also invalidate child windows
4279 *
4280 * A convenience wrapper around cdk_window_invalidate_region() which
4281 * invalidates a rectangular region. See
4282 * cdk_window_invalidate_region() for details.
4283 **/
4284void
4285cdk_window_invalidate_rect (CdkWindow *window,
4286 const CdkRectangle *rect,
4287 gboolean invalidate_children)
4288{
4289 cdk_window_invalidate_rect_full (window, rect, invalidate_children);
4290}
4291
4292/**
4293 * cdk_window_set_invalidate_handler: (skip)
4294 * @window: a #CdkWindow
4295 * @handler: a #CdkWindowInvalidateHandlerFunc callback function
4296 *
4297 * Registers an invalidate handler for a specific window. This
4298 * will get called whenever a region in the window or its children
4299 * is invalidated.
4300 *
4301 * This can be used to record the invalidated region, which is
4302 * useful if you are keeping an offscreen copy of some region
4303 * and want to keep it up to date. You can also modify the
4304 * invalidated region in case you’re doing some effect where
4305 * e.g. a child widget appears in multiple places.
4306 *
4307 * Since: 3.10
4308 **/
4309void
4310cdk_window_set_invalidate_handler (CdkWindow *window,
4311 CdkWindowInvalidateHandlerFunc handler)
4312{
4313 window->invalidate_handler = handler;
4314}
4315
4316static void
4317draw_ugly_color (CdkWindow *window,
4318 const cairo_region_t *region,
4319 int color)
4320{
4321 cairo_t *cr;
4322
4323 cr = cdk_cairo_create (window);
4324
4325 /* Draw ugly color all over the newly-invalid region */
4326 if (color == 0)
4327 cairo_set_source_rgb (cr, 50000/65535., 10000/65535., 10000/65535.);
4328 else
4329 cairo_set_source_rgb (cr, 10000/65535., 50000/65535., 10000/65535.);
4330
4331 cdk_cairo_region (cr, region);
4332 cairo_fill (cr);
4333
4334 cairo_destroy (cr);
4335}
4336
4337static void
4338impl_window_add_update_area (CdkWindow *impl_window,
4339 cairo_region_t *region)
4340{
4341 if (impl_window->update_area)
4342 cairo_region_union (impl_window->update_area, region);
4343 else
4344 {
4345 cdk_window_add_update_window (impl_window);
4346 impl_window->update_area = cairo_region_copy (region);
4347 cdk_window_schedule_update (impl_window);
4348 }
4349}
4350
4351static void
4352cdk_window_invalidate_maybe_recurse_full (CdkWindow *window,
4353 const cairo_region_t *region,
4354 CdkWindowChildFunc child_func,
4355 gpointer user_data);
4356
4357/* Returns true if window is a decendant of parent, but stops looking
4358 * at the first native window. Also ensures that all parents match
4359 * child_func if non-null..
4360 *
4361 * This is useful in combination with
4362 * window->impl_window->native_children as it lets you find all native
4363 * decendants in an efficient way (assuming few children are native).
4364 */
4365static gboolean
4366has_visible_ancestor_in_impl (CdkWindow *window,
4367 CdkWindow *ancestor,
4368 CdkWindowChildFunc child_func,
4369 gpointer user_data)
4370{
4371 CdkWindow *p;
4372 CdkWindow *stop_at;
4373
4374 p = window->parent;
4375 stop_at = p->impl_window;
4376 while (p != NULL((void*)0))
4377 {
4378 if (!p->viewable)
4379 return FALSE(0);
4380 if (child_func &&
4381 !(*child_func) ((CdkWindow *)p, user_data))
4382 return FALSE(0);
4383 if (p == ancestor)
4384 return TRUE(!(0));
4385 if (p == stop_at)
4386 return FALSE(0);
4387 p = p->parent;
4388 }
4389 return FALSE(0);
4390}
4391
4392static void
4393invalidate_impl_subwindows (CdkWindow *window,
4394 const cairo_region_t *region,
4395 CdkWindowChildFunc child_func,
4396 gpointer user_data)
4397{
4398 GList *l;
4399
4400 /* Iterate over all native children of the native window
4401 that window is in. */
4402 for (l = window->impl_window->native_children;
4403 l != NULL((void*)0);
4404 l = l->next)
4405 {
4406 CdkWindow *native_child = l->data;
4407 cairo_region_t *tmp;
4408 int dx, dy;
4409
4410 if (native_child->input_only)
4411 continue;
4412
4413 /* Then skip any that does not have window as an ancestor,
4414 * also checking that the ancestors are visible and pass child_func
4415 * This is fast if we assume native children are rare */
4416 if (!has_visible_ancestor_in_impl (native_child, window,
4417 child_func, user_data))
4418 continue;
4419
4420 dx = native_child->parent->abs_x + native_child->x - window->abs_x;
4421 dy = native_child->parent->abs_y + native_child->y - window->abs_y;
4422
4423 tmp = cairo_region_copy (region);
4424 cairo_region_translate (tmp, -dx, -dy);
4425 cdk_window_invalidate_maybe_recurse_full (native_child,
4426 tmp, child_func, user_data);
4427 cairo_region_destroy (tmp);
4428 }
4429}
4430
4431static void
4432cdk_window_invalidate_maybe_recurse_full (CdkWindow *window,
4433 const cairo_region_t *region,
4434 CdkWindowChildFunc child_func,
4435 gpointer user_data)
4436{
4437 cairo_region_t *visible_region;
4438 cairo_rectangle_int_t r;
4439 CdkDisplay *display;
4440
4441 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
4442
4443 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
4444 return;
4445
4446 if (window->input_only ||
4447 !window->viewable ||
4448 cairo_region_is_empty (region) ||
4449 window->window_type == CDK_WINDOW_ROOT)
4450 return;
4451
4452 r.x = 0;
4453 r.y = 0;
4454
4455 visible_region = cairo_region_copy (region);
4456
4457 if (child_func)
4458 invalidate_impl_subwindows (window, region, child_func, user_data);
4459
4460 display = cdk_window_get_display (window);
4461 if (cdk_display_get_debug_updates (display))
4462 draw_ugly_color (window, visible_region, 0);
4463
4464 while (window != NULL((void*)0) &&
4465 !cairo_region_is_empty (visible_region))
4466 {
4467 if (window->invalidate_handler)
4468 window->invalidate_handler (window, visible_region);
4469
4470 r.width = window->width;
4471 r.height = window->height;
4472 cairo_region_intersect_rectangle (visible_region, &r);
4473
4474 if (cdk_window_has_impl (window))
4475 {
4476 impl_window_add_update_area (window, visible_region);
4477 break;
4478 }
4479 else
4480 {
4481 cairo_region_translate (visible_region,
4482 window->x, window->y);
4483 window = window->parent;
4484 }
4485 }
4486
4487 cairo_region_destroy (visible_region);
4488}
4489
4490/**
4491 * cdk_window_invalidate_maybe_recurse:
4492 * @window: a #CdkWindow
4493 * @region: a #cairo_region_t
4494 * @child_func: (scope call) (allow-none): function to use to decide if to
4495 * recurse to a child, %NULL means never recurse.
4496 * @user_data: data passed to @child_func
4497 *
4498 * Adds @region to the update area for @window. The update area is the
4499 * region that needs to be redrawn, or “dirty region.” The call
4500 * cdk_window_process_updates() sends one or more expose events to the
4501 * window, which together cover the entire update area. An
4502 * application would normally redraw the contents of @window in
4503 * response to those expose events.
4504 *
4505 * CDK will call cdk_window_process_all_updates() on your behalf
4506 * whenever your program returns to the main loop and becomes idle, so
4507 * normally there’s no need to do that manually, you just need to
4508 * invalidate regions that you know should be redrawn.
4509 *
4510 * The @child_func parameter controls whether the region of
4511 * each child window that intersects @region will also be invalidated.
4512 * Only children for which @child_func returns #TRUE will have the area
4513 * invalidated.
4514 **/
4515void
4516cdk_window_invalidate_maybe_recurse (CdkWindow *window,
4517 const cairo_region_t *region,
4518 CdkWindowChildFunc child_func,
4519 gpointer user_data)
4520{
4521 cdk_window_invalidate_maybe_recurse_full (window, region,
4522 child_func, user_data);
4523}
4524
4525static gboolean
4526true_predicate (CdkWindow *window G_GNUC_UNUSED__attribute__ ((__unused__)),
4527 gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
4528{
4529 return TRUE(!(0));
4530}
4531
4532static void
4533cdk_window_invalidate_region_full (CdkWindow *window,
4534 const cairo_region_t *region,
4535 gboolean invalidate_children)
4536{
4537 cdk_window_invalidate_maybe_recurse_full (window, region,
4538 invalidate_children ?
4539 true_predicate : (gboolean (*) (CdkWindow *, gpointer))NULL((void*)0),
4540 NULL((void*)0));
4541}
4542
4543/**
4544 * cdk_window_invalidate_region:
4545 * @window: a #CdkWindow
4546 * @region: a #cairo_region_t
4547 * @invalidate_children: %TRUE to also invalidate child windows
4548 *
4549 * Adds @region to the update area for @window. The update area is the
4550 * region that needs to be redrawn, or “dirty region.” The call
4551 * cdk_window_process_updates() sends one or more expose events to the
4552 * window, which together cover the entire update area. An
4553 * application would normally redraw the contents of @window in
4554 * response to those expose events.
4555 *
4556 * CDK will call cdk_window_process_all_updates() on your behalf
4557 * whenever your program returns to the main loop and becomes idle, so
4558 * normally there’s no need to do that manually, you just need to
4559 * invalidate regions that you know should be redrawn.
4560 *
4561 * The @invalidate_children parameter controls whether the region of
4562 * each child window that intersects @region will also be invalidated.
4563 * If %FALSE, then the update area for child windows will remain
4564 * unaffected. See cdk_window_invalidate_maybe_recurse if you need
4565 * fine grained control over which children are invalidated.
4566 **/
4567void
4568cdk_window_invalidate_region (CdkWindow *window,
4569 const cairo_region_t *region,
4570 gboolean invalidate_children)
4571{
4572 cdk_window_invalidate_maybe_recurse (window, region,
4573 invalidate_children ?
4574 true_predicate : (gboolean (*) (CdkWindow *, gpointer))NULL((void*)0),
4575 NULL((void*)0));
4576}
4577
4578/**
4579 * _cdk_window_invalidate_for_expose:
4580 * @window: a #CdkWindow
4581 * @region: a #cairo_region_t
4582 *
4583 * Adds @region to the update area for @window. The update area is the
4584 * region that needs to be redrawn, or “dirty region.” The call
4585 * cdk_window_process_updates() sends one or more expose events to the
4586 * window, which together cover the entire update area. An
4587 * application would normally redraw the contents of @window in
4588 * response to those expose events.
4589 *
4590 * CDK will call cdk_window_process_all_updates() on your behalf
4591 * whenever your program returns to the main loop and becomes idle, so
4592 * normally there’s no need to do that manually, you just need to
4593 * invalidate regions that you know should be redrawn.
4594 *
4595 * This version of invalidation is used when you recieve expose events
4596 * from the native window system. It exposes the native window, plus
4597 * any non-native child windows (but not native child windows, as those would
4598 * have gotten their own expose events).
4599 **/
4600void
4601_cdk_window_invalidate_for_expose (CdkWindow *window,
4602 cairo_region_t *region)
4603{
4604 cdk_window_invalidate_maybe_recurse_full (window, region,
4605 (gboolean (*) (CdkWindow *, gpointer))cdk_window_has_no_impl,
4606 NULL((void*)0));
4607}
4608
4609
4610/**
4611 * cdk_window_get_update_area:
4612 * @window: a #CdkWindow
4613 *
4614 * Transfers ownership of the update area from @window to the caller
4615 * of the function. That is, after calling this function, @window will
4616 * no longer have an invalid/dirty region; the update area is removed
4617 * from @window and handed to you. If a window has no update area,
4618 * cdk_window_get_update_area() returns %NULL. You are responsible for
4619 * calling cairo_region_destroy() on the returned region if it’s non-%NULL.
4620 *
4621 * Returns: the update area for @window
4622 **/
4623cairo_region_t *
4624cdk_window_get_update_area (CdkWindow *window)
4625{
4626 CdkWindow *impl_window;
4627 cairo_region_t *tmp_region, *to_remove;
4628
4629 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
4630
4631 impl_window = cdk_window_get_impl_window (window);
4632
4633 if (impl_window->update_area)
4634 {
4635 tmp_region = cairo_region_copy (window->clip_region);
4636 /* Convert to impl coords */
4637 cairo_region_translate (tmp_region, window->abs_x, window->abs_y);
4638 cairo_region_intersect (tmp_region, impl_window->update_area);
4639
4640 if (cairo_region_is_empty (tmp_region))
4641 {
4642 cairo_region_destroy (tmp_region);
4643 return NULL((void*)0);
4644 }
4645 else
4646 {
4647 /* Convert from impl coords */
4648 cairo_region_translate (tmp_region, -window->abs_x, -window->abs_y);
4649
4650 /* Don't remove any update area that is overlapped by sibling windows
4651 or child windows as these really need to be repainted independently of this window. */
4652 to_remove = cairo_region_copy (tmp_region);
4653
4654 remove_child_area (window, FALSE(0), to_remove);
4655 remove_sibling_overlapped_area (window, to_remove);
4656
4657 /* Remove from update_area */
4658 cairo_region_translate (to_remove, window->abs_x, window->abs_y);
4659 cairo_region_subtract (impl_window->update_area, to_remove);
4660
4661 cairo_region_destroy (to_remove);
4662
4663 if (cairo_region_is_empty (impl_window->update_area))
4664 {
4665 cairo_region_destroy (impl_window->update_area);
4666 impl_window->update_area = NULL((void*)0);
4667
4668 cdk_window_remove_update_window ((CdkWindow *)impl_window);
4669 }
4670
4671 return tmp_region;
4672 }
4673 }
4674 else
4675 return NULL((void*)0);
4676}
4677
4678/**
4679 * _cdk_window_clear_update_area:
4680 * @window: a #CdkWindow.
4681 *
4682 * Internal function to clear the update area for a window. This
4683 * is called when the window is hidden or destroyed.
4684 **/
4685void
4686_cdk_window_clear_update_area (CdkWindow *window)
4687{
4688 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
4689
4690 if (window->update_area)
4691 {
4692 cdk_window_remove_update_window (window);
4693
4694 cairo_region_destroy (window->update_area);
4695 window->update_area = NULL((void*)0);
4696 }
4697}
4698
4699/**
4700 * cdk_window_freeze_updates:
4701 * @window: a #CdkWindow
4702 *
4703 * Temporarily freezes a window such that it won’t receive expose
4704 * events. The window will begin receiving expose events again when
4705 * cdk_window_thaw_updates() is called. If cdk_window_freeze_updates()
4706 * has been called more than once, cdk_window_thaw_updates() must be called
4707 * an equal number of times to begin processing exposes.
4708 **/
4709void
4710cdk_window_freeze_updates (CdkWindow *window)
4711{
4712 CdkWindow *impl_window;
4713
4714 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
4715
4716 impl_window = cdk_window_get_impl_window (window);
4717 impl_window->update_freeze_count++;
4718}
4719
4720/**
4721 * cdk_window_thaw_updates:
4722 * @window: a #CdkWindow
4723 *
4724 * Thaws a window frozen with cdk_window_freeze_updates().
4725 **/
4726void
4727cdk_window_thaw_updates (CdkWindow *window)
4728{
4729 CdkWindow *impl_window;
4730
4731 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
4732
4733 impl_window = cdk_window_get_impl_window (window);
4734
4735 g_return_if_fail (impl_window->update_freeze_count > 0)do { if ((impl_window->update_freeze_count > 0)) { } else
{ g_return_if_fail_warning ("Cdk", ((const char*) (__func__)
), "impl_window->update_freeze_count > 0"); return; } }
while (0)
;
4736
4737 if (--impl_window->update_freeze_count == 0)
4738 cdk_window_schedule_update (CDK_WINDOW (impl_window)((((CdkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((impl_window)), ((cdk_window_get_type ()))))))
);
4739}
4740
4741/**
4742 * cdk_window_freeze_toplevel_updates_libctk_only:
4743 * @window: a #CdkWindow
4744 *
4745 * Temporarily freezes a window and all its descendants such that it won't
4746 * receive expose events. The window will begin receiving expose events
4747 * again when cdk_window_thaw_toplevel_updates_libctk_only() is called. If
4748 * cdk_window_freeze_toplevel_updates_libctk_only()
4749 * has been called more than once,
4750 * cdk_window_thaw_toplevel_updates_libctk_only() must be called
4751 * an equal number of times to begin processing exposes.
4752 *
4753 * This function is not part of the CDK public API and is only
4754 * for use by CTK+.
4755 *
4756 * Deprecated: 3.16: This symbol was never meant to be used outside of CTK+
4757 */
4758void
4759cdk_window_freeze_toplevel_updates_libctk_only (CdkWindow *window)
4760{
4761 cdk_window_freeze_toplevel_updates (window);
4762}
4763
4764void
4765cdk_window_freeze_toplevel_updates (CdkWindow *window)
4766{
4767 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
4768 g_return_if_fail (window->window_type != CDK_WINDOW_CHILD)do { if ((window->window_type != CDK_WINDOW_CHILD)) { } else
{ g_return_if_fail_warning ("Cdk", ((const char*) (__func__)
), "window->window_type != CDK_WINDOW_CHILD"); return; } }
while (0)
;
4769
4770 window->update_and_descendants_freeze_count++;
4771 _cdk_frame_clock_freeze (cdk_window_get_frame_clock (window));
4772}
4773
4774/**
4775 * cdk_window_thaw_toplevel_updates_libctk_only:
4776 * @window: a #CdkWindow
4777 *
4778 * Thaws a window frozen with
4779 * cdk_window_freeze_toplevel_updates_libctk_only().
4780 *
4781 * This function is not part of the CDK public API and is only
4782 * for use by CTK+.
4783 *
4784 * Deprecated: 3.16: This symbol was never meant to be used outside of CTK+
4785 */
4786void
4787cdk_window_thaw_toplevel_updates_libctk_only (CdkWindow *window)
4788{
4789 cdk_window_thaw_toplevel_updates (window);
4790}
4791
4792void
4793cdk_window_thaw_toplevel_updates (CdkWindow *window)
4794{
4795 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
4796 g_return_if_fail (window->window_type != CDK_WINDOW_CHILD)do { if ((window->window_type != CDK_WINDOW_CHILD)) { } else
{ g_return_if_fail_warning ("Cdk", ((const char*) (__func__)
), "window->window_type != CDK_WINDOW_CHILD"); return; } }
while (0)
;
4797 g_return_if_fail (window->update_and_descendants_freeze_count > 0)do { if ((window->update_and_descendants_freeze_count >
0)) { } else { g_return_if_fail_warning ("Cdk", ((const char
*) (__func__)), "window->update_and_descendants_freeze_count > 0"
); return; } } while (0)
;
4798
4799 window->update_and_descendants_freeze_count--;
4800 _cdk_frame_clock_thaw (cdk_window_get_frame_clock (window));
4801
4802 cdk_window_schedule_update (window);
4803}
4804
4805/**
4806 * cdk_window_set_debug_updates:
4807 * @setting: %TRUE to turn on update debugging
4808 *
4809 * With update debugging enabled, calls to
4810 * cdk_window_invalidate_region() clear the invalidated region of the
4811 * screen to a noticeable color, and CDK pauses for a short time
4812 * before sending exposes to windows during
4813 * cdk_window_process_updates(). The net effect is that you can see
4814 * the invalid region for each window and watch redraws as they
4815 * occur. This allows you to diagnose inefficiencies in your application.
4816 *
4817 * In essence, because the CDK rendering model prevents all flicker,
4818 * if you are redrawing the same region 400 times you may never
4819 * notice, aside from noticing a speed problem. Enabling update
4820 * debugging causes CTK to flicker slowly and noticeably, so you can
4821 * see exactly what’s being redrawn when, in what order.
4822 *
4823 * The --ctk-debug=updates command line option passed to CTK+ programs
4824 * enables this debug option at application startup time. That's
4825 * usually more useful than calling cdk_window_set_debug_updates()
4826 * yourself, though you might want to use this function to enable
4827 * updates sometime after application startup time.
4828 */
4829void
4830cdk_window_set_debug_updates (gboolean setting)
4831{
4832 _cdk_debug_updates = setting;
4833}
4834
4835/**
4836 * cdk_window_constrain_size:
4837 * @geometry: a #CdkGeometry structure
4838 * @flags: a mask indicating what portions of @geometry are set
4839 * @width: desired width of window
4840 * @height: desired height of the window
4841 * @new_width: (out): location to store resulting width
4842 * @new_height: (out): location to store resulting height
4843 *
4844 * Constrains a desired width and height according to a
4845 * set of geometry hints (such as minimum and maximum size).
4846 */
4847void
4848cdk_window_constrain_size (CdkGeometry *geometry,
4849 CdkWindowHints flags,
4850 gint width,
4851 gint height,
4852 gint *new_width,
4853 gint *new_height)
4854{
4855 /* This routine is partially borrowed from fvwm.
4856 *
4857 * Copyright 1993, Robert Nation
4858 * You may use this code for any purpose, as long as the original
4859 * copyright remains in the source code and all documentation
4860 *
4861 * which in turn borrows parts of the algorithm from uwm
4862 */
4863 gint min_width = 0;
4864 gint min_height = 0;
4865 gint base_width = 0;
4866 gint base_height = 0;
4867 gint xinc = 1;
4868 gint yinc = 1;
4869 gint max_width = G_MAXINT2147483647;
4870 gint max_height = G_MAXINT2147483647;
4871
4872#define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
4873
4874 if ((flags & CDK_HINT_BASE_SIZE) && (flags & CDK_HINT_MIN_SIZE))
4875 {
4876 base_width = geometry->base_width;
4877 base_height = geometry->base_height;
4878 min_width = geometry->min_width;
4879 min_height = geometry->min_height;
4880 }
4881 else if (flags & CDK_HINT_BASE_SIZE)
4882 {
4883 base_width = geometry->base_width;
4884 base_height = geometry->base_height;
4885 min_width = geometry->base_width;
4886 min_height = geometry->base_height;
4887 }
4888 else if (flags & CDK_HINT_MIN_SIZE)
4889 {
4890 base_width = geometry->min_width;
4891 base_height = geometry->min_height;
4892 min_width = geometry->min_width;
4893 min_height = geometry->min_height;
4894 }
4895
4896 if (flags & CDK_HINT_MAX_SIZE)
4897 {
4898 max_width = geometry->max_width ;
4899 max_height = geometry->max_height;
4900 }
4901
4902 if (flags & CDK_HINT_RESIZE_INC)
4903 {
4904 xinc = MAX (xinc, geometry->width_inc)(((xinc) > (geometry->width_inc)) ? (xinc) : (geometry->
width_inc))
;
4905 yinc = MAX (yinc, geometry->height_inc)(((yinc) > (geometry->height_inc)) ? (yinc) : (geometry
->height_inc))
;
4906 }
4907
4908 /* clamp width and height to min and max values
4909 */
4910 width = CLAMP (width, min_width, max_width)(((width) > (max_width)) ? (max_width) : (((width) < (min_width
)) ? (min_width) : (width)))
;
4911 height = CLAMP (height, min_height, max_height)(((height) > (max_height)) ? (max_height) : (((height) <
(min_height)) ? (min_height) : (height)))
;
4912
4913 /* shrink to base + N * inc
4914 */
4915 width = base_width + FLOOR (width - base_width, xinc);
4916 height = base_height + FLOOR (height - base_height, yinc);
4917
4918 /* constrain aspect ratio, according to:
4919 *
4920 * width
4921 * min_aspect <= -------- <= max_aspect
4922 * height
4923 */
4924
4925 if (flags & CDK_HINT_ASPECT &&
4926 geometry->min_aspect > 0 &&
4927 geometry->max_aspect > 0)
4928 {
4929 gint delta;
4930
4931 if (geometry->min_aspect * height > width)
4932 {
4933 delta = FLOOR (height - width / geometry->min_aspect, yinc);
4934 if (height - delta >= min_height)
4935 height -= delta;
4936 else
4937 {
4938 delta = FLOOR (height * geometry->min_aspect - width, xinc);
4939 if (width + delta <= max_width)
4940 width += delta;
4941 }
4942 }
4943
4944 if (geometry->max_aspect * height < width)
4945 {
4946 delta = FLOOR (width - height * geometry->max_aspect, xinc);
4947 if (width - delta >= min_width)
4948 width -= delta;
4949 else
4950 {
4951 delta = FLOOR (width / geometry->max_aspect - height, yinc);
4952 if (height + delta <= max_height)
4953 height += delta;
4954 }
4955 }
4956 }
4957
4958#undef FLOOR
4959
4960 *new_width = width;
4961 *new_height = height;
4962}
4963
4964/**
4965 * cdk_window_get_pointer:
4966 * @window: a #CdkWindow
4967 * @x: (out) (allow-none): return location for X coordinate of pointer or %NULL to not
4968 * return the X coordinate
4969 * @y: (out) (allow-none): return location for Y coordinate of pointer or %NULL to not
4970 * return the Y coordinate
4971 * @mask: (out) (allow-none): return location for modifier mask or %NULL to not return the
4972 * modifier mask
4973 *
4974 * Obtains the current pointer position and modifier state.
4975 * The position is given in coordinates relative to the upper left
4976 * corner of @window.
4977 *
4978 * Returns: (nullable) (transfer none): the window containing the
4979 * pointer (as with cdk_window_at_pointer()), or %NULL if the window
4980 * containing the pointer isn’t known to CDK
4981 **/
4982CdkWindow*
4983cdk_window_get_pointer (CdkWindow *window,
4984 gint *x,
4985 gint *y,
4986 CdkModifierType *mask)
4987{
4988 CdkDisplay *display;
4989 CdkDevice *pointer;
4990
4991 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
4992
4993 display = cdk_window_get_display (window);
4994 pointer = cdk_seat_get_pointer (cdk_display_get_default_seat (display));
4995
4996 return cdk_window_get_device_position (window, pointer, x, y, mask);
4997}
4998
4999/**
5000 * cdk_window_get_device_position_double:
5001 * @window: a #CdkWindow.
5002 * @device: pointer #CdkDevice to query to.
5003 * @x: (out) (allow-none): return location for the X coordinate of @device, or %NULL.
5004 * @y: (out) (allow-none): return location for the Y coordinate of @device, or %NULL.
5005 * @mask: (out) (allow-none): return location for the modifier mask, or %NULL.
5006 *
5007 * Obtains the current device position in doubles and modifier state.
5008 * The position is given in coordinates relative to the upper left
5009 * corner of @window.
5010 *
5011 * Returns: (nullable) (transfer none): The window underneath @device
5012 * (as with cdk_device_get_window_at_position()), or %NULL if the
5013 * window is not known to CDK.
5014 *
5015 * Since: 3.10
5016 **/
5017CdkWindow *
5018cdk_window_get_device_position_double (CdkWindow *window,
5019 CdkDevice *device,
5020 double *x,
5021 double *y,
5022 CdkModifierType *mask)
5023{
5024 gdouble tmp_x, tmp_y;
5025 CdkModifierType tmp_mask;
5026 gboolean normal_child;
5027
5028 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
5029 g_return_val_if_fail (CDK_IS_DEVICE (device), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((device)); GType __t = ((cdk_device_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_DEVICE (device)"); return (((void*)0)); } } while
(0)
;
5030 g_return_val_if_fail (cdk_device_get_source (device) != CDK_SOURCE_KEYBOARD, NULL)do { if ((cdk_device_get_source (device) != CDK_SOURCE_KEYBOARD
)) { } else { g_return_if_fail_warning ("Cdk", ((const char*)
(__func__)), "cdk_device_get_source (device) != CDK_SOURCE_KEYBOARD"
); return (((void*)0)); } } while (0)
;
5031
5032 tmp_x = tmp_y = 0;
5033 tmp_mask = 0;
5034 normal_child = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->get_device_state (window,
5035 device,
5036 &tmp_x, &tmp_y,
5037 &tmp_mask);
5038 /* We got the coords on the impl, convert to the window */
5039 tmp_x -= window->abs_x;
5040 tmp_y -= window->abs_y;
5041
5042 if (x)
5043 *x = tmp_x;
5044 if (y)
5045 *y = tmp_y;
5046 if (mask)
5047 *mask = tmp_mask;
5048
5049 _cdk_display_enable_motion_hints (cdk_window_get_display (window), device);
5050
5051 if (normal_child)
5052 return _cdk_window_find_child_at (window, tmp_x, tmp_y);
5053 return NULL((void*)0);
5054}
5055
5056/**
5057 * cdk_window_get_device_position:
5058 * @window: a #CdkWindow.
5059 * @device: pointer #CdkDevice to query to.
5060 * @x: (out) (allow-none): return location for the X coordinate of @device, or %NULL.
5061 * @y: (out) (allow-none): return location for the Y coordinate of @device, or %NULL.
5062 * @mask: (out) (allow-none): return location for the modifier mask, or %NULL.
5063 *
5064 * Obtains the current device position and modifier state.
5065 * The position is given in coordinates relative to the upper left
5066 * corner of @window.
5067 *
5068 * Use cdk_window_get_device_position_double() if you need subpixel precision.
5069 *
5070 * Returns: (nullable) (transfer none): The window underneath @device
5071 * (as with cdk_device_get_window_at_position()), or %NULL if the
5072 * window is not known to CDK.
5073 *
5074 * Since: 3.0
5075 **/
5076CdkWindow *
5077cdk_window_get_device_position (CdkWindow *window,
5078 CdkDevice *device,
5079 gint *x,
5080 gint *y,
5081 CdkModifierType *mask)
5082{
5083 gdouble tmp_x, tmp_y;
5084
5085 window = cdk_window_get_device_position_double (window, device,
5086 &tmp_x, &tmp_y, mask);
5087 if (x)
5088 *x = round (tmp_x);
5089 if (y)
5090 *y = round (tmp_y);
5091
5092 return window;
5093}
5094
5095/**
5096 * cdk_window_at_pointer:
5097 * @win_x: (out) (allow-none): return location for origin of the window under the pointer
5098 * @win_y: (out) (allow-none): return location for origin of the window under the pointer
5099 *
5100 * Obtains the window underneath the mouse pointer, returning the
5101 * location of that window in @win_x, @win_y. Returns %NULL if the
5102 * window under the mouse pointer is not known to CDK (if the window
5103 * belongs to another application and a #CdkWindow hasn’t been created
5104 * for it with cdk_window_foreign_new())
5105 *
5106 * NOTE: For multihead-aware widgets or applications use
5107 * cdk_display_get_window_at_pointer() instead.
5108 *
5109 * Returns: (transfer none): window under the mouse pointer
5110 **/
5111CdkWindow*
5112cdk_window_at_pointer (gint *win_x,
5113 gint *win_y)
5114{
5115 return cdk_display_get_window_at_pointer (cdk_display_get_default (), win_x, win_y);
5116}
5117
5118/**
5119 * cdk_get_default_root_window:
5120 *
5121 * Obtains the root window (parent all other windows are inside)
5122 * for the default display and screen.
5123 *
5124 * Returns: (transfer none): the default root window
5125 **/
5126CdkWindow *
5127cdk_get_default_root_window (void)
5128{
5129 return cdk_screen_get_root_window (cdk_screen_get_default ());
5130}
5131
5132static void
5133get_all_native_children (CdkWindow *window,
5134 GList **native)
5135{
5136 CdkWindow *child;
5137 GList *l;
5138
5139 for (l = window->children; l != NULL((void*)0); l = l->next)
5140 {
5141 child = l->data;
5142
5143 if (cdk_window_has_impl (child))
5144 *native = g_list_prepend (*native, child);
5145 else
5146 get_all_native_children (child, native);
5147 }
5148}
5149
5150
5151static gboolean
5152cdk_window_raise_internal (CdkWindow *window)
5153{
5154 CdkWindow *parent = window->parent;
5155 CdkWindow *above;
5156 GList *native_children;
5157 GList *l, listhead;
5158 CdkWindowImplClass *impl_class;
5159 gboolean did_raise = FALSE(0);
5160
5161 if (parent && parent->children->data != window)
5162 {
5163 parent->children = g_list_remove_link (parent->children, &window->children_list_node);
5164 parent->children = g_list_concat (&window->children_list_node, parent->children);
5165 did_raise = TRUE(!(0));
5166 }
5167
5168 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
5169 /* Just do native raise for toplevels */
5170 if (cdk_window_is_toplevel (window) ||
5171 /* The restack_under codepath should work correctly even if the parent
5172 is native, but it relies on the order of ->children to be correct,
5173 and some apps like SWT reorder the x windows without cdks knowledge,
5174 so we use raise directly in order to make these behave as before
5175 when using native windows */
5176 (cdk_window_has_impl (window) && cdk_window_has_impl (parent)))
5177 {
5178 impl_class->raise (window);
5179 }
5180 else if (cdk_window_has_impl (window))
5181 {
5182 above = find_native_sibling_above (parent, window);
5183 if (above)
5184 {
5185 listhead.data = window;
5186 listhead.next = NULL((void*)0);
5187 listhead.prev = NULL((void*)0);
5188 impl_class->restack_under ((CdkWindow *)above,
5189 &listhead);
5190 }
5191 else
5192 impl_class->raise (window);
5193 }
5194 else
5195 {
5196 native_children = NULL((void*)0);
5197 get_all_native_children (window, &native_children);
5198 if (native_children != NULL((void*)0))
5199 {
5200 above = find_native_sibling_above (parent, window);
5201
5202 if (above)
5203 impl_class->restack_under (above, native_children);
5204 else
5205 {
5206 /* Right order, since native_children is bottom-topmost first */
5207 for (l = native_children; l != NULL((void*)0); l = l->next)
5208 impl_class->raise (l->data);
5209 }
5210
5211 g_list_free (native_children);
5212 }
5213 }
5214
5215 return did_raise;
5216}
5217
5218/* Returns TRUE If the native window was mapped or unmapped */
5219static gboolean
5220set_viewable (CdkWindow *w,
5221 gboolean val)
5222{
5223 CdkWindow *child;
5224 CdkWindowImplClass *impl_class;
5225 GList *l;
5226
5227 if (w->viewable == val)
5228 return FALSE(0);
5229
5230 w->viewable = val;
5231
5232 if (val)
5233 recompute_visible_regions (w, FALSE(0));
5234
5235 for (l = w->children; l != NULL((void*)0); l = l->next)
5236 {
5237 child = l->data;
5238
5239 if (CDK_WINDOW_IS_MAPPED (child)(((child)->state & CDK_WINDOW_STATE_WITHDRAWN) == 0) &&
5240 child->window_type != CDK_WINDOW_FOREIGN)
5241 set_viewable (child, val);
5242 }
5243
5244 if (cdk_window_has_impl (w) &&
5245 w->window_type != CDK_WINDOW_FOREIGN &&
5246 !cdk_window_is_toplevel (w))
5247 {
5248 /* For most native windows we show/hide them not when they are
5249 * mapped/unmapped, because that may not produce the correct results.
5250 * For instance, if a native window have a non-native parent which is
5251 * hidden, but its native parent is viewable then showing the window
5252 * would make it viewable to X but its not viewable wrt the non-native
5253 * hierarchy. In order to handle this we track the cdk side viewability
5254 * and only map really viewable windows.
5255 *
5256 * There are two exceptions though:
5257 *
5258 * For foreign windows we don't want ever change the mapped state
5259 * except when explicitly done via cdk_window_show/hide, as this may
5260 * cause problems for client owning the foreign window when its window
5261 * is suddenly mapped or unmapped.
5262 *
5263 * For toplevel windows embedded in a foreign window (e.g. a plug)
5264 * we sometimes synthesize a map of a window, but the native
5265 * window is really shown by the embedder, so we don't want to
5266 * do the show ourselves. We can't really tell this case from the normal
5267 * toplevel show as such toplevels are seen by cdk as parents of the
5268 * root window, so we make an exception for all toplevels.
5269 */
5270
5271 impl_class = CDK_WINDOW_IMPL_GET_CLASS (w->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((w->impl)))->
g_class))))
;
5272 if (val)
5273 impl_class->show ((CdkWindow *)w, FALSE(0));
5274 else
5275 impl_class->hide ((CdkWindow *)w);
5276
5277 return TRUE(!(0));
5278 }
5279
5280 return FALSE(0);
5281}
5282
5283/* Returns TRUE If the native window was mapped or unmapped */
5284gboolean
5285_cdk_window_update_viewable (CdkWindow *window)
5286{
5287 gboolean viewable;
5288
5289 if (window->window_type == CDK_WINDOW_FOREIGN ||
5290 window->window_type == CDK_WINDOW_ROOT)
5291 viewable = TRUE(!(0));
5292 else if (cdk_window_is_toplevel (window) ||
5293 window->parent->viewable)
5294 viewable = CDK_WINDOW_IS_MAPPED (window)(((window)->state & CDK_WINDOW_STATE_WITHDRAWN) == 0);
5295 else
5296 viewable = FALSE(0);
5297
5298 return set_viewable (window, viewable);
5299}
5300
5301static void
5302cdk_window_show_internal (CdkWindow *window, gboolean raise)
5303{
5304 CdkWindowImplClass *impl_class;
5305 gboolean was_mapped, was_viewable;
5306 gboolean did_show, did_raise = FALSE(0);
5307
5308 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
5309
5310 if (window->destroyed)
5311 return;
5312
5313 was_mapped = CDK_WINDOW_IS_MAPPED (window)(((window)->state & CDK_WINDOW_STATE_WITHDRAWN) == 0);
5314 was_viewable = window->viewable;
5315
5316 if (raise)
5317 {
5318 /* Keep children in (reverse) stacking order */
5319 did_raise = cdk_window_raise_internal (window);
5320 }
5321
5322 if (cdk_window_has_impl (window))
5323 {
5324 if (!was_mapped)
5325 cdk_synthesize_window_state (window,
5326 CDK_WINDOW_STATE_WITHDRAWN,
5327 CDK_WINDOW_STATE_FOCUSED);
5328 }
5329 else
5330 {
5331 window->state = 0;
5332 }
5333
5334 did_show = _cdk_window_update_viewable (window);
5335
5336 /* If it was already viewable the backend show op won't be called, call it
5337 again to ensure things happen right if the mapped tracking was not right
5338 for e.g. a foreign window.
5339 Dunno if this is strictly needed but its what happened pre-csw.
5340 Also show if not done by cdk_window_update_viewable. */
5341 if (cdk_window_has_impl (window) && (was_viewable || !did_show))
5342 {
5343 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
5344 impl_class->show (window, !did_show ? was_mapped : TRUE(!(0)));
5345 }
5346
5347 if (!was_mapped && !cdk_window_has_impl (window))
5348 {
5349 if (window->event_mask & CDK_STRUCTURE_MASK)
5350 _cdk_make_event (window, CDK_MAP, NULL((void*)0), FALSE(0));
5351
5352 if (window->parent && window->parent->event_mask & CDK_SUBSTRUCTURE_MASK)
5353 _cdk_make_event (window, CDK_MAP, NULL((void*)0), FALSE(0));
5354 }
5355
5356 if (!was_mapped || did_raise)
5357 {
5358 recompute_visible_regions (window, FALSE(0));
5359
5360 /* If any decendants became visible we need to send visibility notify */
5361 cdk_window_update_visibility_recursively (window, NULL((void*)0));
5362
5363 if (cdk_window_is_viewable (window))
5364 {
5365 _cdk_synthesize_crossing_events_for_geometry_change (window);
5366 cdk_window_invalidate_rect_full (window, NULL((void*)0), TRUE(!(0)));
5367 }
5368 }
5369}
5370
5371/**
5372 * cdk_window_show_unraised:
5373 * @window: a #CdkWindow
5374 *
5375 * Shows a #CdkWindow onscreen, but does not modify its stacking
5376 * order. In contrast, cdk_window_show() will raise the window
5377 * to the top of the window stack.
5378 *
5379 * On the X11 platform, in Xlib terms, this function calls
5380 * XMapWindow() (it also updates some internal CDK state, which means
5381 * that you can’t really use XMapWindow() directly on a CDK window).
5382 */
5383void
5384cdk_window_show_unraised (CdkWindow *window)
5385{
5386 cdk_window_show_internal (window, FALSE(0));
5387}
5388
5389/**
5390 * cdk_window_raise:
5391 * @window: a #CdkWindow
5392 *
5393 * Raises @window to the top of the Z-order (stacking order), so that
5394 * other windows with the same parent window appear below @window.
5395 * This is true whether or not the windows are visible.
5396 *
5397 * If @window is a toplevel, the window manager may choose to deny the
5398 * request to move the window in the Z-order, cdk_window_raise() only
5399 * requests the restack, does not guarantee it.
5400 */
5401void
5402cdk_window_raise (CdkWindow *window)
5403{
5404 gboolean did_raise;
5405
5406 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
5407
5408 if (window->destroyed)
5409 return;
5410
5411 /* Keep children in (reverse) stacking order */
5412 did_raise = cdk_window_raise_internal (window);
5413
5414 if (did_raise &&
5415 !cdk_window_is_toplevel (window) &&
5416 cdk_window_is_viewable (window) &&
5417 !window->input_only)
5418 cdk_window_invalidate_region_full (window, window->clip_region, TRUE(!(0)));
5419}
5420
5421static void
5422cdk_window_lower_internal (CdkWindow *window)
5423{
5424 CdkWindow *parent = window->parent;
5425 CdkWindowImplClass *impl_class;
5426 CdkWindow *above;
5427 GList *native_children;
5428 GList *l, listhead;
5429
5430 if (parent)
5431 {
5432 parent->children = g_list_remove_link (parent->children, &window->children_list_node);
5433 parent->children = g_list_concat (parent->children, &window->children_list_node);
5434 }
5435
5436 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
5437 /* Just do native lower for toplevels */
5438 if (cdk_window_is_toplevel (window) ||
5439 /* The restack_under codepath should work correctly even if the parent
5440 is native, but it relies on the order of ->children to be correct,
5441 and some apps like SWT reorder the x windows without cdks knowledge,
5442 so we use lower directly in order to make these behave as before
5443 when using native windows */
5444 (cdk_window_has_impl (window) && cdk_window_has_impl (parent)))
5445 {
5446 impl_class->lower (window);
5447 }
5448 else if (cdk_window_has_impl (window))
5449 {
5450 above = find_native_sibling_above (parent, window);
5451 if (above)
5452 {
5453 listhead.data = window;
5454 listhead.next = NULL((void*)0);
5455 listhead.prev = NULL((void*)0);
5456 impl_class->restack_under ((CdkWindow *)above, &listhead);
5457 }
5458 else
5459 impl_class->raise (window);
5460 }
5461 else
5462 {
5463 native_children = NULL((void*)0);
5464 get_all_native_children (window, &native_children);
5465 if (native_children != NULL((void*)0))
5466 {
5467 above = find_native_sibling_above (parent, window);
5468
5469 if (above)
5470 impl_class->restack_under ((CdkWindow *)above,
5471 native_children);
5472 else
5473 {
5474 /* Right order, since native_children is bottom-topmost first */
5475 for (l = native_children; l != NULL((void*)0); l = l->next)
5476 impl_class->raise (l->data);
5477 }
5478
5479 g_list_free (native_children);
5480 }
5481
5482 }
5483}
5484
5485static void
5486cdk_window_invalidate_in_parent (CdkWindow *private)
5487{
5488 CdkRectangle r, child;
5489
5490 if (cdk_window_is_toplevel (private))
5491 return;
5492
5493 /* get the visible rectangle of the parent */
5494 r.x = r.y = 0;
5495 r.width = private->parent->width;
5496 r.height = private->parent->height;
5497
5498 child.x = private->x;
5499 child.y = private->y;
5500 child.width = private->width;
5501 child.height = private->height;
5502 cdk_rectangle_intersect (&r, &child, &r);
5503
5504 cdk_window_invalidate_rect_full (private->parent, &r, TRUE(!(0)));
5505}
5506
5507
5508/**
5509 * cdk_window_lower:
5510 * @window: a #CdkWindow
5511 *
5512 * Lowers @window to the bottom of the Z-order (stacking order), so that
5513 * other windows with the same parent window appear above @window.
5514 * This is true whether or not the other windows are visible.
5515 *
5516 * If @window is a toplevel, the window manager may choose to deny the
5517 * request to move the window in the Z-order, cdk_window_lower() only
5518 * requests the restack, does not guarantee it.
5519 *
5520 * Note that cdk_window_show() raises the window again, so don’t call this
5521 * function before cdk_window_show(). (Try cdk_window_show_unraised().)
5522 */
5523void
5524cdk_window_lower (CdkWindow *window)
5525{
5526 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
5527
5528 if (window->destroyed)
5529 return;
5530
5531 /* Keep children in (reverse) stacking order */
5532 cdk_window_lower_internal (window);
5533
5534 _cdk_synthesize_crossing_events_for_geometry_change (window);
5535 cdk_window_invalidate_in_parent (window);
5536}
5537
5538/**
5539 * cdk_window_restack:
5540 * @window: a #CdkWindow
5541 * @sibling: (allow-none): a #CdkWindow that is a sibling of @window, or %NULL
5542 * @above: a boolean
5543 *
5544 * Changes the position of @window in the Z-order (stacking order), so that
5545 * it is above @sibling (if @above is %TRUE) or below @sibling (if @above is
5546 * %FALSE).
5547 *
5548 * If @sibling is %NULL, then this either raises (if @above is %TRUE) or
5549 * lowers the window.
5550 *
5551 * If @window is a toplevel, the window manager may choose to deny the
5552 * request to move the window in the Z-order, cdk_window_restack() only
5553 * requests the restack, does not guarantee it.
5554 *
5555 * Since: 2.18
5556 */
5557void
5558cdk_window_restack (CdkWindow *window,
5559 CdkWindow *sibling,
5560 gboolean above)
5561{
5562 CdkWindowImplClass *impl_class;
5563 CdkWindow *parent;
5564 CdkWindow *above_native;
5565 GList *sibling_link;
5566 GList *native_children;
5567 GList *l, listhead;
5568
5569 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
5570 g_return_if_fail (sibling == NULL || CDK_IS_WINDOW (sibling))do { if ((sibling == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((sibling)); GType __t = ((cdk_window_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Cdk", ((const
char*) (__func__)), "sibling == NULL || CDK_IS_WINDOW (sibling)"
); return; } } while (0)
;
5571
5572 if (window->destroyed)
5573 return;
5574
5575 if (sibling == NULL((void*)0))
5576 {
5577 if (above)
5578 cdk_window_raise (window);
5579 else
5580 cdk_window_lower (window);
5581 return;
5582 }
5583
5584 if (cdk_window_is_toplevel (window))
5585 {
5586 g_return_if_fail (cdk_window_is_toplevel (sibling))do { if ((cdk_window_is_toplevel (sibling))) { } else { g_return_if_fail_warning
("Cdk", ((const char*) (__func__)), "cdk_window_is_toplevel (sibling)"
); return; } } while (0)
;
5587 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
5588 impl_class->restack_toplevel (window, sibling, above);
5589 return;
5590 }
5591
5592 parent = window->parent;
5593 if (parent)
5594 {
5595 sibling_link = g_list_find (parent->children, sibling);
5596 g_return_if_fail (sibling_link != NULL)do { if ((sibling_link != ((void*)0))) { } else { g_return_if_fail_warning
("Cdk", ((const char*) (__func__)), "sibling_link != NULL");
return; } } while (0)
;
5597 if (sibling_link == NULL((void*)0))
5598 return;
5599
5600 parent->children = g_list_remove_link (parent->children, &window->children_list_node);
5601 if (above)
5602 parent->children = list_insert_link_before (parent->children,
5603 sibling_link,
5604 &window->children_list_node);
5605 else
5606 parent->children = list_insert_link_before (parent->children,
5607 sibling_link->next,
5608 &window->children_list_node);
5609
5610 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
5611 if (cdk_window_has_impl (window))
5612 {
5613 above_native = find_native_sibling_above (parent, window);
5614 if (above_native)
5615 {
5616 listhead.data = window;
5617 listhead.next = NULL((void*)0);
5618 listhead.prev = NULL((void*)0);
5619 impl_class->restack_under (above_native, &listhead);
5620 }
5621 else
5622 impl_class->raise (window);
5623 }
5624 else
5625 {
5626 native_children = NULL((void*)0);
5627 get_all_native_children (window, &native_children);
5628 if (native_children != NULL((void*)0))
5629 {
5630 above_native = find_native_sibling_above (parent, window);
5631 if (above_native)
5632 impl_class->restack_under (above_native,
5633 native_children);
5634 else
5635 {
5636 /* Right order, since native_children is bottom-topmost first */
5637 for (l = native_children; l != NULL((void*)0); l = l->next)
5638 impl_class->raise (l->data);
5639 }
5640
5641 g_list_free (native_children);
5642 }
5643 }
5644 }
5645
5646 _cdk_synthesize_crossing_events_for_geometry_change (window);
5647 cdk_window_invalidate_in_parent (window);
5648}
5649
5650
5651/**
5652 * cdk_window_show:
5653 * @window: a #CdkWindow
5654 *
5655 * Like cdk_window_show_unraised(), but also raises the window to the
5656 * top of the window stack (moves the window to the front of the
5657 * Z-order).
5658 *
5659 * This function maps a window so it’s visible onscreen. Its opposite
5660 * is cdk_window_hide().
5661 *
5662 * When implementing a #CtkWidget, you should call this function on the widget's
5663 * #CdkWindow as part of the “map” method.
5664 */
5665void
5666cdk_window_show (CdkWindow *window)
5667{
5668 cdk_window_show_internal (window, TRUE(!(0)));
5669}
5670
5671/**
5672 * cdk_window_hide:
5673 * @window: a #CdkWindow
5674 *
5675 * For toplevel windows, withdraws them, so they will no longer be
5676 * known to the window manager; for all windows, unmaps them, so
5677 * they won’t be displayed. Normally done automatically as
5678 * part of ctk_widget_hide().
5679 */
5680void
5681cdk_window_hide (CdkWindow *window)
5682{
5683 CdkWindowImplClass *impl_class;
5684 gboolean was_mapped, did_hide;
5685
5686 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
5687
5688 if (window->destroyed)
5689 return;
5690
5691 was_mapped = CDK_WINDOW_IS_MAPPED (window)(((window)->state & CDK_WINDOW_STATE_WITHDRAWN) == 0);
5692
5693 if (cdk_window_has_impl (window))
5694 {
5695
5696 if (CDK_WINDOW_IS_MAPPED (window)(((window)->state & CDK_WINDOW_STATE_WITHDRAWN) == 0))
5697 cdk_synthesize_window_state (window,
5698 0,
5699 CDK_WINDOW_STATE_WITHDRAWN);
5700 }
5701 else if (was_mapped)
5702 {
5703 CdkDisplay *display;
5704 CdkDeviceManager *device_manager;
5705 GList *devices, *d;
5706
5707 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
;
5708
5709 /* May need to break grabs on children */
5710 display = cdk_window_get_display (window);
5711 device_manager = cdk_display_get_device_manager (display);
5712
5713 /* Get all devices */
5714 devices = cdk_device_manager_list_devices (device_manager, CDK_DEVICE_TYPE_MASTER);
5715 devices = g_list_concat (devices, cdk_device_manager_list_devices (device_manager, CDK_DEVICE_TYPE_SLAVE));
5716 devices = g_list_concat (devices, cdk_device_manager_list_devices (device_manager, CDK_DEVICE_TYPE_FLOATING));
5717
5718 for (d = devices; d; d = d->next)
5719 {
5720 CdkDevice *device = d->data;
5721
5722 if (_cdk_display_end_device_grab (display,
5723 device,
5724 _cdk_display_get_next_serial (display),
5725 window,
5726 TRUE(!(0))))
5727 cdk_device_ungrab (device, CDK_CURRENT_TIME0L);
5728 }
5729
5730 window->state = CDK_WINDOW_STATE_WITHDRAWN;
5731 g_list_free (devices);
5732 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop ;
5733 }
5734
5735 did_hide = _cdk_window_update_viewable (window);
5736
5737 /* Hide foreign window as those are not handled by update_viewable. */
5738 if (cdk_window_has_impl (window) && (!did_hide))
5739 {
5740 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
5741 impl_class->hide (window);
5742 }
5743
5744 cdk_window_clear_old_updated_area (window);
5745 recompute_visible_regions (window, FALSE(0));
5746
5747 /* all decendants became non-visible, we need to send visibility notify */
5748 cdk_window_update_visibility_recursively (window, NULL((void*)0));
5749
5750 if (was_mapped && !cdk_window_has_impl (window))
5751 {
5752 if (window->event_mask & CDK_STRUCTURE_MASK)
5753 _cdk_make_event (window, CDK_UNMAP, NULL((void*)0), FALSE(0));
5754
5755 if (window->parent && window->parent->event_mask & CDK_SUBSTRUCTURE_MASK)
5756 _cdk_make_event (window, CDK_UNMAP, NULL((void*)0), FALSE(0));
5757
5758 _cdk_synthesize_crossing_events_for_geometry_change (window->parent);
5759 }
5760
5761 /* Invalidate the rect */
5762 if (was_mapped)
5763 cdk_window_invalidate_in_parent (window);
5764}
5765
5766/**
5767 * cdk_window_withdraw:
5768 * @window: a toplevel #CdkWindow
5769 *
5770 * Withdraws a window (unmaps it and asks the window manager to forget about it).
5771 * This function is not really useful as cdk_window_hide() automatically
5772 * withdraws toplevel windows before hiding them.
5773 **/
5774void
5775cdk_window_withdraw (CdkWindow *window)
5776{
5777 CdkWindowImplClass *impl_class;
5778 gboolean was_mapped;
5779 CdkGLContext *current_context;
5780
5781 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
5782
5783 if (window->destroyed)
5784 return;
5785
5786 was_mapped = CDK_WINDOW_IS_MAPPED (window)(((window)->state & CDK_WINDOW_STATE_WITHDRAWN) == 0);
5787
5788 if (cdk_window_has_impl (window))
5789 {
5790 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
5791 impl_class->withdraw (window);
5792
5793 if (was_mapped)
5794 {
5795 if (window->event_mask & CDK_STRUCTURE_MASK)
5796 _cdk_make_event (window, CDK_UNMAP, NULL((void*)0), FALSE(0));
5797
5798 if (window->parent && window->parent->event_mask & CDK_SUBSTRUCTURE_MASK)
5799 _cdk_make_event (window, CDK_UNMAP, NULL((void*)0), FALSE(0));
5800
5801 _cdk_synthesize_crossing_events_for_geometry_change (window->parent);
5802 }
5803
5804 current_context = cdk_gl_context_get_current ();
5805 if (current_context != NULL((void*)0) && cdk_gl_context_get_window (current_context) == window)
5806 cdk_gl_context_clear_current ();
5807
5808 recompute_visible_regions (window, FALSE(0));
5809 cdk_window_clear_old_updated_area (window);
5810 }
5811}
5812
5813/**
5814 * cdk_window_set_events:
5815 * @window: a #CdkWindow
5816 * @event_mask: event mask for @window
5817 *
5818 * The event mask for a window determines which events will be reported
5819 * for that window from all master input devices. For example, an event mask
5820 * including #CDK_BUTTON_PRESS_MASK means the window should report button
5821 * press events. The event mask is the bitwise OR of values from the
5822 * #CdkEventMask enumeration.
5823 *
5824 * See the [input handling overview][event-masks] for details.
5825 **/
5826void
5827cdk_window_set_events (CdkWindow *window,
5828 CdkEventMask event_mask)
5829{
5830 CdkWindowImplClass *impl_class;
5831 CdkDisplay *display;
5832
5833 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
5834
5835 if (window->destroyed)
5836 return;
5837
5838 /* If motion hint is disabled, enable motion events again */
5839 display = cdk_window_get_display (window);
5840 if ((window->event_mask & CDK_POINTER_MOTION_HINT_MASK) &&
5841 !(event_mask & CDK_POINTER_MOTION_HINT_MASK))
5842 {
5843 GList *devices = window->devices_inside;
5844
5845 while (devices)
5846 {
5847 _cdk_display_enable_motion_hints (display, (CdkDevice *) devices->data);
5848 devices = devices->next;
5849 }
5850 }
5851
5852 window->event_mask = event_mask;
5853
5854 if (cdk_window_has_impl (window))
5855 {
5856 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
5857 impl_class->set_events (window,
5858 get_native_event_mask (window));
5859 }
5860
5861}
5862
5863/**
5864 * cdk_window_get_events:
5865 * @window: a #CdkWindow
5866 *
5867 * Gets the event mask for @window for all master input devices. See
5868 * cdk_window_set_events().
5869 *
5870 * Returns: event mask for @window
5871 **/
5872CdkEventMask
5873cdk_window_get_events (CdkWindow *window)
5874{
5875 g_return_val_if_fail (CDK_IS_WINDOW (window), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (0); } } while (0)
;
5876
5877 if (window->destroyed)
5878 return 0;
5879
5880 return window->event_mask;
5881}
5882
5883/**
5884 * cdk_window_set_device_events:
5885 * @window: a #CdkWindow
5886 * @device: #CdkDevice to enable events for.
5887 * @event_mask: event mask for @window
5888 *
5889 * Sets the event mask for a given device (Normally a floating device, not
5890 * attached to any visible pointer) to @window. For example, an event mask
5891 * including #CDK_BUTTON_PRESS_MASK means the window should report button
5892 * press events. The event mask is the bitwise OR of values from the
5893 * #CdkEventMask enumeration.
5894 *
5895 * See the [input handling overview][event-masks] for details.
5896 *
5897 * Since: 3.0
5898 **/
5899void
5900cdk_window_set_device_events (CdkWindow *window,
5901 CdkDevice *device,
5902 CdkEventMask event_mask)
5903{
5904 CdkEventMask device_mask;
5905 CdkDisplay *display;
5906 CdkWindow *native;
5907
5908 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
5909 g_return_if_fail (CDK_IS_DEVICE (device))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((device)); GType __t = ((cdk_device_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_DEVICE (device)"); return; } } while (0)
;
5910
5911 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
5912 return;
5913
5914 /* If motion hint is disabled, enable motion events again */
5915 display = cdk_window_get_display (window);
5916 if ((window->event_mask & CDK_POINTER_MOTION_HINT_MASK) &&
5917 !(event_mask & CDK_POINTER_MOTION_HINT_MASK))
5918 _cdk_display_enable_motion_hints (display, device);
5919
5920 if (G_UNLIKELY (!window->device_events)(!window->device_events))
5921 window->device_events = g_hash_table_new (NULL((void*)0), NULL((void*)0));
5922
5923 if (event_mask == 0)
5924 {
5925 /* FIXME: unsetting events on a master device
5926 * would restore window->event_mask
5927 */
5928 g_hash_table_remove (window->device_events, device);
5929 }
5930 else
5931 g_hash_table_insert (window->device_events, device,
5932 GINT_TO_POINTER (event_mask)((gpointer) (glong) (event_mask)));
5933
5934 native = cdk_window_get_toplevel (window);
5935
5936 while (cdk_window_is_offscreen (native))
5937 {
5938 native = cdk_offscreen_window_get_embedder (native);
5939
5940 if (native == NULL((void*)0) ||
5941 (!_cdk_window_has_impl (native) &&
5942 !cdk_window_is_viewable (native)))
5943 return;
5944
5945 native = cdk_window_get_toplevel (native);
5946 }
5947
5948 device_mask = get_native_device_event_mask (window, device);
5949 CDK_DEVICE_GET_CLASS (device)((((CdkDeviceClass*) (((GTypeInstance*) ((device)))->g_class
))))
->select_window_events (device, native, device_mask);
5950}
5951
5952/**
5953 * cdk_window_get_device_events:
5954 * @window: a #CdkWindow.
5955 * @device: a #CdkDevice.
5956 *
5957 * Returns the event mask for @window corresponding to an specific device.
5958 *
5959 * Returns: device event mask for @window
5960 *
5961 * Since: 3.0
5962 **/
5963CdkEventMask
5964cdk_window_get_device_events (CdkWindow *window,
5965 CdkDevice *device)
5966{
5967 CdkEventMask mask;
5968
5969 g_return_val_if_fail (CDK_IS_WINDOW (window), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (0); } } while (0)
;
5970 g_return_val_if_fail (CDK_IS_DEVICE (device), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((device)); GType __t = ((cdk_device_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_DEVICE (device)"); return (0); } } while (0)
;
5971
5972 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
5973 return 0;
5974
5975 if (!window->device_events)
5976 return 0;
5977
5978 mask = GPOINTER_TO_INT (g_hash_table_lookup (window->device_events, device))((gint) (glong) (g_hash_table_lookup (window->device_events
, device)))
;
5979
5980 /* FIXME: device could be controlled by window->event_mask */
5981
5982 return mask;
5983}
5984
5985static void
5986cdk_window_move_resize_toplevel (CdkWindow *window,
5987 gboolean with_move,
5988 gint x,
5989 gint y,
5990 gint width,
5991 gint height)
5992{
5993 cairo_region_t *old_region, *new_region;
5994 CdkWindowImplClass *impl_class;
5995 gboolean expose;
5996 gboolean is_resize;
5997
5998 expose = FALSE(0);
5999 old_region = NULL((void*)0);
6000
6001 is_resize = (width != -1) || (height != -1);
6002
6003 if (cdk_window_is_viewable (window) &&
6004 !window->input_only)
6005 {
6006 expose = TRUE(!(0));
6007 old_region = cairo_region_copy (window->clip_region);
6008 }
6009
6010 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
6011 impl_class->move_resize (window, with_move, x, y, width, height);
6012
6013 /* Avoid recomputing for pure toplevel moves, for performance reasons */
6014 if (is_resize)
6015 recompute_visible_regions (window, FALSE(0));
6016
6017 if (expose)
6018 {
6019 new_region = cairo_region_copy (window->clip_region);
6020
6021 /* This is the newly exposed area (due to any resize),
6022 * X will expose it, but lets do that without the roundtrip
6023 */
6024 cairo_region_subtract (new_region, old_region);
6025 cdk_window_invalidate_region_full (window, new_region, TRUE(!(0)));
6026
6027 cairo_region_destroy (old_region);
6028 cairo_region_destroy (new_region);
6029 }
6030
6031 _cdk_synthesize_crossing_events_for_geometry_change (window);
6032}
6033
6034
6035static void
6036move_native_children (CdkWindow *private)
6037{
6038 GList *l;
6039 CdkWindow *child;
6040 CdkWindowImplClass *impl_class;
6041
6042 for (l = private->children; l; l = l->next)
6043 {
6044 child = l->data;
6045
6046 if (child->impl != private->impl)
6047 {
6048 impl_class = CDK_WINDOW_IMPL_GET_CLASS (child->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((child->impl)
))->g_class))))
;
6049 impl_class->move_resize (child, TRUE(!(0)),
6050 child->x, child->y,
6051 child->width, child->height);
6052 }
6053 else
6054 move_native_children (child);
6055 }
6056}
6057
6058static void
6059cdk_window_move_resize_internal (CdkWindow *window,
6060 gboolean with_move,
6061 gint x,
6062 gint y,
6063 gint width,
6064 gint height)
6065{
6066 cairo_region_t *old_region, *new_region;
6067 CdkWindowImplClass *impl_class;
6068 gboolean expose;
6069 int old_abs_x, old_abs_y;
6070
6071 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
6072
6073 if (window->destroyed)
6074 return;
6075
6076 if (cdk_window_is_toplevel (window))
6077 {
6078 cdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
6079 return;
6080 }
6081
6082 if (width == 0)
6083 width = 1;
6084 if (height == 0)
6085 height = 1;
6086
6087 /* Bail early if no change */
6088 if (window->width == width &&
6089 window->height == height &&
6090 (!with_move ||
6091 (window->x == x &&
6092 window->y == y)))
6093 return;
6094
6095 /* Handle child windows */
6096
6097 expose = FALSE(0);
6098 old_region = NULL((void*)0);
6099
6100 if (cdk_window_is_viewable (window) &&
6101 !window->input_only)
6102 {
6103 CdkRectangle r;
6104
6105 expose = TRUE(!(0));
6106
6107 r.x = window->x;
6108 r.y = window->y;
6109 r.width = window->width;
6110 r.height = window->height;
6111
6112 old_region = cairo_region_create_rectangle (&r);
6113 }
6114
6115 /* Set the new position and size */
6116 if (with_move)
6117 {
6118 window->x = x;
6119 window->y = y;
6120 }
6121 if (!(width < 0 && height < 0))
6122 {
6123 window->width = width;
6124 window->height = height;
6125 }
6126
6127 old_abs_x = window->abs_x;
6128 old_abs_y = window->abs_y;
6129
6130 recompute_visible_regions (window, FALSE(0));
6131
6132 if (cdk_window_has_impl (window))
6133 {
6134 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
6135
6136 /* Do the actual move after recomputing things, as this will have set the shape to
6137 the now correct one, thus avoiding copying regions that should not be copied. */
6138 impl_class->move_resize (window, TRUE(!(0)),
6139 window->x, window->y,
6140 window->width, window->height);
6141 }
6142 else if (old_abs_x != window->abs_x ||
6143 old_abs_y != window->abs_y)
6144 move_native_children (window);
6145
6146 if (expose)
6147 {
6148 CdkRectangle r;
6149
6150 r.x = window->x;
6151 r.y = window->y;
6152 r.width = window->width;
6153 r.height = window->height;
6154
6155 new_region = cairo_region_create_rectangle (&r);
6156
6157 cairo_region_union (new_region, old_region);
6158
6159 cdk_window_invalidate_region_full (window->parent, new_region, TRUE(!(0)));
6160
6161 cairo_region_destroy (old_region);
6162 cairo_region_destroy (new_region);
6163 }
6164
6165 _cdk_synthesize_crossing_events_for_geometry_change (window);
6166}
6167
6168
6169
6170/**
6171 * cdk_window_move:
6172 * @window: a #CdkWindow
6173 * @x: X coordinate relative to window’s parent
6174 * @y: Y coordinate relative to window’s parent
6175 *
6176 * Repositions a window relative to its parent window.
6177 * For toplevel windows, window managers may ignore or modify the move;
6178 * you should probably use ctk_window_move() on a #CtkWindow widget
6179 * anyway, instead of using CDK functions. For child windows,
6180 * the move will reliably succeed.
6181 *
6182 * If you’re also planning to resize the window, use cdk_window_move_resize()
6183 * to both move and resize simultaneously, for a nicer visual effect.
6184 **/
6185void
6186cdk_window_move (CdkWindow *window,
6187 gint x,
6188 gint y)
6189{
6190 cdk_window_move_resize_internal (window, TRUE(!(0)), x, y, -1, -1);
6191}
6192
6193/**
6194 * cdk_window_resize:
6195 * @window: a #CdkWindow
6196 * @width: new width of the window
6197 * @height: new height of the window
6198 *
6199 * Resizes @window; for toplevel windows, asks the window manager to resize
6200 * the window. The window manager may not allow the resize. When using CTK+,
6201 * use ctk_window_resize() instead of this low-level CDK function.
6202 *
6203 * Windows may not be resized below 1x1.
6204 *
6205 * If you’re also planning to move the window, use cdk_window_move_resize()
6206 * to both move and resize simultaneously, for a nicer visual effect.
6207 **/
6208void
6209cdk_window_resize (CdkWindow *window,
6210 gint width,
6211 gint height)
6212{
6213 cdk_window_move_resize_internal (window, FALSE(0), 0, 0, width, height);
6214}
6215
6216
6217/**
6218 * cdk_window_move_resize:
6219 * @window: a #CdkWindow
6220 * @x: new X position relative to window’s parent
6221 * @y: new Y position relative to window’s parent
6222 * @width: new width
6223 * @height: new height
6224 *
6225 * Equivalent to calling cdk_window_move() and cdk_window_resize(),
6226 * except that both operations are performed at once, avoiding strange
6227 * visual effects. (i.e. the user may be able to see the window first
6228 * move, then resize, if you don’t use cdk_window_move_resize().)
6229 **/
6230void
6231cdk_window_move_resize (CdkWindow *window,
6232 gint x,
6233 gint y,
6234 gint width,
6235 gint height)
6236{
6237 cdk_window_move_resize_internal (window, TRUE(!(0)), x, y, width, height);
6238}
6239
6240/**
6241 * cdk_window_move_to_rect:
6242 * @window: the #CdkWindow to move
6243 * @rect: (not nullable): the destination #CdkRectangle to align @window with
6244 * @rect_anchor: the point on @rect to align with @window's anchor point
6245 * @window_anchor: the point on @window to align with @rect's anchor point
6246 * @anchor_hints: positioning hints to use when limited on space
6247 * @rect_anchor_dx: horizontal offset to shift @window, i.e. @rect's anchor
6248 * point
6249 * @rect_anchor_dy: vertical offset to shift @window, i.e. @rect's anchor point
6250 *
6251 * Moves @window to @rect, aligning their anchor points.
6252 *
6253 * @rect is relative to the top-left corner of the window that @window is
6254 * transient for. @rect_anchor and @window_anchor determine anchor points on
6255 * @rect and @window to pin together. @rect's anchor point can optionally be
6256 * offset by @rect_anchor_dx and @rect_anchor_dy, which is equivalent to
6257 * offsetting the position of @window.
6258 *
6259 * @anchor_hints determines how @window will be moved if the anchor points cause
6260 * it to move off-screen. For example, %CDK_ANCHOR_FLIP_X will replace
6261 * %CDK_GRAVITY_NORTH_WEST with %CDK_GRAVITY_NORTH_EAST and vice versa if
6262 * @window extends beyond the left or right edges of the monitor.
6263 *
6264 * Connect to the #CdkWindow::moved-to-rect signal to find out how it was
6265 * actually positioned.
6266 *
6267 * Since: 3.24
6268 */
6269void
6270cdk_window_move_to_rect (CdkWindow *window,
6271 const CdkRectangle *rect,
6272 CdkGravity rect_anchor,
6273 CdkGravity window_anchor,
6274 CdkAnchorHints anchor_hints,
6275 gint rect_anchor_dx,
6276 gint rect_anchor_dy)
6277{
6278 CdkWindowImplClass *impl_class;
6279
6280 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
6281 g_return_if_fail (window->transient_for)do { if ((window->transient_for)) { } else { g_return_if_fail_warning
("Cdk", ((const char*) (__func__)), "window->transient_for"
); return; } } while (0)
;
6282 g_return_if_fail (rect)do { if ((rect)) { } else { g_return_if_fail_warning ("Cdk", (
(const char*) (__func__)), "rect"); return; } } while (0)
;
6283
6284 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
6285 impl_class->move_to_rect (window,
6286 rect,
6287 rect_anchor,
6288 window_anchor,
6289 anchor_hints,
6290 rect_anchor_dx,
6291 rect_anchor_dy);
6292}
6293
6294/**
6295 * cdk_window_scroll:
6296 * @window: a #CdkWindow
6297 * @dx: Amount to scroll in the X direction
6298 * @dy: Amount to scroll in the Y direction
6299 *
6300 * Scroll the contents of @window, both pixels and children, by the
6301 * given amount. @window itself does not move. Portions of the window
6302 * that the scroll operation brings in from offscreen areas are
6303 * invalidated. The invalidated region may be bigger than what would
6304 * strictly be necessary.
6305 *
6306 * For X11, a minimum area will be invalidated if the window has no
6307 * subwindows, or if the edges of the window’s parent do not extend
6308 * beyond the edges of the window. In other cases, a multi-step process
6309 * is used to scroll the window which may produce temporary visual
6310 * artifacts and unnecessary invalidations.
6311 **/
6312void
6313cdk_window_scroll (CdkWindow *window,
6314 gint dx,
6315 gint dy)
6316{
6317 GList *tmp_list;
6318
6319 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
6320
6321 if (dx == 0 && dy == 0)
6322 return;
6323
6324 if (window->destroyed)
6325 return;
6326
6327 /* First move all child windows, without causing invalidation */
6328
6329 tmp_list = window->children;
6330 while (tmp_list)
6331 {
6332 CdkWindow *child = CDK_WINDOW (tmp_list->data)((((CdkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tmp_list->data)), ((cdk_window_get_type ()))))))
;
6333
6334 /* Just update the positions, the bits will move with the copy */
6335 child->x += dx;
6336 child->y += dy;
6337
6338 tmp_list = tmp_list->next;
6339 }
6340
6341 recompute_visible_regions (window, TRUE(!(0)));
6342
6343 move_native_children (window);
6344
6345 cdk_window_invalidate_rect_full (window, NULL((void*)0), TRUE(!(0)));
6346
6347 _cdk_synthesize_crossing_events_for_geometry_change (window);
6348}
6349
6350/**
6351 * cdk_window_move_region:
6352 * @window: a #CdkWindow
6353 * @region: The #cairo_region_t to move
6354 * @dx: Amount to move in the X direction
6355 * @dy: Amount to move in the Y direction
6356 *
6357 * Move the part of @window indicated by @region by @dy pixels in the Y
6358 * direction and @dx pixels in the X direction. The portions of @region
6359 * that not covered by the new position of @region are invalidated.
6360 *
6361 * Child windows are not moved.
6362 *
6363 * Since: 2.8
6364 */
6365void
6366cdk_window_move_region (CdkWindow *window,
6367 const cairo_region_t *region,
6368 gint dx,
6369 gint dy)
6370{
6371 cairo_region_t *expose_area;
6372
6373 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
6374 g_return_if_fail (region != NULL)do { if ((region != ((void*)0))) { } else { g_return_if_fail_warning
("Cdk", ((const char*) (__func__)), "region != NULL"); return
; } } while (0)
;
6375
6376 if (dx == 0 && dy == 0)
6377 return;
6378
6379 if (window->destroyed)
6380 return;
6381
6382 expose_area = cairo_region_copy (region);
6383 cairo_region_translate (expose_area, dx, dy);
6384 cairo_region_union (expose_area, region);
6385
6386 cdk_window_invalidate_region_full (window, expose_area, FALSE(0));
6387 cairo_region_destroy (expose_area);
6388}
6389
6390/**
6391 * cdk_window_set_background:
6392 * @window: a #CdkWindow
6393 * @color: a #CdkColor
6394 *
6395 * Sets the background color of @window.
6396 *
6397 * However, when using CTK+, influence the background of a widget
6398 * using a style class or CSS — if you’re an application — or with
6399 * ctk_style_context_set_background() — if you're implementing a
6400 * custom widget.
6401 */
6402void
6403cdk_window_set_background (CdkWindow *window,
6404 const CdkColor *color)
6405{
6406 cairo_pattern_t *pattern;
6407
6408 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
6409
6410 pattern = cairo_pattern_create_rgb (color->red / 65535.,
6411 color->green / 65535.,
6412 color->blue / 65535.);
6413
6414 cdk_window_set_background_pattern (window, pattern);
6415
6416 cairo_pattern_destroy (pattern);
6417}
6418
6419/**
6420 * cdk_window_set_background_rgba:
6421 * @window: a #CdkWindow
6422 * @rgba: a #CdkRGBA color
6423 *
6424 * Sets the background color of @window.
6425 *
6426 * See also cdk_window_set_background_pattern().
6427 **/
6428void
6429cdk_window_set_background_rgba (CdkWindow *window,
6430 const CdkRGBA *rgba)
6431{
6432 cairo_pattern_t *pattern;
6433 CdkRGBA prev_rgba;
6434
6435 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
6436 g_return_if_fail (rgba != NULL)do { if ((rgba != ((void*)0))) { } else { g_return_if_fail_warning
("Cdk", ((const char*) (__func__)), "rgba != NULL"); return;
} } while (0)
;
6437
6438 /*
6439 * If the new RGBA matches the previous pattern, ignore the change so that
6440 * we do not invalidate the window contents.
6441 */
6442 if ((window->background != NULL((void*)0)) &&
6443 (cairo_pattern_get_type (window->background) == CAIRO_PATTERN_TYPE_SOLID) &&
6444 (cairo_pattern_get_rgba (window->background,
6445 &prev_rgba.red,
6446 &prev_rgba.green,
6447 &prev_rgba.blue,
6448 &prev_rgba.alpha) == CAIRO_STATUS_SUCCESS) &&
6449 cdk_rgba_equal (&prev_rgba, rgba))
6450 return;
6451
6452 pattern = cairo_pattern_create_rgba (rgba->red, rgba->green,
6453 rgba->blue, rgba->alpha);
6454
6455 cdk_window_set_background_pattern (window, pattern);
6456
6457 cairo_pattern_destroy (pattern);
6458}
6459
6460
6461/**
6462 * cdk_window_set_background_pattern:
6463 * @window: a #CdkWindow
6464 * @pattern: (allow-none): a pattern to use, or %NULL
6465 *
6466 * Sets the background of @window.
6467 *
6468 * A background of %NULL means that the window won't have any background. On the
6469 * X11 backend it's also possible to inherit the background from the parent
6470 * window using cdk_x11_get_parent_relative_pattern().
6471 *
6472 * The windowing system will normally fill a window with its background
6473 * when the window is obscured then exposed.
6474 */
6475void
6476cdk_window_set_background_pattern (CdkWindow *window,
6477 cairo_pattern_t *pattern)
6478{
6479 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
6480
6481 if (window->input_only)
6482 return;
6483
6484 if (pattern)
6485 cairo_pattern_reference (pattern);
6486 if (window->background)
6487 cairo_pattern_destroy (window->background);
6488 window->background = pattern;
6489
6490 if (cdk_window_has_impl (window))
6491 {
6492 CdkWindowImplClass *impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
6493 impl_class->set_background (window, pattern);
6494 }
6495 else
6496 cdk_window_invalidate_rect_full (window, NULL((void*)0), TRUE(!(0)));
6497}
6498
6499/**
6500 * cdk_window_get_background_pattern:
6501 * @window: a window
6502 *
6503 * Gets the pattern used to clear the background on @window.
6504 *
6505 * Returns: (nullable) (transfer none): The pattern to use for the
6506 * background or %NULL if there is no background.
6507 *
6508 * Since: 2.22
6509 **/
6510cairo_pattern_t *
6511cdk_window_get_background_pattern (CdkWindow *window)
6512{
6513 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
6514
6515 return window->background;
6516}
6517
6518static void
6519cdk_window_set_cursor_internal (CdkWindow *window,
6520 CdkDevice *device,
6521 CdkCursor *cursor)
6522{
6523 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
6524 return;
6525
6526 g_assert (cdk_window_get_display (window) == cdk_device_get_display (device))do { if (cdk_window_get_display (window) == cdk_device_get_display
(device)) ; else g_assertion_message_expr ("Cdk", "cdkwindow.c"
, 6526, ((const char*) (__func__)), "cdk_window_get_display (window) == cdk_device_get_display (device)"
); } while (0)
;
6527 g_assert (!cursor || cdk_window_get_display (window) == cdk_cursor_get_display (cursor))do { if (!cursor || cdk_window_get_display (window) == cdk_cursor_get_display
(cursor)) ; else g_assertion_message_expr ("Cdk", "cdkwindow.c"
, 6527, ((const char*) (__func__)), "!cursor || cdk_window_get_display (window) == cdk_cursor_get_display (cursor)"
); } while (0)
;
6528
6529 if (window->window_type == CDK_WINDOW_ROOT ||
6530 window->window_type == CDK_WINDOW_FOREIGN)
6531 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_device_cursor (window, device, cursor);
6532 else
6533 {
6534 CdkPointerWindowInfo *pointer_info;
6535 CdkDisplay *display;
6536
6537 display = cdk_window_get_display (window);
6538 pointer_info = _cdk_display_get_pointer_info (display, device);
6539
6540 if (_cdk_window_event_parent_of (window, pointer_info->window_under_pointer))
6541 update_cursor (display, device);
6542 }
6543}
6544
6545/**
6546 * cdk_window_get_cursor:
6547 * @window: a #CdkWindow
6548 *
6549 * Retrieves a #CdkCursor pointer for the cursor currently set on the
6550 * specified #CdkWindow, or %NULL. If the return value is %NULL then
6551 * there is no custom cursor set on the specified window, and it is
6552 * using the cursor for its parent window.
6553 *
6554 * Returns: (nullable) (transfer none): a #CdkCursor, or %NULL. The
6555 * returned object is owned by the #CdkWindow and should not be
6556 * unreferenced directly. Use cdk_window_set_cursor() to unset the
6557 * cursor of the window
6558 *
6559 * Since: 2.18
6560 */
6561CdkCursor *
6562cdk_window_get_cursor (CdkWindow *window)
6563{
6564 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
6565
6566 return window->cursor;
6567}
6568
6569/**
6570 * cdk_window_set_cursor:
6571 * @window: a #CdkWindow
6572 * @cursor: (allow-none): a cursor
6573 *
6574 * Sets the default mouse pointer for a #CdkWindow.
6575 *
6576 * Note that @cursor must be for the same display as @window.
6577 *
6578 * Use cdk_cursor_new_for_display() or cdk_cursor_new_from_pixbuf() to
6579 * create the cursor. To make the cursor invisible, use %CDK_BLANK_CURSOR.
6580 * Passing %NULL for the @cursor argument to cdk_window_set_cursor() means
6581 * that @window will use the cursor of its parent window. Most windows
6582 * should use this default.
6583 */
6584void
6585cdk_window_set_cursor (CdkWindow *window,
6586 CdkCursor *cursor)
6587{
6588 CdkDisplay *display;
6589
6590 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
6591
6592 display = cdk_window_get_display (window);
6593
6594 if (window->cursor)
6595 {
6596 g_object_unref (window->cursor);
6597 window->cursor = NULL((void*)0);
6598 }
6599
6600 if (!CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
6601 {
6602 CdkDevice *device;
6603 GList *seats, *s;
6604
6605 if (cursor)
6606 window->cursor = g_object_ref (cursor)((__typeof__ (cursor)) (g_object_ref) (cursor));
6607
6608 seats = cdk_display_list_seats (display);
6609
6610 for (s = seats; s; s = s->next)
6611 {
6612 GList *devices, *d;
6613
6614 device = cdk_seat_get_pointer (s->data);
6615 cdk_window_set_cursor_internal (window, device, window->cursor);
6616
6617 devices = cdk_seat_get_slaves (s->data, CDK_SEAT_CAPABILITY_TABLET_STYLUS);
6618 for (d = devices; d; d = d->next)
6619 {
6620 device = cdk_device_get_associated_device (d->data);
6621 cdk_window_set_cursor_internal (window, device, window->cursor);
6622 }
6623 g_list_free (devices);
6624 }
6625
6626 g_list_free (seats);
6627 g_object_notify_by_pspec (G_OBJECT (window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), (((GType) ((20) << (2))))))))
, properties[PROP_CURSOR]);
6628 }
6629}
6630
6631/**
6632 * cdk_window_get_device_cursor:
6633 * @window: a #CdkWindow.
6634 * @device: a master, pointer #CdkDevice.
6635 *
6636 * Retrieves a #CdkCursor pointer for the @device currently set on the
6637 * specified #CdkWindow, or %NULL. If the return value is %NULL then
6638 * there is no custom cursor set on the specified window, and it is
6639 * using the cursor for its parent window.
6640 *
6641 * Returns: (nullable) (transfer none): a #CdkCursor, or %NULL. The
6642 * returned object is owned by the #CdkWindow and should not be
6643 * unreferenced directly. Use cdk_window_set_cursor() to unset the
6644 * cursor of the window
6645 *
6646 * Since: 3.0
6647 **/
6648CdkCursor *
6649cdk_window_get_device_cursor (CdkWindow *window,
6650 CdkDevice *device)
6651{
6652 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
6653 g_return_val_if_fail (CDK_IS_DEVICE (device), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((device)); GType __t = ((cdk_device_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_DEVICE (device)"); return (((void*)0)); } } while
(0)
;
6654 g_return_val_if_fail (cdk_device_get_source (device) != CDK_SOURCE_KEYBOARD, NULL)do { if ((cdk_device_get_source (device) != CDK_SOURCE_KEYBOARD
)) { } else { g_return_if_fail_warning ("Cdk", ((const char*)
(__func__)), "cdk_device_get_source (device) != CDK_SOURCE_KEYBOARD"
); return (((void*)0)); } } while (0)
;
6655 g_return_val_if_fail (cdk_device_get_device_type (device) == CDK_DEVICE_TYPE_MASTER, NULL)do { if ((cdk_device_get_device_type (device) == CDK_DEVICE_TYPE_MASTER
)) { } else { g_return_if_fail_warning ("Cdk", ((const char*)
(__func__)), "cdk_device_get_device_type (device) == CDK_DEVICE_TYPE_MASTER"
); return (((void*)0)); } } while (0)
;
6656
6657 return g_hash_table_lookup (window->device_cursor, device);
6658}
6659
6660/**
6661 * cdk_window_set_device_cursor:
6662 * @window: a #CdkWindow
6663 * @device: a master, pointer #CdkDevice
6664 * @cursor: a #CdkCursor
6665 *
6666 * Sets a specific #CdkCursor for a given device when it gets inside @window.
6667 * Use cdk_cursor_new_for_display() or cdk_cursor_new_from_pixbuf() to create
6668 * the cursor. To make the cursor invisible, use %CDK_BLANK_CURSOR. Passing
6669 * %NULL for the @cursor argument to cdk_window_set_cursor() means that
6670 * @window will use the cursor of its parent window. Most windows should
6671 * use this default.
6672 *
6673 * Since: 3.0
6674 **/
6675void
6676cdk_window_set_device_cursor (CdkWindow *window,
6677 CdkDevice *device,
6678 CdkCursor *cursor)
6679{
6680 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
6681 g_return_if_fail (CDK_IS_DEVICE (device))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((device)); GType __t = ((cdk_device_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_DEVICE (device)"); return; } } while (0)
;
6682 g_return_if_fail (cdk_device_get_source (device) != CDK_SOURCE_KEYBOARD)do { if ((cdk_device_get_source (device) != CDK_SOURCE_KEYBOARD
)) { } else { g_return_if_fail_warning ("Cdk", ((const char*)
(__func__)), "cdk_device_get_source (device) != CDK_SOURCE_KEYBOARD"
); return; } } while (0)
;
6683 g_return_if_fail (cdk_device_get_device_type (device) == CDK_DEVICE_TYPE_MASTER)do { if ((cdk_device_get_device_type (device) == CDK_DEVICE_TYPE_MASTER
)) { } else { g_return_if_fail_warning ("Cdk", ((const char*)
(__func__)), "cdk_device_get_device_type (device) == CDK_DEVICE_TYPE_MASTER"
); return; } } while (0)
;
6684
6685 if (!cursor)
6686 g_hash_table_remove (window->device_cursor, device);
6687 else
6688 g_hash_table_replace (window->device_cursor, device, g_object_ref (cursor)((__typeof__ (cursor)) (g_object_ref) (cursor)));
6689
6690 cdk_window_set_cursor_internal (window, device, cursor);
6691}
6692
6693/**
6694 * cdk_window_get_geometry:
6695 * @window: a #CdkWindow
6696 * @x: (out) (allow-none): return location for X coordinate of window (relative to its parent)
6697 * @y: (out) (allow-none): return location for Y coordinate of window (relative to its parent)
6698 * @width: (out) (allow-none): return location for width of window
6699 * @height: (out) (allow-none): return location for height of window
6700 *
6701 * Any of the return location arguments to this function may be %NULL,
6702 * if you aren’t interested in getting the value of that field.
6703 *
6704 * The X and Y coordinates returned are relative to the parent window
6705 * of @window, which for toplevels usually means relative to the
6706 * window decorations (titlebar, etc.) rather than relative to the
6707 * root window (screen-size background window).
6708 *
6709 * On the X11 platform, the geometry is obtained from the X server,
6710 * so reflects the latest position of @window; this may be out-of-sync
6711 * with the position of @window delivered in the most-recently-processed
6712 * #CdkEventConfigure. cdk_window_get_position() in contrast gets the
6713 * position from the most recent configure event.
6714 *
6715 * Note: If @window is not a toplevel, it is much better
6716 * to call cdk_window_get_position(), cdk_window_get_width() and
6717 * cdk_window_get_height() instead, because it avoids the roundtrip to
6718 * the X server and because these functions support the full 32-bit
6719 * coordinate space, whereas cdk_window_get_geometry() is restricted to
6720 * the 16-bit coordinates of X11.
6721 */
6722void
6723cdk_window_get_geometry (CdkWindow *window,
6724 gint *x,
6725 gint *y,
6726 gint *width,
6727 gint *height)
6728{
6729 CdkWindow *parent;
6730 CdkWindowImplClass *impl_class;
6731
6732 if (!window)
6733 window = cdk_screen_get_root_window ((cdk_screen_get_default ()));
6734
6735 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
6736
6737 if (!CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
6738 {
6739 if (cdk_window_has_impl (window))
6740 {
6741 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
6742 impl_class->get_geometry (window, x, y,
6743 width, height);
6744 /* This reports the position wrt to the native parent, we need to convert
6745 it to be relative to the client side parent */
6746 parent = window->parent;
6747 if (parent && !cdk_window_has_impl (parent))
6748 {
6749 if (x)
6750 *x -= parent->abs_x;
6751 if (y)
6752 *y -= parent->abs_y;
6753 }
6754 }
6755 else
6756 {
6757 if (x)
6758 *x = window->x;
6759 if (y)
6760 *y = window->y;
6761 if (width)
6762 *width = window->width;
6763 if (height)
6764 *height = window->height;
6765 }
6766 }
6767}
6768
6769/**
6770 * cdk_window_get_width:
6771 * @window: a #CdkWindow
6772 *
6773 * Returns the width of the given @window.
6774 *
6775 * On the X11 platform the returned size is the size reported in the
6776 * most-recently-processed configure event, rather than the current
6777 * size on the X server.
6778 *
6779 * Returns: The width of @window
6780 *
6781 * Since: 2.24
6782 */
6783int
6784cdk_window_get_width (CdkWindow *window)
6785{
6786 g_return_val_if_fail (CDK_IS_WINDOW (window), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (0); } } while (0)
;
6787
6788 return window->width;
6789}
6790
6791/**
6792 * cdk_window_get_height:
6793 * @window: a #CdkWindow
6794 *
6795 * Returns the height of the given @window.
6796 *
6797 * On the X11 platform the returned size is the size reported in the
6798 * most-recently-processed configure event, rather than the current
6799 * size on the X server.
6800 *
6801 * Returns: The height of @window
6802 *
6803 * Since: 2.24
6804 */
6805int
6806cdk_window_get_height (CdkWindow *window)
6807{
6808 g_return_val_if_fail (CDK_IS_WINDOW (window), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (0); } } while (0)
;
6809
6810 return window->height;
6811}
6812
6813/**
6814 * cdk_window_get_origin:
6815 * @window: a #CdkWindow
6816 * @x: (out) (allow-none): return location for X coordinate
6817 * @y: (out) (allow-none): return location for Y coordinate
6818 *
6819 * Obtains the position of a window in root window coordinates.
6820 * (Compare with cdk_window_get_position() and
6821 * cdk_window_get_geometry() which return the position of a window
6822 * relative to its parent window.)
6823 *
6824 * Returns: not meaningful, ignore
6825 */
6826gint
6827cdk_window_get_origin (CdkWindow *window,
6828 gint *x,
6829 gint *y)
6830{
6831 gint dummy_x, dummy_y;
6832
6833 g_return_val_if_fail (CDK_IS_WINDOW (window), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (0); } } while (0)
;
6834
6835 cdk_window_get_root_coords (window,
6836 0, 0,
6837 x ? x : &dummy_x,
6838 y ? y : &dummy_y);
6839
6840 return TRUE(!(0));
6841}
6842
6843/**
6844 * cdk_window_get_root_coords:
6845 * @window: a #CdkWindow
6846 * @x: X coordinate in window
6847 * @y: Y coordinate in window
6848 * @root_x: (out): return location for X coordinate
6849 * @root_y: (out): return location for Y coordinate
6850 *
6851 * Obtains the position of a window position in root
6852 * window coordinates. This is similar to
6853 * cdk_window_get_origin() but allows you to pass
6854 * in any position in the window, not just the origin.
6855 *
6856 * Since: 2.18
6857 */
6858void
6859cdk_window_get_root_coords (CdkWindow *window,
6860 gint x,
6861 gint y,
6862 gint *root_x,
6863 gint *root_y)
6864{
6865 CdkWindowImplClass *impl_class;
6866
6867 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
6868
6869 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
6870 {
6871 *root_x = 0;
6872 *root_y = 0;
6873 return;
6874 }
6875
6876 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
6877 impl_class->get_root_coords (window->impl_window,
6878 x + window->abs_x,
6879 y + window->abs_y,
6880 root_x, root_y);
6881}
6882
6883/**
6884 * cdk_window_coords_to_parent:
6885 * @window: a child window
6886 * @x: X coordinate in child’s coordinate system
6887 * @y: Y coordinate in child’s coordinate system
6888 * @parent_x: (out) (allow-none): return location for X coordinate
6889 * in parent’s coordinate system, or %NULL
6890 * @parent_y: (out) (allow-none): return location for Y coordinate
6891 * in parent’s coordinate system, or %NULL
6892 *
6893 * Transforms window coordinates from a child window to its parent
6894 * window, where the parent window is the normal parent as returned by
6895 * cdk_window_get_parent() for normal windows, and the window's
6896 * embedder as returned by cdk_offscreen_window_get_embedder() for
6897 * offscreen windows.
6898 *
6899 * For normal windows, calling this function is equivalent to adding
6900 * the return values of cdk_window_get_position() to the child coordinates.
6901 * For offscreen windows however (which can be arbitrarily transformed),
6902 * this function calls the CdkWindow::to-embedder: signal to translate
6903 * the coordinates.
6904 *
6905 * You should always use this function when writing generic code that
6906 * walks up a window hierarchy.
6907 *
6908 * See also: cdk_window_coords_from_parent()
6909 *
6910 * Since: 2.22
6911 **/
6912void
6913cdk_window_coords_to_parent (CdkWindow *window,
6914 gdouble x,
6915 gdouble y,
6916 gdouble *parent_x,
6917 gdouble *parent_y)
6918{
6919 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
6920
6921 if (cdk_window_is_offscreen (window))
6922 {
6923 gdouble px, py;
6924
6925 to_embedder (window, x, y, &px, &py);
6926
6927 if (parent_x)
6928 *parent_x = px;
6929
6930 if (parent_y)
6931 *parent_y = py;
6932 }
6933 else
6934 {
6935 if (parent_x)
6936 *parent_x = x + window->x;
6937
6938 if (parent_y)
6939 *parent_y = y + window->y;
6940 }
6941}
6942
6943/**
6944 * cdk_window_coords_from_parent:
6945 * @window: a child window
6946 * @parent_x: X coordinate in parent’s coordinate system
6947 * @parent_y: Y coordinate in parent’s coordinate system
6948 * @x: (out) (allow-none): return location for X coordinate in child’s coordinate system
6949 * @y: (out) (allow-none): return location for Y coordinate in child’s coordinate system
6950 *
6951 * Transforms window coordinates from a parent window to a child
6952 * window, where the parent window is the normal parent as returned by
6953 * cdk_window_get_parent() for normal windows, and the window's
6954 * embedder as returned by cdk_offscreen_window_get_embedder() for
6955 * offscreen windows.
6956 *
6957 * For normal windows, calling this function is equivalent to subtracting
6958 * the return values of cdk_window_get_position() from the parent coordinates.
6959 * For offscreen windows however (which can be arbitrarily transformed),
6960 * this function calls the CdkWindow::from-embedder: signal to translate
6961 * the coordinates.
6962 *
6963 * You should always use this function when writing generic code that
6964 * walks down a window hierarchy.
6965 *
6966 * See also: cdk_window_coords_to_parent()
6967 *
6968 * Since: 2.22
6969 **/
6970void
6971cdk_window_coords_from_parent (CdkWindow *window,
6972 gdouble parent_x,
6973 gdouble parent_y,
6974 gdouble *x,
6975 gdouble *y)
6976{
6977 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
6978
6979 if (cdk_window_is_offscreen (window))
6980 {
6981 gdouble cx, cy;
6982
6983 from_embedder (window, parent_x, parent_y, &cx, &cy);
6984
6985 if (x)
6986 *x = cx;
6987
6988 if (y)
6989 *y = cy;
6990 }
6991 else
6992 {
6993 if (x)
6994 *x = parent_x - window->x;
6995
6996 if (y)
6997 *y = parent_y - window->y;
6998 }
6999}
7000
7001/**
7002 * cdk_window_shape_combine_region:
7003 * @window: a #CdkWindow
7004 * @shape_region: (allow-none): region of window to be non-transparent
7005 * @offset_x: X position of @shape_region in @window coordinates
7006 * @offset_y: Y position of @shape_region in @window coordinates
7007 *
7008 * Makes pixels in @window outside @shape_region be transparent,
7009 * so that the window may be nonrectangular.
7010 *
7011 * If @shape_region is %NULL, the shape will be unset, so the whole
7012 * window will be opaque again. @offset_x and @offset_y are ignored
7013 * if @shape_region is %NULL.
7014 *
7015 * On the X11 platform, this uses an X server extension which is
7016 * widely available on most common platforms, but not available on
7017 * very old X servers, and occasionally the implementation will be
7018 * buggy. On servers without the shape extension, this function
7019 * will do nothing.
7020 *
7021 * This function works on both toplevel and child windows.
7022 */
7023void
7024cdk_window_shape_combine_region (CdkWindow *window,
7025 const cairo_region_t *shape_region,
7026 gint offset_x,
7027 gint offset_y)
7028{
7029 cairo_region_t *old_region, *new_region, *diff;
7030
7031 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
7032
7033 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
7034 return;
7035
7036 if (!window->shape && shape_region == NULL((void*)0))
7037 return;
7038
7039 window->shaped = (shape_region != NULL((void*)0));
7040
7041 if (window->shape)
7042 cairo_region_destroy (window->shape);
7043
7044 old_region = NULL((void*)0);
7045 if (CDK_WINDOW_IS_MAPPED (window)(((window)->state & CDK_WINDOW_STATE_WITHDRAWN) == 0))
7046 old_region = cairo_region_copy (window->clip_region);
7047
7048 if (shape_region)
7049 {
7050 window->shape = cairo_region_copy (shape_region);
7051 cairo_region_translate (window->shape, offset_x, offset_y);
7052 }
7053 else
7054 window->shape = NULL((void*)0);
7055
7056 recompute_visible_regions (window, FALSE(0));
7057
7058 if (old_region)
7059 {
7060 new_region = cairo_region_copy (window->clip_region);
7061
7062 /* New area in the window, needs invalidation */
7063 diff = cairo_region_copy (new_region);
7064 cairo_region_subtract (diff, old_region);
7065
7066 cdk_window_invalidate_region_full (window, diff, TRUE(!(0)));
7067
7068 cairo_region_destroy (diff);
7069
7070 if (!cdk_window_is_toplevel (window))
7071 {
7072 /* New area in the non-root parent window, needs invalidation */
7073 diff = cairo_region_copy (old_region);
7074 cairo_region_subtract (diff, new_region);
7075
7076 /* Adjust region to parent window coords */
7077 cairo_region_translate (diff, window->x, window->y);
7078
7079 cdk_window_invalidate_region_full (window->parent, diff, TRUE(!(0)));
7080
7081 cairo_region_destroy (diff);
7082 }
7083
7084 cairo_region_destroy (new_region);
7085 cairo_region_destroy (old_region);
7086 }
7087}
7088
7089static void
7090do_child_shapes (CdkWindow *window,
7091 gboolean merge)
7092{
7093 CdkRectangle r;
7094 cairo_region_t *region;
7095
7096 r.x = 0;
7097 r.y = 0;
7098 r.width = window->width;
7099 r.height = window->height;
7100
7101 region = cairo_region_create_rectangle (&r);
7102 remove_child_area (window, FALSE(0), region);
7103
7104 if (merge && window->shape)
7105 cairo_region_subtract (region, window->shape);
7106
7107 cairo_region_xor_rectangle (region, &r);
7108
7109 cdk_window_shape_combine_region (window, region, 0, 0);
7110
7111 cairo_region_destroy (region);
7112}
7113
7114/**
7115 * cdk_window_set_child_shapes:
7116 * @window: a #CdkWindow
7117 *
7118 * Sets the shape mask of @window to the union of shape masks
7119 * for all children of @window, ignoring the shape mask of @window
7120 * itself. Contrast with cdk_window_merge_child_shapes() which includes
7121 * the shape mask of @window in the masks to be merged.
7122 **/
7123void
7124cdk_window_set_child_shapes (CdkWindow *window)
7125{
7126 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
7127
7128 do_child_shapes (window, FALSE(0));
7129}
7130
7131/**
7132 * cdk_window_merge_child_shapes:
7133 * @window: a #CdkWindow
7134 *
7135 * Merges the shape masks for any child windows into the
7136 * shape mask for @window. i.e. the union of all masks
7137 * for @window and its children will become the new mask
7138 * for @window. See cdk_window_shape_combine_region().
7139 *
7140 * This function is distinct from cdk_window_set_child_shapes()
7141 * because it includes @window’s shape mask in the set of shapes to
7142 * be merged.
7143 */
7144void
7145cdk_window_merge_child_shapes (CdkWindow *window)
7146{
7147 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
7148
7149 do_child_shapes (window, TRUE(!(0)));
7150}
7151
7152/**
7153 * cdk_window_input_shape_combine_region:
7154 * @window: a #CdkWindow
7155 * @shape_region: region of window to be non-transparent
7156 * @offset_x: X position of @shape_region in @window coordinates
7157 * @offset_y: Y position of @shape_region in @window coordinates
7158 *
7159 * Like cdk_window_shape_combine_region(), but the shape applies
7160 * only to event handling. Mouse events which happen while
7161 * the pointer position corresponds to an unset bit in the
7162 * mask will be passed on the window below @window.
7163 *
7164 * An input shape is typically used with RGBA windows.
7165 * The alpha channel of the window defines which pixels are
7166 * invisible and allows for nicely antialiased borders,
7167 * and the input shape controls where the window is
7168 * “clickable”.
7169 *
7170 * On the X11 platform, this requires version 1.1 of the
7171 * shape extension.
7172 *
7173 * On the Win32 platform, this functionality is not present and the
7174 * function does nothing.
7175 *
7176 * Since: 2.10
7177 */
7178void
7179cdk_window_input_shape_combine_region (CdkWindow *window,
7180 const cairo_region_t *shape_region,
7181 gint offset_x,
7182 gint offset_y)
7183{
7184 CdkWindowImplClass *impl_class;
7185
7186 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
7187
7188 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
7189 return;
7190
7191 if (window->input_shape)
7192 cairo_region_destroy (window->input_shape);
7193
7194 if (shape_region)
7195 {
7196 window->input_shape = cairo_region_copy (shape_region);
7197 cairo_region_translate (window->input_shape, offset_x, offset_y);
7198 }
7199 else
7200 window->input_shape = NULL((void*)0);
7201
7202 if (cdk_window_has_impl (window))
7203 {
7204 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
7205 impl_class->input_shape_combine_region (window, window->input_shape, 0, 0);
7206 }
7207
7208 /* Pointer may have e.g. moved outside window due to the input mask change */
7209 _cdk_synthesize_crossing_events_for_geometry_change (window);
7210}
7211
7212static void
7213do_child_input_shapes (CdkWindow *window,
7214 gboolean merge)
7215{
7216 CdkRectangle r;
7217 cairo_region_t *region;
7218
7219 r.x = 0;
7220 r.y = 0;
7221 r.width = window->width;
7222 r.height = window->height;
7223
7224 region = cairo_region_create_rectangle (&r);
7225 remove_child_area (window, TRUE(!(0)), region);
7226
7227 if (merge && window->shape)
7228 cairo_region_subtract (region, window->shape);
7229 if (merge && window->input_shape)
7230 cairo_region_subtract (region, window->input_shape);
7231
7232 cairo_region_xor_rectangle (region, &r);
7233
7234 cdk_window_input_shape_combine_region (window, region, 0, 0);
7235}
7236
7237
7238/**
7239 * cdk_window_set_child_input_shapes:
7240 * @window: a #CdkWindow
7241 *
7242 * Sets the input shape mask of @window to the union of input shape masks
7243 * for all children of @window, ignoring the input shape mask of @window
7244 * itself. Contrast with cdk_window_merge_child_input_shapes() which includes
7245 * the input shape mask of @window in the masks to be merged.
7246 *
7247 * Since: 2.10
7248 **/
7249void
7250cdk_window_set_child_input_shapes (CdkWindow *window)
7251{
7252 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
7253
7254 do_child_input_shapes (window, FALSE(0));
7255}
7256
7257/**
7258 * cdk_window_set_pass_through:
7259 * @window: a #CdkWindow
7260 * @pass_through: a boolean
7261 *
7262 * Sets whether input to the window is passed through to the window
7263 * below.
7264 *
7265 * The default value of this is %FALSE, which means that pointer
7266 * events that happen inside the window are send first to the window,
7267 * but if the event is not selected by the event mask then the event
7268 * is sent to the parent window, and so on up the hierarchy.
7269 *
7270 * If @pass_through is %TRUE then such pointer events happen as if the
7271 * window wasn't there at all, and thus will be sent first to any
7272 * windows below @window. This is useful if the window is used in a
7273 * transparent fashion. In the terminology of the web this would be called
7274 * "pointer-events: none".
7275 *
7276 * Note that a window with @pass_through %TRUE can still have a subwindow
7277 * without pass through, so you can get events on a subset of a window. And in
7278 * that cases you would get the in-between related events such as the pointer
7279 * enter/leave events on its way to the destination window.
7280 *
7281 * Since: 3.18
7282 **/
7283void
7284cdk_window_set_pass_through (CdkWindow *window,
7285 gboolean pass_through)
7286{
7287 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
7288
7289 window->pass_through = !!pass_through;
7290
7291 /* Pointer may have e.g. moved outside window due to the input region change */
7292 _cdk_synthesize_crossing_events_for_geometry_change (window);
7293}
7294
7295/**
7296 * cdk_window_get_pass_through:
7297 * @window: a #CdkWindow
7298 *
7299 * Returns whether input to the window is passed through to the window
7300 * below.
7301 *
7302 * See cdk_window_set_pass_through() for details
7303 *
7304 * Since: 3.18
7305 **/
7306gboolean
7307cdk_window_get_pass_through (CdkWindow *window)
7308{
7309 g_return_val_if_fail (CDK_IS_WINDOW (window), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return ((0)); } } while (0)
;
7310
7311 return window->pass_through;
7312}
7313
7314/**
7315 * cdk_window_merge_child_input_shapes:
7316 * @window: a #CdkWindow
7317 *
7318 * Merges the input shape masks for any child windows into the
7319 * input shape mask for @window. i.e. the union of all input masks
7320 * for @window and its children will become the new input mask
7321 * for @window. See cdk_window_input_shape_combine_region().
7322 *
7323 * This function is distinct from cdk_window_set_child_input_shapes()
7324 * because it includes @window’s input shape mask in the set of
7325 * shapes to be merged.
7326 *
7327 * Since: 2.10
7328 **/
7329void
7330cdk_window_merge_child_input_shapes (CdkWindow *window)
7331{
7332 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
7333
7334 do_child_input_shapes (window, TRUE(!(0)));
7335}
7336
7337
7338/**
7339 * cdk_window_set_static_gravities:
7340 * @window: a #CdkWindow
7341 * @use_static: %TRUE to turn on static gravity
7342 *
7343 * Used to set the bit gravity of the given window to static, and flag
7344 * it so all children get static subwindow gravity. This is used if you
7345 * are implementing scary features that involve deep knowledge of the
7346 * windowing system. Don’t worry about it.
7347 *
7348 * Returns: %FALSE
7349 *
7350 * Deprecated: 3.16: static gravities haven't worked on anything but X11
7351 * for a long time.
7352 */
7353gboolean
7354cdk_window_set_static_gravities (CdkWindow *window,
7355 gboolean use_static G_GNUC_UNUSED__attribute__ ((__unused__)))
7356{
7357 g_return_val_if_fail (CDK_IS_WINDOW (window), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return ((0)); } } while (0)
;
7358
7359 return FALSE(0);
7360}
7361
7362/**
7363 * cdk_window_get_composited:
7364 * @window: a #CdkWindow
7365 *
7366 * Determines whether @window is composited.
7367 *
7368 * See cdk_window_set_composited().
7369 *
7370 * Returns: %TRUE if the window is composited.
7371 *
7372 * Since: 2.22
7373 **/
7374gboolean
7375cdk_window_get_composited (CdkWindow *window)
7376{
7377 g_return_val_if_fail (CDK_IS_WINDOW (window), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return ((0)); } } while (0)
;
7378
7379 return window->composited;
7380}
7381
7382/**
7383 * cdk_window_set_composited:
7384 * @window: a #CdkWindow
7385 * @composited: %TRUE to set the window as composited
7386 *
7387 * Sets a #CdkWindow as composited, or unsets it. Composited
7388 * windows do not automatically have their contents drawn to
7389 * the screen. Drawing is redirected to an offscreen buffer
7390 * and an expose event is emitted on the parent of the composited
7391 * window. It is the responsibility of the parent’s expose handler
7392 * to manually merge the off-screen content onto the screen in
7393 * whatever way it sees fit.
7394 *
7395 * It only makes sense for child windows to be composited; see
7396 * cdk_window_set_opacity() if you need translucent toplevel
7397 * windows.
7398 *
7399 * An additional effect of this call is that the area of this
7400 * window is no longer clipped from regions marked for
7401 * invalidation on its parent. Draws done on the parent
7402 * window are also no longer clipped by the child.
7403 *
7404 * This call is only supported on some systems (currently,
7405 * only X11 with new enough Xcomposite and Xdamage extensions).
7406 * You must call cdk_display_supports_composite() to check if
7407 * setting a window as composited is supported before
7408 * attempting to do so.
7409 *
7410 * Since: 2.12
7411 */
7412void
7413cdk_window_set_composited (CdkWindow *window,
7414 gboolean composited)
7415{
7416 CdkDisplay *display;
7417 CdkWindowImplClass *impl_class;
7418
7419 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
7420
7421 composited = composited != FALSE(0);
7422
7423 if (window->composited == composited)
7424 return;
7425
7426 if (composited)
7427 cdk_window_ensure_native (window);
7428
7429 display = cdk_window_get_display (window);
7430
7431 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
7432
7433 if (composited && (!cdk_display_supports_composite (display) || !impl_class->set_composited))
7434 {
7435 g_warning ("cdk_window_set_composited called but "
7436 "compositing is not supported");
7437 return;
7438 }
7439
7440 impl_class->set_composited (window, composited);
7441
7442 recompute_visible_regions (window, FALSE(0));
7443
7444 if (CDK_WINDOW_IS_MAPPED (window)(((window)->state & CDK_WINDOW_STATE_WITHDRAWN) == 0))
7445 cdk_window_invalidate_in_parent (window);
7446
7447 window->composited = composited;
7448}
7449
7450/**
7451 * cdk_window_get_modal_hint:
7452 * @window: A toplevel #CdkWindow.
7453 *
7454 * Determines whether or not the window manager is hinted that @window
7455 * has modal behaviour.
7456 *
7457 * Returns: whether or not the window has the modal hint set.
7458 *
7459 * Since: 2.22
7460 */
7461gboolean
7462cdk_window_get_modal_hint (CdkWindow *window)
7463{
7464 g_return_val_if_fail (CDK_IS_WINDOW (window), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return ((0)); } } while (0)
;
7465
7466 return window->modal_hint;
7467}
7468
7469/**
7470 * cdk_window_get_accept_focus:
7471 * @window: a toplevel #CdkWindow.
7472 *
7473 * Determines whether or not the desktop environment shuld be hinted that
7474 * the window does not want to receive input focus.
7475 *
7476 * Returns: whether or not the window should receive input focus.
7477 *
7478 * Since: 2.22
7479 */
7480gboolean
7481cdk_window_get_accept_focus (CdkWindow *window)
7482{
7483 g_return_val_if_fail (CDK_IS_WINDOW (window), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return ((0)); } } while (0)
;
7484
7485 return window->accept_focus;
7486}
7487
7488/**
7489 * cdk_window_get_focus_on_map:
7490 * @window: a toplevel #CdkWindow.
7491 *
7492 * Determines whether or not the desktop environment should be hinted that the
7493 * window does not want to receive input focus when it is mapped.
7494 *
7495 * Returns: whether or not the window wants to receive input focus when
7496 * it is mapped.
7497 *
7498 * Since: 2.22
7499 */
7500gboolean
7501cdk_window_get_focus_on_map (CdkWindow *window)
7502{
7503 g_return_val_if_fail (CDK_IS_WINDOW (window), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return ((0)); } } while (0)
;
7504
7505 return window->focus_on_map;
7506}
7507
7508/**
7509 * cdk_window_is_input_only:
7510 * @window: a toplevel #CdkWindow
7511 *
7512 * Determines whether or not the window is an input only window.
7513 *
7514 * Returns: %TRUE if @window is input only
7515 *
7516 * Since: 2.22
7517 */
7518gboolean
7519cdk_window_is_input_only (CdkWindow *window)
7520{
7521 g_return_val_if_fail (CDK_IS_WINDOW (window), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return ((0)); } } while (0)
;
7522
7523 return window->input_only;
7524}
7525
7526/**
7527 * cdk_window_is_shaped:
7528 * @window: a toplevel #CdkWindow
7529 *
7530 * Determines whether or not the window is shaped.
7531 *
7532 * Returns: %TRUE if @window is shaped
7533 *
7534 * Since: 2.22
7535 */
7536gboolean
7537cdk_window_is_shaped (CdkWindow *window)
7538{
7539 g_return_val_if_fail (CDK_IS_WINDOW (window), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return ((0)); } } while (0)
;
7540
7541 return window->shaped;
7542}
7543
7544/* Gets the toplevel for a window as used for events,
7545 i.e. including offscreen parents */
7546static CdkWindow *
7547get_event_parent (CdkWindow *window)
7548{
7549 if (cdk_window_is_offscreen (window))
7550 return cdk_offscreen_window_get_embedder ((CdkWindow *)window);
7551 else
7552 return window->parent;
7553}
7554
7555/* Gets the toplevel for a window as used for events,
7556 i.e. including offscreen parents going up to the native
7557 toplevel */
7558static CdkWindow *
7559get_event_toplevel (CdkWindow *window)
7560{
7561 CdkWindow *parent;
7562
7563 while ((parent = get_event_parent (window)) != NULL((void*)0) &&
7564 (parent->window_type != CDK_WINDOW_ROOT))
7565 window = parent;
7566
7567 return window;
7568}
7569
7570gboolean
7571_cdk_window_event_parent_of (CdkWindow *parent,
7572 CdkWindow *child)
7573{
7574 CdkWindow *w;
7575
7576 w = child;
7577 while (w != NULL((void*)0))
7578 {
7579 if (w == parent)
7580 return TRUE(!(0));
7581
7582 w = get_event_parent (w);
7583 }
7584
7585 return FALSE(0);
7586}
7587
7588static void
7589update_cursor (CdkDisplay *display,
7590 CdkDevice *device)
7591{
7592 CdkWindow *cursor_window, *parent, *toplevel;
7593 CdkWindow *pointer_window;
7594 CdkWindowImplClass *impl_class;
7595 CdkPointerWindowInfo *pointer_info;
7596 CdkDeviceGrabInfo *grab;
7597 CdkCursor *cursor;
7598
7599 pointer_info = _cdk_display_get_pointer_info (display, device);
7600 pointer_window = pointer_info->window_under_pointer;
7601
7602 /* We ignore the serials here and just pick the last grab
7603 we've sent, as that would shortly be used anyway. */
7604 grab = _cdk_display_get_last_device_grab (display, device);
7605 if (/* have grab */
7606 grab != NULL((void*)0) &&
7607 /* the pointer is not in a descendant of the grab window */
7608 !_cdk_window_event_parent_of (grab->window, pointer_window))
7609 {
7610 /* use the cursor from the grab window */
7611 cursor_window = grab->window;
7612 }
7613 else
7614 {
7615 /* otherwise use the cursor from the pointer window */
7616 cursor_window = pointer_window;
7617 }
7618
7619 /* Find the first window with the cursor actually set, as
7620 the cursor is inherited from the parent */
7621 while (cursor_window->cursor == NULL((void*)0) &&
7622 !g_hash_table_contains (cursor_window->device_cursor, device) &&
7623 (parent = get_event_parent (cursor_window)) != NULL((void*)0) &&
7624 parent->window_type != CDK_WINDOW_ROOT)
7625 cursor_window = parent;
7626
7627 cursor = g_hash_table_lookup (cursor_window->device_cursor, device);
7628
7629 if (!cursor)
7630 cursor = cursor_window->cursor;
7631
7632 /* Set all cursors on toplevel, otherwise its tricky to keep track of
7633 * which native window has what cursor set. */
7634 toplevel = get_event_toplevel (pointer_window);
7635 impl_class = CDK_WINDOW_IMPL_GET_CLASS (toplevel->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((toplevel->impl
)))->g_class))))
;
7636 impl_class->set_device_cursor (toplevel, device, cursor);
7637}
7638
7639static gboolean
7640point_in_window (CdkWindow *window,
7641 gdouble x,
7642 gdouble y)
7643{
7644 return
7645 x >= 0 && x < window->width &&
7646 y >= 0 && y < window->height &&
7647 (window->shape == NULL((void*)0) ||
7648 cairo_region_contains_point (window->shape,
7649 x, y)) &&
7650 (window->input_shape == NULL((void*)0) ||
7651 cairo_region_contains_point (window->input_shape,
7652 x, y));
7653}
7654
7655/* Same as point_in_window, except it also takes pass_through and its
7656 interaction with child windows into account */
7657static gboolean
7658point_in_input_window (CdkWindow *window,
7659 gdouble x,
7660 gdouble y,
7661 CdkWindow **input_window,
7662 gdouble *input_window_x,
7663 gdouble *input_window_y)
7664{
7665 CdkWindow *sub;
7666 double child_x, child_y;
7667 GList *l;
7668
7669 if (!point_in_window (window, x, y))
7670 return FALSE(0);
7671
7672 if (!window->pass_through)
7673 {
7674 if (input_window)
7675 {
7676 *input_window = window;
7677 *input_window_x = x;
7678 *input_window_y = y;
7679 }
7680 return TRUE(!(0));
7681 }
7682
7683 /* For pass-through, must be over a child input window */
7684
7685 /* Children is ordered in reverse stack order, i.e. first is topmost */
7686 for (l = window->children; l != NULL((void*)0); l = l->next)
7687 {
7688 sub = l->data;
7689
7690 if (!CDK_WINDOW_IS_MAPPED (sub)(((sub)->state & CDK_WINDOW_STATE_WITHDRAWN) == 0))
7691 continue;
7692
7693 cdk_window_coords_from_parent ((CdkWindow *)sub,
7694 x, y,
7695 &child_x, &child_y);
7696 if (point_in_input_window (sub, child_x, child_y,
7697 input_window, input_window_x, input_window_y))
7698 {
7699 if (input_window)
7700 cdk_window_coords_to_parent (sub,
7701 *input_window_x,
7702 *input_window_y,
7703 input_window_x,
7704 input_window_y);
7705 return TRUE(!(0));
7706 }
7707 }
7708
7709 return FALSE(0);
7710}
7711
7712static CdkWindow *
7713convert_native_coords_to_toplevel (CdkWindow *window,
7714 gdouble child_x,
7715 gdouble child_y,
7716 gdouble *toplevel_x,
7717 gdouble *toplevel_y)
7718{
7719 gdouble x, y;
7720
7721 x = child_x;
7722 y = child_y;
7723
7724 while (!cdk_window_is_toplevel (window))
7725 {
7726 x += window->x;
7727 y += window->y;
7728 window = window->parent;
7729 }
7730
7731 *toplevel_x = x;
7732 *toplevel_y = y;
7733
7734 return window;
7735}
7736
7737static void
7738convert_toplevel_coords_to_window (CdkWindow *window,
7739 gdouble toplevel_x,
7740 gdouble toplevel_y,
7741 gdouble *window_x,
7742 gdouble *window_y)
7743{
7744 CdkWindow *parent;
7745 gdouble x, y;
7746 GList *children, *l;
7747
7748 x = toplevel_x;
7749 y = toplevel_y;
7750
7751 children = NULL((void*)0);
7752 while ((parent = get_event_parent (window)) != NULL((void*)0) &&
7753 (parent->window_type != CDK_WINDOW_ROOT))
7754 {
7755 children = g_list_prepend (children, window);
7756 window = parent;
7757 }
7758
7759 for (l = children; l != NULL((void*)0); l = l->next)
7760 cdk_window_coords_from_parent (l->data, x, y, &x, &y);
7761
7762 g_list_free (children);
7763
7764 *window_x = x;
7765 *window_y = y;
7766}
7767
7768static CdkWindow *
7769pick_embedded_child (CdkWindow *window,
7770 gdouble x,
7771 gdouble y)
7772{
7773 CdkWindow *res;
7774
7775 res = NULL((void*)0);
7776 g_signal_emit (window,
7777 signals[PICK_EMBEDDED_CHILD], 0,
7778 x, y, &res);
7779
7780 return res;
7781}
7782
7783CdkWindow *
7784_cdk_window_find_child_at (CdkWindow *window,
7785 double x,
7786 double y)
7787{
7788 CdkWindow *sub;
7789 double child_x, child_y;
7790 GList *l;
7791
7792 if (point_in_window (window, x, y))
7793 {
7794 /* Children is ordered in reverse stack order, i.e. first is topmost */
7795 for (l = window->children; l != NULL((void*)0); l = l->next)
7796 {
7797 sub = l->data;
7798
7799 if (!CDK_WINDOW_IS_MAPPED (sub)(((sub)->state & CDK_WINDOW_STATE_WITHDRAWN) == 0))
7800 continue;
7801
7802 cdk_window_coords_from_parent ((CdkWindow *)sub,
7803 x, y,
7804 &child_x, &child_y);
7805 if (point_in_input_window (sub, child_x, child_y,
7806 NULL((void*)0), NULL((void*)0), NULL((void*)0)))
7807 return (CdkWindow *)sub;
7808 }
7809
7810 if (window->num_offscreen_children > 0)
7811 {
7812 sub = pick_embedded_child (window,
7813 x, y);
7814 if (sub)
7815 return (CdkWindow *)sub;
7816 }
7817 }
7818
7819 return NULL((void*)0);
7820}
7821
7822CdkWindow *
7823_cdk_window_find_descendant_at (CdkWindow *window,
7824 gdouble x,
7825 gdouble y,
7826 gdouble *found_x,
7827 gdouble *found_y)
7828{
7829 CdkWindow *sub, *input_window;
7830 gdouble child_x, child_y;
7831 GList *l;
7832 gboolean found;
7833
7834 if (point_in_window (window, x, y))
7835 {
7836 do
7837 {
7838 found = FALSE(0);
7839 /* Children is ordered in reverse stack order, i.e. first is topmost */
7840 for (l = window->children; l != NULL((void*)0); l = l->next)
7841 {
7842 sub = l->data;
7843
7844 if (!CDK_WINDOW_IS_MAPPED (sub)(((sub)->state & CDK_WINDOW_STATE_WITHDRAWN) == 0))
7845 continue;
7846
7847 cdk_window_coords_from_parent ((CdkWindow *)sub,
7848 x, y,
7849 &child_x, &child_y);
7850 if (point_in_input_window (sub, child_x, child_y,
7851 &input_window, &child_x, &child_y))
7852 {
7853 x = child_x;
7854 y = child_y;
7855 window = input_window;
7856 found = TRUE(!(0));
7857 break;
7858 }
7859 }
7860 if (!found &&
7861 window->num_offscreen_children > 0)
7862 {
7863 sub = pick_embedded_child (window,
7864 x, y);
7865 if (sub)
7866 {
7867 found = TRUE(!(0));
7868 window = sub;
7869 from_embedder (sub, x, y, &x, &y);
7870 }
7871 }
7872 }
7873 while (found);
7874 }
7875 else
7876 {
7877 /* Not in window at all */
7878 window = NULL((void*)0);
7879 }
7880
7881 if (found_x)
7882 *found_x = x;
7883 if (found_y)
7884 *found_y = y;
7885
7886 return window;
7887}
7888
7889/**
7890 * cdk_window_beep:
7891 * @window: a toplevel #CdkWindow
7892 *
7893 * Emits a short beep associated to @window in the appropriate
7894 * display, if supported. Otherwise, emits a short beep on
7895 * the display just as cdk_display_beep().
7896 *
7897 * Since: 2.12
7898 **/
7899void
7900cdk_window_beep (CdkWindow *window)
7901{
7902 CdkDisplay *display;
7903 CdkWindow *toplevel;
7904
7905 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
7906
7907 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
7908 return;
7909
7910 toplevel = get_event_toplevel (window);
7911 display = cdk_window_get_display (window);
7912
7913 if (toplevel)
7914 {
7915 if (CDK_WINDOW_IMPL_GET_CLASS (toplevel->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((toplevel->impl
)))->g_class))))
->beep (toplevel))
7916 return;
7917 }
7918
7919 /* If windows fail to beep, we beep the display. */
7920 cdk_display_beep (display);
7921}
7922
7923/**
7924 * cdk_window_set_support_multidevice:
7925 * @window: a #CdkWindow.
7926 * @support_multidevice: %TRUE to enable multidevice support in @window.
7927 *
7928 * This function will enable multidevice features in @window.
7929 *
7930 * Multidevice aware windows will need to handle properly multiple,
7931 * per device enter/leave events, device grabs and grab ownerships.
7932 *
7933 * Since: 3.0
7934 **/
7935void
7936cdk_window_set_support_multidevice (CdkWindow *window,
7937 gboolean support_multidevice)
7938{
7939 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
7940
7941 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
7942 return;
7943
7944 if (window->support_multidevice == support_multidevice)
7945 return;
7946
7947 window->support_multidevice = support_multidevice;
7948
7949 /* FIXME: What to do if called when some pointers are inside the window ? */
7950}
7951
7952/**
7953 * cdk_window_get_support_multidevice:
7954 * @window: a #CdkWindow.
7955 *
7956 * Returns %TRUE if the window is aware of the existence of multiple
7957 * devices.
7958 *
7959 * Returns: %TRUE if the window handles multidevice features.
7960 *
7961 * Since: 3.0
7962 **/
7963gboolean
7964cdk_window_get_support_multidevice (CdkWindow *window)
7965{
7966 g_return_val_if_fail (CDK_IS_WINDOW (window), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return ((0)); } } while (0)
;
7967
7968 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
7969 return FALSE(0);
7970
7971 return window->support_multidevice;
7972}
7973
7974static const guint type_masks[] = {
7975 CDK_SUBSTRUCTURE_MASK, /* CDK_DELETE = 0 */
7976 CDK_STRUCTURE_MASK, /* CDK_DESTROY = 1 */
7977 CDK_EXPOSURE_MASK, /* CDK_EXPOSE = 2 */
7978 CDK_POINTER_MOTION_MASK, /* CDK_MOTION_NOTIFY = 3 */
7979 CDK_BUTTON_PRESS_MASK, /* CDK_BUTTON_PRESS = 4 */
7980 CDK_BUTTON_PRESS_MASK, /* CDK_2BUTTON_PRESS = 5 */
7981 CDK_BUTTON_PRESS_MASK, /* CDK_3BUTTON_PRESS = 6 */
7982 CDK_BUTTON_RELEASE_MASK, /* CDK_BUTTON_RELEASE = 7 */
7983 CDK_KEY_PRESS_MASK, /* CDK_KEY_PRESS = 8 */
7984 CDK_KEY_RELEASE_MASK, /* CDK_KEY_RELEASE = 9 */
7985 CDK_ENTER_NOTIFY_MASK, /* CDK_ENTER_NOTIFY = 10 */
7986 CDK_LEAVE_NOTIFY_MASK, /* CDK_LEAVE_NOTIFY = 11 */
7987 CDK_FOCUS_CHANGE_MASK, /* CDK_FOCUS_CHANGE = 12 */
7988 CDK_STRUCTURE_MASK, /* CDK_CONFIGURE = 13 */
7989 CDK_VISIBILITY_NOTIFY_MASK, /* CDK_MAP = 14 */
7990 CDK_VISIBILITY_NOTIFY_MASK, /* CDK_UNMAP = 15 */
7991 CDK_PROPERTY_CHANGE_MASK, /* CDK_PROPERTY_NOTIFY = 16 */
7992 CDK_PROPERTY_CHANGE_MASK, /* CDK_SELECTION_CLEAR = 17 */
7993 CDK_PROPERTY_CHANGE_MASK, /* CDK_SELECTION_REQUEST = 18 */
7994 CDK_PROPERTY_CHANGE_MASK, /* CDK_SELECTION_NOTIFY = 19 */
7995 CDK_PROXIMITY_IN_MASK, /* CDK_PROXIMITY_IN = 20 */
7996 CDK_PROXIMITY_OUT_MASK, /* CDK_PROXIMITY_OUT = 21 */
7997 CDK_ALL_EVENTS_MASK, /* CDK_DRAG_ENTER = 22 */
7998 CDK_ALL_EVENTS_MASK, /* CDK_DRAG_LEAVE = 23 */
7999 CDK_ALL_EVENTS_MASK, /* CDK_DRAG_MOTION = 24 */
8000 CDK_ALL_EVENTS_MASK, /* CDK_DRAG_STATUS = 25 */
8001 CDK_ALL_EVENTS_MASK, /* CDK_DROP_START = 26 */
8002 CDK_ALL_EVENTS_MASK, /* CDK_DROP_FINISHED = 27 */
8003 CDK_ALL_EVENTS_MASK, /* CDK_CLIENT_EVENT = 28 */
8004 CDK_VISIBILITY_NOTIFY_MASK, /* CDK_VISIBILITY_NOTIFY = 29 */
8005 CDK_EXPOSURE_MASK, /* CDK_NO_EXPOSE = 30 */
8006 CDK_SCROLL_MASK | CDK_SMOOTH_SCROLL_MASK,/* CDK_SCROLL= 31 */
8007 0, /* CDK_WINDOW_STATE = 32 */
8008 0, /* CDK_SETTING = 33 */
8009 0, /* CDK_OWNER_CHANGE = 34 */
8010 0, /* CDK_GRAB_BROKEN = 35 */
8011 0, /* CDK_DAMAGE = 36 */
8012 CDK_TOUCH_MASK, /* CDK_TOUCH_BEGIN = 37 */
8013 CDK_TOUCH_MASK, /* CDK_TOUCH_UPDATE = 38 */
8014 CDK_TOUCH_MASK, /* CDK_TOUCH_END = 39 */
8015 CDK_TOUCH_MASK, /* CDK_TOUCH_CANCEL = 40 */
8016 CDK_TOUCHPAD_GESTURE_MASK, /* CDK_TOUCHPAD_SWIPE = 41 */
8017 CDK_TOUCHPAD_GESTURE_MASK, /* CDK_TOUCHPAD_PINCH = 42 */
8018 CDK_TABLET_PAD_MASK, /* CDK_PAD_BUTTON_PRESS = 43 */
8019 CDK_TABLET_PAD_MASK, /* CDK_PAD_BUTTON_RELEASE = 44 */
8020 CDK_TABLET_PAD_MASK, /* CDK_PAD_RING = 45 */
8021 CDK_TABLET_PAD_MASK, /* CDK_PAD_STRIP = 46 */
8022 CDK_TABLET_PAD_MASK, /* CDK_PAD_GROUP_MODE = 47 */
8023};
8024G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == CDK_EVENT_LAST)_Static_assert ((sizeof (type_masks) / sizeof ((type_masks)[0
])) == CDK_EVENT_LAST, "Expression evaluates to false")
;
8025
8026/* send motion events if the right buttons are down */
8027static guint
8028update_evmask_for_button_motion (guint evmask,
8029 CdkModifierType mask)
8030{
8031 if (evmask & CDK_BUTTON_MOTION_MASK &&
8032 mask & (CDK_BUTTON1_MASK |
8033 CDK_BUTTON2_MASK |
8034 CDK_BUTTON3_MASK |
8035 CDK_BUTTON4_MASK |
8036 CDK_BUTTON5_MASK))
8037 evmask |= CDK_POINTER_MOTION_MASK;
8038
8039 if ((evmask & CDK_BUTTON1_MOTION_MASK && mask & CDK_BUTTON1_MASK) ||
8040 (evmask & CDK_BUTTON2_MOTION_MASK && mask & CDK_BUTTON2_MASK) ||
8041 (evmask & CDK_BUTTON3_MOTION_MASK && mask & CDK_BUTTON3_MASK))
8042 evmask |= CDK_POINTER_MOTION_MASK;
8043
8044 return evmask;
8045}
8046
8047static gboolean
8048is_button_type (CdkEventType type)
8049{
8050 return type == CDK_BUTTON_PRESS ||
8051 type == CDK_2BUTTON_PRESS ||
8052 type == CDK_3BUTTON_PRESS ||
8053 type == CDK_BUTTON_RELEASE ||
8054 type == CDK_TOUCH_BEGIN ||
8055 type == CDK_TOUCH_END ||
8056 type == CDK_TOUCH_CANCEL ||
8057 type == CDK_SCROLL;
8058}
8059
8060static gboolean
8061is_gesture_type (CdkEventType type)
8062{
8063 return (type == CDK_TOUCHPAD_SWIPE ||
8064 type == CDK_TOUCHPAD_PINCH);
8065}
8066
8067static gboolean
8068is_motion_type (CdkEventType type)
8069{
8070 return type == CDK_MOTION_NOTIFY ||
8071 type == CDK_TOUCH_UPDATE ||
8072 type == CDK_ENTER_NOTIFY ||
8073 type == CDK_LEAVE_NOTIFY;
8074}
8075
8076static gboolean
8077is_touch_type (CdkEventType type)
8078{
8079 return type == CDK_TOUCH_BEGIN ||
8080 type == CDK_TOUCH_UPDATE ||
8081 type == CDK_TOUCH_END ||
8082 type == CDK_TOUCH_CANCEL;
8083}
8084
8085static CdkWindow *
8086find_common_ancestor (CdkWindow *win1,
8087 CdkWindow *win2)
8088{
8089 CdkWindow *tmp;
8090 GList *path1 = NULL((void*)0), *path2 = NULL((void*)0);
8091 GList *list1, *list2;
8092
8093 tmp = win1;
8094 while (tmp != NULL((void*)0) && tmp->window_type != CDK_WINDOW_ROOT)
8095 {
8096 path1 = g_list_prepend (path1, tmp);
8097 tmp = get_event_parent (tmp);
8098 }
8099
8100 tmp = win2;
8101 while (tmp != NULL((void*)0) && tmp->window_type != CDK_WINDOW_ROOT)
8102 {
8103 path2 = g_list_prepend (path2, tmp);
8104 tmp = get_event_parent (tmp);
8105 }
8106
8107 list1 = path1;
8108 list2 = path2;
8109 tmp = NULL((void*)0);
8110 while (list1 && list2 && (list1->data == list2->data))
8111 {
8112 tmp = list1->data;
8113 list1 = list1->next;
8114 list2 = list2->next;
8115 }
8116 g_list_free (path1);
8117 g_list_free (path2);
8118
8119 return tmp;
8120}
8121
8122CdkEvent *
8123_cdk_make_event (CdkWindow *window,
8124 CdkEventType type,
8125 CdkEvent *event_in_queue,
8126 gboolean before_event)
8127{
8128 CdkEvent *event = cdk_event_new (type);
8129 guint32 the_time;
8130 CdkModifierType the_state;
8131
8132 the_time = cdk_event_get_time (event_in_queue);
8133 cdk_event_get_state (event_in_queue, &the_state);
8134
8135 event->any.window = g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
8136 event->any.send_event = FALSE(0);
8137 if (event_in_queue && event_in_queue->any.send_event)
8138 event->any.send_event = TRUE(!(0));
8139
8140 switch (type)
8141 {
8142 case CDK_MOTION_NOTIFY:
8143 event->motion.time = the_time;
8144 event->motion.axes = NULL((void*)0);
8145 event->motion.state = the_state;
8146 break;
8147
8148 case CDK_BUTTON_PRESS:
8149 case CDK_2BUTTON_PRESS:
8150 case CDK_3BUTTON_PRESS:
8151 case CDK_BUTTON_RELEASE:
8152 event->button.time = the_time;
8153 event->button.axes = NULL((void*)0);
8154 event->button.state = the_state;
8155 break;
8156
8157 case CDK_TOUCH_BEGIN:
8158 case CDK_TOUCH_UPDATE:
8159 case CDK_TOUCH_END:
8160 case CDK_TOUCH_CANCEL:
8161 event->touch.time = the_time;
8162 event->touch.axes = NULL((void*)0);
8163 event->touch.state = the_state;
8164 break;
8165
8166 case CDK_SCROLL:
8167 event->scroll.time = the_time;
8168 event->scroll.state = the_state;
8169 break;
8170
8171 case CDK_KEY_PRESS:
8172 case CDK_KEY_RELEASE:
8173 event->key.time = the_time;
8174 event->key.state = the_state;
8175 break;
8176
8177 case CDK_ENTER_NOTIFY:
8178 case CDK_LEAVE_NOTIFY:
8179 event->crossing.time = the_time;
8180 event->crossing.state = the_state;
8181 break;
8182
8183 case CDK_PROPERTY_NOTIFY:
8184 event->property.time = the_time;
8185 event->property.state = the_state;
8186 break;
8187
8188 case CDK_SELECTION_CLEAR:
8189 case CDK_SELECTION_REQUEST:
8190 case CDK_SELECTION_NOTIFY:
8191 event->selection.time = the_time;
8192 break;
8193
8194 case CDK_PROXIMITY_IN:
8195 case CDK_PROXIMITY_OUT:
8196 event->proximity.time = the_time;
8197 break;
8198
8199 case CDK_DRAG_ENTER:
8200 case CDK_DRAG_LEAVE:
8201 case CDK_DRAG_MOTION:
8202 case CDK_DRAG_STATUS:
8203 case CDK_DROP_START:
8204 case CDK_DROP_FINISHED:
8205 event->dnd.time = the_time;
8206 break;
8207
8208 case CDK_TOUCHPAD_SWIPE:
8209 event->touchpad_swipe.time = the_time;
8210 event->touchpad_swipe.state = the_state;
8211 break;
8212
8213 case CDK_TOUCHPAD_PINCH:
8214 event->touchpad_pinch.time = the_time;
8215 event->touchpad_pinch.state = the_state;
8216 break;
8217
8218 case CDK_FOCUS_CHANGE:
8219 case CDK_CONFIGURE:
8220 case CDK_MAP:
8221 case CDK_UNMAP:
8222 case CDK_CLIENT_EVENT:
8223 case CDK_VISIBILITY_NOTIFY:
8224 case CDK_DELETE:
8225 case CDK_DESTROY:
8226 case CDK_EXPOSE:
8227 default:
8228 break;
8229 }
8230
8231 if (event_in_queue)
8232 {
8233 if (before_event)
8234 _cdk_event_queue_insert_before (cdk_window_get_display (window), event_in_queue, event);
8235 else
8236 _cdk_event_queue_insert_after (cdk_window_get_display (window), event_in_queue, event);
8237 }
8238 else
8239 _cdk_event_queue_append (cdk_window_get_display (window), event);
8240
8241 return event;
8242}
8243
8244static void
8245send_crossing_event (CdkDisplay *display,
8246 CdkWindow *toplevel,
8247 CdkWindow *window,
8248 CdkEventType type,
8249 CdkCrossingMode mode,
8250 CdkNotifyType notify_type,
8251 CdkWindow *subwindow,
8252 CdkDevice *device,
8253 CdkDevice *source_device,
8254 gdouble toplevel_x,
8255 gdouble toplevel_y,
8256 CdkModifierType mask,
8257 guint32 time_,
8258 CdkEvent *event_in_queue,
8259 gulong serial)
8260{
8261 CdkEvent *event;
8262 guint32 window_event_mask, type_event_mask;
8263 CdkDeviceGrabInfo *grab;
8264 CdkTouchGrabInfo *touch_grab = NULL((void*)0);
8265 CdkPointerWindowInfo *pointer_info;
8266 gboolean block_event = FALSE(0);
8267 CdkEventSequence *sequence;
8268
8269 grab = _cdk_display_has_device_grab (display, device, serial);
8270 pointer_info = _cdk_display_get_pointer_info (display, device);
8271
8272 sequence = cdk_event_get_event_sequence (event_in_queue);
8273 if (sequence)
8274 touch_grab = _cdk_display_has_touch_grab (display, device, sequence, serial);
8275
8276 if (touch_grab)
8277 {
8278 if (window != touch_grab->window)
8279 return;
8280
8281 window_event_mask = touch_grab->event_mask;
8282 }
8283 else if (grab != NULL((void*)0) &&
8284 !grab->owner_events)
8285 {
8286 /* !owner_event => only report events wrt grab window, ignore rest */
8287 if ((CdkWindow *)window != grab->window)
8288 return;
8289 window_event_mask = grab->event_mask;
8290 }
8291 else
8292 window_event_mask = window->event_mask;
8293
8294 if (type == CDK_ENTER_NOTIFY &&
8295 (pointer_info->need_touch_press_enter ||
8296 (source_device &&
8297 cdk_device_get_source (source_device) == CDK_SOURCE_TOUCHSCREEN)) &&
8298 mode != CDK_CROSSING_TOUCH_BEGIN &&
8299 mode != CDK_CROSSING_TOUCH_END)
8300 {
8301 pointer_info->need_touch_press_enter = TRUE(!(0));
8302 block_event = TRUE(!(0));
8303 }
8304 else if (type == CDK_LEAVE_NOTIFY)
8305 {
8306 type_event_mask = CDK_LEAVE_NOTIFY_MASK;
8307 window->devices_inside = g_list_remove (window->devices_inside, device);
8308
8309 if (!window->support_multidevice && window->devices_inside)
8310 {
8311 /* Block leave events unless it's the last pointer */
8312 block_event = TRUE(!(0));
8313 }
8314 }
8315 else
8316 {
8317 type_event_mask = CDK_ENTER_NOTIFY_MASK;
8318
8319 if (!window->support_multidevice && window->devices_inside)
8320 {
8321 /* Only emit enter events for the first device */
8322 block_event = TRUE(!(0));
8323 }
8324
8325 if (cdk_device_get_device_type (device) == CDK_DEVICE_TYPE_MASTER &&
8326 cdk_device_get_mode (device) != CDK_MODE_DISABLED &&
8327 !g_list_find (window->devices_inside, device))
8328 window->devices_inside = g_list_prepend (window->devices_inside, device);
8329 }
8330
8331 if (block_event)
8332 return;
8333
8334 if (window_event_mask & type_event_mask)
8335 {
8336 event = _cdk_make_event ((CdkWindow *)window, type, event_in_queue, TRUE(!(0)));
8337 cdk_event_set_device (event, device);
8338 cdk_event_set_seat (event, cdk_device_get_seat (device));
8339
8340 if (source_device)
8341 cdk_event_set_source_device (event, source_device);
8342
8343 event->crossing.time = time_;
8344 event->crossing.subwindow = subwindow;
8345 if (subwindow)
8346 g_object_ref (subwindow)((__typeof__ (subwindow)) (g_object_ref) (subwindow));
8347 convert_toplevel_coords_to_window ((CdkWindow *)window,
8348 toplevel_x, toplevel_y,
8349 &event->crossing.x, &event->crossing.y);
8350 event->crossing.x_root = toplevel_x + toplevel->x;
8351 event->crossing.y_root = toplevel_y + toplevel->y;
8352 event->crossing.mode = mode;
8353 event->crossing.detail = notify_type;
8354 event->crossing.focus = FALSE(0);
8355 event->crossing.state = mask;
8356 }
8357}
8358
8359
8360/* The coordinates are in the toplevel window that src/dest are in.
8361 * src and dest are always (if != NULL) in the same toplevel, as
8362 * we get a leave-notify and set the window_under_pointer to null
8363 * before crossing to another toplevel.
8364 */
8365void
8366_cdk_synthesize_crossing_events (CdkDisplay *display,
8367 CdkWindow *src,
8368 CdkWindow *dest,
8369 CdkDevice *device,
8370 CdkDevice *source_device,
8371 CdkCrossingMode mode,
8372 double toplevel_x,
8373 double toplevel_y,
8374 CdkModifierType mask,
8375 guint32 time_,
8376 CdkEvent *event_in_queue,
8377 gulong serial,
8378 gboolean non_linear)
8379{
8380 CdkWindow *c;
8381 CdkWindow *win, *last, *next;
8382 GList *path, *list;
8383 CdkWindow *a;
8384 CdkWindow *b;
8385 CdkWindow *toplevel;
8386 CdkNotifyType notify_type;
8387
8388 /* TODO: Don't send events to toplevel, as we get those from the windowing system */
8389
8390 a = (src && CDK_IS_WINDOW (src)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(src)); GType __t = ((cdk_window_get_type ())); gboolean __r;
if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
) ? src : NULL((void*)0);
8391 b = (dest && CDK_IS_WINDOW (dest)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(dest)); GType __t = ((cdk_window_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
) ? dest : NULL((void*)0);
8392
8393 if (src == dest)
8394 return; /* No crossings generated between src and dest */
8395
8396 if (cdk_device_get_device_type (device) != CDK_DEVICE_TYPE_MASTER)
8397 {
8398 if (a && cdk_window_get_device_events (src, device) == 0)
8399 a = NULL((void*)0);
8400
8401 if (b && cdk_window_get_device_events (dest, device) == 0)
8402 b = NULL((void*)0);
8403 }
8404
8405 if (!a && !b)
8406 return;
8407
8408 c = find_common_ancestor (a, b);
8409
8410 non_linear |= (c != a) && (c != b);
8411
8412 if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
8413 {
8414 toplevel = cdk_window_get_toplevel (a);
8415
8416 /* Traverse up from a to (excluding) c sending leave events */
8417 if (non_linear)
8418 notify_type = CDK_NOTIFY_NONLINEAR;
8419 else if (c == a)
8420 notify_type = CDK_NOTIFY_INFERIOR;
8421 else
8422 notify_type = CDK_NOTIFY_ANCESTOR;
8423 send_crossing_event (display, toplevel,
8424 a, CDK_LEAVE_NOTIFY,
8425 mode,
8426 notify_type,
8427 NULL((void*)0), device, source_device,
8428 toplevel_x, toplevel_y,
8429 mask, time_,
8430 event_in_queue,
8431 serial);
8432
8433 if (c != a)
8434 {
8435 if (non_linear)
8436 notify_type = CDK_NOTIFY_NONLINEAR_VIRTUAL;
8437 else
8438 notify_type = CDK_NOTIFY_VIRTUAL;
8439
8440 last = a;
8441 win = get_event_parent (a);
8442 while (win != c && win->window_type != CDK_WINDOW_ROOT)
8443 {
8444 send_crossing_event (display, toplevel,
8445 win, CDK_LEAVE_NOTIFY,
8446 mode,
8447 notify_type,
8448 (CdkWindow *)last,
8449 device, source_device,
8450 toplevel_x, toplevel_y,
8451 mask, time_,
8452 event_in_queue,
8453 serial);
8454
8455 last = win;
8456 win = get_event_parent (win);
8457 }
8458 }
8459 }
8460
8461 if (b) /* Might not be a dest, e.g. if we're moving out of the window */
8462 {
8463 toplevel = cdk_window_get_toplevel ((CdkWindow *)b);
8464
8465 /* Traverse down from c to b */
8466 if (c != b)
8467 {
8468 path = NULL((void*)0);
8469 win = get_event_parent (b);
8470 while (win != c && win->window_type != CDK_WINDOW_ROOT)
8471 {
8472 path = g_list_prepend (path, win);
8473 win = get_event_parent (win);
8474 }
8475
8476 if (non_linear)
8477 notify_type = CDK_NOTIFY_NONLINEAR_VIRTUAL;
8478 else
8479 notify_type = CDK_NOTIFY_VIRTUAL;
8480
8481 list = path;
8482 while (list)
8483 {
8484 win = list->data;
8485 list = list->next;
8486 if (list)
8487 next = list->data;
8488 else
8489 next = b;
8490
8491 send_crossing_event (display, toplevel,
8492 win, CDK_ENTER_NOTIFY,
8493 mode,
8494 notify_type,
8495 (CdkWindow *)next,
8496 device, source_device,
8497 toplevel_x, toplevel_y,
8498 mask, time_,
8499 event_in_queue,
8500 serial);
8501 }
8502 g_list_free (path);
8503 }
8504
8505
8506 if (non_linear)
8507 notify_type = CDK_NOTIFY_NONLINEAR;
8508 else if (c == a)
8509 notify_type = CDK_NOTIFY_ANCESTOR;
8510 else
8511 notify_type = CDK_NOTIFY_INFERIOR;
8512
8513 send_crossing_event (display, toplevel,
8514 b, CDK_ENTER_NOTIFY,
8515 mode,
8516 notify_type,
8517 NULL((void*)0),
8518 device, source_device,
8519 toplevel_x, toplevel_y,
8520 mask, time_,
8521 event_in_queue,
8522 serial);
8523 }
8524}
8525
8526/* Returns the window inside the event window with the pointer in it
8527 * at the specified coordinates, or NULL if its not in any child of
8528 * the toplevel. It also takes into account !owner_events grabs.
8529 */
8530static CdkWindow *
8531get_pointer_window (CdkDisplay *display,
8532 CdkWindow *event_window,
8533 CdkDevice *device,
8534 gdouble toplevel_x,
8535 gdouble toplevel_y,
8536 gulong serial)
8537{
8538 CdkWindow *pointer_window;
8539 CdkDeviceGrabInfo *grab;
8540 CdkPointerWindowInfo *pointer_info;
8541
8542 pointer_info = _cdk_display_get_pointer_info (display, device);
8543
8544 if (event_window == pointer_info->toplevel_under_pointer)
8545 pointer_window =
8546 _cdk_window_find_descendant_at (event_window,
8547 toplevel_x, toplevel_y,
8548 NULL((void*)0), NULL((void*)0));
8549 else
8550 pointer_window = NULL((void*)0);
8551
8552 grab = _cdk_display_has_device_grab (display, device, serial);
8553 if (grab != NULL((void*)0) &&
8554 !grab->owner_events &&
8555 pointer_window != grab->window &&
8556 !cdk_window_is_ancestor (pointer_window, grab->window))
8557 pointer_window = NULL((void*)0);
8558
8559 return pointer_window;
8560}
8561
8562void
8563_cdk_display_set_window_under_pointer (CdkDisplay *display,
8564 CdkDevice *device,
8565 CdkWindow *window)
8566{
8567 CdkPointerWindowInfo *device_info;
8568
8569 device_info = _cdk_display_get_pointer_info (display, device);
8570
8571 if (device_info->window_under_pointer)
8572 g_object_unref (device_info->window_under_pointer);
8573 device_info->window_under_pointer = window;
8574
8575 if (window)
8576 {
8577 g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
8578 update_cursor (display, device);
8579 }
8580
8581 _cdk_display_enable_motion_hints (display, device);
8582}
8583
8584/**
8585 * cdk_pointer_grab:
8586 * @window: the #CdkWindow which will own the grab (the grab window).
8587 * @owner_events: if %FALSE then all pointer events are reported with respect to
8588 * @window and are only reported if selected by @event_mask. If %TRUE then pointer
8589 * events for this application are reported as normal, but pointer events outside
8590 * this application are reported with respect to @window and only if selected by
8591 * @event_mask. In either mode, unreported events are discarded.
8592 * @event_mask: specifies the event mask, which is used in accordance with
8593 * @owner_events. Note that only pointer events (i.e. button and motion events)
8594 * may be selected.
8595 * @confine_to: (allow-none): If non-%NULL, the pointer will be confined to this
8596 * window during the grab. If the pointer is outside @confine_to, it will
8597 * automatically be moved to the closest edge of @confine_to and enter
8598 * and leave events will be generated as necessary.
8599 * @cursor: (allow-none): the cursor to display while the grab is active. If this is %NULL then
8600 * the normal cursors are used for @window and its descendants, and the cursor
8601 * for @window is used for all other windows.
8602 * @time_: the timestamp of the event which led to this pointer grab. This usually
8603 * comes from a #CdkEventButton struct, though %CDK_CURRENT_TIME can be used if
8604 * the time isn’t known.
8605 *
8606 * Grabs the pointer (usually a mouse) so that all events are passed to this
8607 * application until the pointer is ungrabbed with cdk_pointer_ungrab(), or
8608 * the grab window becomes unviewable.
8609 * This overrides any previous pointer grab by this client.
8610 *
8611 * Pointer grabs are used for operations which need complete control over mouse
8612 * events, even if the mouse leaves the application.
8613 * For example in CTK+ it is used for Drag and Drop, for dragging the handle in
8614 * the #CtkHPaned and #CtkVPaned widgets.
8615 *
8616 * Note that if the event mask of an X window has selected both button press and
8617 * button release events, then a button press event will cause an automatic
8618 * pointer grab until the button is released.
8619 * X does this automatically since most applications expect to receive button
8620 * press and release events in pairs.
8621 * It is equivalent to a pointer grab on the window with @owner_events set to
8622 * %TRUE.
8623 *
8624 * If you set up anything at the time you take the grab that needs to be cleaned
8625 * up when the grab ends, you should handle the #CdkEventGrabBroken events that
8626 * are emitted when the grab ends unvoluntarily.
8627 *
8628 * Returns: %CDK_GRAB_SUCCESS if the grab was successful.
8629 **/
8630CdkGrabStatus
8631cdk_pointer_grab (CdkWindow * window,
8632 gboolean owner_events,
8633 CdkEventMask event_mask,
8634 CdkWindow * confine_to,
8635 CdkCursor * cursor,
8636 guint32 time)
8637{
8638 CdkWindow *native;
8639 CdkDisplay *display;
8640 CdkDevice *device;
8641 CdkGrabStatus res = 0;
8642 gulong serial;
8643 GList *seats, *s;
8644
8645 g_return_val_if_fail (window != NULL, CDK_GRAB_FAILED)do { if ((window != ((void*)0))) { } else { g_return_if_fail_warning
("Cdk", ((const char*) (__func__)), "window != NULL"); return
(CDK_GRAB_FAILED); } } while (0)
;
8646 g_return_val_if_fail (CDK_IS_WINDOW (window), CDK_GRAB_FAILED)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (CDK_GRAB_FAILED); } } while
(0)
;
8647 g_return_val_if_fail (confine_to == NULL || CDK_IS_WINDOW (confine_to), CDK_GRAB_FAILED)do { if ((confine_to == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((confine_to)); GType __t = ((cdk_window_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Cdk", ((const
char*) (__func__)), "confine_to == NULL || CDK_IS_WINDOW (confine_to)"
); return (CDK_GRAB_FAILED); } } while (0)
;
8648
8649 /* We need a native window for confine to to work, ensure we have one */
8650 if (confine_to)
8651 {
8652 if (!cdk_window_ensure_native (confine_to))
8653 {
8654 g_warning ("Can't confine to grabbed window, not native");
8655 confine_to = NULL((void*)0);
8656 }
8657 }
8658
8659 /* Non-viewable client side window => fail */
8660 if (!_cdk_window_has_impl (window) &&
8661 !cdk_window_is_viewable (window))
8662 return CDK_GRAB_NOT_VIEWABLE;
8663
8664 native = cdk_window_get_toplevel (window);
8665 while (cdk_window_is_offscreen (native))
8666 {
8667 native = cdk_offscreen_window_get_embedder (native);
8668
8669 if (native == NULL((void*)0) ||
8670 (!_cdk_window_has_impl (native) &&
8671 !cdk_window_is_viewable (native)))
8672 return CDK_GRAB_NOT_VIEWABLE;
8673
8674 native = cdk_window_get_toplevel (native);
8675 }
8676
8677 display = cdk_window_get_display (window);
8678
8679 serial = _cdk_display_get_next_serial (display);
8680 seats = cdk_display_list_seats (display);
8681
8682 for (s = seats; s; s = s->next)
8683 {
8684 device = cdk_seat_get_pointer (s->data);
8685
8686 res = CDK_DEVICE_GET_CLASS (device)((((CdkDeviceClass*) (((GTypeInstance*) ((device)))->g_class
))))
->grab (device,
8687 native,
8688 owner_events,
8689 get_native_grab_event_mask (event_mask),
8690 confine_to,
8691 cursor,
8692 time);
8693
8694 if (res == CDK_GRAB_SUCCESS)
8695 _cdk_display_add_device_grab (display,
8696 device,
8697 window,
8698 native,
8699 CDK_OWNERSHIP_NONE,
8700 owner_events,
8701 event_mask,
8702 serial,
8703 time,
8704 FALSE(0));
8705 }
8706
8707 /* FIXME: handle errors when grabbing */
8708
8709 g_list_free (seats);
8710
8711 return res;
8712}
8713
8714/**
8715 * cdk_keyboard_grab:
8716 * @window: the #CdkWindow which will own the grab (the grab window).
8717 * @owner_events: if %FALSE then all keyboard events are reported with respect to
8718 * @window. If %TRUE then keyboard events for this application are
8719 * reported as normal, but keyboard events outside this application
8720 * are reported with respect to @window. Both key press and key
8721 * release events are always reported, independant of the event mask
8722 * set by the application.
8723 * @time_: a timestamp from a #CdkEvent, or %CDK_CURRENT_TIME if no timestamp is
8724 * available.
8725 *
8726 * Grabs the keyboard so that all events are passed to this
8727 * application until the keyboard is ungrabbed with cdk_keyboard_ungrab().
8728 * This overrides any previous keyboard grab by this client.
8729 *
8730 * If you set up anything at the time you take the grab that needs to be cleaned
8731 * up when the grab ends, you should handle the #CdkEventGrabBroken events that
8732 * are emitted when the grab ends unvoluntarily.
8733 *
8734 * Returns: %CDK_GRAB_SUCCESS if the grab was successful.
8735 **/
8736CdkGrabStatus
8737cdk_keyboard_grab (CdkWindow *window,
8738 gboolean owner_events,
8739 guint32 time)
8740{
8741 CdkWindow *native;
8742 CdkDisplay *display;
8743 CdkDevice *device;
8744 CdkGrabStatus res = 0;
8745 gulong serial;
8746 GList *seats, *s;
8747
8748 g_return_val_if_fail (CDK_IS_WINDOW (window), CDK_GRAB_FAILED)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (CDK_GRAB_FAILED); } } while
(0)
;
8749
8750 /* Non-viewable client side window => fail */
8751 if (!_cdk_window_has_impl (window) &&
8752 !cdk_window_is_viewable (window))
8753 return CDK_GRAB_NOT_VIEWABLE;
8754
8755 native = cdk_window_get_toplevel (window);
8756
8757 while (cdk_window_is_offscreen (native))
8758 {
8759 native = cdk_offscreen_window_get_embedder (native);
8760
8761 if (native == NULL((void*)0) ||
8762 (!_cdk_window_has_impl (native) &&
8763 !cdk_window_is_viewable (native)))
8764 return CDK_GRAB_NOT_VIEWABLE;
8765
8766 native = cdk_window_get_toplevel (native);
8767 }
8768
8769 display = cdk_window_get_display (window);
8770 serial = _cdk_display_get_next_serial (display);
8771 seats = cdk_display_list_seats (display);
8772
8773 for (s = seats; s; s = s->next)
8774 {
8775 device = cdk_seat_get_keyboard (s->data);
8776
8777 res = CDK_DEVICE_GET_CLASS (device)((((CdkDeviceClass*) (((GTypeInstance*) ((device)))->g_class
))))
->grab (device,
8778 native,
8779 owner_events,
8780 CDK_KEY_PRESS_MASK | CDK_KEY_RELEASE_MASK,
8781 NULL((void*)0),
8782 NULL((void*)0),
8783 time);
8784
8785 if (res == CDK_GRAB_SUCCESS)
8786 _cdk_display_add_device_grab (display,
8787 device,
8788 window,
8789 native,
8790 CDK_OWNERSHIP_NONE,
8791 owner_events, 0,
8792 serial,
8793 time,
8794 FALSE(0));
8795 }
8796
8797 /* FIXME: handle errors when grabbing */
8798
8799 g_list_free (seats);
8800
8801 return res;
8802}
8803
8804/**
8805 * cdk_window_geometry_changed:
8806 * @window: an embedded offscreen #CdkWindow
8807 *
8808 * This function informs CDK that the geometry of an embedded
8809 * offscreen window has changed. This is necessary for CDK to keep
8810 * track of which offscreen window the pointer is in.
8811 *
8812 * Since: 2.18
8813 */
8814void
8815cdk_window_geometry_changed (CdkWindow *window)
8816{
8817 _cdk_synthesize_crossing_events_for_geometry_change (window);
8818}
8819
8820static void
8821source_events_device_added (CdkDeviceManager *device_manager G_GNUC_UNUSED__attribute__ ((__unused__)),
8822 CdkDevice *device,
8823 gpointer user_data)
8824{
8825 CdkWindow *window;
8826 CdkEventMask event_mask;
8827 CdkInputSource source;
8828
8829 if (cdk_device_get_device_type (device) != CDK_DEVICE_TYPE_FLOATING)
8830 return;
8831
8832 window = user_data;
8833 source = cdk_device_get_source (device);
8834
8835 event_mask = GPOINTER_TO_INT (g_hash_table_lookup (window->source_event_masks,((gint) (glong) (g_hash_table_lookup (window->source_event_masks
, ((gpointer) (glong) (source)))))
8836 GINT_TO_POINTER (source)))((gint) (glong) (g_hash_table_lookup (window->source_event_masks
, ((gpointer) (glong) (source)))))
;
8837 if (event_mask)
8838 cdk_window_set_device_events (window, device, event_mask);
8839}
8840
8841static void
8842source_events_device_changed (CdkDeviceManager *device_manager G_GNUC_UNUSED__attribute__ ((__unused__)),
8843 CdkDevice *device,
8844 gpointer user_data)
8845{
8846 CdkDeviceType type;
8847 CdkInputSource source;
8848 CdkEventMask event_mask;
8849 CdkWindow *window;
8850
8851 window = user_data;
8852 type = cdk_device_get_device_type (device);
8853 source = cdk_device_get_source (device);
8854
8855 event_mask = GPOINTER_TO_INT (g_hash_table_lookup (window->source_event_masks,((gint) (glong) (g_hash_table_lookup (window->source_event_masks
, ((gpointer) (glong) (source)))))
8856 GINT_TO_POINTER (source)))((gint) (glong) (g_hash_table_lookup (window->source_event_masks
, ((gpointer) (glong) (source)))))
;
8857
8858 if (!event_mask)
8859 return;
8860
8861 if (type == CDK_DEVICE_TYPE_FLOATING)
8862 {
8863 /* The device was just floated, enable its event mask */
8864 cdk_window_set_device_events (window, device, event_mask);
8865 }
8866 else if (type == CDK_DEVICE_TYPE_SLAVE)
8867 cdk_window_set_device_events (window, device, 0);
8868}
8869
8870/**
8871 * cdk_window_set_source_events:
8872 * @window: a #CdkWindow
8873 * @source: a #CdkInputSource to define the source class.
8874 * @event_mask: event mask for @window
8875 *
8876 * Sets the event mask for any floating device (i.e. not attached to any
8877 * visible pointer) that has the source defined as @source. This event
8878 * mask will be applied both to currently existing, newly added devices
8879 * after this call, and devices being attached/detached.
8880 *
8881 * Since: 3.0
8882 **/
8883void
8884cdk_window_set_source_events (CdkWindow *window,
8885 CdkInputSource source,
8886 CdkEventMask event_mask)
8887{
8888 CdkDeviceManager *device_manager;
8889 CdkDisplay *display;
8890 GList *devices, *d;
8891 guint size;
8892
8893 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
8894
8895 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
;
8896 display = cdk_window_get_display (window);
8897 device_manager = cdk_display_get_device_manager (display);
8898
8899 devices = cdk_device_manager_list_devices (device_manager, CDK_DEVICE_TYPE_FLOATING);
8900
8901 /* Set event mask for existing devices */
8902 for (d = devices; d; d = d->next)
8903 {
8904 CdkDevice *device = d->data;
8905
8906 if (source == cdk_device_get_source (device))
8907 cdk_window_set_device_events (window, device, event_mask);
8908 }
8909
8910 g_list_free (devices);
8911 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop ;
8912
8913 /* Update accounting */
8914 if (G_UNLIKELY (!window->source_event_masks)(!window->source_event_masks))
8915 window->source_event_masks = g_hash_table_new (NULL((void*)0), NULL((void*)0));
8916
8917 if (event_mask)
8918 g_hash_table_insert (window->source_event_masks,
8919 GUINT_TO_POINTER (source)((gpointer) (gulong) (source)),
8920 GUINT_TO_POINTER (event_mask)((gpointer) (gulong) (event_mask)));
8921 else
8922 g_hash_table_remove (window->source_event_masks,
8923 GUINT_TO_POINTER (source)((gpointer) (gulong) (source)));
8924
8925 size = g_hash_table_size (window->source_event_masks);
8926
8927 /* Update handler if needed */
8928 if (!window->device_added_handler_id && size > 0)
8929 {
8930 window->device_added_handler_id =
8931 g_signal_connect (device_manager, "device-added",g_signal_connect_data ((device_manager), ("device-added"), ((
(GCallback) (source_events_device_added))), (window), ((void*
)0), (GConnectFlags) 0)
8932 G_CALLBACK (source_events_device_added), window)g_signal_connect_data ((device_manager), ("device-added"), ((
(GCallback) (source_events_device_added))), (window), ((void*
)0), (GConnectFlags) 0)
;
8933 window->device_changed_handler_id =
8934 g_signal_connect (device_manager, "device-changed",g_signal_connect_data ((device_manager), ("device-changed"), (
((GCallback) (source_events_device_changed))), (window), ((void
*)0), (GConnectFlags) 0)
8935 G_CALLBACK (source_events_device_changed), window)g_signal_connect_data ((device_manager), ("device-changed"), (
((GCallback) (source_events_device_changed))), (window), ((void
*)0), (GConnectFlags) 0)
;
8936 }
8937 else if (window->device_added_handler_id && size == 0)
8938 g_signal_handler_disconnect (device_manager, window->device_added_handler_id);
8939}
8940
8941/**
8942 * cdk_window_get_source_events:
8943 * @window: a #CdkWindow
8944 * @source: a #CdkInputSource to define the source class.
8945 *
8946 * Returns the event mask for @window corresponding to the device class specified
8947 * by @source.
8948 *
8949 * Returns: source event mask for @window
8950 **/
8951CdkEventMask
8952cdk_window_get_source_events (CdkWindow *window,
8953 CdkInputSource source)
8954{
8955 g_return_val_if_fail (CDK_IS_WINDOW (window), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (0); } } while (0)
;
8956
8957 return GPOINTER_TO_UINT (g_hash_table_lookup (window->source_event_masks,((guint) (gulong) (g_hash_table_lookup (window->source_event_masks
, ((gpointer) (gulong) (source)))))
8958 GUINT_TO_POINTER (source)))((guint) (gulong) (g_hash_table_lookup (window->source_event_masks
, ((gpointer) (gulong) (source)))))
;
8959}
8960
8961static gboolean
8962do_synthesize_crossing_event (gpointer data)
8963{
8964 CdkDisplay *display;
8965 CdkWindow *changed_toplevel;
8966 GHashTableIter iter;
8967 gpointer key, value;
8968 gulong serial;
8969
8970 changed_toplevel = data;
8971
8972 changed_toplevel->synthesized_crossing_event_id = 0;
8973
8974 if (CDK_WINDOW_DESTROYED (changed_toplevel)(((CdkWindow *)(changed_toplevel))->destroyed))
8975 return FALSE(0);
8976
8977 display = cdk_window_get_display (changed_toplevel);
8978 serial = _cdk_display_get_next_serial (display);
8979 g_hash_table_iter_init (&iter, display->pointers_info);
8980
8981 while (g_hash_table_iter_next (&iter, &key, &value))
8982 {
8983 CdkWindow *new_window_under_pointer;
8984 CdkPointerWindowInfo *pointer_info = value;
8985 CdkDevice *device = key;
8986
8987 if (changed_toplevel == pointer_info->toplevel_under_pointer)
8988 {
8989 new_window_under_pointer =
8990 get_pointer_window (display, changed_toplevel,
8991 device,
8992 pointer_info->toplevel_x,
8993 pointer_info->toplevel_y,
8994 serial);
8995 if (new_window_under_pointer != pointer_info->window_under_pointer)
8996 {
8997 CdkDevice *source_device;
8998
8999 if (pointer_info->last_slave)
9000 source_device = pointer_info->last_slave;
9001 else
9002 source_device = device;
9003
9004 _cdk_synthesize_crossing_events (display,
9005 pointer_info->window_under_pointer,
9006 new_window_under_pointer,
9007 device, source_device,
9008 CDK_CROSSING_NORMAL,
9009 pointer_info->toplevel_x,
9010 pointer_info->toplevel_y,
9011 pointer_info->state,
9012 CDK_CURRENT_TIME0L,
9013 NULL((void*)0),
9014 serial,
9015 FALSE(0));
9016 _cdk_display_set_window_under_pointer (display, device, new_window_under_pointer);
9017 }
9018 }
9019 }
9020
9021 return FALSE(0);
9022}
9023
9024void
9025_cdk_synthesize_crossing_events_for_geometry_change (CdkWindow *changed_window)
9026{
9027 CdkWindow *toplevel;
9028
9029 toplevel = get_event_toplevel (changed_window);
9030
9031 if (toplevel->synthesized_crossing_event_id == 0)
9032 {
9033 toplevel->synthesized_crossing_event_id =
9034 cdk_threads_add_idle_full (CDK_PRIORITY_EVENTS(0) - 1,
9035 do_synthesize_crossing_event,
9036 toplevel, NULL((void*)0));
9037 g_source_set_name_by_id (toplevel->synthesized_crossing_event_id,
9038 "[ctk+] do_synthesize_crossing_event");
9039 }
9040}
9041
9042/* Don't use for crossing events */
9043static CdkWindow *
9044get_event_window (CdkDisplay *display,
9045 CdkDevice *device,
9046 CdkEventSequence *sequence,
9047 CdkWindow *pointer_window,
9048 CdkEventType type,
9049 CdkModifierType mask,
9050 guint *evmask_out,
9051 gboolean pointer_emulated,
9052 gulong serial)
9053{
9054 guint evmask, emulated_mask = 0;
9055 CdkWindow *grab_window;
9056 CdkDeviceGrabInfo *grab;
9057 CdkTouchGrabInfo *touch_grab;
9058
9059 touch_grab = _cdk_display_has_touch_grab (display, device, sequence, serial);
9060 grab = _cdk_display_get_last_device_grab (display, device);
9061
9062 /* Default value. */
9063 if (evmask_out)
9064 *evmask_out = 0;
9065
9066 if (is_touch_type (type) && pointer_emulated)
9067 {
9068 switch (type)
9069 {
9070 case CDK_TOUCH_BEGIN:
9071 emulated_mask |= CDK_BUTTON_PRESS_MASK;
9072 break;
9073 case CDK_TOUCH_UPDATE:
9074 emulated_mask |= CDK_POINTER_MOTION_MASK;
9075 break;
9076 case CDK_TOUCH_END:
9077 emulated_mask |= CDK_BUTTON_RELEASE_MASK;
9078 default:
9079 break;
9080 }
9081 }
9082
9083 if (touch_grab != NULL((void*)0) &&
9084 (!grab || grab->implicit || touch_grab->serial >= grab->serial_start))
9085 {
9086 evmask = touch_grab->event_mask;
9087 evmask = update_evmask_for_button_motion (evmask, mask);
9088
9089 if (evmask & (type_masks[type] | emulated_mask))
9090 {
9091 if (evmask_out)
9092 *evmask_out = evmask;
9093 return touch_grab->window;
9094 }
9095 else
9096 return NULL((void*)0);
9097 }
9098
9099 if (grab != NULL((void*)0) && !grab->owner_events)
9100 {
9101 evmask = grab->event_mask;
9102 evmask = update_evmask_for_button_motion (evmask, mask);
9103
9104 grab_window = grab->window;
9105
9106 if (evmask & (type_masks[type] | emulated_mask))
9107 {
9108 if (evmask_out)
9109 *evmask_out = evmask;
9110 return grab_window;
9111 }
9112 else
9113 return NULL((void*)0);
9114 }
9115
9116 while (pointer_window != NULL((void*)0))
9117 {
9118 evmask = pointer_window->event_mask;
9119 evmask = update_evmask_for_button_motion (evmask, mask);
9120
9121 if (evmask & (type_masks[type] | emulated_mask))
9122 {
9123 if (evmask_out)
9124 *evmask_out = evmask;
9125 return pointer_window;
9126 }
9127
9128 pointer_window = get_event_parent (pointer_window);
9129 }
9130
9131 if (grab != NULL((void*)0) &&
9132 grab->owner_events)
9133 {
9134 evmask = grab->event_mask;
9135 evmask = update_evmask_for_button_motion (evmask, mask);
9136
9137 if (evmask & (type_masks[type] | emulated_mask))
9138 {
9139 if (evmask_out)
9140 *evmask_out = evmask;
9141 return grab->window;
9142 }
9143 else
9144 return NULL((void*)0);
9145 }
9146
9147 return NULL((void*)0);
9148}
9149
9150static gboolean
9151proxy_pointer_event (CdkDisplay *display,
9152 CdkEvent *source_event,
9153 gulong serial)
9154{
9155 CdkWindow *toplevel_window, *event_window;
9156 CdkWindow *pointer_window;
9157 CdkPointerWindowInfo *pointer_info;
9158 CdkDevice *device, *source_device;
9159 CdkEvent *event;
9160 guint state;
9161 gdouble toplevel_x, toplevel_y;
9162 guint32 time_;
9163 gboolean non_linear, need_synthetic_enter = FALSE(0);
9164 gint event_type;
9165
9166 event_type = source_event->type;
9167 event_window = source_event->any.window;
9168 cdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9169 cdk_event_get_state (source_event, &state);
9170 time_ = cdk_event_get_time (source_event);
9171 device = cdk_event_get_device (source_event);
9172 source_device = cdk_event_get_source_device (source_event);
9173 pointer_info = _cdk_display_get_pointer_info (display, device);
9174 toplevel_window = convert_native_coords_to_toplevel (event_window,
9175 toplevel_x, toplevel_y,
9176 &toplevel_x, &toplevel_y);
9177
9178 non_linear = FALSE(0);
9179 if ((source_event->type == CDK_LEAVE_NOTIFY ||
9180 source_event->type == CDK_ENTER_NOTIFY) &&
9181 (source_event->crossing.detail == CDK_NOTIFY_NONLINEAR ||
9182 source_event->crossing.detail == CDK_NOTIFY_NONLINEAR_VIRTUAL))
9183 non_linear = TRUE(!(0));
9184
9185 if (pointer_info->need_touch_press_enter &&
9186 cdk_device_get_source (pointer_info->last_slave) != CDK_SOURCE_TOUCHSCREEN &&
9187 (source_event->type != CDK_TOUCH_UPDATE ||
9188 cdk_event_get_pointer_emulated (source_event)))
9189 {
9190 pointer_info->need_touch_press_enter = FALSE(0);
9191 need_synthetic_enter = TRUE(!(0));
9192 }
9193
9194 /* If we get crossing events with subwindow unexpectedly being NULL
9195 that means there is a native subwindow that cdk doesn't know about.
9196 We track these and forward them, with the correct virtual window
9197 events inbetween.
9198 This is important to get right, as metacity uses cdk for the frame
9199 windows, but cdk doesn't know about the client windows reparented
9200 into the frame. */
9201 if (((source_event->type == CDK_LEAVE_NOTIFY &&
9202 source_event->crossing.detail == CDK_NOTIFY_INFERIOR) ||
9203 (source_event->type == CDK_ENTER_NOTIFY &&
9204 (source_event->crossing.detail == CDK_NOTIFY_VIRTUAL ||
9205 source_event->crossing.detail == CDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
9206 source_event->crossing.subwindow == NULL((void*)0))
9207 {
9208 /* Left for an unknown (to cdk) subwindow */
9209
9210 /* Send leave events from window under pointer to event window
9211 that will get the subwindow == NULL window */
9212 _cdk_synthesize_crossing_events (display,
9213 pointer_info->window_under_pointer,
9214 event_window,
9215 device, source_device,
9216 source_event->crossing.mode,
9217 toplevel_x, toplevel_y,
9218 state, time_,
9219 source_event,
9220 serial,
9221 non_linear);
9222
9223 /* Send subwindow == NULL event */
9224 send_crossing_event (display,
9225 toplevel_window,
9226 event_window,
9227 source_event->type,
9228 source_event->crossing.mode,
9229 source_event->crossing.detail,
9230 NULL((void*)0),
9231 device, source_device,
9232 toplevel_x, toplevel_y,
9233 state, time_,
9234 source_event,
9235 serial);
9236
9237 _cdk_display_set_window_under_pointer (display, device, NULL((void*)0));
9238 return TRUE(!(0));
9239 }
9240
9241 pointer_window = get_pointer_window (display, toplevel_window, device,
9242 toplevel_x, toplevel_y, serial);
9243
9244 if (((source_event->type == CDK_ENTER_NOTIFY &&
9245 source_event->crossing.detail == CDK_NOTIFY_INFERIOR) ||
9246 (source_event->type == CDK_LEAVE_NOTIFY &&
9247 (source_event->crossing.detail == CDK_NOTIFY_VIRTUAL ||
9248 source_event->crossing.detail == CDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
9249 source_event->crossing.subwindow == NULL((void*)0))
9250 {
9251 /* Entered from an unknown (to cdk) subwindow */
9252
9253 /* Send subwindow == NULL event */
9254 send_crossing_event (display,
9255 toplevel_window,
9256 event_window,
9257 source_event->type,
9258 source_event->crossing.mode,
9259 source_event->crossing.detail,
9260 NULL((void*)0),
9261 device, source_device,
9262 toplevel_x, toplevel_y,
9263 state, time_,
9264 source_event,
9265 serial);
9266
9267 /* Send enter events from event window to pointer_window */
9268 _cdk_synthesize_crossing_events (display,
9269 event_window,
9270 pointer_window,
9271 device, source_device,
9272 source_event->crossing.mode,
9273 toplevel_x, toplevel_y,
9274 state, time_,
9275 source_event,
9276 serial, non_linear);
9277 _cdk_display_set_window_under_pointer (display, device, pointer_window);
9278 return TRUE(!(0));
9279 }
9280
9281 if ((source_event->type != CDK_TOUCH_UPDATE ||
9282 cdk_event_get_pointer_emulated (source_event)) &&
9283 pointer_info->window_under_pointer != pointer_window)
9284 {
9285 /* Either a toplevel crossing notify that ended up inside a child window,
9286 or a motion notify that got into another child window */
9287
9288 /* Different than last time, send crossing events */
9289 _cdk_synthesize_crossing_events (display,
9290 pointer_info->window_under_pointer,
9291 pointer_window,
9292 device, source_device,
9293 CDK_CROSSING_NORMAL,
9294 toplevel_x, toplevel_y,
9295 state, time_,
9296 source_event,
9297 serial, non_linear);
9298 _cdk_display_set_window_under_pointer (display, device, pointer_window);
9299 }
9300
9301 if (source_event->type == CDK_MOTION_NOTIFY ||
9302 source_event->type == CDK_TOUCH_UPDATE)
9303 {
9304 CdkWindow *event_win;
9305 guint evmask;
9306 gboolean is_hint;
9307 CdkEventSequence *sequence;
9308
9309 sequence = cdk_event_get_event_sequence (source_event);
9310
9311 event_win = get_event_window (display,
9312 device,
9313 sequence,
9314 pointer_window,
9315 source_event->type,
9316 state,
9317 &evmask,
9318 cdk_event_get_pointer_emulated (source_event),
9319 serial);
9320
9321 if (event_type == CDK_TOUCH_UPDATE)
9322 {
9323 if (cdk_event_get_pointer_emulated (source_event))
9324 {
9325 /* Touch events emulating pointer events are transformed back
9326 * to pointer events if:
9327 * 1 - The event window doesn't select for touch events
9328 * 2 - There's no touch grab for this sequence, which means
9329 * it was started as a pointer sequence, but a device
9330 * grab added touch events afterwards, the sequence must
9331 * not mutate in this case.
9332 */
9333 if ((evmask & CDK_TOUCH_MASK) == 0 ||
9334 !_cdk_display_has_touch_grab (display, device, sequence, serial))
9335 event_type = CDK_MOTION_NOTIFY;
9336 }
9337 else if ((evmask & CDK_TOUCH_MASK) == 0)
9338 return TRUE(!(0));
9339 }
9340
9341 if (is_touch_type (source_event->type) && !is_touch_type (event_type))
9342 state |= CDK_BUTTON1_MASK;
9343
9344 if (event_win &&
9345 cdk_device_get_device_type (device) != CDK_DEVICE_TYPE_MASTER &&
9346 cdk_window_get_device_events (event_win, device) == 0)
9347 return TRUE(!(0));
9348
9349 /* The last device to interact with the window was a touch device,
9350 * which synthesized a leave notify event, so synthesize another enter
9351 * notify to tell the pointer is on the window.
9352 */
9353 if (need_synthetic_enter)
9354 _cdk_synthesize_crossing_events (display,
9355 NULL((void*)0), pointer_window,
9356 device, source_device,
9357 CDK_CROSSING_DEVICE_SWITCH,
9358 toplevel_x, toplevel_y,
9359 state, time_, NULL((void*)0),
9360 serial, FALSE(0));
9361
9362 is_hint = FALSE(0);
9363
9364 if (event_win &&
9365 event_type == CDK_MOTION_NOTIFY &&
9366 (evmask & CDK_POINTER_MOTION_HINT_MASK))
9367 {
9368 gulong *device_serial;
9369
9370 device_serial = g_hash_table_lookup (display->motion_hint_info, device);
9371
9372 if (!device_serial ||
9373 (*device_serial != 0 &&
9374 serial < *device_serial))
9375 event_win = NULL((void*)0); /* Ignore event */
9376 else
9377 {
9378 is_hint = TRUE(!(0));
9379 *device_serial = G_MAXULONG(9223372036854775807L *2UL+1UL);
9380 }
9381 }
9382
9383 if (!event_win)
9384 return TRUE(!(0));
9385
9386 event = cdk_event_new (event_type);
9387 event->any.window = g_object_ref (event_win)((__typeof__ (event_win)) (g_object_ref) (event_win));
9388 event->any.send_event = source_event->any.send_event;
9389
9390 cdk_event_set_device (event, cdk_event_get_device (source_event));
9391 cdk_event_set_source_device (event, source_device);
9392 cdk_event_set_seat (event, cdk_device_get_seat (device));
9393 cdk_event_set_device_tool (event, cdk_event_get_device_tool (source_event));
9394
9395 if (event_type == CDK_TOUCH_UPDATE)
9396 {
9397 event->touch.time = time_;
9398 event->touch.state = state | CDK_BUTTON1_MASK;
9399 event->touch.sequence = source_event->touch.sequence;
9400 event->touch.emulating_pointer = source_event->touch.emulating_pointer;
9401 convert_toplevel_coords_to_window (event_win,
9402 toplevel_x, toplevel_y,
9403 &event->touch.x, &event->touch.y);
9404 cdk_event_get_root_coords (source_event,
9405 &event->touch.x_root,
9406 &event->touch.y_root);
9407
9408 event->touch.axes = g_memdup2 (source_event->touch.axes,
9409 sizeof (gdouble) * cdk_device_get_n_axes (source_event->touch.device));
9410 }
9411 else
9412 {
9413 event->motion.time = time_;
9414 event->motion.state = state;
9415 event->motion.is_hint = is_hint;
9416
9417 convert_toplevel_coords_to_window (event_win,
9418 toplevel_x, toplevel_y,
9419 &event->motion.x, &event->motion.y);
9420 cdk_event_get_root_coords (source_event,
9421 &event->motion.x_root,
9422 &event->motion.y_root);
9423
9424 if (is_touch_type (source_event->type))
9425 event->motion.axes = g_memdup2 (source_event->touch.axes,
9426 sizeof (gdouble) * cdk_device_get_n_axes (source_event->touch.device));
9427 else
9428 event->motion.axes = g_memdup2 (source_event->motion.axes,
9429 sizeof (gdouble) * cdk_device_get_n_axes (source_event->motion.device));
9430 }
9431
9432 /* Just insert the event */
9433 _cdk_event_queue_insert_after (cdk_window_get_display (event_win),
9434 source_event, event);
9435 }
9436
9437 /* unlink all move events from queue.
9438 We handle our own, including our emulated masks. */
9439 return TRUE(!(0));
9440}
9441
9442#define CDK_ANY_BUTTON_MASK(CDK_BUTTON1_MASK | CDK_BUTTON2_MASK | CDK_BUTTON3_MASK | CDK_BUTTON4_MASK
| CDK_BUTTON5_MASK)
(CDK_BUTTON1_MASK | \
9443 CDK_BUTTON2_MASK | \
9444 CDK_BUTTON3_MASK | \
9445 CDK_BUTTON4_MASK | \
9446 CDK_BUTTON5_MASK)
9447
9448static gboolean
9449proxy_button_event (CdkEvent *source_event,
9450 gulong serial)
9451{
9452 CdkWindow *toplevel_window, *event_window;
9453 CdkWindow *event_win;
9454 CdkWindow *pointer_window;
9455 CdkWindow *parent;
9456 CdkEvent *event;
9457 CdkPointerWindowInfo *pointer_info;
9458 CdkDeviceGrabInfo *pointer_grab;
9459 guint state;
9460 guint32 time_;
9461 CdkEventType type;
9462 gdouble toplevel_x, toplevel_y;
9463 CdkDisplay *display;
9464 CdkWindow *w;
9465 CdkDevice *device, *source_device;
9466 CdkEventMask evmask;
9467 CdkEventSequence *sequence;
9468
9469 type = source_event->any.type;
9470 event_window = source_event->any.window;
9471 cdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9472 cdk_event_get_state (source_event, &state);
9473 time_ = cdk_event_get_time (source_event);
9474 device = cdk_event_get_device (source_event);
9475 source_device = cdk_event_get_source_device (source_event);
9476 display = cdk_window_get_display (source_event->any.window);
9477 toplevel_window = convert_native_coords_to_toplevel (event_window,
9478 toplevel_x, toplevel_y,
9479 &toplevel_x, &toplevel_y);
9480
9481 sequence = cdk_event_get_event_sequence (source_event);
9482
9483 pointer_info = _cdk_display_get_pointer_info (display, device);
9484 pointer_grab = _cdk_display_has_device_grab (display, device, serial);
9485
9486 if ((type == CDK_BUTTON_PRESS ||
9487 type == CDK_TOUCH_BEGIN) &&
9488 !source_event->any.send_event &&
9489 (!pointer_grab ||
9490 (type == CDK_TOUCH_BEGIN && pointer_grab->implicit &&
9491 !cdk_event_get_pointer_emulated (source_event))))
9492 {
9493 pointer_window =
9494 _cdk_window_find_descendant_at (toplevel_window,
9495 toplevel_x, toplevel_y,
9496 NULL((void*)0), NULL((void*)0));
9497
9498 /* Find the event window, that gets the grab */
9499 w = pointer_window;
9500 while (w != NULL((void*)0) &&
9501 (parent = get_event_parent (w)) != NULL((void*)0) &&
9502 parent->window_type != CDK_WINDOW_ROOT)
9503 {
9504 if (w->event_mask & CDK_BUTTON_PRESS_MASK &&
9505 (type == CDK_BUTTON_PRESS ||
9506 cdk_event_get_pointer_emulated (source_event)))
9507 break;
9508
9509 if (type == CDK_TOUCH_BEGIN &&
9510 w->event_mask & CDK_TOUCH_MASK)
9511 break;
9512
9513 w = parent;
9514 }
9515 pointer_window = w;
9516
9517 if (pointer_window)
9518 {
9519 if (type == CDK_TOUCH_BEGIN &&
9520 pointer_window->event_mask & CDK_TOUCH_MASK)
9521 {
9522 _cdk_display_add_touch_grab (display, device, sequence,
9523 pointer_window, event_window,
9524 cdk_window_get_events (pointer_window),
9525 serial, time_);
9526 }
9527 else if (type == CDK_BUTTON_PRESS ||
9528 cdk_event_get_pointer_emulated (source_event))
9529 {
9530 _cdk_display_add_device_grab (display,
9531 device,
9532 pointer_window,
9533 event_window,
9534 CDK_OWNERSHIP_NONE,
9535 FALSE(0),
9536 cdk_window_get_events (pointer_window),
9537 serial,
9538 time_,
9539 TRUE(!(0)));
9540 _cdk_display_device_grab_update (display, device,
9541 source_device, serial);
9542 }
9543 }
9544 }
9545
9546 pointer_window = get_pointer_window (display, toplevel_window, device,
9547 toplevel_x, toplevel_y,
9548 serial);
9549
9550 event_win = get_event_window (display,
9551 device,
9552 sequence,
9553 pointer_window,
9554 type, state,
9555 &evmask,
9556 cdk_event_get_pointer_emulated (source_event),
9557 serial);
9558
9559 if (type == CDK_TOUCH_BEGIN || type == CDK_TOUCH_END)
9560 {
9561 if (cdk_event_get_pointer_emulated (source_event))
9562 {
9563 if ((evmask & CDK_TOUCH_MASK) == 0 ||
9564 !_cdk_display_has_touch_grab (display, device, sequence, serial))
9565 {
9566 if (type == CDK_TOUCH_BEGIN)
9567 type = CDK_BUTTON_PRESS;
9568 else if (type == CDK_TOUCH_END)
9569 type = CDK_BUTTON_RELEASE;
9570 }
9571 }
9572 else if ((evmask & CDK_TOUCH_MASK) == 0)
9573 return TRUE(!(0));
9574 }
9575
9576 if (source_event->type == CDK_TOUCH_END && !is_touch_type (type))
9577 state |= CDK_BUTTON1_MASK;
9578
9579 if (event_win == NULL((void*)0))
9580 return TRUE(!(0));
9581
9582 if (cdk_device_get_device_type (device) != CDK_DEVICE_TYPE_MASTER &&
9583 cdk_window_get_device_events (event_win, device) == 0)
9584 return TRUE(!(0));
9585
9586 if ((type == CDK_BUTTON_PRESS ||
9587 (type == CDK_TOUCH_BEGIN &&
9588 cdk_event_get_pointer_emulated (source_event))) &&
9589 pointer_info->need_touch_press_enter)
9590 {
9591 CdkCrossingMode mode;
9592
9593 /* The last device to interact with the window was a touch device,
9594 * which synthesized a leave notify event, so synthesize another enter
9595 * notify to tell the pointer is on the window.
9596 */
9597 if (cdk_device_get_source (source_device) == CDK_SOURCE_TOUCHSCREEN)
9598 mode = CDK_CROSSING_TOUCH_BEGIN;
9599 else
9600 mode = CDK_CROSSING_DEVICE_SWITCH;
9601
9602 pointer_info->need_touch_press_enter = FALSE(0);
9603 _cdk_synthesize_crossing_events (display,
9604 NULL((void*)0),
9605 pointer_info->window_under_pointer,
9606 device, source_device, mode,
9607 toplevel_x, toplevel_y,
9608 state, time_, source_event,
9609 serial, FALSE(0));
9610 }
9611 else if (type == CDK_SCROLL &&
9612 (((evmask & CDK_SMOOTH_SCROLL_MASK) == 0 &&
9613 source_event->scroll.direction == CDK_SCROLL_SMOOTH) ||
9614 ((evmask & CDK_SMOOTH_SCROLL_MASK) != 0 &&
9615 source_event->scroll.direction != CDK_SCROLL_SMOOTH &&
9616 cdk_event_get_pointer_emulated (source_event))))
9617 return FALSE(0);
9618
9619 event = _cdk_make_event (event_win, type, source_event, FALSE(0));
9620
9621 switch (type)
9622 {
9623 case CDK_BUTTON_PRESS:
9624 case CDK_BUTTON_RELEASE:
9625 event->button.button = source_event->button.button;
9626 convert_toplevel_coords_to_window (event_win,
9627 toplevel_x, toplevel_y,
9628 &event->button.x, &event->button.y);
9629 cdk_event_get_root_coords (source_event,
9630 &event->button.x_root,
9631 &event->button.y_root);
9632 cdk_event_set_device (event, cdk_event_get_device (source_event));
9633 cdk_event_set_source_device (event, source_device);
9634 cdk_event_set_seat (event, cdk_device_get_seat (device));
9635 cdk_event_set_device_tool (event, cdk_event_get_device_tool (source_event));
9636
9637 if (is_touch_type (source_event->type))
9638 {
9639 if (type == CDK_BUTTON_RELEASE)
9640 event->button.state |= CDK_BUTTON1_MASK;
9641 event->button.button = 1;
9642 event->button.axes = g_memdup2 (source_event->touch.axes,
9643 sizeof (gdouble) * cdk_device_get_n_axes (source_event->touch.device));
9644 }
9645 else
9646 {
9647 event->button.button = source_event->button.button;
9648 event->button.axes = g_memdup2 (source_event->button.axes,
9649 sizeof (gdouble) * cdk_device_get_n_axes (source_event->button.device));
9650 }
9651
9652 if (type == CDK_BUTTON_PRESS)
9653 _cdk_event_button_generate (display, event);
9654 else if ((type == CDK_BUTTON_RELEASE ||
9655 (type == CDK_TOUCH_END &&
9656 cdk_event_get_pointer_emulated (source_event))) &&
9657 pointer_window == pointer_info->window_under_pointer &&
9658 cdk_device_get_source (source_device) == CDK_SOURCE_TOUCHSCREEN)
9659 {
9660 /* Synthesize a leave notify event
9661 * whenever a touch device is released
9662 */
9663 pointer_info->need_touch_press_enter = TRUE(!(0));
9664 _cdk_synthesize_crossing_events (display,
9665 pointer_window, NULL((void*)0),
9666 device, source_device,
9667 CDK_CROSSING_TOUCH_END,
9668 toplevel_x, toplevel_y,
9669 state, time_, NULL((void*)0),
9670 serial, FALSE(0));
9671 }
9672 return TRUE(!(0));
9673
9674 case CDK_TOUCH_BEGIN:
9675 case CDK_TOUCH_END:
9676 case CDK_TOUCH_CANCEL:
9677 convert_toplevel_coords_to_window (event_win,
9678 toplevel_x, toplevel_y,
9679 &event->button.x, &event->button.y);
9680 cdk_event_get_root_coords (source_event,
9681 &event->touch.x_root,
9682 &event->touch.y_root);
9683 event->touch.state = state;
9684 event->touch.device = source_event->touch.device;
9685 event->touch.axes = g_memdup2 (source_event->touch.axes,
9686 sizeof (gdouble) * cdk_device_get_n_axes (source_event->touch.device));
9687 event->touch.sequence = source_event->touch.sequence;
9688 event->touch.emulating_pointer = source_event->touch.emulating_pointer;
9689
9690 cdk_event_set_source_device (event, source_device);
9691
9692 if (((type == CDK_TOUCH_END || type == CDK_TOUCH_CANCEL) &&
9693 cdk_event_get_pointer_emulated (source_event)) &&
9694 pointer_window == pointer_info->window_under_pointer &&
9695 cdk_device_get_source (source_device) == CDK_SOURCE_TOUCHSCREEN)
9696 {
9697 /* Synthesize a leave notify event
9698 * whenever a touch device is released
9699 */
9700 pointer_info->need_touch_press_enter = TRUE(!(0));
9701 _cdk_synthesize_crossing_events (display,
9702 pointer_window, NULL((void*)0),
9703 device, source_device,
9704 CDK_CROSSING_TOUCH_END,
9705 toplevel_x, toplevel_y,
9706 state, time_, NULL((void*)0),
9707 serial, FALSE(0));
9708 }
9709 return TRUE(!(0));
9710
9711 case CDK_SCROLL:
9712 event->scroll.direction = source_event->scroll.direction;
9713 convert_toplevel_coords_to_window (event_win,
9714 toplevel_x, toplevel_y,
9715 &event->scroll.x, &event->scroll.y);
9716 event->scroll.x_root = source_event->scroll.x_root;
9717 event->scroll.y_root = source_event->scroll.y_root;
9718 event->scroll.state = state;
9719 event->scroll.device = source_event->scroll.device;
9720 event->scroll.delta_x = source_event->scroll.delta_x;
9721 event->scroll.delta_y = source_event->scroll.delta_y;
9722 event->scroll.is_stop = source_event->scroll.is_stop;
9723 cdk_event_set_source_device (event, source_device);
9724 return TRUE(!(0));
9725
9726 default:
9727 return FALSE(0);
9728 }
9729
9730 return TRUE(!(0)); /* Always unlink original, we want to obey the emulated event mask */
9731}
9732
9733static gboolean
9734proxy_gesture_event (CdkEvent *source_event,
9735 gulong serial)
9736{
9737 CdkWindow *toplevel_window, *pointer_window, *event_win;
9738 CdkDevice *device, *source_device;
9739 gdouble toplevel_x, toplevel_y;
9740 CdkDisplay *display;
9741 CdkEventMask evmask;
9742 CdkEventType evtype;
9743 CdkEvent *event;
9744 guint state;
9745
9746 evtype = source_event->any.type;
9747 cdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9748 cdk_event_get_state (source_event, &state);
9749 device = cdk_event_get_device (source_event);
9750 source_device = cdk_event_get_source_device (source_event);
9751 display = cdk_window_get_display (source_event->any.window);
9752 toplevel_window = convert_native_coords_to_toplevel (source_event->any.window,
9753 toplevel_x, toplevel_y,
9754 &toplevel_x, &toplevel_y);
9755
9756 pointer_window = get_pointer_window (display, toplevel_window, device,
9757 toplevel_x, toplevel_y,
9758 serial);
9759
9760 event_win = get_event_window (display, device, NULL((void*)0),
9761 pointer_window, evtype, state,
9762 &evmask, FALSE(0), serial);
9763 if (!event_win)
9764 return TRUE(!(0));
9765
9766 if ((evmask & CDK_TOUCHPAD_GESTURE_MASK) == 0)
9767 return TRUE(!(0));
9768
9769 event = _cdk_make_event (event_win, evtype, source_event, FALSE(0));
9770 cdk_event_set_device (event, device);
9771 cdk_event_set_source_device (event, source_device);
9772 cdk_event_set_seat (event, cdk_device_get_seat (device));
9773
9774 switch (evtype)
9775 {
9776 case CDK_TOUCHPAD_SWIPE:
9777 convert_toplevel_coords_to_window (event_win,
9778 toplevel_x, toplevel_y,
9779 &event->touchpad_swipe.x,
9780 &event->touchpad_swipe.y);
9781 cdk_event_get_root_coords (source_event,
9782 &event->touchpad_swipe.x_root,
9783 &event->touchpad_swipe.y_root);
9784 event->touchpad_swipe.dx = source_event->touchpad_swipe.dx;
9785 event->touchpad_swipe.dy = source_event->touchpad_swipe.dy;
9786 event->touchpad_swipe.n_fingers = source_event->touchpad_swipe.n_fingers;
9787 event->touchpad_swipe.phase = source_event->touchpad_swipe.phase;
9788 break;
9789
9790 case CDK_TOUCHPAD_PINCH:
9791 convert_toplevel_coords_to_window (event_win,
9792 toplevel_x, toplevel_y,
9793 &event->touchpad_pinch.x,
9794 &event->touchpad_pinch.y);
9795 cdk_event_get_root_coords (source_event,
9796 &event->touchpad_pinch.x_root,
9797 &event->touchpad_pinch.y_root);
9798 event->touchpad_pinch.dx = source_event->touchpad_pinch.dx;
9799 event->touchpad_pinch.dy = source_event->touchpad_pinch.dy;
9800 event->touchpad_pinch.scale = source_event->touchpad_pinch.scale;
9801 event->touchpad_pinch.angle_delta = source_event->touchpad_pinch.angle_delta;
9802 event->touchpad_pinch.n_fingers = source_event->touchpad_pinch.n_fingers;
9803 event->touchpad_pinch.phase = source_event->touchpad_pinch.phase;
9804 break;
9805
9806 default:
9807 break;
9808 }
9809
9810 return TRUE(!(0));
9811}
9812
9813#ifdef DEBUG_WINDOW_PRINTING
9814
9815#ifdef CDK_WINDOWING_X11
9816#include "x11/cdkx.h"
9817#endif
9818
9819static void
9820cdk_window_print (CdkWindow *window,
9821 int indent)
9822{
9823 char *s;
9824 const char *window_types[] = {
9825 "root",
9826 "toplevel",
9827 "child",
9828 "dialog",
9829 "temp",
9830 "foreign",
9831 "offscreen"
9832 };
9833
9834 g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
9835 window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
9836 window->x, window->y,
9837 window->width, window->height
9838 );
9839
9840 if (cdk_window_has_impl (window))
9841 {
9842#ifdef CDK_WINDOWING_X11
9843 g_print (" impl(0x%lx)", cdk_x11_window_get_xid (window));
9844#endif
9845 }
9846
9847 if (window->window_type != CDK_WINDOW_CHILD)
9848 g_print (" %s", window_types[window->window_type]);
9849
9850 if (window->input_only)
9851 g_print (" input-only");
9852
9853 if (window->shaped)
9854 g_print (" shaped");
9855
9856 if (!cdk_window_is_visible ((CdkWindow *)window))
9857 g_print (" hidden");
9858
9859 g_print (" abs[%d,%d]",
9860 window->abs_x, window->abs_y);
9861
9862 if (window->alpha != 255)
9863 g_print (" alpha[%d]",
9864 window->alpha);
9865
9866 s = print_region (window->clip_region);
9867 g_print (" clipbox[%s]", s);
9868
9869 g_print ("\n");
9870}
9871
9872
9873static void
9874cdk_window_print_tree (CdkWindow *window,
9875 int indent,
9876 gboolean include_input_only)
9877{
9878 GList *l;
9879
9880 if (window->input_only && !include_input_only)
9881 return;
9882
9883 cdk_window_print (window, indent);
9884
9885 for (l = window->children; l != NULL((void*)0); l = l->next)
9886 cdk_window_print_tree (l->data, indent + 4, include_input_only);
9887}
9888
9889#endif /* DEBUG_WINDOW_PRINTING */
9890
9891void
9892_cdk_windowing_got_event (CdkDisplay *display,
9893 GList *event_link,
9894 CdkEvent *event,
9895 gulong serial)
9896{
9897 CdkWindow *event_window;
9898 gdouble x, y;
9899 gboolean unlink_event = FALSE(0);
9900 CdkDeviceGrabInfo *button_release_grab;
9901 CdkPointerWindowInfo *pointer_info = NULL((void*)0);
9902 CdkDevice *device, *source_device;
9903 gboolean is_toplevel;
9904
9905 _cdk_display_update_last_event (display, event);
9906
9907 device = cdk_event_get_device (event);
9908 source_device = cdk_event_get_source_device (event);
9909
9910 if (device)
9911 {
9912 if (cdk_device_get_source (device) != CDK_SOURCE_KEYBOARD &&
9913 cdk_device_get_source (device) != CDK_SOURCE_TABLET_PAD)
9914 {
9915 pointer_info = _cdk_display_get_pointer_info (display, device);
9916
9917 if (source_device != pointer_info->last_slave &&
9918 cdk_device_get_device_type (source_device) == CDK_DEVICE_TYPE_SLAVE)
9919 g_set_object (&pointer_info->last_slave, source_device)(__extension__ ({ _Static_assert (sizeof *(&pointer_info->
last_slave) == sizeof (source_device), "Expression evaluates to false"
); union { char *in; GObject **out; } _object_ptr; _object_ptr
.in = (char *) (&pointer_info->last_slave); (void) (0 ?
*(&pointer_info->last_slave) = (source_device), (0) :
(0)); (g_set_object) (_object_ptr.out, (GObject *) source_device
); }))
;
9920 else if (pointer_info->last_slave)
9921 source_device = pointer_info->last_slave;
9922 }
9923
9924 _cdk_display_device_grab_update (display, device, source_device, serial);
9925
9926 if (cdk_device_get_input_mode (device) == CDK_MODE_DISABLED ||
9927 !_cdk_display_check_grab_ownership (display, device, serial))
9928 {
9929 /* Device events are blocked by another
9930 * device grab, or the device is disabled
9931 */
9932 unlink_event = TRUE(!(0));
9933 goto out;
9934 }
9935 }
9936
9937 event_window = event->any.window;
9938 if (!event_window)
9939 goto out;
9940
9941#ifdef DEBUG_WINDOW_PRINTING
9942 if (event->type == CDK_KEY_PRESS &&
9943 (event->key.keyval == 0xa7 ||
9944 event->key.keyval == 0xbd))
9945 {
9946 cdk_window_print_tree (event_window, 0, event->key.keyval == 0xbd);
9947 }
9948#endif
9949
9950 if (event->type == CDK_VISIBILITY_NOTIFY)
9951 {
9952 event_window->native_visibility = event->visibility.state;
9953 cdk_window_update_visibility_recursively (event_window, event_window);
9954 goto out;
9955 }
9956
9957 if (!(event->type == CDK_TOUCH_CANCEL ||
9958 is_button_type (event->type) ||
9959 is_motion_type (event->type) ||
9960 is_gesture_type (event->type)) ||
9961 event_window->window_type == CDK_WINDOW_ROOT)
9962 goto out;
9963
9964 is_toplevel = cdk_window_is_toplevel (event_window);
9965
9966 if ((event->type == CDK_ENTER_NOTIFY ||
9967 event->type == CDK_LEAVE_NOTIFY) &&
9968 (event->crossing.mode == CDK_CROSSING_GRAB ||
9969 event->crossing.mode == CDK_CROSSING_UNGRAB) &&
9970 (_cdk_display_has_device_grab (display, device, serial) ||
9971 event->crossing.detail == CDK_NOTIFY_INFERIOR))
9972 {
9973 /* We synthesize all crossing events due to grabs ourselves,
9974 * so we ignore the native ones caused by our native pointer_grab
9975 * calls. Otherwise we would proxy these crossing event and cause
9976 * multiple copies of crossing events for grabs.
9977 *
9978 * We do want to handle grabs from other clients though, as for
9979 * instance alt-tab in metacity causes grabs like these and
9980 * we want to handle those. Thus the has_pointer_grab check.
9981 *
9982 * Implicit grabs on child windows create some grabbing events
9983 * that are sent before the button press. This means we can't
9984 * detect these with the has_pointer_grab check (as the implicit
9985 * grab is only noticed when we get button press event), so we
9986 * detect these events by checking for INFERIOR enter or leave
9987 * events. These should never be a problem to filter out.
9988 */
9989
9990 /* We ended up in this window after some (perhaps other clients)
9991 * grab, so update the toplevel_under_window state
9992 */
9993 if (pointer_info && is_toplevel &&
9994 event->type == CDK_ENTER_NOTIFY &&
9995 event->crossing.mode == CDK_CROSSING_UNGRAB)
9996 {
9997 if (pointer_info->toplevel_under_pointer)
9998 g_object_unref (pointer_info->toplevel_under_pointer);
9999 pointer_info->toplevel_under_pointer = g_object_ref (event_window)((__typeof__ (event_window)) (g_object_ref) (event_window));
10000 }
10001
10002 unlink_event = TRUE(!(0));
10003 goto out;
10004 }
10005
10006 /* Track toplevel_under_pointer */
10007 if (pointer_info && is_toplevel)
10008 {
10009 if (event->type == CDK_ENTER_NOTIFY &&
10010 event->crossing.detail != CDK_NOTIFY_INFERIOR)
10011 {
10012 if (pointer_info->toplevel_under_pointer)
10013 g_object_unref (pointer_info->toplevel_under_pointer);
10014 pointer_info->toplevel_under_pointer = g_object_ref (event_window)((__typeof__ (event_window)) (g_object_ref) (event_window));
10015 }
10016 else if (event->type == CDK_LEAVE_NOTIFY &&
10017 event->crossing.detail != CDK_NOTIFY_INFERIOR &&
10018 pointer_info->toplevel_under_pointer == event_window)
10019 {
10020 if (pointer_info->toplevel_under_pointer)
10021 g_object_unref (pointer_info->toplevel_under_pointer);
10022 pointer_info->toplevel_under_pointer = NULL((void*)0);
10023 }
10024 }
10025
10026 if (pointer_info &&
10027 (!is_touch_type (event->type) ||
10028 cdk_event_get_pointer_emulated (event)))
10029 {
10030 guint old_state, old_button;
10031
10032 /* Store last pointer window and position/state */
10033 old_state = pointer_info->state;
10034 old_button = pointer_info->button;
10035
10036 cdk_event_get_coords (event, &x, &y);
10037 convert_native_coords_to_toplevel (event_window, x, y, &x, &y);
10038 pointer_info->toplevel_x = x;
10039 pointer_info->toplevel_y = y;
10040 cdk_event_get_state (event, &pointer_info->state);
10041
10042 if (event->type == CDK_BUTTON_PRESS ||
10043 event->type == CDK_BUTTON_RELEASE)
10044 pointer_info->button = event->button.button;
10045 else if (event->type == CDK_TOUCH_BEGIN ||
10046 event->type == CDK_TOUCH_END)
10047 pointer_info->button = 1;
10048
10049 if (device &&
10050 (pointer_info->state != old_state ||
10051 pointer_info->button != old_button))
10052 _cdk_display_enable_motion_hints (display, device);
10053 }
10054
10055 if (is_motion_type (event->type))
10056 unlink_event = proxy_pointer_event (display, event, serial);
10057 else if (is_button_type (event->type))
10058 unlink_event = proxy_button_event (event, serial);
10059 else if (is_gesture_type (event->type))
10060 unlink_event = proxy_gesture_event (event, serial);
10061
10062 if ((event->type == CDK_BUTTON_RELEASE ||
10063 event->type == CDK_TOUCH_CANCEL ||
10064 event->type == CDK_TOUCH_END) &&
10065 !event->any.send_event)
10066 {
10067 CdkEventSequence *sequence;
10068
10069 sequence = cdk_event_get_event_sequence (event);
10070 if (sequence)
10071 {
10072 _cdk_display_end_touch_grab (display, device, sequence);
10073 }
10074
10075 if (event->type == CDK_BUTTON_RELEASE ||
10076 cdk_event_get_pointer_emulated (event))
10077 {
10078 button_release_grab =
10079 _cdk_display_has_device_grab (display, device, serial);
10080
10081 if (button_release_grab &&
10082 button_release_grab->implicit &&
10083 (event->button.state & CDK_ANY_BUTTON_MASK(CDK_BUTTON1_MASK | CDK_BUTTON2_MASK | CDK_BUTTON3_MASK | CDK_BUTTON4_MASK
| CDK_BUTTON5_MASK)
& ~(CDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
10084 {
10085 button_release_grab->serial_end = serial;
10086 button_release_grab->implicit_ungrab = FALSE(0);
10087 _cdk_display_device_grab_update (display, device, source_device, serial);
10088 }
10089 }
10090 }
10091
10092 out:
10093 if (unlink_event)
10094 {
10095 _cdk_event_queue_remove_link (display, event_link);
10096 g_list_free_1 (event_link);
10097 cdk_event_free (event);
10098 }
10099
10100 /* This does two things - first it sees if there are motions at the
10101 * end of the queue that can be compressed. Second, if there is just
10102 * a single motion that won't be dispatched because it is a compression
10103 * candidate it queues up flushing the event queue.
10104 */
10105 _cdk_event_queue_handle_motion_compression (display);
10106}
10107
10108/**
10109 * cdk_window_create_similar_surface:
10110 * @window: window to make new surface similar to
10111 * @content: the content for the new surface
10112 * @width: width of the new surface
10113 * @height: height of the new surface
10114 *
10115 * Create a new surface that is as compatible as possible with the
10116 * given @window. For example the new surface will have the same
10117 * fallback resolution and font options as @window. Generally, the new
10118 * surface will also use the same backend as @window, unless that is
10119 * not possible for some reason. The type of the returned surface may
10120 * be examined with cairo_surface_get_type().
10121 *
10122 * Initially the surface contents are all 0 (transparent if contents
10123 * have transparency, black otherwise.)
10124 *
10125 * Returns: a pointer to the newly allocated surface. The caller
10126 * owns the surface and should call cairo_surface_destroy() when done
10127 * with it.
10128 *
10129 * This function always returns a valid pointer, but it will return a
10130 * pointer to a “nil” surface if @other is already in an error state
10131 * or any other error occurs.
10132 *
10133 * Since: 2.22
10134 **/
10135cairo_surface_t *
10136cdk_window_create_similar_surface (CdkWindow * window,
10137 cairo_content_t content,
10138 int width,
10139 int height)
10140{
10141 CdkDisplay *display;
10142 CdkRenderingMode rendering_mode;
10143 cairo_surface_t *window_surface, *surface;
10144 double sx, sy;
10145
10146 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
10147
10148 window_surface = cdk_window_ref_impl_surface (window);
10149 sx = sy = 1;
10150 cairo_surface_get_device_scale (window_surface, &sx, &sy);
10151
10152 display = cdk_window_get_display (window);
10153 rendering_mode = cdk_display_get_rendering_mode (display);
10154
10155 switch (rendering_mode)
10156 {
10157 case CDK_RENDERING_MODE_RECORDING:
10158 {
10159 cairo_rectangle_t rect = { 0, 0, width * sx, height *sy };
10160 surface = cairo_recording_surface_create (content, &rect);
10161 cairo_surface_set_device_scale (surface, sx, sy);
10162 }
10163 break;
10164 case CDK_RENDERING_MODE_IMAGE:
10165 surface = cairo_image_surface_create (content == CAIRO_CONTENT_COLOR ? CAIRO_FORMAT_RGB24 :
10166 content == CAIRO_CONTENT_ALPHA ? CAIRO_FORMAT_A8 : CAIRO_FORMAT_ARGB32,
10167 width * sx, height * sy);
10168 cairo_surface_set_device_scale (surface, sx, sy);
10169 break;
10170 case CDK_RENDERING_MODE_SIMILAR:
10171 default:
10172 surface = cairo_surface_create_similar (window_surface,
10173 content,
10174 width, height);
10175 break;
10176 }
10177
10178 cairo_surface_destroy (window_surface);
10179
10180 return surface;
10181}
10182
10183
10184/**
10185 * cdk_window_create_similar_image_surface:
10186 * @window: (nullable): window to make new surface similar to, or
10187 * %NULL if none
10188 * @format: (type int): the format for the new surface
10189 * @width: width of the new surface
10190 * @height: height of the new surface
10191 * @scale: the scale of the new surface, or 0 to use same as @window
10192 *
10193 * Create a new image surface that is efficient to draw on the
10194 * given @window.
10195 *
10196 * Initially the surface contents are all 0 (transparent if contents
10197 * have transparency, black otherwise.)
10198 *
10199 * The @width and @height of the new surface are not affected by
10200 * the scaling factor of the @window, or by the @scale argument; they
10201 * are the size of the surface in device pixels. If you wish to create
10202 * an image surface capable of holding the contents of @window you can
10203 * use:
10204 *
10205 * |[<!-- language="C" -->
10206 * int scale = cdk_window_get_scale_factor (window);
10207 * int width = cdk_window_get_width (window) * scale;
10208 * int height = cdk_window_get_height (window) * scale;
10209 *
10210 * // format is set elsewhere
10211 * cairo_surface_t *surface =
10212 * cdk_window_create_similar_image_surface (window,
10213 * format,
10214 * width, height,
10215 * scale);
10216 * ]|
10217 *
10218 * Note that unlike cairo_surface_create_similar_image(), the new
10219 * surface's device scale is set to @scale, or to the scale factor of
10220 * @window if @scale is 0.
10221 *
10222 * Returns: a pointer to the newly allocated surface. The caller
10223 * owns the surface and should call cairo_surface_destroy() when done
10224 * with it.
10225 *
10226 * This function always returns a valid pointer, but it will return a
10227 * pointer to a “nil” surface if @other is already in an error state
10228 * or any other error occurs.
10229 *
10230 * Since: 3.10
10231 **/
10232cairo_surface_t *
10233cdk_window_create_similar_image_surface (CdkWindow * window,
10234 cairo_format_t format,
10235 int width,
10236 int height,
10237 int scale)
10238{
10239 CdkWindowImplClass *impl_class;
10240 cairo_surface_t *window_surface, *surface;
10241 CdkDisplay *display;
10242 CdkScreen *screen;
10243
10244 g_return_val_if_fail (window ==NULL || CDK_IS_WINDOW (window), NULL)do { if ((window ==((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((window)); GType __t = ((cdk_window_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Cdk", ((const
char*) (__func__)), "window ==NULL || CDK_IS_WINDOW (window)"
); return (((void*)0)); } } while (0)
;
10245
10246 if (window == NULL((void*)0))
10247 {
10248 display = cdk_display_get_default ();
10249 screen = cdk_display_get_default_screen (display);
10250 window = cdk_screen_get_root_window (screen);
10251 }
10252
10253 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
10254
10255 if (impl_class->create_similar_image_surface)
10256 surface = impl_class->create_similar_image_surface (window, format, width, height);
10257 else
10258 {
10259 window_surface = cdk_window_ref_impl_surface (window);
10260 surface =
10261 cairo_surface_create_similar_image (window_surface,
10262 format,
10263 width,
10264 height);
10265 cairo_surface_destroy (window_surface);
10266 }
10267
10268 if (scale == 0)
10269 scale = cdk_window_get_scale_factor (window);
10270
10271 cairo_surface_set_device_scale (surface, scale, scale);
10272
10273 return surface;
10274}
10275
10276
10277/**
10278 * cdk_window_focus:
10279 * @window: a #CdkWindow
10280 * @timestamp: timestamp of the event triggering the window focus
10281 *
10282 * Sets keyboard focus to @window. In most cases, ctk_window_present_with_time()
10283 * should be used on a #CtkWindow, rather than calling this function.
10284 *
10285 **/
10286void
10287cdk_window_focus (CdkWindow *window,
10288 guint32 timestamp)
10289{
10290 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->focus (window, timestamp);
10291}
10292
10293/**
10294 * cdk_window_set_type_hint:
10295 * @window: A toplevel #CdkWindow
10296 * @hint: A hint of the function this window will have
10297 *
10298 * The application can use this call to provide a hint to the window
10299 * manager about the functionality of a window. The window manager
10300 * can use this information when determining the decoration and behaviour
10301 * of the window.
10302 *
10303 * The hint must be set before the window is mapped.
10304 **/
10305void
10306cdk_window_set_type_hint (CdkWindow *window,
10307 CdkWindowTypeHint hint)
10308{
10309 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_type_hint (window, hint);
10310}
10311
10312/**
10313 * cdk_window_get_type_hint:
10314 * @window: A toplevel #CdkWindow
10315 *
10316 * This function returns the type hint set for a window.
10317 *
10318 * Returns: The type hint set for @window
10319 *
10320 * Since: 2.10
10321 **/
10322CdkWindowTypeHint
10323cdk_window_get_type_hint (CdkWindow *window)
10324{
10325 return CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->get_type_hint (window);
10326}
10327
10328/**
10329 * cdk_window_set_modal_hint:
10330 * @window: A toplevel #CdkWindow
10331 * @modal: %TRUE if the window is modal, %FALSE otherwise.
10332 *
10333 * The application can use this hint to tell the window manager
10334 * that a certain window has modal behaviour. The window manager
10335 * can use this information to handle modal windows in a special
10336 * way.
10337 *
10338 * You should only use this on windows for which you have
10339 * previously called cdk_window_set_transient_for()
10340 **/
10341void
10342cdk_window_set_modal_hint (CdkWindow *window,
10343 gboolean modal)
10344{
10345 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_modal_hint (window, modal);
10346}
10347
10348/**
10349 * cdk_window_set_skip_taskbar_hint:
10350 * @window: a toplevel #CdkWindow
10351 * @skips_taskbar: %TRUE to skip the taskbar
10352 *
10353 * Toggles whether a window should appear in a task list or window
10354 * list. If a window’s semantic type as specified with
10355 * cdk_window_set_type_hint() already fully describes the window, this
10356 * function should not be called in addition,
10357 * instead you should allow the window to be treated according to
10358 * standard policy for its semantic type.
10359 *
10360 * Since: 2.2
10361 **/
10362void
10363cdk_window_set_skip_taskbar_hint (CdkWindow *window,
10364 gboolean skips_taskbar)
10365{
10366 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_skip_taskbar_hint (window, skips_taskbar);
10367}
10368
10369/**
10370 * cdk_window_set_skip_pager_hint:
10371 * @window: a toplevel #CdkWindow
10372 * @skips_pager: %TRUE to skip the pager
10373 *
10374 * Toggles whether a window should appear in a pager (workspace
10375 * switcher, or other desktop utility program that displays a small
10376 * thumbnail representation of the windows on the desktop). If a
10377 * window’s semantic type as specified with cdk_window_set_type_hint()
10378 * already fully describes the window, this function should
10379 * not be called in addition, instead you should
10380 * allow the window to be treated according to standard policy for
10381 * its semantic type.
10382 *
10383 * Since: 2.2
10384 **/
10385void
10386cdk_window_set_skip_pager_hint (CdkWindow *window,
10387 gboolean skips_pager)
10388{
10389 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_skip_pager_hint (window, skips_pager);
10390}
10391
10392/**
10393 * cdk_window_set_urgency_hint:
10394 * @window: a toplevel #CdkWindow
10395 * @urgent: %TRUE if the window is urgent
10396 *
10397 * Toggles whether a window needs the user's
10398 * urgent attention.
10399 *
10400 * Since: 2.8
10401 **/
10402void
10403cdk_window_set_urgency_hint (CdkWindow *window,
10404 gboolean urgent)
10405{
10406 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_urgency_hint (window, urgent);
10407}
10408
10409/**
10410 * cdk_window_set_geometry_hints:
10411 * @window: a toplevel #CdkWindow
10412 * @geometry: geometry hints
10413 * @geom_mask: bitmask indicating fields of @geometry to pay attention to
10414 *
10415 * Sets the geometry hints for @window. Hints flagged in @geom_mask
10416 * are set, hints not flagged in @geom_mask are unset.
10417 * To unset all hints, use a @geom_mask of 0 and a @geometry of %NULL.
10418 *
10419 * This function provides hints to the windowing system about
10420 * acceptable sizes for a toplevel window. The purpose of
10421 * this is to constrain user resizing, but the windowing system
10422 * will typically (but is not required to) also constrain the
10423 * current size of the window to the provided values and
10424 * constrain programatic resizing via cdk_window_resize() or
10425 * cdk_window_move_resize().
10426 *
10427 * Note that on X11, this effect has no effect on windows
10428 * of type %CDK_WINDOW_TEMP or windows where override redirect
10429 * has been turned on via cdk_window_set_override_redirect()
10430 * since these windows are not resizable by the user.
10431 *
10432 * Since you can’t count on the windowing system doing the
10433 * constraints for programmatic resizes, you should generally
10434 * call cdk_window_constrain_size() yourself to determine
10435 * appropriate sizes.
10436 *
10437 **/
10438void
10439cdk_window_set_geometry_hints (CdkWindow *window,
10440 const CdkGeometry *geometry,
10441 CdkWindowHints geom_mask)
10442{
10443 g_return_if_fail (geometry != NULL || geom_mask == 0)do { if ((geometry != ((void*)0) || geom_mask == 0)) { } else
{ g_return_if_fail_warning ("Cdk", ((const char*) (__func__)
), "geometry != NULL || geom_mask == 0"); return; } } while (
0)
;
10444
10445 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_geometry_hints (window, geometry, geom_mask);
10446}
10447
10448/**
10449 * cdk_window_set_title:
10450 * @window: a toplevel #CdkWindow
10451 * @title: title of @window
10452 *
10453 * Sets the title of a toplevel window, to be displayed in the titlebar.
10454 * If you haven’t explicitly set the icon name for the window
10455 * (using cdk_window_set_icon_name()), the icon name will be set to
10456 * @title as well. @title must be in UTF-8 encoding (as with all
10457 * user-readable strings in CDK/CTK+). @title may not be %NULL.
10458 **/
10459void
10460cdk_window_set_title (CdkWindow *window,
10461 const gchar *title)
10462{
10463 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_title (window, title);
10464}
10465
10466/**
10467 * cdk_window_set_role:
10468 * @window: a toplevel #CdkWindow
10469 * @role: a string indicating its role
10470 *
10471 * When using CTK+, typically you should use ctk_window_set_role() instead
10472 * of this low-level function.
10473 *
10474 * The window manager and session manager use a window’s role to
10475 * distinguish it from other kinds of window in the same application.
10476 * When an application is restarted after being saved in a previous
10477 * session, all windows with the same title and role are treated as
10478 * interchangeable. So if you have two windows with the same title
10479 * that should be distinguished for session management purposes, you
10480 * should set the role on those windows. It doesn’t matter what string
10481 * you use for the role, as long as you have a different role for each
10482 * non-interchangeable kind of window.
10483 *
10484 **/
10485void
10486cdk_window_set_role (CdkWindow *window,
10487 const gchar *role)
10488{
10489 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_role (window, role);
10490}
10491
10492/**
10493 * cdk_window_set_startup_id:
10494 * @window: a toplevel #CdkWindow
10495 * @startup_id: a string with startup-notification identifier
10496 *
10497 * When using CTK+, typically you should use ctk_window_set_startup_id()
10498 * instead of this low-level function.
10499 *
10500 * Since: 2.12
10501 *
10502 **/
10503void
10504cdk_window_set_startup_id (CdkWindow *window,
10505 const gchar *startup_id)
10506{
10507 CdkWindowImplClass *klass = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
10508
10509 if (klass->set_startup_id)
10510 klass->set_startup_id (window, startup_id);
10511}
10512
10513/**
10514 * cdk_window_set_transient_for:
10515 * @window: a toplevel #CdkWindow
10516 * @parent: another toplevel #CdkWindow
10517 *
10518 * Indicates to the window manager that @window is a transient dialog
10519 * associated with the application window @parent. This allows the
10520 * window manager to do things like center @window on @parent and
10521 * keep @window above @parent.
10522 *
10523 * See ctk_window_set_transient_for() if you’re using #CtkWindow or
10524 * #CtkDialog.
10525 **/
10526void
10527cdk_window_set_transient_for (CdkWindow *window,
10528 CdkWindow *parent)
10529{
10530 window->transient_for = parent;
10531
10532 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_transient_for (window, parent);
10533}
10534
10535/**
10536 * cdk_window_get_root_origin:
10537 * @window: a toplevel #CdkWindow
10538 * @x: (out): return location for X position of window frame
10539 * @y: (out): return location for Y position of window frame
10540 *
10541 * Obtains the top-left corner of the window manager frame in root
10542 * window coordinates.
10543 *
10544 **/
10545void
10546cdk_window_get_root_origin (CdkWindow *window,
10547 gint *x,
10548 gint *y)
10549{
10550 CdkRectangle rect;
10551
10552 cdk_window_get_frame_extents (window, &rect);
10553
10554 if (x)
10555 *x = rect.x;
10556
10557 if (y)
10558 *y = rect.y;
10559}
10560
10561/**
10562 * cdk_window_get_frame_extents:
10563 * @window: a toplevel #CdkWindow
10564 * @rect: (out): rectangle to fill with bounding box of the window frame
10565 *
10566 * Obtains the bounding box of the window, including window manager
10567 * titlebar/borders if any. The frame position is given in root window
10568 * coordinates. To get the position of the window itself (rather than
10569 * the frame) in root window coordinates, use cdk_window_get_origin().
10570 *
10571 **/
10572void
10573cdk_window_get_frame_extents (CdkWindow *window,
10574 CdkRectangle *rect)
10575{
10576 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->get_frame_extents (window, rect);
10577}
10578
10579/**
10580 * cdk_window_set_override_redirect:
10581 * @window: a toplevel #CdkWindow
10582 * @override_redirect: %TRUE if window should be override redirect
10583 *
10584 * An override redirect window is not under the control of the window manager.
10585 * This means it won’t have a titlebar, won’t be minimizable, etc. - it will
10586 * be entirely under the control of the application. The window manager
10587 * can’t see the override redirect window at all.
10588 *
10589 * Override redirect should only be used for short-lived temporary
10590 * windows, such as popup menus. #CtkMenu uses an override redirect
10591 * window in its implementation, for example.
10592 *
10593 **/
10594void
10595cdk_window_set_override_redirect (CdkWindow *window,
10596 gboolean override_redirect)
10597{
10598 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_override_redirect (window, override_redirect);
10599}
10600
10601/**
10602 * cdk_window_set_accept_focus:
10603 * @window: a toplevel #CdkWindow
10604 * @accept_focus: %TRUE if the window should receive input focus
10605 *
10606 * Setting @accept_focus to %FALSE hints the desktop environment that the
10607 * window doesn’t want to receive input focus.
10608 *
10609 * On X, it is the responsibility of the window manager to interpret this
10610 * hint. ICCCM-compliant window manager usually respect it.
10611 *
10612 * Since: 2.4
10613 **/
10614void
10615cdk_window_set_accept_focus (CdkWindow *window,
10616 gboolean accept_focus)
10617{
10618 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_accept_focus (window, accept_focus);
10619}
10620
10621/**
10622 * cdk_window_set_focus_on_map:
10623 * @window: a toplevel #CdkWindow
10624 * @focus_on_map: %TRUE if the window should receive input focus when mapped
10625 *
10626 * Setting @focus_on_map to %FALSE hints the desktop environment that the
10627 * window doesn’t want to receive input focus when it is mapped.
10628 * focus_on_map should be turned off for windows that aren’t triggered
10629 * interactively (such as popups from network activity).
10630 *
10631 * On X, it is the responsibility of the window manager to interpret
10632 * this hint. Window managers following the freedesktop.org window
10633 * manager extension specification should respect it.
10634 *
10635 * Since: 2.6
10636 **/
10637void
10638cdk_window_set_focus_on_map (CdkWindow *window,
10639 gboolean focus_on_map)
10640{
10641 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_focus_on_map (window, focus_on_map);
10642}
10643
10644/**
10645 * cdk_window_set_event_compression:
10646 * @window: a #CdkWindow
10647 * @event_compression: %TRUE if motion events should be compressed
10648 *
10649 * Determines whether or not extra unprocessed motion events in
10650 * the event queue can be discarded. If %TRUE only the most recent
10651 * event will be delivered.
10652 *
10653 * Some types of applications, e.g. paint programs, need to see all
10654 * motion events and will benefit from turning off event compression.
10655 *
10656 * By default, event compression is enabled.
10657 *
10658 * Since: 3.12
10659 **/
10660void
10661cdk_window_set_event_compression (CdkWindow *window,
10662 gboolean event_compression)
10663{
10664 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
10665
10666 window->event_compression = !!event_compression;
10667}
10668
10669/**
10670 * cdk_window_get_event_compression:
10671 * @window: a #CdkWindow
10672 *
10673 * Get the current event compression setting for this window.
10674 *
10675 * Returns: %TRUE if motion events will be compressed
10676 *
10677 * Since: 3.12
10678 **/
10679gboolean
10680cdk_window_get_event_compression (CdkWindow *window)
10681{
10682 g_return_val_if_fail (CDK_IS_WINDOW (window), TRUE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return ((!(0))); } } while (0)
;
10683
10684 return window->event_compression;
10685}
10686
10687/**
10688 * cdk_window_set_icon_list:
10689 * @window: The #CdkWindow toplevel window to set the icon of.
10690 * @pixbufs: (transfer none) (element-type GdkPixbuf):
10691 * A list of pixbufs, of different sizes.
10692 *
10693 * Sets a list of icons for the window. One of these will be used
10694 * to represent the window when it has been iconified. The icon is
10695 * usually shown in an icon box or some sort of task bar. Which icon
10696 * size is shown depends on the window manager. The window manager
10697 * can scale the icon but setting several size icons can give better
10698 * image quality since the window manager may only need to scale the
10699 * icon by a small amount or not at all.
10700 *
10701 * Note that some platforms don't support window icons.
10702 */
10703void
10704cdk_window_set_icon_list (CdkWindow *window,
10705 GList *pixbufs)
10706{
10707 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_icon_list (window, pixbufs);
10708}
10709
10710/**
10711 * cdk_window_set_icon_name:
10712 * @window: a toplevel #CdkWindow
10713 * @name: (allow-none): name of window while iconified (minimized)
10714 *
10715 * Windows may have a name used while minimized, distinct from the
10716 * name they display in their titlebar. Most of the time this is a bad
10717 * idea from a user interface standpoint. But you can set such a name
10718 * with this function, if you like.
10719 *
10720 * After calling this with a non-%NULL @name, calls to cdk_window_set_title()
10721 * will not update the icon title.
10722 *
10723 * Using %NULL for @name unsets the icon title; further calls to
10724 * cdk_window_set_title() will again update the icon title as well.
10725 *
10726 * Note that some platforms don't support window icons.
10727 **/
10728void
10729cdk_window_set_icon_name (CdkWindow *window,
10730 const gchar *name)
10731{
10732 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_icon_name (window, name);
10733}
10734
10735/**
10736 * cdk_window_iconify:
10737 * @window: a toplevel #CdkWindow
10738 *
10739 * Asks to iconify (minimize) @window. The window manager may choose
10740 * to ignore the request, but normally will honor it. Using
10741 * ctk_window_iconify() is preferred, if you have a #CtkWindow widget.
10742 *
10743 * This function only makes sense when @window is a toplevel window.
10744 *
10745 **/
10746void
10747cdk_window_iconify (CdkWindow *window)
10748{
10749 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->iconify (window);
10750}
10751
10752/**
10753 * cdk_window_deiconify:
10754 * @window: a toplevel #CdkWindow
10755 *
10756 * Attempt to deiconify (unminimize) @window. On X11 the window manager may
10757 * choose to ignore the request to deiconify. When using CTK+,
10758 * use ctk_window_deiconify() instead of the #CdkWindow variant. Or better yet,
10759 * you probably want to use ctk_window_present_with_time(), which raises the window, focuses it,
10760 * unminimizes it, and puts it on the current desktop.
10761 *
10762 **/
10763void
10764cdk_window_deiconify (CdkWindow *window)
10765{
10766 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->deiconify (window);
10767}
10768
10769/**
10770 * cdk_window_stick:
10771 * @window: a toplevel #CdkWindow
10772 *
10773 * “Pins” a window such that it’s on all workspaces and does not scroll
10774 * with viewports, for window managers that have scrollable viewports.
10775 * (When using #CtkWindow, ctk_window_stick() may be more useful.)
10776 *
10777 * On the X11 platform, this function depends on window manager
10778 * support, so may have no effect with many window managers. However,
10779 * CDK will do the best it can to convince the window manager to stick
10780 * the window. For window managers that don’t support this operation,
10781 * there’s nothing you can do to force it to happen.
10782 *
10783 **/
10784void
10785cdk_window_stick (CdkWindow *window)
10786{
10787 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->stick (window);
10788}
10789
10790/**
10791 * cdk_window_unstick:
10792 * @window: a toplevel #CdkWindow
10793 *
10794 * Reverse operation for cdk_window_stick(); see cdk_window_stick(),
10795 * and ctk_window_unstick().
10796 *
10797 **/
10798void
10799cdk_window_unstick (CdkWindow *window)
10800{
10801 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->unstick (window);
10802}
10803
10804/**
10805 * cdk_window_maximize:
10806 * @window: a toplevel #CdkWindow
10807 *
10808 * Maximizes the window. If the window was already maximized, then
10809 * this function does nothing.
10810 *
10811 * On X11, asks the window manager to maximize @window, if the window
10812 * manager supports this operation. Not all window managers support
10813 * this, and some deliberately ignore it or don’t have a concept of
10814 * “maximized”; so you can’t rely on the maximization actually
10815 * happening. But it will happen with most standard window managers,
10816 * and CDK makes a best effort to get it to happen.
10817 *
10818 * On Windows, reliably maximizes the window.
10819 *
10820 **/
10821void
10822cdk_window_maximize (CdkWindow *window)
10823{
10824 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->maximize (window);
10825}
10826
10827/**
10828 * cdk_window_unmaximize:
10829 * @window: a toplevel #CdkWindow
10830 *
10831 * Unmaximizes the window. If the window wasn’t maximized, then this
10832 * function does nothing.
10833 *
10834 * On X11, asks the window manager to unmaximize @window, if the
10835 * window manager supports this operation. Not all window managers
10836 * support this, and some deliberately ignore it or don’t have a
10837 * concept of “maximized”; so you can’t rely on the unmaximization
10838 * actually happening. But it will happen with most standard window
10839 * managers, and CDK makes a best effort to get it to happen.
10840 *
10841 * On Windows, reliably unmaximizes the window.
10842 *
10843 **/
10844void
10845cdk_window_unmaximize (CdkWindow *window)
10846{
10847 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->unmaximize (window);
10848}
10849
10850/**
10851 * cdk_window_fullscreen:
10852 * @window: a toplevel #CdkWindow
10853 *
10854 * Moves the window into fullscreen mode. This means the
10855 * window covers the entire screen and is above any panels
10856 * or task bars.
10857 *
10858 * If the window was already fullscreen, then this function does nothing.
10859 *
10860 * On X11, asks the window manager to put @window in a fullscreen
10861 * state, if the window manager supports this operation. Not all
10862 * window managers support this, and some deliberately ignore it or
10863 * don’t have a concept of “fullscreen”; so you can’t rely on the
10864 * fullscreenification actually happening. But it will happen with
10865 * most standard window managers, and CDK makes a best effort to get
10866 * it to happen.
10867 *
10868 * Since: 2.2
10869 **/
10870void
10871cdk_window_fullscreen (CdkWindow *window)
10872{
10873 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->fullscreen (window);
10874}
10875
10876/**
10877 * cdk_window_fullscreen_on_monitor:
10878 * @window: a toplevel #CdkWindow
10879 * @monitor: Which monitor to display fullscreen on.
10880 *
10881 * Moves the window into fullscreen mode on the given monitor. This means
10882 * the window covers the entire screen and is above any panels or task bars.
10883 *
10884 * If the window was already fullscreen, then this function does nothing.
10885 * Since: UNRELEASED
10886 **/
10887void
10888cdk_window_fullscreen_on_monitor (CdkWindow *window,
10889 gint monitor)
10890{
10891 CdkDisplay *display = cdk_window_get_display (window);
10892
10893 g_return_if_fail (monitor >= 0)do { if ((monitor >= 0)) { } else { g_return_if_fail_warning
("Cdk", ((const char*) (__func__)), "monitor >= 0"); return
; } } while (0)
;
10894 g_return_if_fail (monitor < cdk_display_get_n_monitors (display))do { if ((monitor < cdk_display_get_n_monitors (display)))
{ } else { g_return_if_fail_warning ("Cdk", ((const char*) (
__func__)), "monitor < cdk_display_get_n_monitors (display)"
); return; } } while (0)
;
10895
10896 if (CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->fullscreen_on_monitor != NULL((void*)0))
10897 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->fullscreen_on_monitor (window, monitor);
10898 else
10899 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->fullscreen (window);
10900}
10901
10902/**
10903 * cdk_window_set_fullscreen_mode:
10904 * @window: a toplevel #CdkWindow
10905 * @mode: fullscreen mode
10906 *
10907 * Specifies whether the @window should span over all monitors (in a multi-head
10908 * setup) or only the current monitor when in fullscreen mode.
10909 *
10910 * The @mode argument is from the #CdkFullscreenMode enumeration.
10911 * If #CDK_FULLSCREEN_ON_ALL_MONITORS is specified, the fullscreen @window will
10912 * span over all monitors from the #CdkScreen.
10913 *
10914 * On X11, searches through the list of monitors from the #CdkScreen the ones
10915 * which delimit the 4 edges of the entire #CdkScreen and will ask the window
10916 * manager to span the @window over these monitors.
10917 *
10918 * If the XINERAMA extension is not available or not usable, this function
10919 * has no effect.
10920 *
10921 * Not all window managers support this, so you can’t rely on the fullscreen
10922 * window to span over the multiple monitors when #CDK_FULLSCREEN_ON_ALL_MONITORS
10923 * is specified.
10924 *
10925 * Since: 3.8
10926 **/
10927void
10928cdk_window_set_fullscreen_mode (CdkWindow *window,
10929 CdkFullscreenMode mode)
10930{
10931 CdkWindowImplClass *impl_class;
10932
10933 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
10934
10935 if (window->fullscreen_mode != mode)
10936 {
10937 window->fullscreen_mode = mode;
10938
10939 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
10940 if (impl_class->apply_fullscreen_mode != NULL((void*)0))
10941 impl_class->apply_fullscreen_mode (window);
10942 }
10943}
10944
10945/**
10946 * cdk_window_get_fullscreen_mode:
10947 * @window: a toplevel #CdkWindow
10948 *
10949 * Obtains the #CdkFullscreenMode of the @window.
10950 *
10951 * Returns: The #CdkFullscreenMode applied to the window when fullscreen.
10952 *
10953 * Since: 3.8
10954 **/
10955CdkFullscreenMode
10956cdk_window_get_fullscreen_mode (CdkWindow *window)
10957{
10958 g_return_val_if_fail (CDK_IS_WINDOW (window), CDK_FULLSCREEN_ON_CURRENT_MONITOR)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (CDK_FULLSCREEN_ON_CURRENT_MONITOR
); } } while (0)
;
10959
10960 return window->fullscreen_mode;
10961}
10962
10963/**
10964 * cdk_window_unfullscreen:
10965 * @window: a toplevel #CdkWindow
10966 *
10967 * Moves the window out of fullscreen mode. If the window was not
10968 * fullscreen, does nothing.
10969 *
10970 * On X11, asks the window manager to move @window out of the fullscreen
10971 * state, if the window manager supports this operation. Not all
10972 * window managers support this, and some deliberately ignore it or
10973 * don’t have a concept of “fullscreen”; so you can’t rely on the
10974 * unfullscreenification actually happening. But it will happen with
10975 * most standard window managers, and CDK makes a best effort to get
10976 * it to happen.
10977 *
10978 * Since: 2.2
10979 **/
10980void
10981cdk_window_unfullscreen (CdkWindow *window)
10982{
10983 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->unfullscreen (window);
10984}
10985
10986/**
10987 * cdk_window_set_keep_above:
10988 * @window: a toplevel #CdkWindow
10989 * @setting: whether to keep @window above other windows
10990 *
10991 * Set if @window must be kept above other windows. If the
10992 * window was already above, then this function does nothing.
10993 *
10994 * On X11, asks the window manager to keep @window above, if the window
10995 * manager supports this operation. Not all window managers support
10996 * this, and some deliberately ignore it or don’t have a concept of
10997 * “keep above”; so you can’t rely on the window being kept above.
10998 * But it will happen with most standard window managers,
10999 * and CDK makes a best effort to get it to happen.
11000 *
11001 * Since: 2.4
11002 **/
11003void
11004cdk_window_set_keep_above (CdkWindow *window,
11005 gboolean setting)
11006{
11007 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_keep_above (window, setting);
11008}
11009
11010/**
11011 * cdk_window_set_keep_below:
11012 * @window: a toplevel #CdkWindow
11013 * @setting: whether to keep @window below other windows
11014 *
11015 * Set if @window must be kept below other windows. If the
11016 * window was already below, then this function does nothing.
11017 *
11018 * On X11, asks the window manager to keep @window below, if the window
11019 * manager supports this operation. Not all window managers support
11020 * this, and some deliberately ignore it or don’t have a concept of
11021 * “keep below”; so you can’t rely on the window being kept below.
11022 * But it will happen with most standard window managers,
11023 * and CDK makes a best effort to get it to happen.
11024 *
11025 * Since: 2.4
11026 **/
11027void
11028cdk_window_set_keep_below (CdkWindow *window, gboolean setting)
11029{
11030 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_keep_below (window, setting);
11031}
11032
11033/**
11034 * cdk_window_get_group:
11035 * @window: a toplevel #CdkWindow
11036 *
11037 * Returns the group leader window for @window. See cdk_window_set_group().
11038 *
11039 * Returns: (transfer none): the group leader window for @window
11040 *
11041 * Since: 2.4
11042 **/
11043CdkWindow *
11044cdk_window_get_group (CdkWindow *window)
11045{
11046 return CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->get_group (window);
11047}
11048
11049/**
11050 * cdk_window_set_group:
11051 * @window: a toplevel #CdkWindow
11052 * @leader: (allow-none): group leader window, or %NULL to restore the default group leader window
11053 *
11054 * Sets the group leader window for @window. By default,
11055 * CDK sets the group leader for all toplevel windows
11056 * to a global window implicitly created by CDK. With this function
11057 * you can override this default.
11058 *
11059 * The group leader window allows the window manager to distinguish
11060 * all windows that belong to a single application. It may for example
11061 * allow users to minimize/unminimize all windows belonging to an
11062 * application at once. You should only set a non-default group window
11063 * if your application pretends to be multiple applications.
11064 **/
11065void
11066cdk_window_set_group (CdkWindow *window,
11067 CdkWindow *leader)
11068{
11069 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_group (window, leader);
11070}
11071
11072/**
11073 * cdk_window_set_decorations:
11074 * @window: a toplevel #CdkWindow
11075 * @decorations: decoration hint mask
11076 *
11077 * “Decorations” are the features the window manager adds to a toplevel #CdkWindow.
11078 * This function sets the traditional Motif window manager hints that tell the
11079 * window manager which decorations you would like your window to have.
11080 * Usually you should use ctk_window_set_decorated() on a #CtkWindow instead of
11081 * using the CDK function directly.
11082 *
11083 * The @decorations argument is the logical OR of the fields in
11084 * the #CdkWMDecoration enumeration. If #CDK_DECOR_ALL is included in the
11085 * mask, the other bits indicate which decorations should be turned off.
11086 * If #CDK_DECOR_ALL is not included, then the other bits indicate
11087 * which decorations should be turned on.
11088 *
11089 * Most window managers honor a decorations hint of 0 to disable all decorations,
11090 * but very few honor all possible combinations of bits.
11091 *
11092 **/
11093void
11094cdk_window_set_decorations (CdkWindow *window,
11095 CdkWMDecoration decorations)
11096{
11097 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_decorations (window, decorations);
11098}
11099
11100/**
11101 * cdk_window_get_decorations:
11102 * @window: The toplevel #CdkWindow to get the decorations from
11103 * @decorations: (out): The window decorations will be written here
11104 *
11105 * Returns the decorations set on the CdkWindow with
11106 * cdk_window_set_decorations().
11107 *
11108 * Returns: %TRUE if the window has decorations set, %FALSE otherwise.
11109 **/
11110gboolean
11111cdk_window_get_decorations(CdkWindow *window,
11112 CdkWMDecoration *decorations)
11113{
11114 return CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->get_decorations (window, decorations);
11115}
11116
11117/**
11118 * cdk_window_set_functions:
11119 * @window: a toplevel #CdkWindow
11120 * @functions: bitmask of operations to allow on @window
11121 *
11122 * Sets hints about the window management functions to make available
11123 * via buttons on the window frame.
11124 *
11125 * On the X backend, this function sets the traditional Motif window
11126 * manager hint for this purpose. However, few window managers do
11127 * anything reliable or interesting with this hint. Many ignore it
11128 * entirely.
11129 *
11130 * The @functions argument is the logical OR of values from the
11131 * #CdkWMFunction enumeration. If the bitmask includes #CDK_FUNC_ALL,
11132 * then the other bits indicate which functions to disable; if
11133 * it doesn’t include #CDK_FUNC_ALL, it indicates which functions to
11134 * enable.
11135 *
11136 **/
11137void
11138cdk_window_set_functions (CdkWindow *window,
11139 CdkWMFunction functions)
11140{
11141 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_functions (window, functions);
11142}
11143
11144/**
11145 * cdk_window_begin_resize_drag_for_device:
11146 * @window: a toplevel #CdkWindow
11147 * @edge: the edge or corner from which the drag is started
11148 * @device: the device used for the operation
11149 * @button: the button being used to drag, or 0 for a keyboard-initiated drag
11150 * @root_x: root window X coordinate of mouse click that began the drag
11151 * @root_y: root window Y coordinate of mouse click that began the drag
11152 * @timestamp: timestamp of mouse click that began the drag (use cdk_event_get_time())
11153 *
11154 * Begins a window resize operation (for a toplevel window).
11155 * You might use this function to implement a “window resize grip,” for
11156 * example; in fact #CtkStatusbar uses it. The function works best
11157 * with window managers that support the
11158 * [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec)
11159 * but has a fallback implementation for other window managers.
11160 *
11161 * Since: 3.4
11162 */
11163void
11164cdk_window_begin_resize_drag_for_device (CdkWindow *window,
11165 CdkWindowEdge edge,
11166 CdkDevice *device,
11167 gint button,
11168 gint root_x,
11169 gint root_y,
11170 guint32 timestamp)
11171{
11172 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->begin_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
11173}
11174
11175/**
11176 * cdk_window_begin_resize_drag:
11177 * @window: a toplevel #CdkWindow
11178 * @edge: the edge or corner from which the drag is started
11179 * @button: the button being used to drag, or 0 for a keyboard-initiated drag
11180 * @root_x: root window X coordinate of mouse click that began the drag
11181 * @root_y: root window Y coordinate of mouse click that began the drag
11182 * @timestamp: timestamp of mouse click that began the drag (use cdk_event_get_time())
11183 *
11184 * Begins a window resize operation (for a toplevel window).
11185 *
11186 * This function assumes that the drag is controlled by the
11187 * client pointer device, use cdk_window_begin_resize_drag_for_device()
11188 * to begin a drag with a different device.
11189 */
11190void
11191cdk_window_begin_resize_drag (CdkWindow *window,
11192 CdkWindowEdge edge,
11193 gint button,
11194 gint root_x,
11195 gint root_y,
11196 guint32 timestamp)
11197{
11198 CdkDisplay *display;
11199 CdkDevice *device;
11200
11201 display = cdk_window_get_display (window);
11202 device = cdk_seat_get_pointer (cdk_display_get_default_seat (display));
11203 cdk_window_begin_resize_drag_for_device (window, edge,
11204 device, button, root_x, root_y, timestamp);
11205}
11206
11207/**
11208 * cdk_window_begin_move_drag_for_device:
11209 * @window: a toplevel #CdkWindow
11210 * @device: the device used for the operation
11211 * @button: the button being used to drag, or 0 for a keyboard-initiated drag
11212 * @root_x: root window X coordinate of mouse click that began the drag
11213 * @root_y: root window Y coordinate of mouse click that began the drag
11214 * @timestamp: timestamp of mouse click that began the drag
11215 *
11216 * Begins a window move operation (for a toplevel window).
11217 * You might use this function to implement a “window move grip,” for
11218 * example. The function works best with window managers that support the
11219 * [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec)
11220 * but has a fallback implementation for other window managers.
11221 *
11222 * Since: 3.4
11223 */
11224void
11225cdk_window_begin_move_drag_for_device (CdkWindow *window,
11226 CdkDevice *device,
11227 gint button,
11228 gint root_x,
11229 gint root_y,
11230 guint32 timestamp)
11231{
11232 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->begin_move_drag (window,
11233 device, button, root_x, root_y, timestamp);
11234}
11235
11236/**
11237 * cdk_window_begin_move_drag:
11238 * @window: a toplevel #CdkWindow
11239 * @button: the button being used to drag, or 0 for a keyboard-initiated drag
11240 * @root_x: root window X coordinate of mouse click that began the drag
11241 * @root_y: root window Y coordinate of mouse click that began the drag
11242 * @timestamp: timestamp of mouse click that began the drag
11243 *
11244 * Begins a window move operation (for a toplevel window).
11245 *
11246 * This function assumes that the drag is controlled by the
11247 * client pointer device, use cdk_window_begin_move_drag_for_device()
11248 * to begin a drag with a different device.
11249 */
11250void
11251cdk_window_begin_move_drag (CdkWindow *window,
11252 gint button,
11253 gint root_x,
11254 gint root_y,
11255 guint32 timestamp)
11256{
11257 CdkDisplay *display;
11258 CdkDevice *device;
11259
11260 display = cdk_window_get_display (window);
11261 device = cdk_seat_get_pointer (cdk_display_get_default_seat (display));
11262 cdk_window_begin_move_drag_for_device (window, device, button, root_x, root_y, timestamp);
11263}
11264
11265/**
11266 * cdk_window_enable_synchronized_configure:
11267 * @window: a toplevel #CdkWindow
11268 *
11269 * Does nothing, present only for compatiblity.
11270 *
11271 * Since: 2.6
11272 * Deprecated: 3.8: this function is no longer needed
11273 **/
11274void
11275cdk_window_enable_synchronized_configure (CdkWindow *window G_GNUC_UNUSED__attribute__ ((__unused__)))
11276{
11277}
11278
11279/**
11280 * cdk_window_configure_finished:
11281 * @window: a toplevel #CdkWindow
11282 *
11283 * Does nothing, present only for compatiblity.
11284 *
11285 * Since: 2.6
11286 * Deprecated: 3.8: this function is no longer needed
11287 **/
11288void
11289cdk_window_configure_finished (CdkWindow *window G_GNUC_UNUSED__attribute__ ((__unused__)))
11290{
11291}
11292
11293/**
11294 * cdk_window_set_opacity:
11295 * @window: a top-level or non-native #CdkWindow
11296 * @opacity: opacity
11297 *
11298 * Set @window to render as partially transparent,
11299 * with opacity 0 being fully transparent and 1 fully opaque. (Values
11300 * of the opacity parameter are clamped to the [0,1] range.)
11301 *
11302 * For toplevel windows this depends on support from the windowing system
11303 * that may not always be there. For instance, On X11, this works only on
11304 * X screens with a compositing manager running. On Wayland, there is no
11305 * per-window opacity value that the compositor would apply. Instead, use
11306 * `cdk_window_set_opaque_region (window, NULL)` to tell the compositor
11307 * that the entire window is (potentially) non-opaque, and draw your content
11308 * with alpha, or use ctk_widget_set_opacity() to set an overall opacity
11309 * for your widgets.
11310 *
11311 * For child windows this function only works for non-native windows.
11312 *
11313 * For setting up per-pixel alpha topelevels, see cdk_screen_get_rgba_visual(),
11314 * and for non-toplevels, see cdk_window_set_composited().
11315 *
11316 * Support for non-toplevel windows was added in 3.8.
11317 *
11318 * Since: 2.12
11319 */
11320void
11321cdk_window_set_opacity (CdkWindow *window,
11322 gdouble opacity)
11323{
11324 if (opacity < 0)
11325 opacity = 0;
11326 else if (opacity > 1)
11327 opacity = 1;
11328
11329 window->alpha = round (opacity * 255);
11330
11331 if (window->destroyed)
11332 return;
11333
11334 if (cdk_window_has_impl (window))
11335 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->set_opacity (window, opacity);
11336 else
11337 {
11338 recompute_visible_regions (window, FALSE(0));
11339 cdk_window_invalidate_rect_full (window, NULL((void*)0), TRUE(!(0)));
11340 }
11341}
11342
11343/* This function is called when the XWindow is really gone.
11344 */
11345void
11346cdk_window_destroy_notify (CdkWindow *window)
11347{
11348 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->destroy_notify (window);
11349}
11350
11351/**
11352 * cdk_window_register_dnd:
11353 * @window: a #CdkWindow.
11354 *
11355 * Registers a window as a potential drop destination.
11356 */
11357void
11358cdk_window_register_dnd (CdkWindow *window)
11359{
11360 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->register_dnd (window);
11361}
11362
11363/**
11364 * cdk_window_get_drag_protocol:
11365 * @window: the destination window
11366 * @target: (out) (allow-none) (transfer full): location of the window
11367 * where the drop should happen. This may be @window or a proxy window,
11368 * or %NULL if @window does not support Drag and Drop.
11369 *
11370 * Finds out the DND protocol supported by a window.
11371 *
11372 * Returns: the supported DND protocol.
11373 *
11374 * Since: 3.0
11375 */
11376CdkDragProtocol
11377cdk_window_get_drag_protocol (CdkWindow *window,
11378 CdkWindow **target)
11379{
11380 g_return_val_if_fail (CDK_IS_WINDOW (window), CDK_DRAG_PROTO_NONE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (CDK_DRAG_PROTO_NONE); }
} while (0)
;
11381
11382 return CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->get_drag_protocol (window, target);
11383}
11384
11385/**
11386 * cdk_drag_begin:
11387 * @window: the source window for this drag.
11388 * @targets: (transfer none) (element-type CdkAtom): the offered targets,
11389 * as list of #CdkAtoms
11390 *
11391 * Starts a drag and creates a new drag context for it.
11392 * This function assumes that the drag is controlled by the
11393 * client pointer device, use cdk_drag_begin_for_device() to
11394 * begin a drag with a different device.
11395 *
11396 * This function is called by the drag source.
11397 *
11398 * Returns: (transfer full): a newly created #CdkDragContext
11399 */
11400CdkDragContext *
11401cdk_drag_begin (CdkWindow *window,
11402 GList *targets)
11403{
11404 CdkDisplay *display;
11405 CdkDevice *device;
11406
11407 display = cdk_window_get_display (window);
11408 device = cdk_seat_get_pointer (cdk_display_get_default_seat (display));
11409
11410 return cdk_drag_begin_for_device (window, device, targets);
11411}
11412
11413/**
11414 * cdk_drag_begin_for_device:
11415 * @window: the source window for this drag
11416 * @device: the device that controls this drag
11417 * @targets: (transfer none) (element-type CdkAtom): the offered targets,
11418 * as list of #CdkAtoms
11419 *
11420 * Starts a drag and creates a new drag context for it.
11421 *
11422 * This function is called by the drag source.
11423 *
11424 * Returns: (transfer full): a newly created #CdkDragContext
11425 */
11426CdkDragContext *
11427cdk_drag_begin_for_device (CdkWindow *window,
11428 CdkDevice *device,
11429 GList *targets)
11430{
11431 gint x, y;
11432
11433 cdk_device_get_position (device, NULL((void*)0), &x, &y);
11434
11435 return cdk_drag_begin_from_point (window, device, targets, x, y);
11436}
11437
11438/**
11439 * cdk_drag_begin_from_point:
11440 * @window: the source window for this drag
11441 * @device: the device that controls this drag
11442 * @targets: (transfer none) (element-type CdkAtom): the offered targets,
11443 * as list of #CdkAtoms
11444 * @x_root: the x coordinate where the drag nominally started
11445 * @y_root: the y coordinate where the drag nominally started
11446 *
11447 * Starts a drag and creates a new drag context for it.
11448 *
11449 * This function is called by the drag source.
11450 *
11451 * Returns: (transfer full): a newly created #CdkDragContext
11452 *
11453 * Since: 3.20
11454 */
11455CdkDragContext *
11456cdk_drag_begin_from_point (CdkWindow *window,
11457 CdkDevice *device,
11458 GList *targets,
11459 gint x_root,
11460 gint y_root)
11461{
11462 return CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->drag_begin (window, device, targets, x_root, y_root);
11463}
11464
11465/**
11466 * cdk_test_render_sync:
11467 * @window: a mapped #CdkWindow
11468 *
11469 * Retrieves a pixel from @window to force the windowing
11470 * system to carry out any pending rendering commands.
11471 *
11472 * This function is intended to be used to synchronize with rendering
11473 * pipelines, to benchmark windowing system rendering operations.
11474 *
11475 * Since: 2.14
11476 **/
11477void
11478cdk_test_render_sync (CdkWindow *window)
11479{
11480 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->sync_rendering (window);
11481}
11482
11483/**
11484 * cdk_test_simulate_key:
11485 * @window: a #CdkWindow to simulate a key event for
11486 * @x: x coordinate within @window for the key event
11487 * @y: y coordinate within @window for the key event
11488 * @keyval: A CDK keyboard value
11489 * @modifiers: Keyboard modifiers the event is setup with
11490 * @key_pressrelease: either %CDK_KEY_PRESS or %CDK_KEY_RELEASE
11491 *
11492 * This function is intended to be used in CTK+ test programs.
11493 * If (@x,@y) are > (-1,-1), it will warp the mouse pointer to
11494 * the given (@x,@y) coordinates within @window and simulate a
11495 * key press or release event.
11496 *
11497 * When the mouse pointer is warped to the target location, use
11498 * of this function outside of test programs that run in their
11499 * own virtual windowing system (e.g. Xvfb) is not recommended.
11500 * If (@x,@y) are passed as (-1,-1), the mouse pointer will not
11501 * be warped and @window origin will be used as mouse pointer
11502 * location for the event.
11503 *
11504 * Also, cdk_test_simulate_key() is a fairly low level function,
11505 * for most testing purposes, ctk_test_widget_send_key() is the
11506 * right function to call which will generate a key press event
11507 * followed by its accompanying key release event.
11508 *
11509 * Returns: whether all actions necessary for a key event simulation
11510 * were carried out successfully
11511 *
11512 * Since: 2.14
11513 */
11514gboolean
11515cdk_test_simulate_key (CdkWindow *window,
11516 gint x,
11517 gint y,
11518 guint keyval,
11519 CdkModifierType modifiers,
11520 CdkEventType key_pressrelease)
11521{
11522 return CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
11523 ->simulate_key (window, x, y, keyval, modifiers, key_pressrelease);
11524}
11525
11526/**
11527 * cdk_test_simulate_button:
11528 * @window: a #CdkWindow to simulate a button event for
11529 * @x: x coordinate within @window for the button event
11530 * @y: y coordinate within @window for the button event
11531 * @button: Number of the pointer button for the event, usually 1, 2 or 3
11532 * @modifiers: Keyboard modifiers the event is setup with
11533 * @button_pressrelease: either %CDK_BUTTON_PRESS or %CDK_BUTTON_RELEASE
11534 *
11535 * This function is intended to be used in CTK+ test programs.
11536 * It will warp the mouse pointer to the given (@x,@y) coordinates
11537 * within @window and simulate a button press or release event.
11538 * Because the mouse pointer needs to be warped to the target
11539 * location, use of this function outside of test programs that
11540 * run in their own virtual windowing system (e.g. Xvfb) is not
11541 * recommended.
11542 *
11543* Also, cdk_test_simulate_button() is a fairly low level function,
11544 * for most testing purposes, ctk_test_widget_click() is the right
11545 * function to call which will generate a button press event followed
11546 * by its accompanying button release event.
11547 *
11548 * Returns: whether all actions necessary for a button event simulation
11549 * were carried out successfully
11550 *
11551 * Since: 2.14
11552 */
11553gboolean
11554cdk_test_simulate_button (CdkWindow *window,
11555 gint x,
11556 gint y,
11557 guint button, /*1..3*/
11558 CdkModifierType modifiers,
11559 CdkEventType button_pressrelease)
11560{
11561 return CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
11562 ->simulate_button (window, x, y, button, modifiers, button_pressrelease);
11563}
11564
11565/**
11566 * cdk_property_get:
11567 * @window: a #CdkWindow
11568 * @property: the property to retrieve
11569 * @type: the desired property type, or %CDK_NONE, if any type of data
11570 * is acceptable. If this does not match the actual
11571 * type, then @actual_format and @actual_length will
11572 * be filled in, a warning will be printed to stderr
11573 * and no data will be returned.
11574 * @offset: the offset into the property at which to begin
11575 * retrieving data, in 4 byte units.
11576 * @length: the length of the data to retrieve in bytes. Data is
11577 * considered to be retrieved in 4 byte chunks, so @length
11578 * will be rounded up to the next highest 4 byte boundary
11579 * (so be careful not to pass a value that might overflow
11580 * when rounded up).
11581 * @pdelete: if %TRUE, delete the property after retrieving the
11582 * data.
11583 * @actual_property_type: (out) (transfer none): location to store the
11584 * actual type of the property.
11585 * @actual_format: (out): location to store the actual return format of the
11586 * data; either 8, 16 or 32 bits.
11587 * @actual_length: location to store the length of the retrieved data, in
11588 * bytes. Data returned in the 32 bit format is stored
11589 * in a long variable, so the actual number of 32 bit
11590 * elements should be be calculated via
11591 * @actual_length / sizeof(glong) to ensure portability to
11592 * 64 bit systems.
11593 * @data: (out) (array length=actual_length) (transfer full): location
11594 * to store a pointer to the data. The retrieved data should be
11595 * freed with g_free() when you are finished using it.
11596 *
11597 * Retrieves a portion of the contents of a property. If the
11598 * property does not exist, then the function returns %FALSE,
11599 * and %CDK_NONE will be stored in @actual_property_type.
11600 *
11601 * The XGetWindowProperty() function that cdk_property_get()
11602 * uses has a very confusing and complicated set of semantics.
11603 * Unfortunately, cdk_property_get() makes the situation
11604 * worse instead of better (the semantics should be considered
11605 * undefined), and also prints warnings to stderr in cases where it
11606 * should return a useful error to the program. You are advised to use
11607 * XGetWindowProperty() directly until a replacement function for
11608 * cdk_property_get() is provided.
11609 *
11610 * Returns: %TRUE if data was successfully received and stored
11611 * in @data, otherwise %FALSE.
11612 */
11613gboolean
11614cdk_property_get (CdkWindow *window,
11615 CdkAtom property,
11616 CdkAtom type,
11617 gulong offset,
11618 gulong length,
11619 gint pdelete,
11620 CdkAtom *actual_property_type,
11621 gint *actual_format_type,
11622 gint *actual_length,
11623 guchar **data)
11624{
11625 return CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
11626 ->get_property (window, property, type, offset, length, pdelete,
11627 actual_property_type, actual_format_type,
11628 actual_length, data);
11629}
11630
11631/**
11632 * cdk_property_change: (skip)
11633 * @window: a #CdkWindow
11634 * @property: the property to change
11635 * @type: the new type for the property. If @mode is
11636 * %CDK_PROP_MODE_PREPEND or %CDK_PROP_MODE_APPEND, then this
11637 * must match the existing type or an error will occur.
11638 * @format: the new format for the property. If @mode is
11639 * %CDK_PROP_MODE_PREPEND or %CDK_PROP_MODE_APPEND, then this
11640 * must match the existing format or an error will occur.
11641 * @mode: a value describing how the new data is to be combined
11642 * with the current data.
11643 * @data: the data (a `guchar *`
11644 * `gushort *`, or `gulong *`,
11645 * depending on @format), cast to a `guchar *`.
11646 * @nelements: the number of elements of size determined by the format,
11647 * contained in @data.
11648 *
11649 * Changes the contents of a property on a window.
11650 */
11651void
11652cdk_property_change (CdkWindow *window,
11653 CdkAtom property,
11654 CdkAtom type,
11655 gint format,
11656 CdkPropMode mode,
11657 const guchar *data,
11658 gint nelements)
11659{
11660 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
11661 ->change_property (window, property, type, format, mode, data, nelements);
11662}
11663
11664/**
11665 * cdk_property_delete:
11666 * @window: a #CdkWindow
11667 * @property: the property to delete
11668 *
11669 * Deletes a property from a window.
11670 */
11671void
11672cdk_property_delete (CdkWindow *window,
11673 CdkAtom property)
11674{
11675 CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
->delete_property (window, property);
11676}
11677
11678static void
11679cdk_window_flush_events (CdkFrameClock *clock,
11680 void *data)
11681{
11682 CdkWindow *window;
11683 CdkDisplay *display;
11684
11685 window = CDK_WINDOW (data)((((CdkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((cdk_window_get_type ()))))))
;
11686
11687 display = cdk_window_get_display (window);
11688 _cdk_event_queue_flush (display);
11689 _cdk_display_pause_events (display);
11690
11691 cdk_frame_clock_request_phase (clock, CDK_FRAME_CLOCK_PHASE_RESUME_EVENTS);
11692
11693 window->frame_clock_events_paused = TRUE(!(0));
11694}
11695
11696static void
11697cdk_window_paint_on_clock (CdkFrameClock *clock G_GNUC_UNUSED__attribute__ ((__unused__)),
11698 void *data)
11699{
11700 CdkWindow *window;
11701
11702 window = CDK_WINDOW (data)((((CdkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((cdk_window_get_type ()))))))
;
11703
11704 /* Update window and any children on the same clock.
11705 */
11706 cdk_window_process_updates_with_mode (window, PROCESS_UPDATES_WITH_SAME_CLOCK_CHILDREN);
11707}
11708
11709static void
11710cdk_window_resume_events (CdkFrameClock *clock G_GNUC_UNUSED__attribute__ ((__unused__)),
11711 void *data)
11712{
11713 CdkWindow *window;
11714 CdkDisplay *display;
11715
11716 window = CDK_WINDOW (data)((((CdkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((cdk_window_get_type ()))))))
;
11717
11718 display = cdk_window_get_display (window);
11719 _cdk_display_unpause_events (display);
11720
11721 window->frame_clock_events_paused = FALSE(0);
11722}
11723
11724static void
11725cdk_window_set_frame_clock (CdkWindow *window,
11726 CdkFrameClock *clock)
11727{
11728 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
11729 g_return_if_fail (clock == NULL || CDK_IS_FRAME_CLOCK (clock))do { if ((clock == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((clock)); GType __t = ((cdk_frame_clock_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Cdk", ((const
char*) (__func__)), "clock == NULL || CDK_IS_FRAME_CLOCK (clock)"
); return; } } while (0)
;
11730 g_return_if_fail (clock == NULL || cdk_window_is_toplevel (window))do { if ((clock == ((void*)0) || cdk_window_is_toplevel (window
))) { } else { g_return_if_fail_warning ("Cdk", ((const char*
) (__func__)), "clock == NULL || cdk_window_is_toplevel (window)"
); return; } } while (0)
;
11731
11732 if (clock == window->frame_clock)
11733 return;
11734
11735 if (clock)
11736 {
11737 g_object_ref (clock)((__typeof__ (clock)) (g_object_ref) (clock));
11738 g_signal_connect (G_OBJECT (clock),g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((clock)), (((GType) ((20) << (2))))
))))), ("flush-events"), (((GCallback) (cdk_window_flush_events
))), (window), ((void*)0), (GConnectFlags) 0)
11739 "flush-events",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((clock)), (((GType) ((20) << (2))))
))))), ("flush-events"), (((GCallback) (cdk_window_flush_events
))), (window), ((void*)0), (GConnectFlags) 0)
11740 G_CALLBACK (cdk_window_flush_events),g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((clock)), (((GType) ((20) << (2))))
))))), ("flush-events"), (((GCallback) (cdk_window_flush_events
))), (window), ((void*)0), (GConnectFlags) 0)
11741 window)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((clock)), (((GType) ((20) << (2))))
))))), ("flush-events"), (((GCallback) (cdk_window_flush_events
))), (window), ((void*)0), (GConnectFlags) 0)
;
11742 g_signal_connect (G_OBJECT (clock),g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((clock)), (((GType) ((20) << (2))))
))))), ("paint"), (((GCallback) (cdk_window_paint_on_clock)))
, (window), ((void*)0), (GConnectFlags) 0)
11743 "paint",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((clock)), (((GType) ((20) << (2))))
))))), ("paint"), (((GCallback) (cdk_window_paint_on_clock)))
, (window), ((void*)0), (GConnectFlags) 0)
11744 G_CALLBACK (cdk_window_paint_on_clock),g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((clock)), (((GType) ((20) << (2))))
))))), ("paint"), (((GCallback) (cdk_window_paint_on_clock)))
, (window), ((void*)0), (GConnectFlags) 0)
11745 window)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((clock)), (((GType) ((20) << (2))))
))))), ("paint"), (((GCallback) (cdk_window_paint_on_clock)))
, (window), ((void*)0), (GConnectFlags) 0)
;
11746 g_signal_connect (G_OBJECT (clock),g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((clock)), (((GType) ((20) << (2))))
))))), ("resume-events"), (((GCallback) (cdk_window_resume_events
))), (window), ((void*)0), (GConnectFlags) 0)
11747 "resume-events",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((clock)), (((GType) ((20) << (2))))
))))), ("resume-events"), (((GCallback) (cdk_window_resume_events
))), (window), ((void*)0), (GConnectFlags) 0)
11748 G_CALLBACK (cdk_window_resume_events),g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((clock)), (((GType) ((20) << (2))))
))))), ("resume-events"), (((GCallback) (cdk_window_resume_events
))), (window), ((void*)0), (GConnectFlags) 0)
11749 window)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((clock)), (((GType) ((20) << (2))))
))))), ("resume-events"), (((GCallback) (cdk_window_resume_events
))), (window), ((void*)0), (GConnectFlags) 0)
;
11750 }
11751
11752 if (window->frame_clock)
11753 {
11754 if (window->frame_clock_events_paused)
11755 cdk_window_resume_events (window->frame_clock, G_OBJECT (window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), (((GType) ((20) << (2))))))))
);
11756
11757 g_signal_handlers_disconnect_by_func (G_OBJECT (window->frame_clock),g_signal_handlers_disconnect_matched ((((((GObject*) (void *)
g_type_check_instance_cast ((GTypeInstance*) ((window->frame_clock
)), (((GType) ((20) << (2))))))))), (GSignalMatchType) (
G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0),
(((GCallback) (cdk_window_flush_events))), (window))
11758 G_CALLBACK (cdk_window_flush_events),g_signal_handlers_disconnect_matched ((((((GObject*) (void *)
g_type_check_instance_cast ((GTypeInstance*) ((window->frame_clock
)), (((GType) ((20) << (2))))))))), (GSignalMatchType) (
G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0),
(((GCallback) (cdk_window_flush_events))), (window))
11759 window)g_signal_handlers_disconnect_matched ((((((GObject*) (void *)
g_type_check_instance_cast ((GTypeInstance*) ((window->frame_clock
)), (((GType) ((20) << (2))))))))), (GSignalMatchType) (
G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0),
(((GCallback) (cdk_window_flush_events))), (window))
;
11760 g_signal_handlers_disconnect_by_func (G_OBJECT (window->frame_clock),g_signal_handlers_disconnect_matched ((((((GObject*) (void *)
g_type_check_instance_cast ((GTypeInstance*) ((window->frame_clock
)), (((GType) ((20) << (2))))))))), (GSignalMatchType) (
G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0),
(((GCallback) (cdk_window_paint_on_clock))), (window))
11761 G_CALLBACK (cdk_window_paint_on_clock),g_signal_handlers_disconnect_matched ((((((GObject*) (void *)
g_type_check_instance_cast ((GTypeInstance*) ((window->frame_clock
)), (((GType) ((20) << (2))))))))), (GSignalMatchType) (
G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0),
(((GCallback) (cdk_window_paint_on_clock))), (window))
11762 window)g_signal_handlers_disconnect_matched ((((((GObject*) (void *)
g_type_check_instance_cast ((GTypeInstance*) ((window->frame_clock
)), (((GType) ((20) << (2))))))))), (GSignalMatchType) (
G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0),
(((GCallback) (cdk_window_paint_on_clock))), (window))
;
11763 g_signal_handlers_disconnect_by_func (G_OBJECT (window->frame_clock),g_signal_handlers_disconnect_matched ((((((GObject*) (void *)
g_type_check_instance_cast ((GTypeInstance*) ((window->frame_clock
)), (((GType) ((20) << (2))))))))), (GSignalMatchType) (
G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0),
(((GCallback) (cdk_window_resume_events))), (window))
11764 G_CALLBACK (cdk_window_resume_events),g_signal_handlers_disconnect_matched ((((((GObject*) (void *)
g_type_check_instance_cast ((GTypeInstance*) ((window->frame_clock
)), (((GType) ((20) << (2))))))))), (GSignalMatchType) (
G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0),
(((GCallback) (cdk_window_resume_events))), (window))
11765 window)g_signal_handlers_disconnect_matched ((((((GObject*) (void *)
g_type_check_instance_cast ((GTypeInstance*) ((window->frame_clock
)), (((GType) ((20) << (2))))))))), (GSignalMatchType) (
G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0),
(((GCallback) (cdk_window_resume_events))), (window))
;
11766 g_object_unref (window->frame_clock);
11767 }
11768
11769 window->frame_clock = clock;
11770}
11771
11772/**
11773 * cdk_window_get_frame_clock:
11774 * @window: window to get frame clock for
11775 *
11776 * Gets the frame clock for the window. The frame clock for a window
11777 * never changes unless the window is reparented to a new toplevel
11778 * window.
11779 *
11780 * Since: 3.8
11781 * Returns: (transfer none): the frame clock
11782 */
11783CdkFrameClock*
11784cdk_window_get_frame_clock (CdkWindow *window)
11785{
11786 CdkWindow *toplevel;
11787
11788 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
11789
11790 toplevel = cdk_window_get_toplevel (window);
11791
11792 return toplevel->frame_clock;
11793}
11794
11795/**
11796 * cdk_window_get_scale_factor:
11797 * @window: window to get scale factor for
11798 *
11799 * Returns the internal scale factor that maps from window coordiantes
11800 * to the actual device pixels. On traditional systems this is 1, but
11801 * on very high density outputs this can be a higher value (often 2).
11802 *
11803 * A higher value means that drawing is automatically scaled up to
11804 * a higher resolution, so any code doing drawing will automatically look
11805 * nicer. However, if you are supplying pixel-based data the scale
11806 * value can be used to determine whether to use a pixel resource
11807 * with higher resolution data.
11808 *
11809 * The scale of a window may change during runtime, if this happens
11810 * a configure event will be sent to the toplevel window.
11811 *
11812 * Since: 3.10
11813 * Returns: the scale factor
11814 */
11815gint
11816cdk_window_get_scale_factor (CdkWindow *window)
11817{
11818 CdkWindowImplClass *impl_class;
11819
11820 g_return_val_if_fail (CDK_IS_WINDOW (window), 1)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (1); } } while (0)
;
11821
11822 if (CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed))
11823 return 1;
11824
11825 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
11826
11827 if (impl_class->get_scale_factor)
11828 return impl_class->get_scale_factor (window);
11829
11830 return 1;
11831}
11832
11833/* Returns the *real* unscaled size, which may be a fractional size
11834 in window scale coordinates. We need this to properly handle GL
11835 coordinates which are y-flipped in the real coordinates. */
11836void
11837cdk_window_get_unscaled_size (CdkWindow *window,
11838 int *unscaled_width,
11839 int *unscaled_height)
11840{
11841 CdkWindowImplClass *impl_class;
11842 gint scale;
11843
11844 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
11845
11846 if (window->impl_window == window)
11847 {
11848 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
11849
11850 if (impl_class->get_unscaled_size)
11851 {
11852 impl_class->get_unscaled_size (window, unscaled_width, unscaled_height);
11853 return;
11854 }
11855 }
11856
11857 scale = cdk_window_get_scale_factor (window);
11858
11859 if (unscaled_width)
11860 *unscaled_width = window->width * scale;
11861
11862 if (unscaled_height)
11863 *unscaled_height = window->height * scale;
11864}
11865
11866
11867/**
11868 * cdk_window_set_opaque_region:
11869 * @window: a top-level or non-native #CdkWindow
11870 * @region: (allow-none): a region, or %NULL
11871 *
11872 * For optimisation purposes, compositing window managers may
11873 * like to not draw obscured regions of windows, or turn off blending
11874 * during for these regions. With RGB windows with no transparency,
11875 * this is just the shape of the window, but with ARGB32 windows, the
11876 * compositor does not know what regions of the window are transparent
11877 * or not.
11878 *
11879 * This function only works for toplevel windows.
11880 *
11881 * CTK+ will update this property automatically if
11882 * the @window background is opaque, as we know where the opaque regions
11883 * are. If your window background is not opaque, please update this
11884 * property in your #CtkWidget::style-updated handler.
11885 *
11886 * Since: 3.10
11887 */
11888void
11889cdk_window_set_opaque_region (CdkWindow *window,
11890 cairo_region_t *region)
11891{
11892 CdkWindowImplClass *impl_class;
11893
11894 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
11895 g_return_if_fail (!CDK_WINDOW_DESTROYED (window))do { if ((!(((CdkWindow *)(window))->destroyed))) { } else
{ g_return_if_fail_warning ("Cdk", ((const char*) (__func__)
), "!CDK_WINDOW_DESTROYED (window)"); return; } } while (0)
;
11896
11897 if (cairo_region_equal (window->opaque_region, region))
11898 return;
11899
11900 g_clear_pointer (&window->opaque_region, cairo_region_destroy)do { _Static_assert (sizeof *(&window->opaque_region) ==
sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&window->opaque_region)) _pp = (&window->opaque_region
); __typeof__ (*(&window->opaque_region)) _ptr = *_pp;
*_pp = ((void*)0); if (_ptr) (cairo_region_destroy) (_ptr); }
while (0)
;
11901
11902 if (region != NULL((void*)0))
11903 window->opaque_region = cairo_region_reference (region);
11904
11905 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
11906
11907 if (impl_class->set_opaque_region)
11908 impl_class->set_opaque_region (window, region);
11909}
11910
11911/**
11912 * cdk_window_set_shadow_width:
11913 * @window: a #CdkWindow
11914 * @left: The left extent
11915 * @right: The right extent
11916 * @top: The top extent
11917 * @bottom: The bottom extent
11918 *
11919 * Newer CTK+ windows using client-side decorations use extra geometry
11920 * around their frames for effects like shadows and invisible borders.
11921 * Window managers that want to maximize windows or snap to edges need
11922 * to know where the extents of the actual frame lie, so that users
11923 * don’t feel like windows are snapping against random invisible edges.
11924 *
11925 * Note that this property is automatically updated by CTK+, so this
11926 * function should only be used by applications which do not use CTK+
11927 * to create toplevel windows.
11928 *
11929 * Since: 3.12
11930 */
11931void
11932cdk_window_set_shadow_width (CdkWindow *window,
11933 gint left,
11934 gint right,
11935 gint top,
11936 gint bottom)
11937{
11938 CdkWindowImplClass *impl_class;
11939
11940 g_return_if_fail (CDK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return; } } while (0)
;
11941 g_return_if_fail (!CDK_WINDOW_DESTROYED (window))do { if ((!(((CdkWindow *)(window))->destroyed))) { } else
{ g_return_if_fail_warning ("Cdk", ((const char*) (__func__)
), "!CDK_WINDOW_DESTROYED (window)"); return; } } while (0)
;
11942 g_return_if_fail (left >= 0 && right >= 0 && top >= 0 && bottom >= 0)do { if ((left >= 0 && right >= 0 && top
>= 0 && bottom >= 0)) { } else { g_return_if_fail_warning
("Cdk", ((const char*) (__func__)), "left >= 0 && right >= 0 && top >= 0 && bottom >= 0"
); return; } } while (0)
;
11943
11944 window->shadow_top = top;
11945 window->shadow_left = left;
11946 window->shadow_right = right;
11947 window->shadow_bottom = bottom;
11948
11949 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
11950
11951 if (impl_class->set_shadow_width)
11952 impl_class->set_shadow_width (window, left, right, top, bottom);
11953}
11954
11955/**
11956 * cdk_window_show_window_menu:
11957 * @window: a #CdkWindow
11958 * @event: a #CdkEvent to show the menu for
11959 *
11960 * Asks the windowing system to show the window menu. The window menu
11961 * is the menu shown when right-clicking the titlebar on traditional
11962 * windows managed by the window manager. This is useful for windows
11963 * using client-side decorations, activating it with a right-click
11964 * on the window decorations.
11965 *
11966 * Returns: %TRUE if the window menu was shown and %FALSE otherwise.
11967 *
11968 * Since: 3.14
11969 */
11970gboolean
11971cdk_window_show_window_menu (CdkWindow *window,
11972 CdkEvent *event)
11973{
11974 CdkWindowImplClass *impl_class;
11975
11976 g_return_val_if_fail (CDK_IS_WINDOW (window), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return ((0)); } } while (0)
;
11977 g_return_val_if_fail (!CDK_WINDOW_DESTROYED (window), FALSE)do { if ((!(((CdkWindow *)(window))->destroyed))) { } else
{ g_return_if_fail_warning ("Cdk", ((const char*) (__func__)
), "!CDK_WINDOW_DESTROYED (window)"); return ((0)); } } while
(0)
;
11978
11979 impl_class = CDK_WINDOW_IMPL_GET_CLASS (window->impl)((((CdkWindowImplClass*) (((GTypeInstance*) ((window->impl
)))->g_class))))
;
11980
11981 if (impl_class->show_window_menu)
11982 return impl_class->show_window_menu (window, event);
11983 else
11984 return FALSE(0);
11985}