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 
42 typedef struct _GdkOffscreenWindow      GdkOffscreenWindow;
43 typedef struct _GdkOffscreenWindowClass GdkOffscreenWindowClass;
44 
45 struct _GdkOffscreenWindow
46 {
47   GdkWindowImpl parent_instance;
48 
49   GdkWindow *wrapper;
50 
51   cairo_surface_t *surface;
52   GdkWindow *embedder;
53 };
54 
55 struct _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 
67 static void       gdk_offscreen_window_hide               (GdkWindow                  *window);
68 
G_DEFINE_TYPE(GdkOffscreenWindow,gdk_offscreen_window,GDK_TYPE_WINDOW_IMPL)69 G_DEFINE_TYPE (GdkOffscreenWindow, gdk_offscreen_window, GDK_TYPE_WINDOW_IMPL)
70 
71 
72 static void
73 gdk_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 
83 static void
gdk_offscreen_window_init(GdkOffscreenWindow * window)84 gdk_offscreen_window_init (GdkOffscreenWindow *window)
85 {
86 }
87 
88 static void
gdk_offscreen_window_destroy(GdkWindow * window,gboolean recursing,gboolean foreign_destroy)89 gdk_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 
99 static cairo_surface_t *
get_surface(GdkOffscreenWindow * offscreen)100 get_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 
115 static gboolean
is_parent_of(GdkWindow * parent,GdkWindow * child)116 is_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 
133 static cairo_surface_t *
gdk_offscreen_window_ref_cairo_surface(GdkWindow * window)134 gdk_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 
141 cairo_surface_t *
_gdk_offscreen_window_create_surface(GdkWindow * offscreen,gint width,gint height)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 
159 void
_gdk_offscreen_window_new(GdkWindow * window,GdkWindowAttr * attributes,gint attributes_mask)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 
179 static gboolean
gdk_offscreen_window_reparent(GdkWindow * window,GdkWindow * new_parent,gint x,gint y)180 gdk_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 
221 static void
gdk_offscreen_window_set_device_cursor(GdkWindow * window,GdkDevice * device,GdkCursor * cursor)222 gdk_offscreen_window_set_device_cursor (GdkWindow     *window,
223 					GdkDevice     *device,
224 					GdkCursor     *cursor)
225 {
226 }
227 
228 static void
from_embedder(GdkWindow * window,double embedder_x,double embedder_y,double * offscreen_x,double * offscreen_y)229 from_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 
240 static void
to_embedder(GdkWindow * window,double offscreen_x,double offscreen_y,double * embedder_x,double * embedder_y)241 to_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 
252 static void
gdk_offscreen_window_get_root_coords(GdkWindow * window,gint x,gint y,gint * root_x,gint * root_y)253 gdk_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 
286 static gboolean
gdk_offscreen_window_get_device_state(GdkWindow * window,GdkDevice * device,gdouble * x,gdouble * y,GdkModifierType * mask)287 gdk_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  */
333 cairo_surface_t *
gdk_offscreen_window_get_surface(GdkWindow * window)334 gdk_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 
348 static void
gdk_offscreen_window_raise(GdkWindow * window)349 gdk_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 
355 static void
gdk_offscreen_window_lower(GdkWindow * window)356 gdk_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 
362 static void
gdk_offscreen_window_move_resize_internal(GdkWindow * window,gint x,gint y,gint width,gint height,gboolean send_expose_events)363 gdk_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 
418 static void
gdk_offscreen_window_move_resize(GdkWindow * window,gboolean with_move,gint x,gint y,gint width,gint height)419 gdk_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 
443 static void
gdk_offscreen_window_show(GdkWindow * window,gboolean already_mapped)444 gdk_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 
453 static void
gdk_offscreen_window_hide(GdkWindow * window)454 gdk_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 
485 static void
gdk_offscreen_window_withdraw(GdkWindow * window)486 gdk_offscreen_window_withdraw (GdkWindow *window)
487 {
488 }
489 
490 static GdkEventMask
gdk_offscreen_window_get_events(GdkWindow * window)491 gdk_offscreen_window_get_events (GdkWindow *window)
492 {
493   return 0;
494 }
495 
496 static void
gdk_offscreen_window_set_events(GdkWindow * window,GdkEventMask event_mask)497 gdk_offscreen_window_set_events (GdkWindow       *window,
498 				 GdkEventMask     event_mask)
499 {
500 }
501 
502 static void
gdk_offscreen_window_set_background(GdkWindow * window,cairo_pattern_t * pattern)503 gdk_offscreen_window_set_background (GdkWindow      *window,
504 				     cairo_pattern_t *pattern)
505 {
506 }
507 
508 static void
gdk_offscreen_window_shape_combine_region(GdkWindow * window,const cairo_region_t * shape_region,gint offset_x,gint offset_y)509 gdk_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 
516 static void
gdk_offscreen_window_input_shape_combine_region(GdkWindow * window,const cairo_region_t * shape_region,gint offset_x,gint offset_y)517 gdk_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 
524 static void
gdk_offscreen_window_get_geometry(GdkWindow * window,gint * x,gint * y,gint * width,gint * height)525 gdk_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 
544 static void
gdk_offscreen_window_queue_antiexpose(GdkWindow * window,cairo_region_t * area)545 gdk_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  */
564 void
gdk_offscreen_window_set_embedder(GdkWindow * window,GdkWindow * embedder)565 gdk_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  */
603 GdkWindow *
gdk_offscreen_window_get_embedder(GdkWindow * window)604 gdk_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 
618 static void
gdk_offscreen_window_do_nothing(GdkWindow * window)619 gdk_offscreen_window_do_nothing (GdkWindow *window)
620 {
621 }
622 
623 static void
gdk_offscreen_window_set_boolean(GdkWindow * window,gboolean setting)624 gdk_offscreen_window_set_boolean (GdkWindow *window,
625                                   gboolean   setting)
626 {
627 }
628 
629 static void
gdk_offscreen_window_set_string(GdkWindow * window,const gchar * setting)630 gdk_offscreen_window_set_string (GdkWindow *window,
631 				 const gchar *setting)
632 {
633 }
634 
635 static void
gdk_offscreen_window_set_list(GdkWindow * window,GList * list)636 gdk_offscreen_window_set_list (GdkWindow *window,
637                                GList *list)
638 {
639 }
640 
641 static void
gdk_offscreen_window_set_wmfunctions(GdkWindow * window,GdkWMFunction functions)642 gdk_offscreen_window_set_wmfunctions (GdkWindow	    *window,
643 				      GdkWMFunction  functions)
644 {
645 }
646 
647 static void
gdk_offscreen_window_begin_move_drag(GdkWindow * window,GdkDevice * device,gint button,gint root_x,gint root_y,guint32 timestamp)648 gdk_offscreen_window_begin_move_drag (GdkWindow *window,
649                                       GdkDevice *device,
650                                       gint       button,
651                                       gint       root_x,
652                                       gint       root_y,
653                                       guint32    timestamp)
654 {
655 }
656 
657 static void
gdk_offscreen_window_set_transient_for(GdkWindow * window,GdkWindow * another)658 gdk_offscreen_window_set_transient_for (GdkWindow *window,
659 					GdkWindow *another)
660 {
661 }
662 
663 static void
gdk_offscreen_window_get_frame_extents(GdkWindow * window,GdkRectangle * rect)664 gdk_offscreen_window_get_frame_extents (GdkWindow    *window,
665 					GdkRectangle *rect)
666 {
667   rect->x = window->x;
668   rect->y = window->y;
669   rect->width = window->width;
670   rect->height = window->height;
671 }
672 
673 static gint
gdk_offscreen_window_get_scale_factor(GdkWindow * window)674 gdk_offscreen_window_get_scale_factor (GdkWindow *window)
675 {
676   GdkOffscreenWindow *offscreen;
677 
678   if (GDK_WINDOW_DESTROYED (window))
679     return 1;
680 
681   offscreen = GDK_OFFSCREEN_WINDOW (window->impl);
682   if (offscreen->embedder)
683     return gdk_window_get_scale_factor (offscreen->embedder);
684 
685   return gdk_window_get_scale_factor (window->parent);
686 }
687 
688 static void
gdk_offscreen_window_set_opacity(GdkWindow * window,gdouble opacity)689 gdk_offscreen_window_set_opacity (GdkWindow *window, gdouble opacity)
690 {
691 }
692 
693 static gboolean
gdk_offscreen_window_beep(GdkWindow * window)694 gdk_offscreen_window_beep (GdkWindow *window)
695 {
696   return FALSE;
697 }
698 
699 static void
gdk_offscreen_window_class_init(GdkOffscreenWindowClass * klass)700 gdk_offscreen_window_class_init (GdkOffscreenWindowClass *klass)
701 {
702   GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
703   GObjectClass *object_class = G_OBJECT_CLASS (klass);
704 
705   object_class->finalize = gdk_offscreen_window_finalize;
706 
707   impl_class->ref_cairo_surface = gdk_offscreen_window_ref_cairo_surface;
708   impl_class->show = gdk_offscreen_window_show;
709   impl_class->hide = gdk_offscreen_window_hide;
710   impl_class->withdraw = gdk_offscreen_window_withdraw;
711   impl_class->set_events = gdk_offscreen_window_set_events;
712   impl_class->get_events = gdk_offscreen_window_get_events;
713   impl_class->raise = gdk_offscreen_window_raise;
714   impl_class->lower = gdk_offscreen_window_lower;
715   impl_class->restack_under = NULL;
716   impl_class->restack_toplevel = NULL;
717   impl_class->move_resize = gdk_offscreen_window_move_resize;
718   impl_class->set_background = gdk_offscreen_window_set_background;
719   impl_class->reparent = gdk_offscreen_window_reparent;
720   impl_class->set_device_cursor = gdk_offscreen_window_set_device_cursor;
721   impl_class->get_geometry = gdk_offscreen_window_get_geometry;
722   impl_class->get_root_coords = gdk_offscreen_window_get_root_coords;
723   impl_class->get_device_state = gdk_offscreen_window_get_device_state;
724   impl_class->shape_combine_region = gdk_offscreen_window_shape_combine_region;
725   impl_class->input_shape_combine_region = gdk_offscreen_window_input_shape_combine_region;
726   impl_class->queue_antiexpose = gdk_offscreen_window_queue_antiexpose;
727   impl_class->destroy = gdk_offscreen_window_destroy;
728   impl_class->destroy_foreign = NULL;
729   impl_class->get_shape = NULL;
730   impl_class->get_input_shape = NULL;
731   impl_class->beep = gdk_offscreen_window_beep;
732 
733   impl_class->focus = NULL;
734   impl_class->set_type_hint = NULL;
735   impl_class->get_type_hint = NULL;
736   impl_class->set_modal_hint = gdk_offscreen_window_set_boolean;
737   impl_class->set_skip_taskbar_hint = gdk_offscreen_window_set_boolean;
738   impl_class->set_skip_pager_hint = gdk_offscreen_window_set_boolean;
739   impl_class->set_urgency_hint = gdk_offscreen_window_set_boolean;
740   impl_class->set_geometry_hints = NULL;
741   impl_class->set_title = gdk_offscreen_window_set_string;
742   impl_class->set_role = gdk_offscreen_window_set_string;
743   impl_class->set_startup_id = gdk_offscreen_window_set_string;
744   impl_class->set_transient_for = gdk_offscreen_window_set_transient_for;
745   impl_class->get_frame_extents = gdk_offscreen_window_get_frame_extents;
746   impl_class->set_override_redirect = NULL;
747   impl_class->set_accept_focus = gdk_offscreen_window_set_boolean;
748   impl_class->set_focus_on_map = gdk_offscreen_window_set_boolean;
749   impl_class->set_icon_list = gdk_offscreen_window_set_list;
750   impl_class->set_icon_name = gdk_offscreen_window_set_string;
751   impl_class->iconify = gdk_offscreen_window_do_nothing;
752   impl_class->deiconify = gdk_offscreen_window_do_nothing;
753   impl_class->stick = gdk_offscreen_window_do_nothing;
754   impl_class->unstick = gdk_offscreen_window_do_nothing;
755   impl_class->maximize = gdk_offscreen_window_do_nothing;
756   impl_class->unmaximize = gdk_offscreen_window_do_nothing;
757   impl_class->fullscreen = gdk_offscreen_window_do_nothing;
758   impl_class->unfullscreen = gdk_offscreen_window_do_nothing;
759   impl_class->set_keep_above = gdk_offscreen_window_set_boolean;
760   impl_class->set_keep_below = gdk_offscreen_window_set_boolean;
761   impl_class->get_group = NULL;
762   impl_class->set_group = NULL;
763   impl_class->set_decorations = NULL;
764   impl_class->get_decorations = NULL;
765   impl_class->set_functions = gdk_offscreen_window_set_wmfunctions;
766   impl_class->begin_resize_drag = NULL;
767   impl_class->begin_move_drag = gdk_offscreen_window_begin_move_drag;
768   impl_class->enable_synchronized_configure = gdk_offscreen_window_do_nothing;
769   impl_class->configure_finished = NULL;
770   impl_class->set_opacity = gdk_offscreen_window_set_opacity;
771   impl_class->set_composited = NULL;
772   impl_class->destroy_notify = NULL;
773   impl_class->register_dnd = gdk_offscreen_window_do_nothing;
774   impl_class->drag_begin = NULL;
775   impl_class->sync_rendering = NULL;
776   impl_class->simulate_key = NULL;
777   impl_class->simulate_button = NULL;
778   impl_class->get_property = NULL;
779   impl_class->change_property = NULL;
780   impl_class->delete_property = NULL;
781   impl_class->get_scale_factor = gdk_offscreen_window_get_scale_factor;
782 }
783