]> Pileus Git - ~andy/gtk/blob - gdk/gdkoffscreenwindow.c
Merge branch 'master' into client-side-windows
[~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                                     gint         xsrc,
285                                     gint         ysrc,
286                                     gint         xdest,
287                                     gint         ydest,
288                                     gint         width,
289                                     gint         height)
290 {
291   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
292   GdkDrawable *real_drawable = get_real_drawable (offscreen);
293   
294   gdk_draw_drawable (real_drawable, gc,
295                      src, xsrc, ysrc,
296                      xdest, ydest,
297                      width, height);
298
299   add_damage (offscreen, xdest, ydest, width, height);
300 }
301
302 static void
303 gdk_offscreen_window_draw_rectangle (GdkDrawable  *drawable,
304                                      GdkGC        *gc,
305                                      gboolean      filled,
306                                      gint          x,
307                                      gint          y,
308                                      gint          width,
309                                      gint          height)
310 {
311   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
312   GdkDrawable *real_drawable = get_real_drawable (offscreen);
313
314   gdk_draw_rectangle (real_drawable,
315                       gc, filled, x, y, width, height);
316
317   add_damage (offscreen, x, y, width, height);
318   
319 }
320
321 static void
322 gdk_offscreen_window_draw_arc (GdkDrawable  *drawable,
323                                GdkGC           *gc,
324                                gboolean filled,
325                                gint             x,
326                                gint             y,
327                                gint             width,
328                                gint             height,
329                                gint             angle1,
330                                gint             angle2)
331 {
332   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
333   GdkDrawable *real_drawable = get_real_drawable (offscreen);
334
335   gdk_draw_arc (real_drawable,
336                 gc,
337                 filled,
338                 x,
339                 y,
340                 width,
341                 height,
342                 angle1,
343                 angle2);
344   add_damage (offscreen, x, y, width, height);
345 }
346
347 static void
348 gdk_offscreen_window_draw_polygon (GdkDrawable  *drawable,
349                                    GdkGC               *gc,
350                                    gboolean     filled,
351                                    GdkPoint     *points,
352                                    gint         npoints)
353 {
354   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
355   GdkDrawable *real_drawable = get_real_drawable (offscreen);
356   
357   gdk_draw_polygon (real_drawable,
358                     gc,
359                     filled,
360                     points,
361                     npoints);
362
363   if (npoints > 0)
364     {
365       int min_x, min_y, max_x, max_y, i;
366       
367       min_x = max_x = points[0].x;
368       min_y = max_y = points[0].y;
369       
370         for (i = 1; i < npoints; i++)
371           {
372             min_x = MIN (min_x, points[i].x);
373             max_x = MAX (max_x, points[i].x);
374             min_y = MIN (min_y, points[i].y);
375             max_y = MAX (max_y, points[i].y);
376           }
377         
378         add_damage (offscreen, min_x, min_y,
379                     max_x - min_x,
380                     max_y - min_y);
381     }
382 }
383
384 static void
385 gdk_offscreen_window_draw_text (GdkDrawable  *drawable,
386                                 GdkFont      *font,
387                                 GdkGC          *gc,
388                                 gint            x,
389                                 gint            y,
390                                 const gchar  *text,
391                                 gint            text_length)
392 {
393   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
394   GdkDrawable *real_drawable = get_real_drawable (offscreen);
395   GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
396
397   gdk_draw_text (real_drawable,
398                  font,
399                  gc,
400                  x,
401                  y,
402                  text,
403                  text_length);
404
405   /* Hard to compute the minimal size, not that often used anyway. */
406   add_damage (offscreen, 0, 0, private->width, private->height);
407 }
408
409 static void
410 gdk_offscreen_window_draw_text_wc (GdkDrawable   *drawable,
411                                    GdkFont       *font,
412                                    GdkGC                 *gc,
413                                    gint           x,
414                                    gint           y,
415                                    const GdkWChar *text,
416                                    gint           text_length)
417 {
418   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
419   GdkDrawable *real_drawable = get_real_drawable (offscreen);
420   GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
421
422   gdk_draw_text_wc (real_drawable,
423                     font,
424                     gc,
425                     x,
426                     y,
427                     text,
428                     text_length);
429
430   /* Hard to compute the minimal size, not that often used anyway. */
431   add_damage (offscreen, 0, 0, private->width, private->height);
432 }
433
434 static void
435 gdk_offscreen_window_draw_points (GdkDrawable  *drawable,
436                                   GdkGC        *gc,
437                                   GdkPoint     *points,
438                                   gint          npoints)
439 {
440   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
441   GdkDrawable *real_drawable = get_real_drawable (offscreen);
442
443   gdk_draw_points (real_drawable,
444                    gc,
445                    points,
446                    npoints);
447
448
449   if (npoints > 0)
450     {
451       int min_x, min_y, max_x, max_y, i;
452       
453       min_x = max_x = points[0].x;
454       min_y = max_y = points[0].y;
455       
456         for (i = 1; i < npoints; i++)
457           {
458             min_x = MIN (min_x, points[i].x);
459             max_x = MAX (max_x, points[i].x);
460             min_y = MIN (min_y, points[i].y);
461             max_y = MAX (max_y, points[i].y);
462           }
463         
464         add_damage (offscreen, min_x, min_y,
465                     max_x - min_x,
466                     max_y - min_y);
467     }
468 }
469
470 static void
471 gdk_offscreen_window_draw_segments (GdkDrawable  *drawable,
472                                     GdkGC        *gc,
473                                     GdkSegment   *segs,
474                                     gint          nsegs)
475 {
476   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
477   GdkDrawable *real_drawable = get_real_drawable (offscreen);
478
479   gdk_draw_segments (real_drawable,
480                      gc,
481                      segs,
482                      nsegs);
483
484   if (nsegs > 0)
485     {
486       int min_x, min_y, max_x, max_y, i;
487       
488       min_x = max_x = segs[0].x1;
489       min_y = max_y = segs[0].y1;
490       
491         for (i = 1; i < nsegs; i++)
492           {
493             min_x = MIN (min_x, segs[i].x1);
494             max_x = MAX (max_x, segs[i].x1);
495             min_x = MIN (min_x, segs[i].x2);
496             max_x = MAX (max_x, segs[i].x2);
497             min_y = MIN (min_y, segs[i].y1);
498             max_y = MAX (max_y, segs[i].y1);
499             min_y = MIN (min_y, segs[i].y2);
500             max_y = MAX (max_y, segs[i].y2);
501           }
502         
503         add_damage (offscreen, min_x, min_y,
504                     max_x - min_x,
505                     max_y - min_y);
506     }
507
508 }
509
510 static void
511 gdk_offscreen_window_draw_lines (GdkDrawable  *drawable,
512                                  GdkGC        *gc,
513                                  GdkPoint     *points,
514                                  gint          npoints)
515 {
516   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
517   GdkDrawable *real_drawable = get_real_drawable (offscreen);
518   GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
519
520   gdk_draw_lines (real_drawable,
521                   gc,
522                   points,
523                   npoints);
524
525   /* Hard to compute the minimal size, as we don't know the line
526      width, and since joins are hard to calculate.
527      Its not that often used anyway, damage it all */
528   add_damage (offscreen, 0, 0, private->width, private->height);
529 }
530
531 static void
532 gdk_offscreen_window_draw_image (GdkDrawable *drawable,
533                                  GdkGC        *gc,
534                                  GdkImage    *image,
535                                  gint          xsrc,
536                                  gint          ysrc,
537                                  gint          xdest,
538                                  gint          ydest,
539                                  gint          width,
540                                  gint          height)
541 {
542   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
543   GdkDrawable *real_drawable = get_real_drawable (offscreen);
544
545   gdk_draw_image (real_drawable,
546                   gc,
547                   image,
548                   xsrc,
549                   ysrc,
550                   xdest,
551                   ydest,
552                   width,
553                   height);
554
555   add_damage (offscreen, xdest, ydest, width, height);
556 }
557
558
559 static void
560 gdk_offscreen_window_draw_pixbuf (GdkDrawable *drawable,
561                                   GdkGC       *gc,
562                                   GdkPixbuf   *pixbuf,
563                                   gint         src_x,
564                                   gint         src_y,
565                                   gint         dest_x,
566                                   gint         dest_y,
567                                   gint         width,
568                                   gint         height,
569                                   GdkRgbDither dither,
570                                   gint         x_dither,
571                                   gint         y_dither)
572 {
573   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
574   GdkDrawable *real_drawable = get_real_drawable (offscreen);
575   
576   gdk_draw_pixbuf (real_drawable,
577                    gc,
578                    pixbuf,
579                    src_x,
580                    src_y,
581                    dest_x,
582                    dest_y,
583                    width,
584                    height,
585                    dither,
586                    x_dither,
587                    y_dither);
588
589   add_damage (offscreen, dest_x, dest_y, width, height);
590
591 }
592
593 void 
594 _gdk_offscreen_window_new (GdkWindow     *window,
595                            GdkScreen     *screen,
596                            GdkVisual     *visual,
597                            GdkWindowAttr *attributes,
598                            gint           attributes_mask)
599 {
600   GdkWindowObject *parent_private;
601   GdkWindowObject *private;
602   GdkOffscreenWindow *offscreen;
603
604   g_return_if_fail (attributes != NULL);
605
606   if (attributes->wclass != GDK_INPUT_OUTPUT)
607     return; /* Can't support input only offscreens */
608   
609   private = (GdkWindowObject *)window;
610
611   if (private->parent != NULL && GDK_WINDOW_DESTROYED (private->parent))
612     return;
613
614   parent_private = (GdkWindowObject*) private->parent;
615   private->impl = g_object_new (GDK_TYPE_OFFSCREEN_WINDOW, NULL);
616   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
617   offscreen->wrapper = window;
618
619   offscreen->screen = screen;
620
621   if (attributes_mask & GDK_WA_COLORMAP)
622     offscreen->colormap = g_object_ref (attributes->colormap);
623   else
624     {
625       if (gdk_screen_get_system_visual (screen) == visual)
626         {
627           offscreen->colormap = gdk_screen_get_system_colormap (screen);
628           g_object_ref (offscreen->colormap);
629         }
630       else
631         offscreen->colormap = gdk_colormap_new (visual, FALSE);
632     }
633
634   offscreen->pixmap = gdk_pixmap_new ((GdkDrawable *)private->parent,
635                                       private->width,
636                                       private->height,
637                                       private->depth);
638 }
639
640 static gboolean
641 gdk_offscreen_window_reparent (GdkWindow *window,
642                                GdkWindow *new_parent,
643                                gint       x,
644                                gint       y)
645 {
646   GdkWindowObject *private = (GdkWindowObject *)window;
647   GdkWindowObject *new_parent_private = (GdkWindowObject *)new_parent;
648   GdkWindowObject *old_parent;
649   GdkOffscreenWindow *offscreen;
650   gboolean was_mapped;
651
652   if (new_parent)
653     {
654       /* No input-output children of input-only windows */
655       if (new_parent_private->input_only && !private->input_only)
656         return FALSE;
657       
658       /* Don't create loops in hierarchy */
659       if (is_parent_of (window, new_parent))
660         return FALSE;
661     }
662
663   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
664
665   was_mapped = GDK_WINDOW_IS_MAPPED (window);
666
667   gdk_window_hide (window);
668
669   if (private->parent)
670     private->parent->children = g_list_remove (private->parent->children, window);
671
672   old_parent = private->parent;
673   private->parent = new_parent_private;
674   private->x = x;
675   private->y = y;
676
677   if (new_parent_private)
678     private->parent->children = g_list_prepend (private->parent->children, window);
679
680   _gdk_syntesize_crossing_events_for_geometry_change (window);
681   if (old_parent)
682     _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (old_parent));
683   
684   return was_mapped;
685 }
686
687 static gint
688 gdk_offscreen_window_get_origin (GdkWindow *window,
689                                  gint      *x,
690                                  gint      *y)
691 {
692   if (x)
693     *x = 0;
694   if (y)
695     *y = 0;
696
697   return TRUE;
698 }
699
700 /**
701  * gdk_window_get_offscreen_pixmap:
702  * @window: a #GdkWindow
703  *
704  * Gets the offscreen pixmap that an offscreen window renders into. If
705  * you need to keep this around over window resizes, you need to add a
706  * reference to it.
707  *
708  * Returns: The offscreen pixmap, or NULL if not offscreen
709  **/
710 GdkPixmap *
711 gdk_window_get_offscreen_pixmap (GdkWindow *window)
712 {
713   GdkWindowObject *private = (GdkWindowObject *)window;
714   GdkOffscreenWindow *offscreen;
715   
716   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
717
718   if (!GDK_IS_OFFSCREEN_WINDOW (private->impl))
719     return NULL;
720   
721   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
722   return offscreen->pixmap;
723 }
724
725 static void
726 gdk_offscreen_window_raise (GdkWindow *window)
727 {
728   /* gdk_window_raise already changed the stacking order */
729   _gdk_syntesize_crossing_events_for_geometry_change (window);
730 }
731
732 static void
733 gdk_offscreen_window_lower (GdkWindow *window)
734 {
735   /* gdk_window_lower already changed the stacking order */
736   _gdk_syntesize_crossing_events_for_geometry_change (window);
737 }
738
739 static void
740 gdk_offscreen_window_move_resize_internal (GdkWindow *window,
741                                            gint       x,
742                                            gint       y,
743                                            gint       width,
744                                            gint       height,
745                                            gboolean   send_expose_events)
746 {
747   GdkWindowObject *private = (GdkWindowObject *)window;
748   GdkOffscreenWindow *offscreen;
749   gint dx, dy, dw, dh;
750   GdkGC *gc;
751   GdkPixmap *old_pixmap;
752
753   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
754
755   if (width < 1)
756     width = 1;
757   if (height < 1)
758     height = 1;
759
760   if (private->destroyed)
761     return;
762
763   dx = x - private->x;
764   dy = y - private->y;
765   dw = width - private->width;
766   dh = height - private->height;
767
768   private->x = x;
769   private->y = y;
770
771   if (private->width != width ||
772       private->height != height)
773     {
774       private->width = width;
775       private->height = height;
776       
777       old_pixmap = offscreen->pixmap;
778       offscreen->pixmap = gdk_pixmap_new (GDK_DRAWABLE (old_pixmap),
779                                           width,
780                                           height,
781                                           private->depth);
782
783       gc = _gdk_drawable_get_scratch_gc (offscreen->pixmap, FALSE);
784       gdk_draw_drawable (offscreen->pixmap,
785                          gc,
786                          old_pixmap,
787                          0,0, 0, 0,
788                          -1, -1);
789       g_object_unref (old_pixmap);
790     }
791   
792   if (GDK_WINDOW_IS_MAPPED (private))
793     {
794       // TODO: Only invalidate new area, i.e. for larger windows
795       gdk_window_invalidate_rect (window, NULL, TRUE);
796       _gdk_syntesize_crossing_events_for_geometry_change (window);
797     }
798 }
799
800 static void
801 gdk_offscreen_window_move_resize (GdkWindow *window,
802                                   gboolean   with_move,
803                                   gint       x,
804                                   gint       y,
805                                   gint       width,
806                                   gint       height)
807 {
808   GdkWindowObject *private = (GdkWindowObject *)window;
809   GdkOffscreenWindow *offscreen;
810
811   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
812
813   if (!with_move)
814     {
815       x = private->x;
816       y = private->y;
817     }
818
819   if (width < 0)
820     width = private->width;
821
822   if (height < 0)
823     height = private->height;
824
825   gdk_offscreen_window_move_resize_internal (window, x, y,
826                                              width, height,
827                                              TRUE);
828 }
829
830 static void
831 gdk_offscreen_window_show (GdkWindow *window)
832 {
833   GdkWindowObject *private = (GdkWindowObject *)window;
834
835   gdk_window_clear_area_e (window, 0, 0,
836                            private->width, private->height);
837 }
838
839
840 static void
841 gdk_offscreen_window_hide (GdkWindow *window)
842 {
843   GdkWindowObject *private;
844   GdkOffscreenWindow *offscreen;
845   GdkDisplay *display;
846
847   g_return_if_fail (window != NULL);
848
849   private = (GdkWindowObject*) window;
850   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
851
852   /* May need to break grabs on children */
853   display = gdk_drawable_get_display (window);
854
855   /* TODO: This needs updating to the new grab world */
856 #if 0
857   if (display->pointer_grab.window != NULL)
858     {
859       if (is_parent_of (window, display->pointer_grab.window))
860         {
861           /* Call this ourselves, even though gdk_display_pointer_ungrab
862              does so too, since we want to pass implicit == TRUE so the
863              broken grab event is generated */
864           _gdk_display_unset_has_pointer_grab (display,
865                                                TRUE,
866                                                FALSE,
867                                                GDK_CURRENT_TIME);
868           gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
869         }
870     }
871 #endif
872 }
873
874 static void
875 gdk_offscreen_window_withdraw (GdkWindow *window)
876 {
877 }
878
879 static GdkEventMask
880 gdk_offscreen_window_get_events (GdkWindow *window)
881 {
882   return 0;
883 }
884
885 static void
886 gdk_offscreen_window_set_events (GdkWindow       *window,
887                                  GdkEventMask     event_mask)
888 {
889 }
890
891 static void
892 gdk_offscreen_window_set_background (GdkWindow      *window,
893                                      const GdkColor *color)
894 {
895   GdkWindowObject *private = (GdkWindowObject *)window;
896   GdkColormap *colormap = gdk_drawable_get_colormap (window);
897
898   private->bg_color = *color;
899   gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
900
901   if (private->bg_pixmap &&
902       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
903       private->bg_pixmap != GDK_NO_BG)
904     g_object_unref (private->bg_pixmap);
905
906   private->bg_pixmap = NULL;
907 }
908
909 static void
910 gdk_offscreen_window_set_back_pixmap (GdkWindow *window,
911                                       GdkPixmap *pixmap)
912 {
913   GdkWindowObject *private = (GdkWindowObject *)window;
914
915   if (pixmap &&
916       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
917       private->bg_pixmap != GDK_NO_BG &&
918       !gdk_drawable_get_colormap (pixmap))
919     {
920       g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
921       return;
922     }
923
924   if (private->bg_pixmap &&
925       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
926       private->bg_pixmap != GDK_NO_BG)
927     g_object_unref (private->bg_pixmap);
928
929   private->bg_pixmap = pixmap;
930
931   if (pixmap &&
932       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
933       private->bg_pixmap != GDK_NO_BG)
934     g_object_ref (pixmap);
935 }
936
937 static void
938 gdk_offscreen_window_shape_combine_region (GdkWindow       *window,
939                                            const GdkRegion *shape_region,
940                                            gint             offset_x,
941                                            gint             offset_y)
942 {
943 }
944
945 static void
946 gdk_offscreen_window_input_shape_combine_region (GdkWindow       *window,
947                                                  const GdkRegion *shape_region,
948                                                  gint             offset_x,
949                                                  gint             offset_y)
950 {
951 }
952
953 static gboolean
954 gdk_offscreen_window_set_static_gravities (GdkWindow *window,
955                                            gboolean   use_static)
956 {
957   return TRUE;
958 }
959
960 static void
961 gdk_offscreen_window_set_cursor (GdkWindow *window,
962                                  GdkCursor *cursor)
963 {
964   GdkWindowObject *private = (GdkWindowObject *)window;
965   GdkOffscreenWindow *offscreen;
966
967   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
968
969   if (offscreen->cursor)
970     {
971       gdk_cursor_unref (offscreen->cursor);
972       offscreen->cursor = NULL;
973     }
974
975   if (cursor)
976     offscreen->cursor = gdk_cursor_ref (cursor);
977
978   /* TODO: The cursor is never actually used... */
979 }
980
981 static void
982 gdk_offscreen_window_get_geometry (GdkWindow *window,
983                                    gint      *x,
984                                    gint      *y,
985                                    gint      *width,
986                                    gint      *height,
987                                    gint      *depth)
988 {
989   GdkWindowObject *private = (GdkWindowObject *)window;
990   GdkOffscreenWindow *offscreen;
991
992   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
993
994   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
995
996   if (!GDK_WINDOW_DESTROYED (window))
997     {
998       if (x)
999         *x = private->x;
1000       if (y)
1001         *y = private->y;
1002       if (width)
1003         *width = private->width;
1004       if (height)
1005         *height = private->height;
1006       if (depth)
1007         *depth = private->depth;
1008     }
1009 }
1010
1011 static gboolean
1012 gdk_offscreen_window_queue_antiexpose (GdkWindow *window,
1013                                        GdkRegion *area)
1014 {
1015   return FALSE;
1016 }
1017
1018 static void
1019 gdk_offscreen_window_queue_translation (GdkWindow *window,
1020                                         GdkRegion *area,
1021                                         gint       dx,
1022                                         gint       dy)
1023 {
1024 }
1025
1026
1027 static void
1028 gdk_offscreen_window_class_init (GdkOffscreenWindowClass *klass)
1029 {
1030   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
1031   GObjectClass *object_class = G_OBJECT_CLASS (klass);
1032
1033   object_class->finalize = gdk_offscreen_window_finalize;
1034
1035   drawable_class->create_gc = gdk_offscreen_window_create_gc;
1036   drawable_class->_copy_to_image = gdk_offscreen_window_copy_to_image;
1037   drawable_class->ref_cairo_surface = gdk_offscreen_window_ref_cairo_surface;
1038   drawable_class->set_colormap = gdk_offscreen_window_set_colormap;
1039   drawable_class->get_colormap = gdk_offscreen_window_get_colormap;
1040   drawable_class->get_depth = gdk_offscreen_window_get_depth;
1041   drawable_class->get_screen = gdk_offscreen_window_get_screen;
1042   drawable_class->get_visual = gdk_offscreen_window_get_visual;
1043   drawable_class->get_source_drawable = gdk_offscreen_window_get_source_drawable;
1044   drawable_class->get_composite_drawable = gdk_offscreen_window_get_composite_drawable;
1045
1046   drawable_class->draw_rectangle = gdk_offscreen_window_draw_rectangle;
1047   drawable_class->draw_arc = gdk_offscreen_window_draw_arc;
1048   drawable_class->draw_polygon = gdk_offscreen_window_draw_polygon;
1049   drawable_class->draw_text = gdk_offscreen_window_draw_text;
1050   drawable_class->draw_text_wc = gdk_offscreen_window_draw_text_wc;
1051   drawable_class->draw_drawable = gdk_offscreen_window_draw_drawable;
1052   drawable_class->draw_points = gdk_offscreen_window_draw_points;
1053   drawable_class->draw_segments = gdk_offscreen_window_draw_segments;
1054   drawable_class->draw_lines = gdk_offscreen_window_draw_lines;
1055   drawable_class->draw_image = gdk_offscreen_window_draw_image;
1056   drawable_class->draw_pixbuf = gdk_offscreen_window_draw_pixbuf;
1057 }
1058
1059 static void
1060 gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface)
1061 {
1062   iface->show = gdk_offscreen_window_show;
1063   iface->hide = gdk_offscreen_window_hide;
1064   iface->withdraw = gdk_offscreen_window_withdraw;
1065   iface->raise = gdk_offscreen_window_raise;
1066   iface->lower = gdk_offscreen_window_lower;
1067   iface->move_resize = gdk_offscreen_window_move_resize;
1068   iface->set_background = gdk_offscreen_window_set_background;
1069   iface->set_back_pixmap = gdk_offscreen_window_set_back_pixmap;
1070   iface->get_events = gdk_offscreen_window_get_events;
1071   iface->set_events = gdk_offscreen_window_set_events;
1072   iface->reparent = gdk_offscreen_window_reparent;
1073   iface->set_cursor = gdk_offscreen_window_set_cursor;
1074   iface->get_geometry = gdk_offscreen_window_get_geometry;
1075   iface->shape_combine_region = gdk_offscreen_window_shape_combine_region;
1076   iface->input_shape_combine_region = gdk_offscreen_window_input_shape_combine_region;
1077   iface->set_static_gravities = gdk_offscreen_window_set_static_gravities;
1078   iface->queue_antiexpose = gdk_offscreen_window_queue_antiexpose;
1079   iface->queue_translation = gdk_offscreen_window_queue_translation;
1080   iface->get_origin = gdk_offscreen_window_get_origin;
1081   iface->destroy = gdk_offscreen_window_destroy;
1082 }
1083
1084 #define __GDK_OFFSCREEN_WINDOW_C__
1085 #include "gdkaliasdef.c"