1/* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * Modified by the GTK+ Team and others 1997-2005. See the AUTHORS
20 * file for a list of people on the GTK+ Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
23 */
24
25#include "config.h"
26
27#include "gdkwindow.h"
28#include "gdkinternals.h"
29#include "gdkwindowimpl.h"
30
31#include <math.h>
32
33#include "fallback-c89.c"
34
35/* LIMITATIONS:
36 *
37 * Offscreen windows can’t be the child of a foreign window,
38 * nor contain foreign windows
39 * GDK_POINTER_MOTION_HINT_MASK isn't effective
40 */
41
42typedef struct _GdkOffscreenWindow GdkOffscreenWindow;
43typedef struct _GdkOffscreenWindowClass GdkOffscreenWindowClass;
44
45struct _GdkOffscreenWindow
46{
47 GdkWindowImpl parent_instance;
48
49 GdkWindow *wrapper;
50
51 cairo_surface_t *surface;
52 GdkWindow *embedder;
53};
54
55struct _GdkOffscreenWindowClass
56{
57 GdkWindowImplClass parent_class;
58};
59
60#define GDK_TYPE_OFFSCREEN_WINDOW (gdk_offscreen_window_get_type())
61#define GDK_OFFSCREEN_WINDOW(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindow))
62#define GDK_IS_OFFSCREEN_WINDOW(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_OFFSCREEN_WINDOW))
63#define GDK_OFFSCREEN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
64#define GDK_IS_OFFSCREEN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_OFFSCREEN_WINDOW))
65#define GDK_OFFSCREEN_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
66
67static void gdk_offscreen_window_hide (GdkWindow *window);
68
69G_DEFINE_TYPE (GdkOffscreenWindow, gdk_offscreen_window, GDK_TYPE_WINDOW_IMPL)
70
71
72static void
73gdk_offscreen_window_finalize (GObject *object)
74{
75 GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (object);
76
77 if (offscreen->surface)
78 cairo_surface_destroy (offscreen->surface);
79
80 G_OBJECT_CLASS (gdk_offscreen_window_parent_class)->finalize (object);
81}
82
83static void
84gdk_offscreen_window_init (GdkOffscreenWindow *window)
85{
86}
87
88static void
89gdk_offscreen_window_destroy (GdkWindow *window,
90 gboolean recursing,
91 gboolean foreign_destroy)
92{
93 gdk_offscreen_window_set_embedder (window, NULL);
94
95 if (!recursing)
96 gdk_offscreen_window_hide (window);
97}
98
99static cairo_surface_t *
100get_surface (GdkOffscreenWindow *offscreen)
101{
102 if (! offscreen->surface)
103 {
104 GdkWindow *window = offscreen->wrapper;
105
106 g_signal_emit_by_name (window, "create-surface",
107 window->width,
108 window->height,
109 &offscreen->surface);
110 }
111
112 return offscreen->surface;
113}
114
115static gboolean
116is_parent_of (GdkWindow *parent,
117 GdkWindow *child)
118{
119 GdkWindow *w;
120
121 w = child;
122 while (w != NULL)
123 {
124 if (w == parent)
125 return TRUE;
126
127 w = gdk_window_get_parent (w);
128 }
129
130 return FALSE;
131}
132
133static cairo_surface_t *
134gdk_offscreen_window_ref_cairo_surface (GdkWindow *window)
135{
136 GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (window->impl);
137
138 return cairo_surface_reference (get_surface (offscreen));
139}
140
141cairo_surface_t *
142_gdk_offscreen_window_create_surface (GdkWindow *offscreen,
143 gint width,
144 gint height)
145{
146 GdkOffscreenWindow *impl;
147 GdkWindow *derived;
148
149 g_return_val_if_fail (GDK_IS_OFFSCREEN_WINDOW (offscreen->impl), NULL);
150
151 impl = GDK_OFFSCREEN_WINDOW (offscreen->impl);
152 derived = impl->embedder ? impl->embedder : offscreen->parent;
153
154 return gdk_window_create_similar_surface (derived,
155 CAIRO_CONTENT_COLOR_ALPHA,
156 width, height);
157}
158
159void
160_gdk_offscreen_window_new (GdkWindow *window,
161 GdkWindowAttr *attributes,
162 gint attributes_mask)
163{
164 GdkOffscreenWindow *offscreen;
165
166 g_return_if_fail (attributes != NULL);
167
168 if (attributes->wclass != GDK_INPUT_OUTPUT)
169 return; /* Can't support input only offscreens */
170
171 if (window->parent != NULL && GDK_WINDOW_DESTROYED (window->parent))
172 return;
173
174 window->impl = g_object_new (GDK_TYPE_OFFSCREEN_WINDOW, NULL);
175 offscreen = GDK_OFFSCREEN_WINDOW (window->impl);
176 offscreen->wrapper = window;
177}
178
179static gboolean
180gdk_offscreen_window_reparent (GdkWindow *window,
181 GdkWindow *new_parent,
182 gint x,
183 gint y)
184{
185 GdkWindow *old_parent;
186 gboolean was_mapped;
187
188 if (new_parent)
189 {
190 /* No input-output children of input-only windows */
191 if (new_parent->input_only && !window->input_only)
192 return FALSE;
193
194 /* Don't create loops in hierarchy */
195 if (is_parent_of (window, new_parent))
196 return FALSE;
197 }
198
199 was_mapped = GDK_WINDOW_IS_MAPPED (window);
200
201 gdk_window_hide (window);
202
203 if (window->parent)
204 window->parent->children = g_list_remove_link (window->parent->children, &window->children_list_node);
205
206 old_parent = window->parent;
207 window->parent = new_parent;
208 window->x = x;
209 window->y = y;
210
211 if (new_parent)
212 window->parent->children = g_list_concat (&window->children_list_node, window->parent->children);
213
214 _gdk_synthesize_crossing_events_for_geometry_change (window);
215 if (old_parent)
216 _gdk_synthesize_crossing_events_for_geometry_change (old_parent);
217
218 return was_mapped;
219}
220
221static void
222gdk_offscreen_window_set_device_cursor (GdkWindow *window,
223 GdkDevice *device,
224 GdkCursor *cursor)
225{
226}
227
228static void
229from_embedder (GdkWindow *window,
230 double embedder_x, double embedder_y,
231 double *offscreen_x, double *offscreen_y)
232{
233 g_signal_emit_by_name (window->impl_window,
234 "from-embedder",
235 embedder_x, embedder_y,
236 offscreen_x, offscreen_y,
237 NULL);
238}
239
240static void
241to_embedder (GdkWindow *window,
242 double offscreen_x, double offscreen_y,
243 double *embedder_x, double *embedder_y)
244{
245 g_signal_emit_by_name (window->impl_window,
246 "to-embedder",
247 offscreen_x, offscreen_y,
248 embedder_x, embedder_y,
249 NULL);
250}
251
252static void
253gdk_offscreen_window_get_root_coords (GdkWindow *window,
254 gint x,
255 gint y,
256 gint *root_x,
257 gint *root_y)
258{
259 GdkOffscreenWindow *offscreen;
260 int tmpx, tmpy;
261
262 tmpx = x;
263 tmpy = y;
264
265 offscreen = GDK_OFFSCREEN_WINDOW (window->impl);
266 if (offscreen->embedder)
267 {
268 double dx, dy;
269 to_embedder (window,
270 x, y,
271 &dx, &dy);
272 tmpx = floor (dx + 0.5);
273 tmpy = floor (dy + 0.5);
274 gdk_window_get_root_coords (offscreen->embedder,
275 tmpx, tmpy,
276 &tmpx, &tmpy);
277
278 }
279
280 if (root_x)
281 *root_x = tmpx;
282 if (root_y)
283 *root_y = tmpy;
284}
285
286static gboolean
287gdk_offscreen_window_get_device_state (GdkWindow *window,
288 GdkDevice *device,
289 gdouble *x,
290 gdouble *y,
291 GdkModifierType *mask)
292{
293 GdkOffscreenWindow *offscreen;
294 double tmpx, tmpy;
295 double dtmpx, dtmpy;
296 GdkModifierType tmpmask;
297
298 tmpx = 0;
299 tmpy = 0;
300 tmpmask = 0;
301
302 offscreen = GDK_OFFSCREEN_WINDOW (window->impl);
303 if (offscreen->embedder != NULL)
304 {
305 gdk_window_get_device_position_double (offscreen->embedder, device, &tmpx, &tmpy, &tmpmask);
306 from_embedder (window,
307 tmpx, tmpy,
308 &dtmpx, &dtmpy);
309 tmpx = dtmpx;
310 tmpy = dtmpy;
311 }
312
313 if (x)
314 *x = round (tmpx);
315 if (y)
316 *y = round (tmpy);
317 if (mask)
318 *mask = tmpmask;
319 return TRUE;
320}
321
322/**
323 * gdk_offscreen_window_get_surface:
324 * @window: a #GdkWindow
325 *
326 * Gets the offscreen surface that an offscreen window renders into.
327 * If you need to keep this around over window resizes, you need to
328 * add a reference to it.
329 *
330 * Returns: (nullable) (transfer none): The offscreen surface, or
331 * %NULL if not offscreen
332 */
333cairo_surface_t *
334gdk_offscreen_window_get_surface (GdkWindow *window)
335{
336 GdkOffscreenWindow *offscreen;
337
338 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
339
340 if (!GDK_IS_OFFSCREEN_WINDOW (window->impl))
341 return NULL;
342
343 offscreen = GDK_OFFSCREEN_WINDOW (window->impl);
344
345 return get_surface (offscreen);
346}
347
348static void
349gdk_offscreen_window_raise (GdkWindow *window)
350{
351 /* gdk_window_raise already changed the stacking order */
352 _gdk_synthesize_crossing_events_for_geometry_change (window);
353}
354
355static void
356gdk_offscreen_window_lower (GdkWindow *window)
357{
358 /* gdk_window_lower already changed the stacking order */
359 _gdk_synthesize_crossing_events_for_geometry_change (window);
360}
361
362static void
363gdk_offscreen_window_move_resize_internal (GdkWindow *window,
364 gint x,
365 gint y,
366 gint width,
367 gint height,
368 gboolean send_expose_events)
369{
370 GdkOffscreenWindow *offscreen;
371
372 offscreen = GDK_OFFSCREEN_WINDOW (window->impl);
373
374 if (width < 1)
375 width = 1;
376 if (height < 1)
377 height = 1;
378
379 if (window->destroyed)
380 return;
381
382 window->x = x;
383 window->y = y;
384
385 if (window->width != width ||
386 window->height != height)
387 {
388 window->width = width;
389 window->height = height;
390
391 if (offscreen->surface)
392 {
393 cairo_surface_t *old_surface;
394 cairo_t *cr;
395
396 old_surface = offscreen->surface;
397 offscreen->surface = NULL;
398
399 offscreen->surface = get_surface (offscreen);
400
401 cr = cairo_create (offscreen->surface);
402 cairo_set_source_surface (cr, old_surface, 0, 0);
403 cairo_paint (cr);
404 cairo_destroy (cr);
405
406 cairo_surface_destroy (old_surface);
407 }
408 }
409
410 if (GDK_WINDOW_IS_MAPPED (window))
411 {
412 /* TODO: Only invalidate new area, i.e. for larger windows */
413 gdk_window_invalidate_rect (window, NULL, TRUE);
414 _gdk_synthesize_crossing_events_for_geometry_change (window);
415 }
416}
417
418static void
419gdk_offscreen_window_move_resize (GdkWindow *window,
420 gboolean with_move,
421 gint x,
422 gint y,
423 gint width,
424 gint height)
425{
426 if (!with_move)
427 {
428 x = window->x;
429 y = window->y;
430 }
431
432 if (width < 0)
433 width = window->width;
434
435 if (height < 0)
436 height = window->height;
437
438 gdk_offscreen_window_move_resize_internal (window,
439 x, y, width, height,
440 TRUE);
441}
442
443static void
444gdk_offscreen_window_show (GdkWindow *window,
445 gboolean already_mapped)
446{
447 GdkRectangle area = { 0, 0, window->width, window->height };
448
449 gdk_window_invalidate_rect (window, &area, FALSE);
450}
451
452
453static void
454gdk_offscreen_window_hide (GdkWindow *window)
455{
456 /* TODO: This needs updating to the new grab world */
457#if 0
458 GdkOffscreenWindow *offscreen;
459 GdkDisplay *display;
460
461 g_return_if_fail (window != NULL);
462
463 offscreen = GDK_OFFSCREEN_WINDOW (window->impl);
464
465 /* May need to break grabs on children */
466 display = gdk_window_get_display (window);
467
468 if (display->pointer_grab.window != NULL)
469 {
470 if (is_parent_of (window, display->pointer_grab.window))
471 {
472 /* Call this ourselves, even though gdk_display_pointer_ungrab
473 does so too, since we want to pass implicit == TRUE so the
474 broken grab event is generated */
475 _gdk_display_unset_has_pointer_grab (display,
476 TRUE,
477 FALSE,
478 GDK_CURRENT_TIME);
479 gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
480 }
481 }
482#endif
483}
484
485static void
486gdk_offscreen_window_withdraw (GdkWindow *window)
487{
488}
489
490static GdkEventMask
491gdk_offscreen_window_get_events (GdkWindow *window)
492{
493 return 0;
494}
495
496static void
497gdk_offscreen_window_set_events (GdkWindow *window,
498 GdkEventMask event_mask)
499{
500}
501
502static void
503gdk_offscreen_window_set_background (GdkWindow *window,
504 cairo_pattern_t *pattern)
505{
506}
507
508static void
509gdk_offscreen_window_shape_combine_region (GdkWindow *window,
510 const cairo_region_t *shape_region,
511 gint offset_x,
512 gint offset_y)
513{
514}
515
516static void
517gdk_offscreen_window_input_shape_combine_region (GdkWindow *window,
518 const cairo_region_t *shape_region,
519 gint offset_x,
520 gint offset_y)
521{
522}
523
524static void
525gdk_offscreen_window_get_geometry (GdkWindow *window,
526 gint *x,
527 gint *y,
528 gint *width,
529 gint *height)
530{
531 if (!GDK_WINDOW_DESTROYED (window))
532 {
533 if (x)
534 *x = window->x;
535 if (y)
536 *y = window->y;
537 if (width)
538 *width = window->width;
539 if (height)
540 *height = window->height;
541 }
542}
543
544static void
545gdk_offscreen_window_queue_antiexpose (GdkWindow *window,
546 cairo_region_t *area)
547{
548}
549
550/**
551 * gdk_offscreen_window_set_embedder:
552 * @window: a #GdkWindow
553 * @embedder: the #GdkWindow that @window gets embedded in
554 *
555 * Sets @window to be embedded in @embedder.
556 *
557 * To fully embed an offscreen window, in addition to calling this
558 * function, it is also necessary to handle the #GdkWindow::pick-embedded-child
559 * signal on the @embedder and the #GdkWindow::to-embedder and
560 * #GdkWindow::from-embedder signals on @window.
561 *
562 * Since: 2.18
563 */
564void
565gdk_offscreen_window_set_embedder (GdkWindow *window,
566 GdkWindow *embedder)
567{
568 GdkOffscreenWindow *offscreen;
569
570 g_return_if_fail (GDK_IS_WINDOW (window));
571
572 if (!GDK_IS_OFFSCREEN_WINDOW (window->impl))
573 return;
574
575 offscreen = GDK_OFFSCREEN_WINDOW (window->impl);
576
577 if (embedder)
578 {
579 g_object_ref (embedder);
580 embedder->num_offscreen_children++;
581 }
582
583 if (offscreen->embedder)
584 {
585 g_object_unref (offscreen->embedder);
586 offscreen->embedder->num_offscreen_children--;
587 }
588
589 offscreen->embedder = embedder;
590}
591
592/**
593 * gdk_offscreen_window_get_embedder:
594 * @window: a #GdkWindow
595 *
596 * Gets the window that @window is embedded in.
597 *
598 * Returns: (nullable) (transfer none): the embedding #GdkWindow, or
599 * %NULL if @window is not an mbedded offscreen window
600 *
601 * Since: 2.18
602 */
603GdkWindow *
604gdk_offscreen_window_get_embedder (GdkWindow *window)
605{
606 GdkOffscreenWindow *offscreen;
607
608 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
609
610 if (!GDK_IS_OFFSCREEN_WINDOW (window->impl))
611 return NULL;
612
613 offscreen = GDK_OFFSCREEN_WINDOW (window->impl);
614
615 return offscreen->embedder;
616}
617
618static void
619gdk_offscreen_window_do_nothing (GdkWindow *window)
620{
621}
622
623static void
624gdk_offscreen_window_set_boolean (GdkWindow *window,
625 gboolean setting)
626{
627}
628
629static void
630gdk_offscreen_window_set_string (GdkWindow *window,
631 const gchar *setting)
632{
633}
634
635static void
636gdk_offscreen_window_set_list (GdkWindow *window,
637 GList *list)
638{
639}
640
641static void
642gdk_offscreen_window_set_wmfunctions (GdkWindow *window,
643 GdkWMFunction functions)
644{
645}
646
647static void
648gdk_offscreen_window_set_transient_for (GdkWindow *window,
649 GdkWindow *another)
650{
651}
652
653static void
654gdk_offscreen_window_get_frame_extents (GdkWindow *window,
655 GdkRectangle *rect)
656{
657 rect->x = window->x;
658 rect->y = window->y;
659 rect->width = window->width;
660 rect->height = window->height;
661}
662
663static gint
664gdk_offscreen_window_get_scale_factor (GdkWindow *window)
665{
666 GdkOffscreenWindow *offscreen;
667
668 if (GDK_WINDOW_DESTROYED (window))
669 return 1;
670
671 offscreen = GDK_OFFSCREEN_WINDOW (window->impl);
672 if (offscreen->embedder)
673 return gdk_window_get_scale_factor (offscreen->embedder);
674
675 return gdk_window_get_scale_factor (window->parent);
676}
677
678static void
679gdk_offscreen_window_set_opacity (GdkWindow *window, gdouble opacity)
680{
681}
682
683static gboolean
684gdk_offscreen_window_beep (GdkWindow *window)
685{
686 return FALSE;
687}
688
689static void
690gdk_offscreen_window_class_init (GdkOffscreenWindowClass *klass)
691{
692 GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
693 GObjectClass *object_class = G_OBJECT_CLASS (klass);
694
695 object_class->finalize = gdk_offscreen_window_finalize;
696
697 impl_class->ref_cairo_surface = gdk_offscreen_window_ref_cairo_surface;
698 impl_class->show = gdk_offscreen_window_show;
699 impl_class->hide = gdk_offscreen_window_hide;
700 impl_class->withdraw = gdk_offscreen_window_withdraw;
701 impl_class->set_events = gdk_offscreen_window_set_events;
702 impl_class->get_events = gdk_offscreen_window_get_events;
703 impl_class->raise = gdk_offscreen_window_raise;
704 impl_class->lower = gdk_offscreen_window_lower;
705 impl_class->restack_under = NULL;
706 impl_class->restack_toplevel = NULL;
707 impl_class->move_resize = gdk_offscreen_window_move_resize;
708 impl_class->set_background = gdk_offscreen_window_set_background;
709 impl_class->reparent = gdk_offscreen_window_reparent;
710 impl_class->set_device_cursor = gdk_offscreen_window_set_device_cursor;
711 impl_class->get_geometry = gdk_offscreen_window_get_geometry;
712 impl_class->get_root_coords = gdk_offscreen_window_get_root_coords;
713 impl_class->get_device_state = gdk_offscreen_window_get_device_state;
714 impl_class->shape_combine_region = gdk_offscreen_window_shape_combine_region;
715 impl_class->input_shape_combine_region = gdk_offscreen_window_input_shape_combine_region;
716 impl_class->queue_antiexpose = gdk_offscreen_window_queue_antiexpose;
717 impl_class->destroy = gdk_offscreen_window_destroy;
718 impl_class->destroy_foreign = NULL;
719 impl_class->get_shape = NULL;
720 impl_class->get_input_shape = NULL;
721 impl_class->beep = gdk_offscreen_window_beep;
722
723 impl_class->focus = NULL;
724 impl_class->set_type_hint = NULL;
725 impl_class->get_type_hint = NULL;
726 impl_class->set_modal_hint = gdk_offscreen_window_set_boolean;
727 impl_class->set_skip_taskbar_hint = gdk_offscreen_window_set_boolean;
728 impl_class->set_skip_pager_hint = gdk_offscreen_window_set_boolean;
729 impl_class->set_urgency_hint = gdk_offscreen_window_set_boolean;
730 impl_class->set_geometry_hints = NULL;
731 impl_class->set_title = gdk_offscreen_window_set_string;
732 impl_class->set_role = gdk_offscreen_window_set_string;
733 impl_class->set_startup_id = gdk_offscreen_window_set_string;
734 impl_class->set_transient_for = gdk_offscreen_window_set_transient_for;
735 impl_class->get_frame_extents = gdk_offscreen_window_get_frame_extents;
736 impl_class->set_override_redirect = NULL;
737 impl_class->set_accept_focus = gdk_offscreen_window_set_boolean;
738 impl_class->set_focus_on_map = gdk_offscreen_window_set_boolean;
739 impl_class->set_icon_list = gdk_offscreen_window_set_list;
740 impl_class->set_icon_name = gdk_offscreen_window_set_string;
741 impl_class->iconify = gdk_offscreen_window_do_nothing;
742 impl_class->deiconify = gdk_offscreen_window_do_nothing;
743 impl_class->stick = gdk_offscreen_window_do_nothing;
744 impl_class->unstick = gdk_offscreen_window_do_nothing;
745 impl_class->maximize = gdk_offscreen_window_do_nothing;
746 impl_class->unmaximize = gdk_offscreen_window_do_nothing;
747 impl_class->fullscreen = gdk_offscreen_window_do_nothing;
748 impl_class->unfullscreen = gdk_offscreen_window_do_nothing;
749 impl_class->set_keep_above = gdk_offscreen_window_set_boolean;
750 impl_class->set_keep_below = gdk_offscreen_window_set_boolean;
751 impl_class->get_group = NULL;
752 impl_class->set_group = NULL;
753 impl_class->set_decorations = NULL;
754 impl_class->get_decorations = NULL;
755 impl_class->set_functions = gdk_offscreen_window_set_wmfunctions;
756 impl_class->begin_resize_drag = NULL;
757 impl_class->begin_move_drag = NULL;
758 impl_class->enable_synchronized_configure = gdk_offscreen_window_do_nothing;
759 impl_class->configure_finished = NULL;
760 impl_class->set_opacity = gdk_offscreen_window_set_opacity;
761 impl_class->set_composited = NULL;
762 impl_class->destroy_notify = NULL;
763 impl_class->register_dnd = gdk_offscreen_window_do_nothing;
764 impl_class->drag_begin = NULL;
765 impl_class->sync_rendering = NULL;
766 impl_class->simulate_key = NULL;
767 impl_class->simulate_button = NULL;
768 impl_class->get_property = NULL;
769 impl_class->change_property = NULL;
770 impl_class->delete_property = NULL;
771 impl_class->get_scale_factor = gdk_offscreen_window_get_scale_factor;
772}
773