]> Pileus Git - ~andy/gtk/blob - gdk/gdkoffscreenwindow.c
Update event emulation to handle offscreen children
[~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
689 static GdkWindow *
690 get_offscreen_parent (GdkWindow *window)
691 {
692   GdkWindowObject *private;
693   GdkWindow *res;
694
695   private = (GdkWindowObject *)window;
696
697   res = NULL;
698   g_signal_emit_by_name (private->impl_window,
699                          "get-offscreen-parent",
700                          &res);
701
702   return res;
703 }
704
705 static void
706 from_parent (GdkWindow *window,
707              double parent_x, double parent_y,
708              double *offscreen_x, double *offscreen_y)
709 {
710   GdkWindowObject *private;
711
712   private = (GdkWindowObject *)window;
713
714   g_signal_emit_by_name (private->impl_window,
715                          "from_parent",
716                          parent_x, parent_y,
717                          offscreen_x, offscreen_y,
718                          NULL);
719 }
720
721 static void
722 to_parent (GdkWindow *window,
723            double offscreen_x, double offscreen_y,
724            double *parent_x, double *parent_y)
725 {
726   GdkWindowObject *private;
727
728   private = (GdkWindowObject *)window;
729
730   g_signal_emit_by_name (private->impl_window,
731                          "to_parent",
732                          offscreen_x, offscreen_y,
733                          parent_x, parent_y,
734                          NULL);
735 }
736
737 static gint
738 gdk_offscreen_window_get_origin (GdkWindow *window,
739                                  gint      *x,
740                                  gint      *y)
741 {
742   GdkWindow *parent;
743   int tmpx, tmpy;
744
745   tmpx = 0;
746   tmpy = 0;
747
748   parent = get_offscreen_parent (window);
749   if (parent)
750     {
751       double dx, dy;
752       gdk_window_get_origin (parent,
753                              &tmpx, &tmpy);
754
755       to_parent (window,
756                  0, 0,
757                  &dx, &dy);
758       tmpx = floor (tmpx + dx + 0.5);
759       tmpy = floor (tmpy + dy + 0.5);
760     }
761
762
763   if (x)
764     *x = tmpx;
765   if (y)
766     *y = tmpy;
767
768   return TRUE;
769 }
770
771 static gint
772 gdk_offscreen_window_get_deskrelative_origin (GdkWindow *window,
773                                               gint      *x,
774                                               gint      *y)
775 {
776   GdkWindow *parent;
777   int tmpx, tmpy;
778
779   tmpx = 0;
780   tmpy = 0;
781
782   parent = get_offscreen_parent (window);
783   if (parent)
784     {
785       double dx, dy;
786       gdk_window_get_deskrelative_origin (parent,
787                                           &tmpx, &tmpy);
788
789       to_parent (window,
790                  0, 0,
791                  &dx, &dy);
792       tmpx = floor (tmpx + dx + 0.5);
793       tmpy = floor (tmpy + dy + 0.5);
794     }
795
796
797   if (x)
798     *x = tmpx;
799   if (y)
800     *y = tmpy;
801
802   return TRUE;
803 }
804
805 static gboolean
806 gdk_offscreen_window_get_pointer (GdkWindow       *window,
807                                   gint            *x,
808                                   gint            *y,
809                                   GdkModifierType *mask)
810 {
811   int tmpx, tmpy;
812   double dtmpx, dtmpy;
813   GdkModifierType tmpmask;
814   GdkWindow *parent;
815
816   tmpx = 0;
817   tmpy = 0;
818   tmpmask = 0;
819
820   parent = get_offscreen_parent (window);
821   if (parent != NULL)
822     {
823       gdk_window_get_pointer (parent, &tmpx, &tmpy, &tmpmask);
824       from_parent (window,
825                    tmpx, tmpy,
826                    &dtmpx, &dtmpy);
827       tmpx = floor (dtmpx + 0.5);
828       tmpy = floor (dtmpy + 0.5);
829     }
830
831   if (x)
832     *x = tmpx;
833   if (y)
834     *y = tmpy;
835   if (mask)
836     *mask = tmpmask;
837   return TRUE;
838 }
839
840 /**
841  * gdk_window_get_offscreen_pixmap:
842  * @window: a #GdkWindow
843  *
844  * Gets the offscreen pixmap that an offscreen window renders into. If
845  * you need to keep this around over window resizes, you need to add a
846  * reference to it.
847  *
848  * Returns: The offscreen pixmap, or NULL if not offscreen
849  **/
850 GdkPixmap *
851 gdk_window_get_offscreen_pixmap (GdkWindow *window)
852 {
853   GdkWindowObject *private = (GdkWindowObject *)window;
854   GdkOffscreenWindow *offscreen;
855
856   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
857
858   if (!GDK_IS_OFFSCREEN_WINDOW (private->impl))
859     return NULL;
860
861   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
862   return offscreen->pixmap;
863 }
864
865 static void
866 gdk_offscreen_window_raise (GdkWindow *window)
867 {
868   /* gdk_window_raise already changed the stacking order */
869   _gdk_syntesize_crossing_events_for_geometry_change (window);
870 }
871
872 static void
873 gdk_offscreen_window_lower (GdkWindow *window)
874 {
875   /* gdk_window_lower already changed the stacking order */
876   _gdk_syntesize_crossing_events_for_geometry_change (window);
877 }
878
879 static void
880 gdk_offscreen_window_move_resize_internal (GdkWindow *window,
881                                            gint       x,
882                                            gint       y,
883                                            gint       width,
884                                            gint       height,
885                                            gboolean   send_expose_events)
886 {
887   GdkWindowObject *private = (GdkWindowObject *)window;
888   GdkOffscreenWindow *offscreen;
889   gint dx, dy, dw, dh;
890   GdkGC *gc;
891   GdkPixmap *old_pixmap;
892
893   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
894
895   if (width < 1)
896     width = 1;
897   if (height < 1)
898     height = 1;
899
900   if (private->destroyed)
901     return;
902
903   dx = x - private->x;
904   dy = y - private->y;
905   dw = width - private->width;
906   dh = height - private->height;
907
908   private->x = x;
909   private->y = y;
910
911   if (private->width != width ||
912       private->height != height)
913     {
914       private->width = width;
915       private->height = height;
916
917       old_pixmap = offscreen->pixmap;
918       offscreen->pixmap = gdk_pixmap_new (GDK_DRAWABLE (old_pixmap),
919                                           width,
920                                           height,
921                                           private->depth);
922
923       gc = _gdk_drawable_get_scratch_gc (offscreen->pixmap, FALSE);
924       gdk_draw_drawable (offscreen->pixmap,
925                          gc,
926                          old_pixmap,
927                          0,0, 0, 0,
928                          -1, -1);
929       g_object_unref (old_pixmap);
930     }
931
932   if (GDK_WINDOW_IS_MAPPED (private))
933     {
934       // TODO: Only invalidate new area, i.e. for larger windows
935       gdk_window_invalidate_rect (window, NULL, TRUE);
936       _gdk_syntesize_crossing_events_for_geometry_change (window);
937     }
938 }
939
940 static void
941 gdk_offscreen_window_move_resize (GdkWindow *window,
942                                   gboolean   with_move,
943                                   gint       x,
944                                   gint       y,
945                                   gint       width,
946                                   gint       height)
947 {
948   GdkWindowObject *private = (GdkWindowObject *)window;
949   GdkOffscreenWindow *offscreen;
950
951   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
952
953   if (!with_move)
954     {
955       x = private->x;
956       y = private->y;
957     }
958
959   if (width < 0)
960     width = private->width;
961
962   if (height < 0)
963     height = private->height;
964
965   gdk_offscreen_window_move_resize_internal (window, x, y,
966                                              width, height,
967                                              TRUE);
968 }
969
970 static void
971 gdk_offscreen_window_show (GdkWindow *window)
972 {
973   GdkWindowObject *private = (GdkWindowObject *)window;
974
975   gdk_window_clear_area_e (window, 0, 0,
976                            private->width, private->height);
977 }
978
979
980 static void
981 gdk_offscreen_window_hide (GdkWindow *window)
982 {
983   GdkWindowObject *private;
984   GdkOffscreenWindow *offscreen;
985   GdkDisplay *display;
986
987   g_return_if_fail (window != NULL);
988
989   private = (GdkWindowObject*) window;
990   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
991
992   /* May need to break grabs on children */
993   display = gdk_drawable_get_display (window);
994
995   /* TODO: This needs updating to the new grab world */
996 #if 0
997   if (display->pointer_grab.window != NULL)
998     {
999       if (is_parent_of (window, display->pointer_grab.window))
1000         {
1001           /* Call this ourselves, even though gdk_display_pointer_ungrab
1002              does so too, since we want to pass implicit == TRUE so the
1003              broken grab event is generated */
1004           _gdk_display_unset_has_pointer_grab (display,
1005                                                TRUE,
1006                                                FALSE,
1007                                                GDK_CURRENT_TIME);
1008           gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
1009         }
1010     }
1011 #endif
1012 }
1013
1014 static void
1015 gdk_offscreen_window_withdraw (GdkWindow *window)
1016 {
1017 }
1018
1019 static GdkEventMask
1020 gdk_offscreen_window_get_events (GdkWindow *window)
1021 {
1022   return 0;
1023 }
1024
1025 static void
1026 gdk_offscreen_window_set_events (GdkWindow       *window,
1027                                  GdkEventMask     event_mask)
1028 {
1029 }
1030
1031 static void
1032 gdk_offscreen_window_set_background (GdkWindow      *window,
1033                                      const GdkColor *color)
1034 {
1035   GdkWindowObject *private = (GdkWindowObject *)window;
1036   GdkColormap *colormap = gdk_drawable_get_colormap (window);
1037
1038   private->bg_color = *color;
1039   gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
1040
1041   if (private->bg_pixmap &&
1042       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1043       private->bg_pixmap != GDK_NO_BG)
1044     g_object_unref (private->bg_pixmap);
1045
1046   private->bg_pixmap = NULL;
1047 }
1048
1049 static void
1050 gdk_offscreen_window_set_back_pixmap (GdkWindow *window,
1051                                       GdkPixmap *pixmap)
1052 {
1053   GdkWindowObject *private = (GdkWindowObject *)window;
1054
1055   if (pixmap &&
1056       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1057       private->bg_pixmap != GDK_NO_BG &&
1058       !gdk_drawable_get_colormap (pixmap))
1059     {
1060       g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
1061       return;
1062     }
1063
1064   if (private->bg_pixmap &&
1065       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1066       private->bg_pixmap != GDK_NO_BG)
1067     g_object_unref (private->bg_pixmap);
1068
1069   private->bg_pixmap = pixmap;
1070
1071   if (pixmap &&
1072       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1073       private->bg_pixmap != GDK_NO_BG)
1074     g_object_ref (pixmap);
1075 }
1076
1077 static void
1078 gdk_offscreen_window_shape_combine_region (GdkWindow       *window,
1079                                            const GdkRegion *shape_region,
1080                                            gint             offset_x,
1081                                            gint             offset_y)
1082 {
1083 }
1084
1085 static void
1086 gdk_offscreen_window_input_shape_combine_region (GdkWindow       *window,
1087                                                  const GdkRegion *shape_region,
1088                                                  gint             offset_x,
1089                                                  gint             offset_y)
1090 {
1091 }
1092
1093 static gboolean
1094 gdk_offscreen_window_set_static_gravities (GdkWindow *window,
1095                                            gboolean   use_static)
1096 {
1097   return TRUE;
1098 }
1099
1100 static void
1101 gdk_offscreen_window_set_cursor (GdkWindow *window,
1102                                  GdkCursor *cursor)
1103 {
1104   GdkWindowObject *private = (GdkWindowObject *)window;
1105   GdkOffscreenWindow *offscreen;
1106
1107   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
1108
1109   if (offscreen->cursor)
1110     {
1111       gdk_cursor_unref (offscreen->cursor);
1112       offscreen->cursor = NULL;
1113     }
1114
1115   if (cursor)
1116     offscreen->cursor = gdk_cursor_ref (cursor);
1117
1118   /* TODO: The cursor is never actually used... */
1119 }
1120
1121 static void
1122 gdk_offscreen_window_get_geometry (GdkWindow *window,
1123                                    gint      *x,
1124                                    gint      *y,
1125                                    gint      *width,
1126                                    gint      *height,
1127                                    gint      *depth)
1128 {
1129   GdkWindowObject *private = (GdkWindowObject *)window;
1130   GdkOffscreenWindow *offscreen;
1131
1132   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
1133
1134   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1135
1136   if (!GDK_WINDOW_DESTROYED (window))
1137     {
1138       if (x)
1139         *x = private->x;
1140       if (y)
1141         *y = private->y;
1142       if (width)
1143         *width = private->width;
1144       if (height)
1145         *height = private->height;
1146       if (depth)
1147         *depth = private->depth;
1148     }
1149 }
1150
1151 static gboolean
1152 gdk_offscreen_window_queue_antiexpose (GdkWindow *window,
1153                                        GdkRegion *area)
1154 {
1155   return FALSE;
1156 }
1157
1158 static void
1159 gdk_offscreen_window_queue_translation (GdkWindow *window,
1160                                         GdkRegion *area,
1161                                         gint       dx,
1162                                         gint       dy)
1163 {
1164 }
1165
1166
1167 static void
1168 gdk_offscreen_window_class_init (GdkOffscreenWindowClass *klass)
1169 {
1170   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
1171   GObjectClass *object_class = G_OBJECT_CLASS (klass);
1172
1173   object_class->finalize = gdk_offscreen_window_finalize;
1174
1175   drawable_class->create_gc = gdk_offscreen_window_create_gc;
1176   drawable_class->_copy_to_image = gdk_offscreen_window_copy_to_image;
1177   drawable_class->ref_cairo_surface = gdk_offscreen_window_ref_cairo_surface;
1178   drawable_class->set_colormap = gdk_offscreen_window_set_colormap;
1179   drawable_class->get_colormap = gdk_offscreen_window_get_colormap;
1180   drawable_class->get_depth = gdk_offscreen_window_get_depth;
1181   drawable_class->get_screen = gdk_offscreen_window_get_screen;
1182   drawable_class->get_visual = gdk_offscreen_window_get_visual;
1183   drawable_class->get_source_drawable = gdk_offscreen_window_get_source_drawable;
1184   drawable_class->get_composite_drawable = gdk_offscreen_window_get_composite_drawable;
1185
1186   drawable_class->draw_rectangle = gdk_offscreen_window_draw_rectangle;
1187   drawable_class->draw_arc = gdk_offscreen_window_draw_arc;
1188   drawable_class->draw_polygon = gdk_offscreen_window_draw_polygon;
1189   drawable_class->draw_text = gdk_offscreen_window_draw_text;
1190   drawable_class->draw_text_wc = gdk_offscreen_window_draw_text_wc;
1191   drawable_class->draw_drawable = gdk_offscreen_window_draw_drawable;
1192   drawable_class->draw_points = gdk_offscreen_window_draw_points;
1193   drawable_class->draw_segments = gdk_offscreen_window_draw_segments;
1194   drawable_class->draw_lines = gdk_offscreen_window_draw_lines;
1195   drawable_class->draw_image = gdk_offscreen_window_draw_image;
1196   drawable_class->draw_pixbuf = gdk_offscreen_window_draw_pixbuf;
1197 }
1198
1199 static void
1200 gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface)
1201 {
1202   iface->show = gdk_offscreen_window_show;
1203   iface->hide = gdk_offscreen_window_hide;
1204   iface->withdraw = gdk_offscreen_window_withdraw;
1205   iface->raise = gdk_offscreen_window_raise;
1206   iface->lower = gdk_offscreen_window_lower;
1207   iface->move_resize = gdk_offscreen_window_move_resize;
1208   iface->set_background = gdk_offscreen_window_set_background;
1209   iface->set_back_pixmap = gdk_offscreen_window_set_back_pixmap;
1210   iface->get_events = gdk_offscreen_window_get_events;
1211   iface->set_events = gdk_offscreen_window_set_events;
1212   iface->reparent = gdk_offscreen_window_reparent;
1213   iface->set_cursor = gdk_offscreen_window_set_cursor;
1214   iface->get_geometry = gdk_offscreen_window_get_geometry;
1215   iface->shape_combine_region = gdk_offscreen_window_shape_combine_region;
1216   iface->input_shape_combine_region = gdk_offscreen_window_input_shape_combine_region;
1217   iface->set_static_gravities = gdk_offscreen_window_set_static_gravities;
1218   iface->queue_antiexpose = gdk_offscreen_window_queue_antiexpose;
1219   iface->queue_translation = gdk_offscreen_window_queue_translation;
1220   iface->get_origin = gdk_offscreen_window_get_origin;
1221   iface->get_deskrelative_origin = gdk_offscreen_window_get_deskrelative_origin;
1222   iface->get_pointer = gdk_offscreen_window_get_pointer;
1223   iface->destroy = gdk_offscreen_window_destroy;
1224 }
1225
1226 #define __GDK_OFFSCREEN_WINDOW_C__
1227 #include "gdkaliasdef.c"