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