]> Pileus Git - ~andy/gtk/blob - gdk/gdkoffscreenwindow.c
Update GdkOffscreenWindow to new draw_drawable prototype
[~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 "gdkpixmap.h"
34 #include "gdkdrawable.h"
35 #include "gdktypes.h"
36 #include "gdkscreen.h"
37 #include "gdkgc.h"
38 #include "gdkcolor.h"
39 #include "gdkcursor.h"
40 #include "gdkalias.h"
41
42 /* LIMITATIONS:
43  *
44  * Offscreen windows can't be the child of a foreign window,
45  *   nor contain foreign windows
46  * GDK_POINTER_MOTION_HINT_MASK isn't effective
47  */
48
49 typedef struct _GdkOffscreenWindow      GdkOffscreenWindow;
50 typedef struct _GdkOffscreenWindowClass GdkOffscreenWindowClass;
51
52 struct _GdkOffscreenWindow
53 {
54   GdkDrawable parent_instance;
55
56   GdkWindow *wrapper;
57   GdkCursor *cursor;
58   GdkColormap *colormap;
59   GdkScreen *screen;
60
61   GdkPixmap *pixmap;
62 };
63
64 struct _GdkOffscreenWindowClass
65 {
66   GdkDrawableClass parent_class;
67 };
68
69 #define GDK_TYPE_OFFSCREEN_WINDOW            (gdk_offscreen_window_get_type())
70 #define GDK_OFFSCREEN_WINDOW(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindow))
71 #define GDK_IS_OFFSCREEN_WINDOW(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_OFFSCREEN_WINDOW))
72 #define GDK_OFFSCREEN_WINDOW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
73 #define GDK_IS_OFFSCREEN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_OFFSCREEN_WINDOW))
74 #define GDK_OFFSCREEN_WINDOW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
75
76 static void       gdk_offscreen_window_impl_iface_init    (GdkWindowImplIface         *iface);
77 static void       gdk_offscreen_window_hide               (GdkWindow                  *window);
78
79 G_DEFINE_TYPE_WITH_CODE (GdkOffscreenWindow,
80                          gdk_offscreen_window,
81                          GDK_TYPE_DRAWABLE,
82                          G_IMPLEMENT_INTERFACE (GDK_TYPE_WINDOW_IMPL,
83                                                 gdk_offscreen_window_impl_iface_init));
84
85
86 static void
87 gdk_offscreen_window_finalize (GObject *object)
88 {
89   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (object);
90
91   if (offscreen->cursor)
92     gdk_cursor_unref (offscreen->cursor);
93
94   offscreen->cursor = NULL;
95
96   gdk_pixmap_unref (offscreen->pixmap);
97   
98   G_OBJECT_CLASS (gdk_offscreen_window_parent_class)->finalize (object);
99 }
100
101 static void
102 gdk_offscreen_window_init (GdkOffscreenWindow *window)
103 {
104 }
105
106 static void
107 gdk_offscreen_window_destroy (GdkWindow *window,
108                               gboolean   recursing,
109                               gboolean   foreign_destroy)
110 {
111   GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
112   GdkOffscreenWindow *offscreen;
113
114   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
115
116   if (!recursing)
117     gdk_offscreen_window_hide (window);
118
119   g_object_unref (offscreen->colormap);
120   offscreen->colormap = NULL;
121 }
122
123 static gboolean
124 is_parent_of (GdkWindow *parent,
125               GdkWindow *child)
126 {
127   GdkWindow *w;
128
129   w = child;
130   while (w != NULL)
131     {
132       if (w == parent)
133         return TRUE;
134
135       w = gdk_window_get_parent (w);
136     }
137
138   return FALSE;
139 }
140
141 static GdkGC *
142 gdk_offscreen_window_create_gc (GdkDrawable     *drawable,
143                                 GdkGCValues     *values,
144                                 GdkGCValuesMask  values_mask)
145 {
146   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
147
148   return gdk_gc_new_with_values (offscreen->pixmap, values, values_mask);
149 }
150
151 static GdkImage*
152 gdk_offscreen_window_copy_to_image (GdkDrawable    *drawable,
153                                     GdkImage       *image,
154                                     gint            src_x,
155                                     gint            src_y,
156                                     gint            dest_x,
157                                     gint            dest_y,
158                                     gint            width,
159                                     gint            height)
160 {
161   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
162
163   return gdk_drawable_copy_to_image (offscreen->pixmap,
164                                      image,
165                                      src_x,
166                                      src_y,
167                                      dest_x, dest_y,
168                                      width, height);
169 }
170
171 static cairo_surface_t *
172 gdk_offscreen_window_ref_cairo_surface (GdkDrawable *drawable)
173 {
174   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
175   
176   return _gdk_drawable_ref_cairo_surface (offscreen->pixmap);
177 }
178
179 static GdkColormap*
180 gdk_offscreen_window_get_colormap (GdkDrawable *drawable)
181 {
182   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
183
184   return offscreen->colormap;
185 }
186
187 static void
188 gdk_offscreen_window_set_colormap (GdkDrawable *drawable,
189                                    GdkColormap*colormap)
190 {
191   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
192
193   if (colormap && GDK_WINDOW_DESTROYED (offscreen->wrapper))
194     return;
195
196   if (offscreen->colormap == colormap)
197     return;
198
199   if (offscreen->colormap)
200     g_object_unref (offscreen->colormap);
201
202   offscreen->colormap = colormap;
203   if (offscreen->colormap)
204     g_object_ref (offscreen->colormap);
205 }
206
207
208 static gint
209 gdk_offscreen_window_get_depth (GdkDrawable *drawable)
210 {
211   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
212
213   return gdk_drawable_get_depth (offscreen->wrapper);
214 }
215
216 static GdkDrawable *
217 gdk_offscreen_window_get_source_drawable (GdkDrawable  *drawable)
218 {
219   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
220
221   return _gdk_drawable_get_source_drawable (offscreen->pixmap);
222 }
223
224 static GdkDrawable *
225 gdk_offscreen_window_get_composite_drawable (GdkDrawable *drawable,
226                                              gint         x,
227                                              gint         y,
228                                              gint         width,
229                                              gint         height,
230                                              gint        *composite_x_offset,
231                                              gint        *composite_y_offset)
232 {
233   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
234
235   return g_object_ref (offscreen->pixmap);
236 }
237
238 static GdkScreen*
239 gdk_offscreen_window_get_screen (GdkDrawable *drawable)
240 {
241   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
242
243   return offscreen->screen;
244 }
245
246 static GdkVisual*
247 gdk_offscreen_window_get_visual (GdkDrawable    *drawable)
248 {
249   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
250
251   return gdk_drawable_get_visual (offscreen->wrapper);
252 }
253
254 static void
255 add_damage (GdkOffscreenWindow *offscreen,
256             int x, int y,
257             int w, int h)
258 {
259   GdkRectangle rect;
260   GdkRegion *damage;
261   
262   rect.x = x;
263   rect.y = y;
264   rect.width = w;
265   rect.height = h;
266
267   damage = gdk_region_rectangle (&rect);
268   _gdk_window_add_damage (offscreen->wrapper, damage);
269   gdk_region_destroy (damage);
270 }
271
272 static GdkDrawable *
273 get_real_drawable (GdkOffscreenWindow *offscreen)
274 {
275   GdkPixmapObject *pixmap;
276   pixmap = (GdkPixmapObject *) offscreen->pixmap;
277   return GDK_DRAWABLE (pixmap->impl);
278 }
279
280 static void
281 gdk_offscreen_window_draw_drawable (GdkDrawable *drawable,
282                                     GdkGC       *gc,
283                                     GdkPixmap   *src,
284                                     GdkDrawable *original_src,
285                                     gint         xsrc,
286                                     gint         ysrc,
287                                     gint         xdest,
288                                     gint         ydest,
289                                     gint         width,
290                                     gint         height)
291 {
292   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
293   GdkDrawable *real_drawable = get_real_drawable (offscreen);
294   
295   gdk_draw_drawable (real_drawable, gc,
296                      src, xsrc, ysrc,
297                      xdest, ydest,
298                      width, height);
299
300   add_damage (offscreen, xdest, ydest, width, height);
301 }
302
303 static void
304 gdk_offscreen_window_draw_rectangle (GdkDrawable  *drawable,
305                                      GdkGC        *gc,
306                                      gboolean      filled,
307                                      gint          x,
308                                      gint          y,
309                                      gint          width,
310                                      gint          height)
311 {
312   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
313   GdkDrawable *real_drawable = get_real_drawable (offscreen);
314
315   gdk_draw_rectangle (real_drawable,
316                       gc, filled, x, y, width, height);
317
318   add_damage (offscreen, x, y, width, height);
319   
320 }
321
322 static void
323 gdk_offscreen_window_draw_arc (GdkDrawable  *drawable,
324                                GdkGC           *gc,
325                                gboolean filled,
326                                gint             x,
327                                gint             y,
328                                gint             width,
329                                gint             height,
330                                gint             angle1,
331                                gint             angle2)
332 {
333   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
334   GdkDrawable *real_drawable = get_real_drawable (offscreen);
335
336   gdk_draw_arc (real_drawable,
337                 gc,
338                 filled,
339                 x,
340                 y,
341                 width,
342                 height,
343                 angle1,
344                 angle2);
345   add_damage (offscreen, x, y, width, height);
346 }
347
348 static void
349 gdk_offscreen_window_draw_polygon (GdkDrawable  *drawable,
350                                    GdkGC               *gc,
351                                    gboolean     filled,
352                                    GdkPoint     *points,
353                                    gint         npoints)
354 {
355   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
356   GdkDrawable *real_drawable = get_real_drawable (offscreen);
357   
358   gdk_draw_polygon (real_drawable,
359                     gc,
360                     filled,
361                     points,
362                     npoints);
363
364   if (npoints > 0)
365     {
366       int min_x, min_y, max_x, max_y, i;
367       
368       min_x = max_x = points[0].x;
369       min_y = max_y = points[0].y;
370       
371         for (i = 1; i < npoints; i++)
372           {
373             min_x = MIN (min_x, points[i].x);
374             max_x = MAX (max_x, points[i].x);
375             min_y = MIN (min_y, points[i].y);
376             max_y = MAX (max_y, points[i].y);
377           }
378         
379         add_damage (offscreen, min_x, min_y,
380                     max_x - min_x,
381                     max_y - min_y);
382     }
383 }
384
385 static void
386 gdk_offscreen_window_draw_text (GdkDrawable  *drawable,
387                                 GdkFont      *font,
388                                 GdkGC          *gc,
389                                 gint            x,
390                                 gint            y,
391                                 const gchar  *text,
392                                 gint            text_length)
393 {
394   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
395   GdkDrawable *real_drawable = get_real_drawable (offscreen);
396   GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
397
398   gdk_draw_text (real_drawable,
399                  font,
400                  gc,
401                  x,
402                  y,
403                  text,
404                  text_length);
405
406   /* Hard to compute the minimal size, not that often used anyway. */
407   add_damage (offscreen, 0, 0, private->width, private->height);
408 }
409
410 static void
411 gdk_offscreen_window_draw_text_wc (GdkDrawable   *drawable,
412                                    GdkFont       *font,
413                                    GdkGC                 *gc,
414                                    gint           x,
415                                    gint           y,
416                                    const GdkWChar *text,
417                                    gint           text_length)
418 {
419   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
420   GdkDrawable *real_drawable = get_real_drawable (offscreen);
421   GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
422
423   gdk_draw_text_wc (real_drawable,
424                     font,
425                     gc,
426                     x,
427                     y,
428                     text,
429                     text_length);
430
431   /* Hard to compute the minimal size, not that often used anyway. */
432   add_damage (offscreen, 0, 0, private->width, private->height);
433 }
434
435 static void
436 gdk_offscreen_window_draw_points (GdkDrawable  *drawable,
437                                   GdkGC        *gc,
438                                   GdkPoint     *points,
439                                   gint          npoints)
440 {
441   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
442   GdkDrawable *real_drawable = get_real_drawable (offscreen);
443
444   gdk_draw_points (real_drawable,
445                    gc,
446                    points,
447                    npoints);
448
449
450   if (npoints > 0)
451     {
452       int min_x, min_y, max_x, max_y, i;
453       
454       min_x = max_x = points[0].x;
455       min_y = max_y = points[0].y;
456       
457         for (i = 1; i < npoints; i++)
458           {
459             min_x = MIN (min_x, points[i].x);
460             max_x = MAX (max_x, points[i].x);
461             min_y = MIN (min_y, points[i].y);
462             max_y = MAX (max_y, points[i].y);
463           }
464         
465         add_damage (offscreen, min_x, min_y,
466                     max_x - min_x,
467                     max_y - min_y);
468     }
469 }
470
471 static void
472 gdk_offscreen_window_draw_segments (GdkDrawable  *drawable,
473                                     GdkGC        *gc,
474                                     GdkSegment   *segs,
475                                     gint          nsegs)
476 {
477   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
478   GdkDrawable *real_drawable = get_real_drawable (offscreen);
479
480   gdk_draw_segments (real_drawable,
481                      gc,
482                      segs,
483                      nsegs);
484
485   if (nsegs > 0)
486     {
487       int min_x, min_y, max_x, max_y, i;
488       
489       min_x = max_x = segs[0].x1;
490       min_y = max_y = segs[0].y1;
491       
492         for (i = 1; i < nsegs; i++)
493           {
494             min_x = MIN (min_x, segs[i].x1);
495             max_x = MAX (max_x, segs[i].x1);
496             min_x = MIN (min_x, segs[i].x2);
497             max_x = MAX (max_x, segs[i].x2);
498             min_y = MIN (min_y, segs[i].y1);
499             max_y = MAX (max_y, segs[i].y1);
500             min_y = MIN (min_y, segs[i].y2);
501             max_y = MAX (max_y, segs[i].y2);
502           }
503         
504         add_damage (offscreen, min_x, min_y,
505                     max_x - min_x,
506                     max_y - min_y);
507     }
508
509 }
510
511 static void
512 gdk_offscreen_window_draw_lines (GdkDrawable  *drawable,
513                                  GdkGC        *gc,
514                                  GdkPoint     *points,
515                                  gint          npoints)
516 {
517   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
518   GdkDrawable *real_drawable = get_real_drawable (offscreen);
519   GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
520
521   gdk_draw_lines (real_drawable,
522                   gc,
523                   points,
524                   npoints);
525
526   /* Hard to compute the minimal size, as we don't know the line
527      width, and since joins are hard to calculate.
528      Its not that often used anyway, damage it all */
529   add_damage (offscreen, 0, 0, private->width, private->height);
530 }
531
532 static void
533 gdk_offscreen_window_draw_image (GdkDrawable *drawable,
534                                  GdkGC        *gc,
535                                  GdkImage    *image,
536                                  gint          xsrc,
537                                  gint          ysrc,
538                                  gint          xdest,
539                                  gint          ydest,
540                                  gint          width,
541                                  gint          height)
542 {
543   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
544   GdkDrawable *real_drawable = get_real_drawable (offscreen);
545
546   gdk_draw_image (real_drawable,
547                   gc,
548                   image,
549                   xsrc,
550                   ysrc,
551                   xdest,
552                   ydest,
553                   width,
554                   height);
555
556   add_damage (offscreen, xdest, ydest, width, height);
557 }
558
559
560 static void
561 gdk_offscreen_window_draw_pixbuf (GdkDrawable *drawable,
562                                   GdkGC       *gc,
563                                   GdkPixbuf   *pixbuf,
564                                   gint         src_x,
565                                   gint         src_y,
566                                   gint         dest_x,
567                                   gint         dest_y,
568                                   gint         width,
569                                   gint         height,
570                                   GdkRgbDither dither,
571                                   gint         x_dither,
572                                   gint         y_dither)
573 {
574   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
575   GdkDrawable *real_drawable = get_real_drawable (offscreen);
576   
577   gdk_draw_pixbuf (real_drawable,
578                    gc,
579                    pixbuf,
580                    src_x,
581                    src_y,
582                    dest_x,
583                    dest_y,
584                    width,
585                    height,
586                    dither,
587                    x_dither,
588                    y_dither);
589
590   add_damage (offscreen, dest_x, dest_y, width, height);
591
592 }
593
594 void 
595 _gdk_offscreen_window_new (GdkWindow     *window,
596                            GdkScreen     *screen,
597                            GdkVisual     *visual,
598                            GdkWindowAttr *attributes,
599                            gint           attributes_mask)
600 {
601   GdkWindowObject *parent_private;
602   GdkWindowObject *private;
603   GdkOffscreenWindow *offscreen;
604
605   g_return_if_fail (attributes != NULL);
606
607   if (attributes->wclass != GDK_INPUT_OUTPUT)
608     return; /* Can't support input only offscreens */
609   
610   private = (GdkWindowObject *)window;
611
612   if (private->parent != NULL && GDK_WINDOW_DESTROYED (private->parent))
613     return;
614
615   parent_private = (GdkWindowObject*) private->parent;
616   private->impl = g_object_new (GDK_TYPE_OFFSCREEN_WINDOW, NULL);
617   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
618   offscreen->wrapper = window;
619
620   offscreen->screen = screen;
621
622   if (attributes_mask & GDK_WA_COLORMAP)
623     offscreen->colormap = g_object_ref (attributes->colormap);
624   else
625     {
626       if (gdk_screen_get_system_visual (screen) == visual)
627         {
628           offscreen->colormap = gdk_screen_get_system_colormap (screen);
629           g_object_ref (offscreen->colormap);
630         }
631       else
632         offscreen->colormap = gdk_colormap_new (visual, FALSE);
633     }
634
635   offscreen->pixmap = gdk_pixmap_new ((GdkDrawable *)private->parent,
636                                       private->width,
637                                       private->height,
638                                       private->depth);
639 }
640
641 static gboolean
642 gdk_offscreen_window_reparent (GdkWindow *window,
643                                GdkWindow *new_parent,
644                                gint       x,
645                                gint       y)
646 {
647   GdkWindowObject *private = (GdkWindowObject *)window;
648   GdkWindowObject *new_parent_private = (GdkWindowObject *)new_parent;
649   GdkWindowObject *old_parent;
650   GdkOffscreenWindow *offscreen;
651   gboolean was_mapped;
652
653   if (new_parent)
654     {
655       /* No input-output children of input-only windows */
656       if (new_parent_private->input_only && !private->input_only)
657         return FALSE;
658       
659       /* Don't create loops in hierarchy */
660       if (is_parent_of (window, new_parent))
661         return FALSE;
662     }
663
664   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
665
666   was_mapped = GDK_WINDOW_IS_MAPPED (window);
667
668   gdk_window_hide (window);
669
670   if (private->parent)
671     private->parent->children = g_list_remove (private->parent->children, window);
672
673   old_parent = private->parent;
674   private->parent = new_parent_private;
675   private->x = x;
676   private->y = y;
677
678   if (new_parent_private)
679     private->parent->children = g_list_prepend (private->parent->children, window);
680
681   _gdk_syntesize_crossing_events_for_geometry_change (window);
682   if (old_parent)
683     _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (old_parent));
684   
685   return was_mapped;
686 }
687
688 static gint
689 gdk_offscreen_window_get_origin (GdkWindow *window,
690                                  gint      *x,
691                                  gint      *y)
692 {
693   if (x)
694     *x = 0;
695   if (y)
696     *y = 0;
697
698   return TRUE;
699 }
700
701 /**
702  * gdk_window_get_offscreen_pixmap:
703  * @window: a #GdkWindow
704  *
705  * Gets the offscreen pixmap that an offscreen window renders into. If
706  * you need to keep this around over window resizes, you need to add a
707  * reference to it.
708  *
709  * Returns: The offscreen pixmap, or NULL if not offscreen
710  **/
711 GdkPixmap *
712 gdk_window_get_offscreen_pixmap (GdkWindow *window)
713 {
714   GdkWindowObject *private = (GdkWindowObject *)window;
715   GdkOffscreenWindow *offscreen;
716   
717   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
718
719   if (!GDK_IS_OFFSCREEN_WINDOW (private->impl))
720     return NULL;
721   
722   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
723   return offscreen->pixmap;
724 }
725
726 static void
727 gdk_offscreen_window_raise (GdkWindow *window)
728 {
729   /* gdk_window_raise already changed the stacking order */
730   _gdk_syntesize_crossing_events_for_geometry_change (window);
731 }
732
733 static void
734 gdk_offscreen_window_lower (GdkWindow *window)
735 {
736   /* gdk_window_lower already changed the stacking order */
737   _gdk_syntesize_crossing_events_for_geometry_change (window);
738 }
739
740 static void
741 gdk_offscreen_window_move_resize_internal (GdkWindow *window,
742                                            gint       x,
743                                            gint       y,
744                                            gint       width,
745                                            gint       height,
746                                            gboolean   send_expose_events)
747 {
748   GdkWindowObject *private = (GdkWindowObject *)window;
749   GdkOffscreenWindow *offscreen;
750   gint dx, dy, dw, dh;
751   GdkGC *gc;
752   GdkPixmap *old_pixmap;
753
754   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
755
756   if (width < 1)
757     width = 1;
758   if (height < 1)
759     height = 1;
760
761   if (private->destroyed)
762     return;
763
764   dx = x - private->x;
765   dy = y - private->y;
766   dw = width - private->width;
767   dh = height - private->height;
768
769   private->x = x;
770   private->y = y;
771
772   if (private->width != width ||
773       private->height != height)
774     {
775       private->width = width;
776       private->height = height;
777       
778       old_pixmap = offscreen->pixmap;
779       offscreen->pixmap = gdk_pixmap_new (GDK_DRAWABLE (old_pixmap),
780                                           width,
781                                           height,
782                                           private->depth);
783
784       gc = _gdk_drawable_get_scratch_gc (offscreen->pixmap, FALSE);
785       gdk_draw_drawable (offscreen->pixmap,
786                          gc,
787                          old_pixmap,
788                          0,0, 0, 0,
789                          -1, -1);
790       g_object_unref (old_pixmap);
791     }
792   
793   if (GDK_WINDOW_IS_MAPPED (private))
794     {
795       // TODO: Only invalidate new area, i.e. for larger windows
796       gdk_window_invalidate_rect (window, NULL, TRUE);
797       _gdk_syntesize_crossing_events_for_geometry_change (window);
798     }
799 }
800
801 static void
802 gdk_offscreen_window_move_resize (GdkWindow *window,
803                                   gboolean   with_move,
804                                   gint       x,
805                                   gint       y,
806                                   gint       width,
807                                   gint       height)
808 {
809   GdkWindowObject *private = (GdkWindowObject *)window;
810   GdkOffscreenWindow *offscreen;
811
812   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
813
814   if (!with_move)
815     {
816       x = private->x;
817       y = private->y;
818     }
819
820   if (width < 0)
821     width = private->width;
822
823   if (height < 0)
824     height = private->height;
825
826   gdk_offscreen_window_move_resize_internal (window, x, y,
827                                              width, height,
828                                              TRUE);
829 }
830
831 static void
832 gdk_offscreen_window_show (GdkWindow *window)
833 {
834   GdkWindowObject *private = (GdkWindowObject *)window;
835
836   gdk_window_clear_area_e (window, 0, 0,
837                            private->width, private->height);
838 }
839
840
841 static void
842 gdk_offscreen_window_hide (GdkWindow *window)
843 {
844   GdkWindowObject *private;
845   GdkOffscreenWindow *offscreen;
846   GdkDisplay *display;
847
848   g_return_if_fail (window != NULL);
849
850   private = (GdkWindowObject*) window;
851   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
852
853   /* May need to break grabs on children */
854   display = gdk_drawable_get_display (window);
855
856   /* TODO: This needs updating to the new grab world */
857 #if 0
858   if (display->pointer_grab.window != NULL)
859     {
860       if (is_parent_of (window, display->pointer_grab.window))
861         {
862           /* Call this ourselves, even though gdk_display_pointer_ungrab
863              does so too, since we want to pass implicit == TRUE so the
864              broken grab event is generated */
865           _gdk_display_unset_has_pointer_grab (display,
866                                                TRUE,
867                                                FALSE,
868                                                GDK_CURRENT_TIME);
869           gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
870         }
871     }
872 #endif
873 }
874
875 static void
876 gdk_offscreen_window_withdraw (GdkWindow *window)
877 {
878 }
879
880 static GdkEventMask
881 gdk_offscreen_window_get_events (GdkWindow *window)
882 {
883   return 0;
884 }
885
886 static void
887 gdk_offscreen_window_set_events (GdkWindow       *window,
888                                  GdkEventMask     event_mask)
889 {
890 }
891
892 static void
893 gdk_offscreen_window_set_background (GdkWindow      *window,
894                                      const GdkColor *color)
895 {
896   GdkWindowObject *private = (GdkWindowObject *)window;
897   GdkColormap *colormap = gdk_drawable_get_colormap (window);
898
899   private->bg_color = *color;
900   gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
901
902   if (private->bg_pixmap &&
903       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
904       private->bg_pixmap != GDK_NO_BG)
905     g_object_unref (private->bg_pixmap);
906
907   private->bg_pixmap = NULL;
908 }
909
910 static void
911 gdk_offscreen_window_set_back_pixmap (GdkWindow *window,
912                                       GdkPixmap *pixmap)
913 {
914   GdkWindowObject *private = (GdkWindowObject *)window;
915
916   if (pixmap &&
917       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
918       private->bg_pixmap != GDK_NO_BG &&
919       !gdk_drawable_get_colormap (pixmap))
920     {
921       g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
922       return;
923     }
924
925   if (private->bg_pixmap &&
926       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
927       private->bg_pixmap != GDK_NO_BG)
928     g_object_unref (private->bg_pixmap);
929
930   private->bg_pixmap = pixmap;
931
932   if (pixmap &&
933       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
934       private->bg_pixmap != GDK_NO_BG)
935     g_object_ref (pixmap);
936 }
937
938 static void
939 gdk_offscreen_window_shape_combine_region (GdkWindow       *window,
940                                            const GdkRegion *shape_region,
941                                            gint             offset_x,
942                                            gint             offset_y)
943 {
944 }
945
946 static void
947 gdk_offscreen_window_input_shape_combine_region (GdkWindow       *window,
948                                                  const GdkRegion *shape_region,
949                                                  gint             offset_x,
950                                                  gint             offset_y)
951 {
952 }
953
954 static gboolean
955 gdk_offscreen_window_set_static_gravities (GdkWindow *window,
956                                            gboolean   use_static)
957 {
958   return TRUE;
959 }
960
961 static void
962 gdk_offscreen_window_set_cursor (GdkWindow *window,
963                                  GdkCursor *cursor)
964 {
965   GdkWindowObject *private = (GdkWindowObject *)window;
966   GdkOffscreenWindow *offscreen;
967
968   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
969
970   if (offscreen->cursor)
971     {
972       gdk_cursor_unref (offscreen->cursor);
973       offscreen->cursor = NULL;
974     }
975
976   if (cursor)
977     offscreen->cursor = gdk_cursor_ref (cursor);
978
979   /* TODO: The cursor is never actually used... */
980 }
981
982 static void
983 gdk_offscreen_window_get_geometry (GdkWindow *window,
984                                    gint      *x,
985                                    gint      *y,
986                                    gint      *width,
987                                    gint      *height,
988                                    gint      *depth)
989 {
990   GdkWindowObject *private = (GdkWindowObject *)window;
991   GdkOffscreenWindow *offscreen;
992
993   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
994
995   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
996
997   if (!GDK_WINDOW_DESTROYED (window))
998     {
999       if (x)
1000         *x = private->x;
1001       if (y)
1002         *y = private->y;
1003       if (width)
1004         *width = private->width;
1005       if (height)
1006         *height = private->height;
1007       if (depth)
1008         *depth = private->depth;
1009     }
1010 }
1011
1012 static gboolean
1013 gdk_offscreen_window_queue_antiexpose (GdkWindow *window,
1014                                        GdkRegion *area)
1015 {
1016   return FALSE;
1017 }
1018
1019 static void
1020 gdk_offscreen_window_queue_translation (GdkWindow *window,
1021                                         GdkRegion *area,
1022                                         gint       dx,
1023                                         gint       dy)
1024 {
1025 }
1026
1027
1028 static void
1029 gdk_offscreen_window_class_init (GdkOffscreenWindowClass *klass)
1030 {
1031   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
1032   GObjectClass *object_class = G_OBJECT_CLASS (klass);
1033
1034   object_class->finalize = gdk_offscreen_window_finalize;
1035
1036   drawable_class->create_gc = gdk_offscreen_window_create_gc;
1037   drawable_class->_copy_to_image = gdk_offscreen_window_copy_to_image;
1038   drawable_class->ref_cairo_surface = gdk_offscreen_window_ref_cairo_surface;
1039   drawable_class->set_colormap = gdk_offscreen_window_set_colormap;
1040   drawable_class->get_colormap = gdk_offscreen_window_get_colormap;
1041   drawable_class->get_depth = gdk_offscreen_window_get_depth;
1042   drawable_class->get_screen = gdk_offscreen_window_get_screen;
1043   drawable_class->get_visual = gdk_offscreen_window_get_visual;
1044   drawable_class->get_source_drawable = gdk_offscreen_window_get_source_drawable;
1045   drawable_class->get_composite_drawable = gdk_offscreen_window_get_composite_drawable;
1046
1047   drawable_class->draw_rectangle = gdk_offscreen_window_draw_rectangle;
1048   drawable_class->draw_arc = gdk_offscreen_window_draw_arc;
1049   drawable_class->draw_polygon = gdk_offscreen_window_draw_polygon;
1050   drawable_class->draw_text = gdk_offscreen_window_draw_text;
1051   drawable_class->draw_text_wc = gdk_offscreen_window_draw_text_wc;
1052   drawable_class->draw_drawable = gdk_offscreen_window_draw_drawable;
1053   drawable_class->draw_points = gdk_offscreen_window_draw_points;
1054   drawable_class->draw_segments = gdk_offscreen_window_draw_segments;
1055   drawable_class->draw_lines = gdk_offscreen_window_draw_lines;
1056   drawable_class->draw_image = gdk_offscreen_window_draw_image;
1057   drawable_class->draw_pixbuf = gdk_offscreen_window_draw_pixbuf;
1058 }
1059
1060 static void
1061 gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface)
1062 {
1063   iface->show = gdk_offscreen_window_show;
1064   iface->hide = gdk_offscreen_window_hide;
1065   iface->withdraw = gdk_offscreen_window_withdraw;
1066   iface->raise = gdk_offscreen_window_raise;
1067   iface->lower = gdk_offscreen_window_lower;
1068   iface->move_resize = gdk_offscreen_window_move_resize;
1069   iface->set_background = gdk_offscreen_window_set_background;
1070   iface->set_back_pixmap = gdk_offscreen_window_set_back_pixmap;
1071   iface->get_events = gdk_offscreen_window_get_events;
1072   iface->set_events = gdk_offscreen_window_set_events;
1073   iface->reparent = gdk_offscreen_window_reparent;
1074   iface->set_cursor = gdk_offscreen_window_set_cursor;
1075   iface->get_geometry = gdk_offscreen_window_get_geometry;
1076   iface->shape_combine_region = gdk_offscreen_window_shape_combine_region;
1077   iface->input_shape_combine_region = gdk_offscreen_window_input_shape_combine_region;
1078   iface->set_static_gravities = gdk_offscreen_window_set_static_gravities;
1079   iface->queue_antiexpose = gdk_offscreen_window_queue_antiexpose;
1080   iface->queue_translation = gdk_offscreen_window_queue_translation;
1081   iface->get_origin = gdk_offscreen_window_get_origin;
1082   iface->destroy = gdk_offscreen_window_destroy;
1083 }
1084
1085 #define __GDK_OFFSCREEN_WINDOW_C__
1086 #include "gdkaliasdef.c"