]> Pileus Git - ~andy/gtk/blob - gdk/gdkoffscreenwindow.c
API: Change offscreen windows to use a cairo_surface_t
[~andy/gtk] / gdk / gdkoffscreenwindow.c
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, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2005.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25  */
26
27 #include <config.h>
28 #include <math.h>
29 #include "gdk.h"
30 #include "gdkwindow.h"
31 #include "gdkinternals.h"
32 #include "gdkwindowimpl.h"
33 #include "gdkdrawable.h"
34 #include "gdktypes.h"
35 #include "gdkscreen.h"
36 #include "gdkcolor.h"
37
38
39 /* LIMITATIONS:
40  *
41  * Offscreen windows can't be the child of a foreign window,
42  *   nor contain foreign windows
43  * GDK_POINTER_MOTION_HINT_MASK isn't effective
44  */
45
46 typedef struct _GdkOffscreenWindow      GdkOffscreenWindow;
47 typedef struct _GdkOffscreenWindowClass GdkOffscreenWindowClass;
48
49 struct _GdkOffscreenWindow
50 {
51   GdkDrawable parent_instance;
52
53   GdkWindow *wrapper;
54   GdkColormap *colormap;
55   GdkScreen *screen;
56
57   cairo_surface_t *surface;
58   GdkWindow *embedder;
59 };
60
61 struct _GdkOffscreenWindowClass
62 {
63   GdkDrawableClass parent_class;
64 };
65
66 #define GDK_TYPE_OFFSCREEN_WINDOW            (gdk_offscreen_window_get_type())
67 #define GDK_OFFSCREEN_WINDOW(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindow))
68 #define GDK_IS_OFFSCREEN_WINDOW(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_OFFSCREEN_WINDOW))
69 #define GDK_OFFSCREEN_WINDOW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
70 #define GDK_IS_OFFSCREEN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_OFFSCREEN_WINDOW))
71 #define GDK_OFFSCREEN_WINDOW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
72
73 static void       gdk_offscreen_window_impl_iface_init    (GdkWindowImplIface         *iface);
74 static void       gdk_offscreen_window_hide               (GdkWindow                  *window);
75
76 G_DEFINE_TYPE_WITH_CODE (GdkOffscreenWindow,
77                          gdk_offscreen_window,
78                          GDK_TYPE_DRAWABLE,
79                          G_IMPLEMENT_INTERFACE (GDK_TYPE_WINDOW_IMPL,
80                                                 gdk_offscreen_window_impl_iface_init));
81
82
83 static void
84 gdk_offscreen_window_finalize (GObject *object)
85 {
86   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (object);
87
88   cairo_surface_destroy (offscreen->surface);
89
90   G_OBJECT_CLASS (gdk_offscreen_window_parent_class)->finalize (object);
91 }
92
93 static void
94 gdk_offscreen_window_init (GdkOffscreenWindow *window)
95 {
96 }
97
98 static void
99 gdk_offscreen_window_destroy (GdkWindow *window,
100                               gboolean   recursing,
101                               gboolean   foreign_destroy)
102 {
103   GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
104   GdkOffscreenWindow *offscreen;
105
106   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
107
108   gdk_offscreen_window_set_embedder (window, NULL);
109   
110   if (!recursing)
111     gdk_offscreen_window_hide (window);
112
113   g_object_unref (offscreen->colormap);
114   offscreen->colormap = NULL;
115 }
116
117 static gboolean
118 is_parent_of (GdkWindow *parent,
119               GdkWindow *child)
120 {
121   GdkWindow *w;
122
123   w = child;
124   while (w != NULL)
125     {
126       if (w == parent)
127         return TRUE;
128
129       w = gdk_window_get_parent (w);
130     }
131
132   return FALSE;
133 }
134
135 static cairo_surface_t *
136 gdk_offscreen_window_ref_cairo_surface (GdkDrawable *drawable)
137 {
138   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
139
140   return cairo_surface_reference (offscreen->surface);
141 }
142
143 static GdkColormap*
144 gdk_offscreen_window_get_colormap (GdkDrawable *drawable)
145 {
146   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
147
148   return offscreen->colormap;
149 }
150
151 static void
152 gdk_offscreen_window_set_colormap (GdkDrawable *drawable,
153                                    GdkColormap*colormap)
154 {
155   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
156
157   if (colormap && GDK_WINDOW_DESTROYED (offscreen->wrapper))
158     return;
159
160   if (offscreen->colormap == colormap)
161     return;
162
163   if (offscreen->colormap)
164     g_object_unref (offscreen->colormap);
165
166   offscreen->colormap = colormap;
167   if (offscreen->colormap)
168     g_object_ref (offscreen->colormap);
169 }
170
171
172 static gint
173 gdk_offscreen_window_get_depth (GdkDrawable *drawable)
174 {
175   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
176
177   return gdk_drawable_get_depth (offscreen->wrapper);
178 }
179
180 static GdkDrawable *
181 gdk_offscreen_window_get_source_drawable (GdkDrawable  *drawable)
182 {
183   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
184
185   return gdk_screen_get_root_window (offscreen->screen);
186 }
187
188 static GdkScreen*
189 gdk_offscreen_window_get_screen (GdkDrawable *drawable)
190 {
191   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
192
193   return offscreen->screen;
194 }
195
196 static GdkVisual*
197 gdk_offscreen_window_get_visual (GdkDrawable    *drawable)
198 {
199   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
200
201   return gdk_drawable_get_visual (offscreen->wrapper);
202 }
203
204 void
205 _gdk_offscreen_window_new (GdkWindow     *window,
206                            GdkScreen     *screen,
207                            GdkVisual     *visual,
208                            GdkWindowAttr *attributes,
209                            gint           attributes_mask)
210 {
211   GdkWindowObject *private;
212   GdkOffscreenWindow *offscreen;
213
214   g_return_if_fail (attributes != NULL);
215
216   if (attributes->wclass != GDK_INPUT_OUTPUT)
217     return; /* Can't support input only offscreens */
218
219   private = (GdkWindowObject *)window;
220
221   if (private->parent != NULL && GDK_WINDOW_DESTROYED (private->parent))
222     return;
223
224   private->impl = g_object_new (GDK_TYPE_OFFSCREEN_WINDOW, NULL);
225   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
226   offscreen->wrapper = window;
227
228   offscreen->screen = screen;
229
230   if (attributes_mask & GDK_WA_COLORMAP)
231     offscreen->colormap = g_object_ref (attributes->colormap);
232   else
233     {
234       if (gdk_screen_get_system_visual (screen) == visual)
235         {
236           offscreen->colormap = gdk_screen_get_system_colormap (screen);
237           g_object_ref (offscreen->colormap);
238         }
239       else
240         offscreen->colormap = gdk_colormap_new (visual, FALSE);
241     }
242
243   offscreen->surface = gdk_window_create_similar_surface ((GdkWindow *)private->parent,
244                                                           CAIRO_CONTENT_COLOR,
245                                                           private->width,
246                                                           private->height);
247 }
248
249 static gboolean
250 gdk_offscreen_window_reparent (GdkWindow *window,
251                                GdkWindow *new_parent,
252                                gint       x,
253                                gint       y)
254 {
255   GdkWindowObject *private = (GdkWindowObject *)window;
256   GdkWindowObject *new_parent_private = (GdkWindowObject *)new_parent;
257   GdkWindowObject *old_parent;
258   gboolean was_mapped;
259
260   if (new_parent)
261     {
262       /* No input-output children of input-only windows */
263       if (new_parent_private->input_only && !private->input_only)
264         return FALSE;
265
266       /* Don't create loops in hierarchy */
267       if (is_parent_of (window, new_parent))
268         return FALSE;
269     }
270
271   was_mapped = GDK_WINDOW_IS_MAPPED (window);
272
273   gdk_window_hide (window);
274
275   if (private->parent)
276     private->parent->children = g_list_remove (private->parent->children, window);
277
278   old_parent = private->parent;
279   private->parent = new_parent_private;
280   private->x = x;
281   private->y = y;
282
283   if (new_parent_private)
284     private->parent->children = g_list_prepend (private->parent->children, window);
285
286   _gdk_synthesize_crossing_events_for_geometry_change (window);
287   if (old_parent)
288     _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (old_parent));
289
290   return was_mapped;
291 }
292
293 static void
294 from_embedder (GdkWindow *window,
295                double embedder_x, double embedder_y,
296                double *offscreen_x, double *offscreen_y)
297 {
298   GdkWindowObject *private;
299
300   private = (GdkWindowObject *)window;
301
302   g_signal_emit_by_name (private->impl_window,
303                          "from-embedder",
304                          embedder_x, embedder_y,
305                          offscreen_x, offscreen_y,
306                          NULL);
307 }
308
309 static void
310 to_embedder (GdkWindow *window,
311              double offscreen_x, double offscreen_y,
312              double *embedder_x, double *embedder_y)
313 {
314   GdkWindowObject *private;
315
316   private = (GdkWindowObject *)window;
317
318   g_signal_emit_by_name (private->impl_window,
319                          "to-embedder",
320                          offscreen_x, offscreen_y,
321                          embedder_x, embedder_y,
322                          NULL);
323 }
324
325 static gint
326 gdk_offscreen_window_get_root_coords (GdkWindow *window,
327                                       gint       x,
328                                       gint       y,
329                                       gint      *root_x,
330                                       gint      *root_y)
331 {
332   GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
333   GdkOffscreenWindow *offscreen;
334   int tmpx, tmpy;
335
336   tmpx = x;
337   tmpy = y;
338
339   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
340   if (offscreen->embedder)
341     {
342       double dx, dy;
343       to_embedder (window,
344                    x, y,
345                    &dx, &dy);
346       tmpx = floor (dx + 0.5);
347       tmpy = floor (dy + 0.5);
348       gdk_window_get_root_coords (offscreen->embedder,
349                                   tmpx, tmpy,
350                                   &tmpx, &tmpy);
351
352     }
353
354   if (root_x)
355     *root_x = tmpx;
356   if (root_y)
357     *root_y = tmpy;
358
359   return TRUE;
360 }
361
362 static gboolean
363 gdk_offscreen_window_get_device_state (GdkWindow       *window,
364                                        GdkDevice       *device,
365                                        gint            *x,
366                                        gint            *y,
367                                        GdkModifierType *mask)
368 {
369   GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
370   GdkOffscreenWindow *offscreen;
371   int tmpx, tmpy;
372   double dtmpx, dtmpy;
373   GdkModifierType tmpmask;
374
375   tmpx = 0;
376   tmpy = 0;
377   tmpmask = 0;
378
379   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
380   if (offscreen->embedder != NULL)
381     {
382       gdk_window_get_device_position (offscreen->embedder, device, &tmpx, &tmpy, &tmpmask);
383       from_embedder (window,
384                      tmpx, tmpy,
385                      &dtmpx, &dtmpy);
386       tmpx = floor (dtmpx + 0.5);
387       tmpy = floor (dtmpy + 0.5);
388     }
389
390   if (x)
391     *x = tmpx;
392   if (y)
393     *y = tmpy;
394   if (mask)
395     *mask = tmpmask;
396   return TRUE;
397 }
398
399 /**
400  * gdk_offscreen_window_get_surface:
401  * @window: a #GdkWindow
402  *
403  * Gets the offscreen surface that an offscreen window renders into.
404  * If you need to keep this around over window resizes, you need to
405  * add a reference to it.
406  *
407  * Returns: The offscreen surface, or %NULL if not offscreen
408  */
409 cairo_surface_t *
410 gdk_offscreen_window_get_surface (GdkWindow *window)
411 {
412   GdkWindowObject *private = (GdkWindowObject *)window;
413   GdkOffscreenWindow *offscreen;
414
415   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
416
417   if (!GDK_IS_OFFSCREEN_WINDOW (private->impl))
418     return NULL;
419
420   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
421   return offscreen->surface;
422 }
423
424 static void
425 gdk_offscreen_window_raise (GdkWindow *window)
426 {
427   /* gdk_window_raise already changed the stacking order */
428   _gdk_synthesize_crossing_events_for_geometry_change (window);
429 }
430
431 static void
432 gdk_offscreen_window_lower (GdkWindow *window)
433 {
434   /* gdk_window_lower already changed the stacking order */
435   _gdk_synthesize_crossing_events_for_geometry_change (window);
436 }
437
438 static void
439 gdk_offscreen_window_move_resize_internal (GdkWindow *window,
440                                            gint       x,
441                                            gint       y,
442                                            gint       width,
443                                            gint       height,
444                                            gboolean   send_expose_events)
445 {
446   GdkWindowObject *private = (GdkWindowObject *)window;
447   GdkOffscreenWindow *offscreen;
448   gint dx, dy, dw, dh;
449   cairo_surface_t *old_surface;
450
451   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
452
453   if (width < 1)
454     width = 1;
455   if (height < 1)
456     height = 1;
457
458   if (private->destroyed)
459     return;
460
461   dx = x - private->x;
462   dy = y - private->y;
463   dw = width - private->width;
464   dh = height - private->height;
465
466   private->x = x;
467   private->y = y;
468
469   if (private->width != width ||
470       private->height != height)
471     {
472       cairo_t *cr;
473
474       private->width = width;
475       private->height = height;
476
477       old_surface = offscreen->surface;
478       offscreen->surface = cairo_surface_create_similar (old_surface,
479                                                          cairo_surface_get_content (old_surface),
480                                                          width,
481                                                          height);
482
483       cr = cairo_create (offscreen->surface);
484       cairo_set_source_surface (cr, old_surface, 0, 0);
485       cairo_paint (cr);
486       cairo_destroy (cr);
487
488       cairo_surface_destroy (old_surface);
489     }
490
491   if (GDK_WINDOW_IS_MAPPED (private))
492     {
493       // TODO: Only invalidate new area, i.e. for larger windows
494       gdk_window_invalidate_rect (window, NULL, TRUE);
495       _gdk_synthesize_crossing_events_for_geometry_change (window);
496     }
497 }
498
499 static void
500 gdk_offscreen_window_move_resize (GdkWindow *window,
501                                   gboolean   with_move,
502                                   gint       x,
503                                   gint       y,
504                                   gint       width,
505                                   gint       height)
506 {
507   GdkWindowObject *private = (GdkWindowObject *)window;
508   GdkOffscreenWindow *offscreen;
509
510   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
511
512   if (!with_move)
513     {
514       x = private->x;
515       y = private->y;
516     }
517
518   if (width < 0)
519     width = private->width;
520
521   if (height < 0)
522     height = private->height;
523
524   gdk_offscreen_window_move_resize_internal (window, x, y,
525                                              width, height,
526                                              TRUE);
527 }
528
529 static void
530 gdk_offscreen_window_show (GdkWindow *window,
531                            gboolean already_mapped)
532 {
533   GdkWindowObject *private = (GdkWindowObject *)window;
534   GdkRectangle area = { 0, 0, private->width, private->height };
535
536   gdk_window_clear_area (window, 0, 0,
537                          private->width, private->height);
538   gdk_window_invalidate_rect (window, &area, FALSE);
539 }
540
541
542 static void
543 gdk_offscreen_window_hide (GdkWindow *window)
544 {
545   GdkWindowObject *private;
546   GdkOffscreenWindow *offscreen;
547   GdkDisplay *display;
548
549   g_return_if_fail (window != NULL);
550
551   private = (GdkWindowObject*) window;
552   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
553
554   /* May need to break grabs on children */
555   display = gdk_drawable_get_display (window);
556
557   /* TODO: This needs updating to the new grab world */
558 #if 0
559   if (display->pointer_grab.window != NULL)
560     {
561       if (is_parent_of (window, display->pointer_grab.window))
562         {
563           /* Call this ourselves, even though gdk_display_pointer_ungrab
564              does so too, since we want to pass implicit == TRUE so the
565              broken grab event is generated */
566           _gdk_display_unset_has_pointer_grab (display,
567                                                TRUE,
568                                                FALSE,
569                                                GDK_CURRENT_TIME);
570           gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
571         }
572     }
573 #endif
574 }
575
576 static void
577 gdk_offscreen_window_withdraw (GdkWindow *window)
578 {
579 }
580
581 static GdkEventMask
582 gdk_offscreen_window_get_events (GdkWindow *window)
583 {
584   return 0;
585 }
586
587 static void
588 gdk_offscreen_window_set_events (GdkWindow       *window,
589                                  GdkEventMask     event_mask)
590 {
591 }
592
593 static void
594 gdk_offscreen_window_set_background (GdkWindow      *window,
595                                      cairo_pattern_t *pattern)
596 {
597 }
598
599 static void
600 gdk_offscreen_window_shape_combine_region (GdkWindow       *window,
601                                            const cairo_region_t *shape_region,
602                                            gint             offset_x,
603                                            gint             offset_y)
604 {
605 }
606
607 static void
608 gdk_offscreen_window_input_shape_combine_region (GdkWindow       *window,
609                                                  const cairo_region_t *shape_region,
610                                                  gint             offset_x,
611                                                  gint             offset_y)
612 {
613 }
614
615 static gboolean
616 gdk_offscreen_window_set_static_gravities (GdkWindow *window,
617                                            gboolean   use_static)
618 {
619   return TRUE;
620 }
621
622 static void
623 gdk_offscreen_window_get_geometry (GdkWindow *window,
624                                    gint      *x,
625                                    gint      *y,
626                                    gint      *width,
627                                    gint      *height,
628                                    gint      *depth)
629 {
630   GdkWindowObject *private = (GdkWindowObject *)window;
631
632   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
633
634   if (!GDK_WINDOW_DESTROYED (window))
635     {
636       if (x)
637         *x = private->x;
638       if (y)
639         *y = private->y;
640       if (width)
641         *width = private->width;
642       if (height)
643         *height = private->height;
644       if (depth)
645         *depth = private->depth;
646     }
647 }
648
649 static gboolean
650 gdk_offscreen_window_queue_antiexpose (GdkWindow *window,
651                                        cairo_region_t *area)
652 {
653   return FALSE;
654 }
655
656 static void
657 gdk_offscreen_window_translate (GdkWindow      *window,
658                                 cairo_region_t *area,
659                                 gint            dx,
660                                 gint            dy)
661 {
662   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (((GdkWindowObject *) window)->impl);
663   cairo_t *cr;
664
665   cr = cairo_create (offscreen->surface);
666
667   area = cairo_region_copy (area);
668
669   gdk_cairo_region (cr, area);
670   cairo_clip (cr);
671   
672   /* NB: This is a self-copy and Cairo doesn't support that yet.
673    * So we do a litle trick.
674    */
675   cairo_push_group (cr);
676
677   cairo_set_source_surface (cr, offscreen->surface, dx, dy);
678   cairo_paint (cr);
679
680   cairo_pop_group_to_source (cr);
681   cairo_paint (cr);
682
683   cairo_destroy (cr);
684
685   _gdk_window_add_damage (window, area);
686 }
687
688 /**
689  * gdk_offscreen_window_set_embedder:
690  * @window: a #GdkWindow
691  * @embedder: the #GdkWindow that @window gets embedded in
692  *
693  * Sets @window to be embedded in @embedder.
694  *
695  * To fully embed an offscreen window, in addition to calling this
696  * function, it is also necessary to handle the #GdkWindow::pick-embedded-child
697  * signal on the @embedder and the #GdkWindow::to-embedder and
698  * #GdkWindow::from-embedder signals on @window.
699  *
700  * Since: 2.18
701  */
702 void
703 gdk_offscreen_window_set_embedder (GdkWindow     *window,
704                                    GdkWindow     *embedder)
705 {
706   GdkWindowObject *private = (GdkWindowObject *)window;
707   GdkOffscreenWindow *offscreen;
708
709   g_return_if_fail (GDK_IS_WINDOW (window));
710
711   if (!GDK_IS_OFFSCREEN_WINDOW (private->impl))
712     return;
713
714   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
715
716   if (embedder)
717     {
718       g_object_ref (embedder);
719       GDK_WINDOW_OBJECT (embedder)->num_offscreen_children++;
720     }
721
722   if (offscreen->embedder)
723     {
724       g_object_unref (offscreen->embedder);
725       GDK_WINDOW_OBJECT (offscreen->embedder)->num_offscreen_children--;
726     }
727
728   offscreen->embedder = embedder;
729 }
730
731 /**
732  * gdk_offscreen_window_get_embedder:
733  * @window: a #GdkWindow
734  *
735  * Gets the window that @window is embedded in.
736  *
737  * Returns: the embedding #GdkWindow, or %NULL if @window is not an
738  *     embedded offscreen window
739  *
740  * Since: 2.18
741  */
742 GdkWindow *
743 gdk_offscreen_window_get_embedder (GdkWindow *window)
744 {
745   GdkWindowObject *private = (GdkWindowObject *)window;
746   GdkOffscreenWindow *offscreen;
747
748   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
749
750   if (!GDK_IS_OFFSCREEN_WINDOW (private->impl))
751     return NULL;
752
753   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
754
755   return offscreen->embedder;
756 }
757
758 static void
759 gdk_offscreen_window_class_init (GdkOffscreenWindowClass *klass)
760 {
761   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
762   GObjectClass *object_class = G_OBJECT_CLASS (klass);
763
764   object_class->finalize = gdk_offscreen_window_finalize;
765
766   drawable_class->ref_cairo_surface = gdk_offscreen_window_ref_cairo_surface;
767   drawable_class->set_colormap = gdk_offscreen_window_set_colormap;
768   drawable_class->get_colormap = gdk_offscreen_window_get_colormap;
769   drawable_class->get_depth = gdk_offscreen_window_get_depth;
770   drawable_class->get_screen = gdk_offscreen_window_get_screen;
771   drawable_class->get_visual = gdk_offscreen_window_get_visual;
772   drawable_class->get_source_drawable = gdk_offscreen_window_get_source_drawable;
773 }
774
775 static void
776 gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface)
777 {
778   iface->show = gdk_offscreen_window_show;
779   iface->hide = gdk_offscreen_window_hide;
780   iface->withdraw = gdk_offscreen_window_withdraw;
781   iface->raise = gdk_offscreen_window_raise;
782   iface->lower = gdk_offscreen_window_lower;
783   iface->move_resize = gdk_offscreen_window_move_resize;
784   iface->set_background = gdk_offscreen_window_set_background;
785   iface->get_events = gdk_offscreen_window_get_events;
786   iface->set_events = gdk_offscreen_window_set_events;
787   iface->reparent = gdk_offscreen_window_reparent;
788   iface->get_geometry = gdk_offscreen_window_get_geometry;
789   iface->shape_combine_region = gdk_offscreen_window_shape_combine_region;
790   iface->input_shape_combine_region = gdk_offscreen_window_input_shape_combine_region;
791   iface->set_static_gravities = gdk_offscreen_window_set_static_gravities;
792   iface->queue_antiexpose = gdk_offscreen_window_queue_antiexpose;
793   iface->translate = gdk_offscreen_window_translate;
794   iface->get_root_coords = gdk_offscreen_window_get_root_coords;
795   iface->get_device_state = gdk_offscreen_window_get_device_state;
796   iface->destroy = gdk_offscreen_window_destroy;
797 }