~ubuntu-branches/ubuntu/trusty/gtk+2.0/trusty-updates

« back to all changes in this revision

Viewing changes to .pc/gdkwindow-Fix-event-unref-iteration.patch/gdk/gdkwindow.c

  • Committer: Package Import Robot
  • Author(s): Vlad Orlov
  • Date: 2015-07-28 10:17:14 UTC
  • Revision ID: package-import@ubuntu.com-20150728101714-rd9msqcb0etcfpsr
Tags: 2.24.23-0ubuntu1.3
* fix_gdk_event_apply_filters.patch: new patch. Makes gdk_event_apply_filters
  function safe against changes in the filter list, prevents weird crashes in
  various apps. (LP: #1351890)
* gdk-Fix-GdkWindowFilter-internal-refcounting.patch,
  gdkwindow-Fix-event-unref-iteration.patch: new patches. Fix refcounting
  errors after fix_gdk_event_apply_filters.patch, prevent crashes in some
  applications like Spotify.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GDK - The GIMP Drawing Kit
 
2
 * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
 
3
 * Josh MacDonald, Ryan Lortie
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Lesser General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Lesser General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License along with this library; if not, write to the
 
17
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
18
 * Boston, MA 02111-1307, USA.
 
19
 */
 
20
 
 
21
/*
 
22
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
 
23
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 
24
 * files for a list of changes.  These files are distributed with
 
25
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
 
26
 */
 
27
 
 
28
#include "config.h"
 
29
#include "gdkwindow.h"
 
30
#include "gdkwindowimpl.h"
 
31
#include "gdkinternals.h"
 
32
#include "gdk.h"                /* For gdk_rectangle_union() */
 
33
#include "gdkpixmap.h"
 
34
#include "gdkdrawable.h"
 
35
#include "gdkintl.h"
 
36
#include "gdkscreen.h"
 
37
#include "gdkmarshalers.h"
 
38
#include "gdkalias.h"
 
39
 
 
40
#undef DEBUG_WINDOW_PRINTING
 
41
 
 
42
#ifdef GDK_WINDOWING_X11
 
43
#include "x11/gdkx.h"           /* For workaround */
 
44
#endif
 
45
 
 
46
#include "math.h"
 
47
 
 
48
/* Historically a GdkWindow always matches a platform native window,
 
49
 * be it a toplevel window or a child window. In this setup the
 
50
 * GdkWindow (and other GdkDrawables) were platform independent classes,
 
51
 * and the actual platform specific implementation was in a delegate
 
52
 * object availible as "impl" in the window object.
 
53
 *
 
54
 * With the addition of client side windows and offscreen windows this
 
55
 * changes a bit. The application-visible GdkWindow object behaves as
 
56
 * it did before, but not all such windows now have a corresponding native
 
57
 * window. Instead windows that are "client side" are emulated by the gdk
 
58
 * code such that clipping, drawing, moving, events etc work as expected.
 
59
 *
 
60
 * For GdkWindows that have a native window the "impl" object is the
 
61
 * same as before. However, for all client side windows the impl object
 
62
 * is shared with its parent (i.e. all client windows descendants of one
 
63
 * native window has the same impl.
 
64
 *
 
65
 * Additionally there is a new type of platform independent impl object,
 
66
 * GdkOffscreenWindow. All windows of type GDK_WINDOW_OFFSCREEN get an impl
 
67
 * of this type (while their children are generally GDK_WINDOW_CHILD virtual
 
68
 * windows). Such windows work by allocating a GdkPixmap as the backing store
 
69
 * for drawing operations, which is resized with the window.
 
70
 *
 
71
 * GdkWindows have a pointer to the "impl window" they are in, i.e.
 
72
 * the topmost GdkWindow which have the same "impl" value. This is stored
 
73
 * in impl_window, which is different from the window itself only for client
 
74
 * side windows.
 
75
 * All GdkWindows (native or not) track the position of the window in the parent
 
76
 * (x, y), the size of the window (width, height), the position of the window
 
77
 * with respect to the impl window (abs_x, abs_y). We also track the clip
 
78
 * region of the window wrt parent windows and siblings, in window-relative
 
79
 * coordinates with and without child windows included (clip_region,
 
80
 * clip_region_with_children).
 
81
 *
 
82
 * All toplevel windows are native windows, but also child windows can be
 
83
 * native (although not children of offscreens). We always listen to
 
84
 * a basic set of events (see get_native_event_mask) for these windows
 
85
 * so that we can emulate events for any client side children.
 
86
 *
 
87
 * For native windows we apply the calculated clip region as a window shape
 
88
 * so that eg. client side siblings that overlap the native child properly
 
89
 * draws over the native child window.
 
90
 *
 
91
 * In order to minimize flicker and for performance we use a couple of cacheing
 
92
 * tricks. First of all, every time we do a window to window copy area, for instance
 
93
 * when moving a client side window or when scrolling/moving a region in a window
 
94
 * we store this in outstanding_moves instead of applying immediately. We then
 
95
 * delay this move until we really need it (because something depends on being
 
96
 * able to read it), or until we're handing a redraw from an expose/invalidation
 
97
 * (actually we delay it past redraw, but before blitting the double buffer pixmap
 
98
 * to the window). This gives us two advantages. First of all it minimizes the time
 
99
 * from the window is moved to the exposes related to that move, secondly it allows
 
100
 * us to be smart about how to do the copy. We combine multiple moves into one (when
 
101
 * possible) and we don't actually do copies to anything that is or will be
 
102
 * invalidated and exposed anyway.
 
103
 *
 
104
 * Secondly, we use something called a "implicit paint" during repaint handling.
 
105
 * An implicit paint is similar to a regular paint for the paint stack, but it is
 
106
 * not put on the stack. Instead, it is set on the impl window, and later when
 
107
 * regular gdk_window_begin_paint_region()  happen on a window of this impl window
 
108
 * we reuse the pixmap from the implicit paint. During repaint we create and at the
 
109
 * end flush an implicit paint, which means we can collect all the paints on
 
110
 * multiple client side windows in the same backing store pixmap.
 
111
 *
 
112
 * All drawing to windows are wrapped with macros that set up the GC such that
 
113
 * the offsets and clip region is right for drawing to the paint object or
 
114
 * directly to the emulated window. It also automatically handles any flushing
 
115
 * needed when drawing directly to a window. Adding window/paint clipping is
 
116
 * done using _gdk_gc_add_drawable_clip which lets us efficiently add and then
 
117
 * remove a custom clip region.
 
118
 */
 
119
 
 
120
#define USE_BACKING_STORE       /* Appears to work on Win32, too, now. */
 
121
 
 
122
/* This adds a local value to the GdkVisibilityState enum */
 
123
#define GDK_VISIBILITY_NOT_VIEWABLE 3
 
124
 
 
125
enum {
 
126
  PICK_EMBEDDED_CHILD, /* only called if children are embedded */
 
127
  TO_EMBEDDER,
 
128
  FROM_EMBEDDER,
 
129
  LAST_SIGNAL
 
130
};
 
131
 
 
132
enum {
 
133
  PROP_0,
 
134
  PROP_CURSOR
 
135
};
 
136
 
 
137
typedef enum {
 
138
  CLEAR_BG_NONE,
 
139
  CLEAR_BG_WINCLEARED, /* Clear backgrounds except those that the window system clears */
 
140
  CLEAR_BG_ALL
 
141
} ClearBg;
 
142
 
 
143
struct _GdkWindowPaint
 
144
{
 
145
  GdkRegion *region;
 
146
  GdkPixmap *pixmap;
 
147
  gint x_offset;
 
148
  gint y_offset;
 
149
  cairo_surface_t *surface;
 
150
  guint uses_implicit : 1;
 
151
  guint flushed : 1;
 
152
  guint32 region_tag;
 
153
};
 
154
 
 
155
typedef struct {
 
156
  GdkRegion *dest_region; /* The destination region */
 
157
  int dx, dy; /* The amount that the source was moved to reach dest_region */
 
158
} GdkWindowRegionMove;
 
159
 
 
160
 
 
161
/* Global info */
 
162
 
 
163
static GdkGC *gdk_window_create_gc      (GdkDrawable     *drawable,
 
164
                                         GdkGCValues     *values,
 
165
                                         GdkGCValuesMask  mask);
 
166
static void   gdk_window_draw_rectangle (GdkDrawable     *drawable,
 
167
                                         GdkGC           *gc,
 
168
                                         gboolean         filled,
 
169
                                         gint             x,
 
170
                                         gint             y,
 
171
                                         gint             width,
 
172
                                         gint             height);
 
173
static void   gdk_window_draw_arc       (GdkDrawable     *drawable,
 
174
                                         GdkGC           *gc,
 
175
                                         gboolean         filled,
 
176
                                         gint             x,
 
177
                                         gint             y,
 
178
                                         gint             width,
 
179
                                         gint             height,
 
180
                                         gint             angle1,
 
181
                                         gint             angle2);
 
182
static void   gdk_window_draw_polygon   (GdkDrawable     *drawable,
 
183
                                         GdkGC           *gc,
 
184
                                         gboolean         filled,
 
185
                                         GdkPoint        *points,
 
186
                                         gint             npoints);
 
187
static void   gdk_window_draw_text      (GdkDrawable     *drawable,
 
188
                                         GdkFont         *font,
 
189
                                         GdkGC           *gc,
 
190
                                         gint             x,
 
191
                                         gint             y,
 
192
                                         const gchar     *text,
 
193
                                         gint             text_length);
 
194
static void   gdk_window_draw_text_wc   (GdkDrawable     *drawable,
 
195
                                         GdkFont         *font,
 
196
                                         GdkGC           *gc,
 
197
                                         gint             x,
 
198
                                         gint             y,
 
199
                                         const GdkWChar  *text,
 
200
                                         gint             text_length);
 
201
static void   gdk_window_draw_drawable  (GdkDrawable     *drawable,
 
202
                                         GdkGC           *gc,
 
203
                                         GdkPixmap       *src,
 
204
                                         gint             xsrc,
 
205
                                         gint             ysrc,
 
206
                                         gint             xdest,
 
207
                                         gint             ydest,
 
208
                                         gint             width,
 
209
                                         gint             height,
 
210
                                         GdkDrawable     *original_src);
 
211
static void   gdk_window_draw_points    (GdkDrawable     *drawable,
 
212
                                         GdkGC           *gc,
 
213
                                         GdkPoint        *points,
 
214
                                         gint             npoints);
 
215
static void   gdk_window_draw_segments  (GdkDrawable     *drawable,
 
216
                                         GdkGC           *gc,
 
217
                                         GdkSegment      *segs,
 
218
                                         gint             nsegs);
 
219
static void   gdk_window_draw_lines     (GdkDrawable     *drawable,
 
220
                                         GdkGC           *gc,
 
221
                                         GdkPoint        *points,
 
222
                                         gint             npoints);
 
223
 
 
224
static void gdk_window_draw_glyphs             (GdkDrawable      *drawable,
 
225
                                                GdkGC            *gc,
 
226
                                                PangoFont        *font,
 
227
                                                gint              x,
 
228
                                                gint              y,
 
229
                                                PangoGlyphString *glyphs);
 
230
static void gdk_window_draw_glyphs_transformed (GdkDrawable      *drawable,
 
231
                                                GdkGC            *gc,
 
232
                                                PangoMatrix      *matrix,
 
233
                                                PangoFont        *font,
 
234
                                                gint              x,
 
235
                                                gint              y,
 
236
                                                PangoGlyphString *glyphs);
 
237
 
 
238
static void   gdk_window_draw_image     (GdkDrawable     *drawable,
 
239
                                         GdkGC           *gc,
 
240
                                         GdkImage        *image,
 
241
                                         gint             xsrc,
 
242
                                         gint             ysrc,
 
243
                                         gint             xdest,
 
244
                                         gint             ydest,
 
245
                                         gint             width,
 
246
                                         gint             height);
 
247
 
 
248
static void gdk_window_draw_pixbuf (GdkDrawable     *drawable,
 
249
                                    GdkGC           *gc,
 
250
                                    GdkPixbuf       *pixbuf,
 
251
                                    gint             src_x,
 
252
                                    gint             src_y,
 
253
                                    gint             dest_x,
 
254
                                    gint             dest_y,
 
255
                                    gint             width,
 
256
                                    gint             height,
 
257
                                    GdkRgbDither     dither,
 
258
                                    gint             x_dither,
 
259
                                    gint             y_dither);
 
260
 
 
261
static void gdk_window_draw_trapezoids (GdkDrawable   *drawable,
 
262
                                        GdkGC         *gc,
 
263
                                        GdkTrapezoid  *trapezoids,
 
264
                                        gint           n_trapezoids);
 
265
 
 
266
static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
 
267
                                           GdkImage    *image,
 
268
                                           gint         src_x,
 
269
                                           gint         src_y,
 
270
                                           gint         dest_x,
 
271
                                           gint         dest_y,
 
272
                                           gint         width,
 
273
                                           gint         height);
 
274
 
 
275
static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
 
276
static cairo_surface_t *gdk_window_create_cairo_surface (GdkDrawable *drawable,
 
277
                                                         int width,
 
278
                                                         int height);
 
279
static void             gdk_window_drop_cairo_surface (GdkWindowObject *private);
 
280
static void             gdk_window_set_cairo_clip    (GdkDrawable *drawable,
 
281
                                                      cairo_t *cr);
 
282
 
 
283
static void   gdk_window_real_get_size  (GdkDrawable     *drawable,
 
284
                                         gint            *width,
 
285
                                         gint            *height);
 
286
 
 
287
static GdkVisual*   gdk_window_real_get_visual   (GdkDrawable *drawable);
 
288
static gint         gdk_window_real_get_depth    (GdkDrawable *drawable);
 
289
static GdkScreen*   gdk_window_real_get_screen   (GdkDrawable *drawable);
 
290
static void         gdk_window_real_set_colormap (GdkDrawable *drawable,
 
291
                                                  GdkColormap *cmap);
 
292
static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
 
293
 
 
294
static GdkDrawable* gdk_window_get_source_drawable    (GdkDrawable *drawable);
 
295
static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
 
296
                                                       gint         x,
 
297
                                                       gint         y,
 
298
                                                       gint         width,
 
299
                                                       gint         height,
 
300
                                                       gint        *composite_x_offset,
 
301
                                                       gint        *composite_y_offset);
 
302
static GdkRegion*   gdk_window_get_clip_region        (GdkDrawable *drawable);
 
303
static GdkRegion*   gdk_window_get_visible_region     (GdkDrawable *drawable);
 
304
 
 
305
static void gdk_window_free_paint_stack (GdkWindow *window);
 
306
 
 
307
static void gdk_window_init       (GdkWindowObject      *window);
 
308
static void gdk_window_class_init (GdkWindowObjectClass *klass);
 
309
static void gdk_window_finalize   (GObject              *object);
 
310
 
 
311
static void gdk_window_set_property (GObject      *object,
 
312
                                     guint         prop_id,
 
313
                                     const GValue *value,
 
314
                                     GParamSpec   *pspec);
 
315
static void gdk_window_get_property (GObject      *object,
 
316
                                     guint         prop_id,
 
317
                                     GValue       *value,
 
318
                                     GParamSpec   *pspec);
 
319
 
 
320
static void gdk_window_clear_backing_region (GdkWindow *window,
 
321
                                             GdkRegion *region);
 
322
static void gdk_window_redirect_free      (GdkWindowRedirect *redirect);
 
323
static void apply_redirect_to_children    (GdkWindowObject   *private,
 
324
                                           GdkWindowRedirect *redirect);
 
325
static void remove_redirect_from_children (GdkWindowObject   *private,
 
326
                                           GdkWindowRedirect *redirect);
 
327
 
 
328
static void recompute_visible_regions   (GdkWindowObject *private,
 
329
                                         gboolean recalculate_siblings,
 
330
                                         gboolean recalculate_children);
 
331
static void gdk_window_flush_outstanding_moves (GdkWindow *window);
 
332
static void gdk_window_flush_recursive  (GdkWindowObject *window);
 
333
static void do_move_region_bits_on_impl (GdkWindowObject *private,
 
334
                                         GdkRegion *region, /* In impl window coords */
 
335
                                         int dx, int dy);
 
336
static void gdk_window_invalidate_in_parent (GdkWindowObject *private);
 
337
static void move_native_children        (GdkWindowObject *private);
 
338
static void update_cursor               (GdkDisplay *display);
 
339
static void impl_window_add_update_area (GdkWindowObject *impl_window,
 
340
                                         GdkRegion *region);
 
341
static void gdk_window_region_move_free (GdkWindowRegionMove *move);
 
342
static void gdk_window_invalidate_region_full (GdkWindow       *window,
 
343
                                               const GdkRegion *region,
 
344
                                               gboolean         invalidate_children,
 
345
                                               ClearBg          clear_bg);
 
346
static void gdk_window_invalidate_rect_full (GdkWindow          *window,
 
347
                                             const GdkRectangle *rect,
 
348
                                             gboolean            invalidate_children,
 
349
                                             ClearBg             clear_bg);
 
350
 
 
351
static guint signals[LAST_SIGNAL] = { 0 };
 
352
 
 
353
static gpointer parent_class = NULL;
 
354
 
 
355
static const cairo_user_data_key_t gdk_window_cairo_key;
 
356
 
 
357
static guint32
 
358
new_region_tag (void)
 
359
{
 
360
  static guint32 tag = 0;
 
361
 
 
362
  return ++tag;
 
363
}
 
364
 
 
365
GType
 
366
gdk_window_object_get_type (void)
 
367
{
 
368
  static GType object_type = 0;
 
369
 
 
370
  if (!object_type)
 
371
    object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
 
372
                                                 "GdkWindow",
 
373
                                                 sizeof (GdkWindowObjectClass),
 
374
                                                 (GClassInitFunc) gdk_window_class_init,
 
375
                                                 sizeof (GdkWindowObject),
 
376
                                                 (GInstanceInitFunc) gdk_window_init,
 
377
                                                 0);
 
378
 
 
379
  return object_type;
 
380
}
 
381
 
 
382
GType
 
383
_gdk_paintable_get_type (void)
 
384
{
 
385
  static GType paintable_type = 0;
 
386
 
 
387
  if (!paintable_type)
 
388
    {
 
389
      const GTypeInfo paintable_info =
 
390
      {
 
391
        sizeof (GdkPaintableIface),  /* class_size */
 
392
        NULL,                        /* base_init */
 
393
        NULL,                        /* base_finalize */
 
394
      };
 
395
 
 
396
      paintable_type = g_type_register_static (G_TYPE_INTERFACE,
 
397
                                               g_intern_static_string ("GdkPaintable"),
 
398
                                               &paintable_info, 0);
 
399
 
 
400
      g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
 
401
    }
 
402
 
 
403
  return paintable_type;
 
404
}
 
405
 
 
406
static void
 
407
gdk_window_init (GdkWindowObject *window)
 
408
{
 
409
  /* 0-initialization is good for all other fields. */
 
410
 
 
411
  window->window_type = GDK_WINDOW_CHILD;
 
412
 
 
413
  window->state = GDK_WINDOW_STATE_WITHDRAWN;
 
414
  window->width = 1;
 
415
  window->height = 1;
 
416
  window->toplevel_window_type = -1;
 
417
  /* starts hidden */
 
418
  window->effective_visibility = GDK_VISIBILITY_NOT_VIEWABLE;
 
419
  window->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
 
420
  /* Default to unobscured since some backends don't send visibility events */
 
421
  window->native_visibility = GDK_VISIBILITY_UNOBSCURED;
 
422
}
 
423
 
 
424
/* Stop and return on the first non-NULL parent */
 
425
static gboolean
 
426
accumulate_get_window (GSignalInvocationHint *ihint,
 
427
                       GValue                  *return_accu,
 
428
                       const GValue            *handler_return,
 
429
                       gpointer               data)
 
430
{
 
431
  g_value_copy (handler_return, return_accu);
 
432
  /* Continue while returning NULL */
 
433
  return g_value_get_object (handler_return) == NULL;
 
434
}
 
435
 
 
436
static GQuark quark_pointer_window = 0;
 
437
 
 
438
static void
 
439
gdk_window_class_init (GdkWindowObjectClass *klass)
 
440
{
 
441
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
442
  GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
 
443
 
 
444
  parent_class = g_type_class_peek_parent (klass);
 
445
 
 
446
  object_class->finalize = gdk_window_finalize;
 
447
  object_class->set_property = gdk_window_set_property;
 
448
  object_class->get_property = gdk_window_get_property;
 
449
 
 
450
  drawable_class->create_gc = gdk_window_create_gc;
 
451
  drawable_class->draw_rectangle = gdk_window_draw_rectangle;
 
452
  drawable_class->draw_arc = gdk_window_draw_arc;
 
453
  drawable_class->draw_polygon = gdk_window_draw_polygon;
 
454
  drawable_class->draw_text = gdk_window_draw_text;
 
455
  drawable_class->draw_text_wc = gdk_window_draw_text_wc;
 
456
  drawable_class->draw_drawable_with_src = gdk_window_draw_drawable;
 
457
  drawable_class->draw_points = gdk_window_draw_points;
 
458
  drawable_class->draw_segments = gdk_window_draw_segments;
 
459
  drawable_class->draw_lines = gdk_window_draw_lines;
 
460
  drawable_class->draw_glyphs = gdk_window_draw_glyphs;
 
461
  drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
 
462
  drawable_class->draw_image = gdk_window_draw_image;
 
463
  drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
 
464
  drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
 
465
  drawable_class->get_depth = gdk_window_real_get_depth;
 
466
  drawable_class->get_screen = gdk_window_real_get_screen;
 
467
  drawable_class->get_size = gdk_window_real_get_size;
 
468
  drawable_class->set_colormap = gdk_window_real_set_colormap;
 
469
  drawable_class->get_colormap = gdk_window_real_get_colormap;
 
470
  drawable_class->get_visual = gdk_window_real_get_visual;
 
471
  drawable_class->_copy_to_image = gdk_window_copy_to_image;
 
472
  drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
 
473
  drawable_class->create_cairo_surface = gdk_window_create_cairo_surface;
 
474
  drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
 
475
  drawable_class->get_clip_region = gdk_window_get_clip_region;
 
476
  drawable_class->get_visible_region = gdk_window_get_visible_region;
 
477
  drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
 
478
  drawable_class->get_source_drawable = gdk_window_get_source_drawable;
 
479
 
 
480
  quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
 
481
 
 
482
 
 
483
  /* Properties */
 
484
 
 
485
  /**
 
486
   * GdkWindow:cursor:
 
487
   *
 
488
   * The mouse pointer for a #GdkWindow. See gdk_window_set_cursor() and
 
489
   * gdk_window_get_cursor() for details.
 
490
   *
 
491
   * Since: 2.18
 
492
   */
 
493
  g_object_class_install_property (object_class,
 
494
                                   PROP_CURSOR,
 
495
                                   g_param_spec_boxed ("cursor",
 
496
                                                       P_("Cursor"),
 
497
                                                       P_("Cursor"),
 
498
                                                       GDK_TYPE_CURSOR,
 
499
                                                       G_PARAM_READWRITE));
 
500
 
 
501
  /**
 
502
   * GdkWindow::pick-embedded-child:
 
503
   * @window: the window on which the signal is emitted
 
504
   * @x: x coordinate in the window
 
505
   * @y: y coordinate in the window
 
506
   *
 
507
   * The ::pick-embedded-child signal is emitted to find an embedded
 
508
   * child at the given position.
 
509
   *
 
510
   * Returns: (transfer none): the #GdkWindow of the embedded child at
 
511
   *     @x, @y, or %NULL
 
512
   *
 
513
   * Since: 2.18
 
514
   */
 
515
  signals[PICK_EMBEDDED_CHILD] =
 
516
    g_signal_new (g_intern_static_string ("pick-embedded-child"),
 
517
                  G_OBJECT_CLASS_TYPE (object_class),
 
518
                  G_SIGNAL_RUN_LAST,
 
519
                  0,
 
520
                  accumulate_get_window, NULL,
 
521
                  _gdk_marshal_OBJECT__DOUBLE_DOUBLE,
 
522
                  GDK_TYPE_WINDOW,
 
523
                  2,
 
524
                  G_TYPE_DOUBLE,
 
525
                  G_TYPE_DOUBLE);
 
526
 
 
527
  /**
 
528
   * GdkWindow::to-embedder:
 
529
   * @window: the offscreen window on which the signal is emitted
 
530
   * @offscreen-x: x coordinate in the offscreen window
 
531
   * @offscreen-y: y coordinate in the offscreen window
 
532
   * @embedder-x: (out) (type double): return location for the x
 
533
   *     coordinate in the embedder window
 
534
   * @embedder-y: (out) (type double): return location for the y
 
535
   *     coordinate in the embedder window
 
536
   *
 
537
   * The ::to-embedder signal is emitted to translate coordinates
 
538
   * in an offscreen window to its embedder.
 
539
   *
 
540
   * See also #GtkWindow::from-embedder.
 
541
   *
 
542
   * Since: 2.18
 
543
   */
 
544
  signals[TO_EMBEDDER] =
 
545
    g_signal_new (g_intern_static_string ("to-embedder"),
 
546
                  G_OBJECT_CLASS_TYPE (object_class),
 
547
                  G_SIGNAL_RUN_LAST,
 
548
                  0,
 
549
                  NULL, NULL,
 
550
                  _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
 
551
                  G_TYPE_NONE,
 
552
                  4,
 
553
                  G_TYPE_DOUBLE,
 
554
                  G_TYPE_DOUBLE,
 
555
                  G_TYPE_POINTER,
 
556
                  G_TYPE_POINTER);
 
557
 
 
558
  /**
 
559
   * GdkWindow::from-embedder:
 
560
   * @window: the offscreen window on which the signal is emitted
 
561
   * @embedder-x: x coordinate in the embedder window
 
562
   * @embedder-y: y coordinate in the embedder window
 
563
   * @offscreen-x: (out) (type double): return location for the x
 
564
   *     coordinate in the offscreen window
 
565
   * @offscreen-y: (out) (type double): return location for the y
 
566
   *     coordinate in the offscreen window
 
567
   *
 
568
   * The ::from-embedder signal is emitted to translate coordinates
 
569
   * in the embedder of an offscreen window to the offscreen window.
 
570
   *
 
571
   * See also #GtkWindow::to-embedder.
 
572
   *
 
573
   * Since: 2.18
 
574
   */
 
575
  signals[FROM_EMBEDDER] =
 
576
    g_signal_new (g_intern_static_string ("from-embedder"),
 
577
                  G_OBJECT_CLASS_TYPE (object_class),
 
578
                  G_SIGNAL_RUN_LAST,
 
579
                  0,
 
580
                  NULL, NULL,
 
581
                  _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
 
582
                  G_TYPE_NONE,
 
583
                  4,
 
584
                  G_TYPE_DOUBLE,
 
585
                  G_TYPE_DOUBLE,
 
586
                  G_TYPE_POINTER,
 
587
                  G_TYPE_POINTER);
 
588
}
 
589
 
 
590
static void
 
591
gdk_window_finalize (GObject *object)
 
592
{
 
593
  GdkWindow *window = GDK_WINDOW (object);
 
594
  GdkWindowObject *obj = (GdkWindowObject *) object;
 
595
 
 
596
  if (!GDK_WINDOW_DESTROYED (window))
 
597
    {
 
598
      if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
 
599
        {
 
600
          g_warning ("losing last reference to undestroyed window\n");
 
601
          _gdk_window_destroy (window, FALSE);
 
602
        }
 
603
      else
 
604
        /* We use TRUE here, to keep us from actually calling
 
605
         * XDestroyWindow() on the window
 
606
         */
 
607
        _gdk_window_destroy (window, TRUE);
 
608
    }
 
609
 
 
610
  if (obj->impl)
 
611
    {
 
612
      g_object_unref (obj->impl);
 
613
      obj->impl = NULL;
 
614
    }
 
615
 
 
616
  if (obj->impl_window != obj)
 
617
    {
 
618
      g_object_unref (obj->impl_window);
 
619
      obj->impl_window = NULL;
 
620
    }
 
621
 
 
622
  if (obj->shape)
 
623
    gdk_region_destroy (obj->shape);
 
624
 
 
625
  if (obj->input_shape)
 
626
    gdk_region_destroy (obj->input_shape);
 
627
 
 
628
  if (obj->cursor)
 
629
    gdk_cursor_unref (obj->cursor);
 
630
 
 
631
  G_OBJECT_CLASS (parent_class)->finalize (object);
 
632
}
 
633
 
 
634
static void
 
635
gdk_window_set_property (GObject      *object,
 
636
                         guint         prop_id,
 
637
                         const GValue *value,
 
638
                         GParamSpec   *pspec)
 
639
{
 
640
  GdkWindow *window = (GdkWindow *)object;
 
641
 
 
642
  switch (prop_id)
 
643
    {
 
644
    case PROP_CURSOR:
 
645
      gdk_window_set_cursor (window, g_value_get_boxed (value));
 
646
      break;
 
647
 
 
648
    default:
 
649
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
650
      break;
 
651
    }
 
652
}
 
653
 
 
654
static void
 
655
gdk_window_get_property (GObject    *object,
 
656
                         guint       prop_id,
 
657
                         GValue     *value,
 
658
                         GParamSpec *pspec)
 
659
{
 
660
  GdkWindow *window = (GdkWindow *) object;
 
661
 
 
662
  switch (prop_id)
 
663
    {
 
664
    case PROP_CURSOR:
 
665
      g_value_set_boxed (value, gdk_window_get_cursor (window));
 
666
      break;
 
667
 
 
668
    default:
 
669
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
670
      break;
 
671
    }
 
672
}
 
673
 
 
674
static gboolean
 
675
gdk_window_is_offscreen (GdkWindowObject *window)
 
676
{
 
677
  return window->window_type == GDK_WINDOW_OFFSCREEN;
 
678
}
 
679
 
 
680
static GdkWindowObject *
 
681
gdk_window_get_impl_window (GdkWindowObject *window)
 
682
{
 
683
  return window->impl_window;
 
684
}
 
685
 
 
686
GdkWindow *
 
687
_gdk_window_get_impl_window (GdkWindow *window)
 
688
{
 
689
  return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
 
690
}
 
691
 
 
692
static gboolean
 
693
gdk_window_has_impl (GdkWindowObject *window)
 
694
{
 
695
  return window->impl_window == window;
 
696
}
 
697
 
 
698
static gboolean
 
699
gdk_window_is_toplevel (GdkWindowObject *window)
 
700
{
 
701
  return
 
702
    window->parent == NULL ||
 
703
    window->parent->window_type == GDK_WINDOW_ROOT;
 
704
}
 
705
 
 
706
gboolean
 
707
_gdk_window_has_impl (GdkWindow *window)
 
708
{
 
709
  return gdk_window_has_impl ((GdkWindowObject *)window);
 
710
}
 
711
 
 
712
static gboolean
 
713
gdk_window_has_no_impl (GdkWindowObject *window)
 
714
{
 
715
  return window->impl_window != window;
 
716
}
 
717
 
 
718
static void
 
719
remove_child_area (GdkWindowObject *private,
 
720
                   GdkWindowObject *until,
 
721
                   gboolean for_input,
 
722
                   GdkRegion *region)
 
723
{
 
724
  GdkWindowObject *child;
 
725
  GdkRegion *child_region;
 
726
  GdkRectangle r;
 
727
  GList *l;
 
728
  GdkRegion *shape;
 
729
 
 
730
  for (l = private->children; l; l = l->next)
 
731
    {
 
732
      child = l->data;
 
733
 
 
734
      if (child == until)
 
735
        break;
 
736
 
 
737
      /* If region is empty already, no need to do
 
738
         anything potentially costly */
 
739
      if (gdk_region_empty (region))
 
740
        break;
 
741
 
 
742
      if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
 
743
        continue;
 
744
 
 
745
      /* Ignore offscreen children, as they don't draw in their parent and
 
746
       * don't take part in the clipping */
 
747
      if (gdk_window_is_offscreen (child))
 
748
        continue;
 
749
 
 
750
      r.x = child->x;
 
751
      r.y = child->y;
 
752
      r.width = child->width;
 
753
      r.height = child->height;
 
754
 
 
755
      /* Bail early if child totally outside region */
 
756
      if (gdk_region_rect_in (region, &r) == GDK_OVERLAP_RECTANGLE_OUT)
 
757
        continue;
 
758
 
 
759
      child_region = gdk_region_rectangle (&r);
 
760
 
 
761
      if (child->shape)
 
762
        {
 
763
          /* Adjust shape region to parent window coords */
 
764
          gdk_region_offset (child->shape, child->x, child->y);
 
765
          gdk_region_intersect (child_region, child->shape);
 
766
          gdk_region_offset (child->shape, -child->x, -child->y);
 
767
        }
 
768
      else if (private->window_type == GDK_WINDOW_FOREIGN)
 
769
        {
 
770
          shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
 
771
          if (shape)
 
772
            {
 
773
              gdk_region_intersect (child_region, shape);
 
774
              gdk_region_destroy (shape);
 
775
            }
 
776
        }
 
777
 
 
778
      if (for_input)
 
779
        {
 
780
          if (child->input_shape)
 
781
            gdk_region_intersect (child_region, child->input_shape);
 
782
          else if (private->window_type == GDK_WINDOW_FOREIGN)
 
783
            {
 
784
              shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child);
 
785
              if (shape)
 
786
                {
 
787
                  gdk_region_intersect (child_region, shape);
 
788
                  gdk_region_destroy (shape);
 
789
                }
 
790
            }
 
791
        }
 
792
 
 
793
      gdk_region_subtract (region, child_region);
 
794
      gdk_region_destroy (child_region);
 
795
 
 
796
    }
 
797
}
 
798
 
 
799
static GdkVisibilityState
 
800
effective_visibility (GdkWindowObject *private)
 
801
{
 
802
  GdkVisibilityState native;
 
803
 
 
804
  if (!gdk_window_is_viewable ((GdkWindow *)private))
 
805
    return GDK_VISIBILITY_NOT_VIEWABLE;
 
806
 
 
807
  native = private->impl_window->native_visibility;
 
808
 
 
809
  if (native == GDK_VISIBILITY_FULLY_OBSCURED ||
 
810
      private->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
 
811
    return GDK_VISIBILITY_FULLY_OBSCURED;
 
812
  else if (native == GDK_VISIBILITY_UNOBSCURED)
 
813
    return private->visibility;
 
814
  else /* native PARTIAL, private partial or unobscured  */
 
815
    return GDK_VISIBILITY_PARTIAL;
 
816
}
 
817
 
 
818
static void
 
819
gdk_window_update_visibility (GdkWindowObject *private)
 
820
{
 
821
  GdkVisibilityState new_visibility;
 
822
  GdkEvent *event;
 
823
 
 
824
  new_visibility = effective_visibility (private);
 
825
 
 
826
  if (new_visibility != private->effective_visibility)
 
827
    {
 
828
      private->effective_visibility = new_visibility;
 
829
 
 
830
      if (new_visibility != GDK_VISIBILITY_NOT_VIEWABLE &&
 
831
          private->event_mask & GDK_VISIBILITY_NOTIFY)
 
832
        {
 
833
          event = _gdk_make_event ((GdkWindow *)private, GDK_VISIBILITY_NOTIFY,
 
834
                                   NULL, FALSE);
 
835
          event->visibility.state = new_visibility;
 
836
        }
 
837
    }
 
838
}
 
839
 
 
840
static void
 
841
gdk_window_update_visibility_recursively (GdkWindowObject *private,
 
842
                                          GdkWindowObject *only_for_impl)
 
843
{
 
844
  GdkWindowObject *child;
 
845
  GList *l;
 
846
 
 
847
  gdk_window_update_visibility (private);
 
848
  for (l = private->children; l != NULL; l = l->next)
 
849
    {
 
850
      child = l->data;
 
851
      if ((only_for_impl == NULL) ||
 
852
          (only_for_impl == child->impl_window))
 
853
        gdk_window_update_visibility_recursively (child, only_for_impl);
 
854
    }
 
855
}
 
856
 
 
857
static gboolean
 
858
should_apply_clip_as_shape (GdkWindowObject *private)
 
859
{
 
860
  return
 
861
    gdk_window_has_impl (private) &&
 
862
    /* Not for offscreens */
 
863
    !gdk_window_is_offscreen (private) &&
 
864
    /* or for toplevels */
 
865
    !gdk_window_is_toplevel (private) &&
 
866
    /* or for foreign windows */
 
867
    private->window_type != GDK_WINDOW_FOREIGN &&
 
868
    /* or for the root window */
 
869
    private->window_type != GDK_WINDOW_ROOT;
 
870
}
 
871
 
 
872
static void
 
873
apply_shape (GdkWindowObject *private,
 
874
             GdkRegion *region)
 
875
{
 
876
  GdkWindowImplIface *impl_iface;
 
877
 
 
878
  /* We trash whether we applied a shape so that
 
879
     we can avoid unsetting it many times, which
 
880
     could happen in e.g. apply_clip_as_shape as
 
881
     windows get resized */
 
882
  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
883
  if (region)
 
884
    impl_iface->shape_combine_region ((GdkWindow *)private,
 
885
                                      region, 0, 0);
 
886
  else if (private->applied_shape)
 
887
    impl_iface->shape_combine_region ((GdkWindow *)private,
 
888
                                      NULL, 0, 0);
 
889
 
 
890
  private->applied_shape = region != NULL;
 
891
}
 
892
 
 
893
static void
 
894
apply_clip_as_shape (GdkWindowObject *private)
 
895
{
 
896
  GdkRectangle r;
 
897
 
 
898
  r.x = r.y = 0;
 
899
  r.width = private->width;
 
900
  r.height = private->height;
 
901
 
 
902
  /* We only apply the clip region if would differ
 
903
     from the actual clip region implied by the size
 
904
     of the window. This is to avoid unneccessarily
 
905
     adding meaningless shapes to all native subwindows */
 
906
  if (!gdk_region_rect_equal (private->clip_region, &r))
 
907
    apply_shape (private, private->clip_region);
 
908
  else
 
909
    apply_shape (private, NULL);
 
910
}
 
911
 
 
912
static void
 
913
recompute_visible_regions_internal (GdkWindowObject *private,
 
914
                                    gboolean recalculate_clip,
 
915
                                    gboolean recalculate_siblings,
 
916
                                    gboolean recalculate_children)
 
917
{
 
918
  GdkRectangle r;
 
919
  GList *l;
 
920
  GdkWindowObject *child;
 
921
  GdkRegion *new_clip, *old_clip_region_with_children;
 
922
  gboolean clip_region_changed;
 
923
  gboolean abs_pos_changed;
 
924
  int old_abs_x, old_abs_y;
 
925
 
 
926
  old_abs_x = private->abs_x;
 
927
  old_abs_y = private->abs_y;
 
928
 
 
929
  /* Update absolute position */
 
930
  if (gdk_window_has_impl (private))
 
931
    {
 
932
      /* Native window starts here */
 
933
      private->abs_x = 0;
 
934
      private->abs_y = 0;
 
935
    }
 
936
  else
 
937
    {
 
938
      private->abs_x = private->parent->abs_x + private->x;
 
939
      private->abs_y = private->parent->abs_y + private->y;
 
940
    }
 
941
 
 
942
  abs_pos_changed =
 
943
    private->abs_x != old_abs_x ||
 
944
    private->abs_y != old_abs_y;
 
945
 
 
946
  /* Update clip region based on:
 
947
   * parent clip
 
948
   * window size
 
949
   * siblings in parents above window
 
950
   */
 
951
  clip_region_changed = FALSE;
 
952
  if (recalculate_clip)
 
953
    {
 
954
      if (private->viewable)
 
955
        {
 
956
          /* Calculate visible region (sans children) in parent window coords */
 
957
          r.x = private->x;
 
958
          r.y = private->y;
 
959
          r.width = private->width;
 
960
          r.height = private->height;
 
961
          new_clip = gdk_region_rectangle (&r);
 
962
 
 
963
          if (!gdk_window_is_toplevel (private))
 
964
            {
 
965
              gdk_region_intersect (new_clip, private->parent->clip_region);
 
966
 
 
967
              /* Remove all overlapping children from parent.
 
968
               * Unless we're all native, because then we don't need to take
 
969
               * siblings into account since X does that clipping for us.
 
970
               * This makes things like SWT that modify the raw X stacking
 
971
               * order without GDKs knowledge work.
 
972
               */
 
973
              if (!_gdk_native_windows)
 
974
                remove_child_area (private->parent, private, FALSE, new_clip);
 
975
            }
 
976
 
 
977
          /* Convert from parent coords to window coords */
 
978
          gdk_region_offset (new_clip, -private->x, -private->y);
 
979
 
 
980
          if (private->shape)
 
981
            gdk_region_intersect (new_clip, private->shape);
 
982
        }
 
983
      else
 
984
        new_clip = gdk_region_new ();
 
985
 
 
986
      if (private->clip_region == NULL ||
 
987
          !gdk_region_equal (private->clip_region, new_clip))
 
988
        clip_region_changed = TRUE;
 
989
 
 
990
      if (private->clip_region)
 
991
        gdk_region_destroy (private->clip_region);
 
992
      private->clip_region = new_clip;
 
993
 
 
994
      old_clip_region_with_children = private->clip_region_with_children;
 
995
      private->clip_region_with_children = gdk_region_copy (private->clip_region);
 
996
      if (private->window_type != GDK_WINDOW_ROOT)
 
997
        remove_child_area (private, NULL, FALSE, private->clip_region_with_children);
 
998
 
 
999
      if (clip_region_changed ||
 
1000
          !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
 
1001
          private->clip_tag = new_region_tag ();
 
1002
 
 
1003
      if (old_clip_region_with_children)
 
1004
        gdk_region_destroy (old_clip_region_with_children);
 
1005
    }
 
1006
 
 
1007
  if (clip_region_changed)
 
1008
    {
 
1009
      GdkVisibilityState visibility;
 
1010
      gboolean fully_visible;
 
1011
 
 
1012
      if (gdk_region_empty (private->clip_region))
 
1013
        visibility = GDK_VISIBILITY_FULLY_OBSCURED;
 
1014
      else
 
1015
        {
 
1016
          if (private->shape)
 
1017
            {
 
1018
              fully_visible = gdk_region_equal (private->clip_region,
 
1019
                                                private->shape);
 
1020
            }
 
1021
          else
 
1022
            {
 
1023
              r.x = 0;
 
1024
              r.y = 0;
 
1025
              r.width = private->width;
 
1026
              r.height = private->height;
 
1027
              fully_visible = gdk_region_rect_equal (private->clip_region, &r);
 
1028
            }
 
1029
 
 
1030
          if (fully_visible)
 
1031
            visibility = GDK_VISIBILITY_UNOBSCURED;
 
1032
          else
 
1033
            visibility = GDK_VISIBILITY_PARTIAL;
 
1034
        }
 
1035
 
 
1036
      if (private->visibility != visibility)
 
1037
        {
 
1038
          private->visibility = visibility;
 
1039
          gdk_window_update_visibility (private);
 
1040
        }
 
1041
    }
 
1042
 
 
1043
  /* Update all children, recursively (except for root, where children are not exact). */
 
1044
  if ((abs_pos_changed || clip_region_changed || recalculate_children) &&
 
1045
      private->window_type != GDK_WINDOW_ROOT)
 
1046
    {
 
1047
      for (l = private->children; l; l = l->next)
 
1048
        {
 
1049
          child = l->data;
 
1050
          /* Only recalculate clip if the the clip region changed, otherwise
 
1051
           * there is no way the child clip region could change (its has not e.g. moved)
 
1052
           * Except if recalculate_children is set to force child updates
 
1053
           */
 
1054
          recompute_visible_regions_internal (child,
 
1055
                                              recalculate_clip && (clip_region_changed || recalculate_children),
 
1056
                                              FALSE, FALSE);
 
1057
        }
 
1058
    }
 
1059
 
 
1060
  if (clip_region_changed &&
 
1061
      should_apply_clip_as_shape (private))
 
1062
    apply_clip_as_shape (private);
 
1063
 
 
1064
  if (recalculate_siblings &&
 
1065
      !gdk_window_is_toplevel (private))
 
1066
    {
 
1067
      /* If we moved a child window in parent or changed the stacking order, then we
 
1068
       * need to recompute the visible area of all the other children in the parent
 
1069
       */
 
1070
      for (l = private->parent->children; l; l = l->next)
 
1071
        {
 
1072
          child = l->data;
 
1073
 
 
1074
          if (child != private)
 
1075
            recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
 
1076
        }
 
1077
 
 
1078
      /* We also need to recompute the _with_children clip for the parent */
 
1079
      recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
 
1080
    }
 
1081
 
 
1082
  if (private->cairo_surface)
 
1083
    {
 
1084
      int width, height;
 
1085
 
 
1086
      /* It would be nice if we had some cairo support here so we
 
1087
         could set the clip rect on the cairo surface */
 
1088
      width = private->abs_x + private->width;
 
1089
      height = private->abs_y + private->height;
 
1090
 
 
1091
      _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
 
1092
                                             width, height);
 
1093
      cairo_surface_set_device_offset (private->cairo_surface,
 
1094
                                       private->abs_x,
 
1095
                                       private->abs_y);
 
1096
    }
 
1097
}
 
1098
 
 
1099
/* Call this when private has changed in one or more of these ways:
 
1100
 *  size changed
 
1101
 *  window moved
 
1102
 *  new window added
 
1103
 *  stacking order of window changed
 
1104
 *  child deleted
 
1105
 *
 
1106
 * It will recalculate abs_x/y and the clip regions
 
1107
 *
 
1108
 * Unless the window didn't change stacking order or size/pos, pass in TRUE
 
1109
 * for recalculate_siblings. (Mostly used internally for the recursion)
 
1110
 *
 
1111
 * If a child window was removed (and you can't use that child for
 
1112
 * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
 
1113
 */
 
1114
static void
 
1115
recompute_visible_regions (GdkWindowObject *private,
 
1116
                           gboolean recalculate_siblings,
 
1117
                           gboolean recalculate_children)
 
1118
{
 
1119
  recompute_visible_regions_internal (private,
 
1120
                                      TRUE,
 
1121
                                      recalculate_siblings,
 
1122
                                      recalculate_children);
 
1123
}
 
1124
 
 
1125
void
 
1126
_gdk_window_update_size (GdkWindow *window)
 
1127
{
 
1128
  recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
 
1129
}
 
1130
 
 
1131
/* Find the native window that would be just above "child"
 
1132
 * in the native stacking order if "child" was a native window
 
1133
 * (it doesn't have to be native). If there is no such native
 
1134
 * window inside this native parent then NULL is returned.
 
1135
 * If child is NULL, find lowest native window in parent.
 
1136
 */
 
1137
static GdkWindowObject *
 
1138
find_native_sibling_above_helper (GdkWindowObject *parent,
 
1139
                                  GdkWindowObject *child)
 
1140
{
 
1141
  GdkWindowObject *w;
 
1142
  GList *l;
 
1143
 
 
1144
  if (child)
 
1145
    {
 
1146
      l = g_list_find (parent->children, child);
 
1147
      g_assert (l != NULL); /* Better be a child of its parent... */
 
1148
      l = l->prev; /* Start looking at the one above the child */
 
1149
    }
 
1150
  else
 
1151
    l = g_list_last (parent->children);
 
1152
 
 
1153
  for (; l != NULL; l = l->prev)
 
1154
    {
 
1155
      w = l->data;
 
1156
 
 
1157
      if (gdk_window_has_impl (w))
 
1158
        return w;
 
1159
 
 
1160
      g_assert (parent != w);
 
1161
      w = find_native_sibling_above_helper (w, NULL);
 
1162
      if (w)
 
1163
        return w;
 
1164
    }
 
1165
 
 
1166
  return NULL;
 
1167
}
 
1168
 
 
1169
 
 
1170
static GdkWindowObject *
 
1171
find_native_sibling_above (GdkWindowObject *parent,
 
1172
                           GdkWindowObject *child)
 
1173
{
 
1174
  GdkWindowObject *w;
 
1175
 
 
1176
  w = find_native_sibling_above_helper (parent, child);
 
1177
  if (w)
 
1178
    return w;
 
1179
 
 
1180
  if (gdk_window_has_impl (parent))
 
1181
    return NULL;
 
1182
  else
 
1183
    return find_native_sibling_above (parent->parent, parent);
 
1184
}
 
1185
 
 
1186
static GdkEventMask
 
1187
get_native_event_mask (GdkWindowObject *private)
 
1188
{
 
1189
  if (_gdk_native_windows ||
 
1190
      private->window_type == GDK_WINDOW_ROOT ||
 
1191
      private->window_type == GDK_WINDOW_FOREIGN)
 
1192
    return private->event_mask;
 
1193
  else
 
1194
    {
 
1195
      GdkEventMask mask;
 
1196
 
 
1197
      /* Do whatever the app asks to, since the app
 
1198
       * may be asking for weird things for native windows,
 
1199
       * but don't use motion hints as that may affect non-native
 
1200
       * child windows that don't want it. Also, we need to
 
1201
       * set all the app-specified masks since they will be picked
 
1202
       * up by any implicit grabs (i.e. if they were not set as
 
1203
       * native we would not get the events we need). */
 
1204
      mask = private->event_mask & ~GDK_POINTER_MOTION_HINT_MASK;
 
1205
 
 
1206
      /* We need thse for all native windows so we can
 
1207
         emulate events on children: */
 
1208
      mask |=
 
1209
        GDK_EXPOSURE_MASK |
 
1210
        GDK_VISIBILITY_NOTIFY_MASK |
 
1211
        GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK;
 
1212
 
 
1213
      /* Additionally we select for pointer and button events
 
1214
       * for toplevels as we need to get these to emulate
 
1215
       * them for non-native subwindows. Even though we don't
 
1216
       * select on them for all native windows we will get them
 
1217
       * as the events are propagated out to the first window
 
1218
       * that select for them.
 
1219
       * Not selecting for button press on all windows is an
 
1220
       * important thing, because in X only one client can do
 
1221
       * so, and we don't want to unexpectedly prevent another
 
1222
       * client from doing it.
 
1223
       *
 
1224
       * We also need to do the same if the app selects for button presses
 
1225
       * because then we will get implicit grabs for this window, and the
 
1226
       * event mask used for that grab is based on the rest of the mask
 
1227
       * for the window, but we might need more events than this window
 
1228
       * lists due to some non-native child window.
 
1229
       */
 
1230
      if (gdk_window_is_toplevel (private) ||
 
1231
          mask & GDK_BUTTON_PRESS_MASK)
 
1232
        mask |=
 
1233
          GDK_POINTER_MOTION_MASK |
 
1234
          GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
 
1235
          GDK_SCROLL_MASK;
 
1236
 
 
1237
      return mask;
 
1238
    }
 
1239
}
 
1240
 
 
1241
static GdkEventMask
 
1242
get_native_grab_event_mask (GdkEventMask grab_mask)
 
1243
{
 
1244
  /* Similar to the above but for pointer events only */
 
1245
  return
 
1246
    GDK_POINTER_MOTION_MASK |
 
1247
    GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
 
1248
    GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
 
1249
    GDK_SCROLL_MASK |
 
1250
    (grab_mask &
 
1251
     ~GDK_POINTER_MOTION_HINT_MASK);
 
1252
}
 
1253
 
 
1254
/* Puts the native window in the right order wrt the other native windows
 
1255
 * in the hierarchy, given the position it has in the client side data.
 
1256
 * This is useful if some operation changed the stacking order.
 
1257
 * This calls assumes the native window is now topmost in its native parent.
 
1258
 */
 
1259
static void
 
1260
sync_native_window_stack_position (GdkWindow *window)
 
1261
{
 
1262
  GdkWindowObject *above;
 
1263
  GdkWindowObject *private;
 
1264
  GdkWindowImplIface *impl_iface;
 
1265
  GList listhead = {0};
 
1266
 
 
1267
  private = (GdkWindowObject *) window;
 
1268
  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
1269
 
 
1270
  above = find_native_sibling_above (private->parent, private);
 
1271
  if (above)
 
1272
    {
 
1273
      listhead.data = window;
 
1274
      impl_iface->restack_under ((GdkWindow *)above,
 
1275
                                 &listhead);
 
1276
    }
 
1277
}
 
1278
 
 
1279
/**
 
1280
 * gdk_window_new:
 
1281
 * @parent: (allow-none): a #GdkWindow, or %NULL to create the window as a child of
 
1282
 *   the default root window for the default display.
 
1283
 * @attributes: attributes of the new window
 
1284
 * @attributes_mask: mask indicating which fields in @attributes are valid
 
1285
 *
 
1286
 * Creates a new #GdkWindow using the attributes from
 
1287
 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
 
1288
 * more details.  Note: to use this on displays other than the default
 
1289
 * display, @parent must be specified.
 
1290
 *
 
1291
 * Return value: (transfer none): the new #GdkWindow
 
1292
 **/
 
1293
GdkWindow*
 
1294
gdk_window_new (GdkWindow     *parent,
 
1295
                GdkWindowAttr *attributes,
 
1296
                gint           attributes_mask)
 
1297
{
 
1298
  GdkWindow *window;
 
1299
  GdkWindowObject *private;
 
1300
  GdkScreen *screen;
 
1301
  GdkVisual *visual;
 
1302
  int x, y;
 
1303
  gboolean native;
 
1304
  GdkEventMask event_mask;
 
1305
  GdkWindow *real_parent;
 
1306
 
 
1307
  g_return_val_if_fail (attributes != NULL, NULL);
 
1308
 
 
1309
  if (!parent)
 
1310
    {
 
1311
      GDK_NOTE (MULTIHEAD,
 
1312
                g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
 
1313
 
 
1314
      screen = gdk_screen_get_default ();
 
1315
      parent = gdk_screen_get_root_window (screen);
 
1316
    }
 
1317
  else
 
1318
    screen = gdk_drawable_get_screen (parent);
 
1319
 
 
1320
  g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
 
1321
 
 
1322
  if (GDK_WINDOW_DESTROYED (parent))
 
1323
    {
 
1324
      g_warning ("gdk_window_new(): parent is destroyed\n");
 
1325
      return NULL;
 
1326
    }
 
1327
 
 
1328
  if (attributes->window_type == GDK_WINDOW_OFFSCREEN &&
 
1329
      _gdk_native_windows)
 
1330
    {
 
1331
      g_warning ("Offscreen windows not supported with native-windows gdk");
 
1332
      return NULL;
 
1333
    }
 
1334
 
 
1335
  window = g_object_new (GDK_TYPE_WINDOW, NULL);
 
1336
  private = (GdkWindowObject *) window;
 
1337
 
 
1338
  /* Windows with a foreign parent are treated as if they are children
 
1339
   * of the root window, except for actual creation.
 
1340
   */
 
1341
  real_parent = parent;
 
1342
  if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
 
1343
    parent = gdk_screen_get_root_window (screen);
 
1344
 
 
1345
  private->parent = (GdkWindowObject *)parent;
 
1346
 
 
1347
  private->accept_focus = TRUE;
 
1348
  private->focus_on_map = TRUE;
 
1349
 
 
1350
  if (attributes_mask & GDK_WA_X)
 
1351
    x = attributes->x;
 
1352
  else
 
1353
    x = 0;
 
1354
 
 
1355
  if (attributes_mask & GDK_WA_Y)
 
1356
    y = attributes->y;
 
1357
  else
 
1358
    y = 0;
 
1359
 
 
1360
  private->x = x;
 
1361
  private->y = y;
 
1362
  private->width = (attributes->width > 1) ? (attributes->width) : (1);
 
1363
  private->height = (attributes->height > 1) ? (attributes->height) : (1);
 
1364
 
 
1365
#ifdef GDK_WINDOWING_X11
 
1366
  /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
 
1367
   * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
 
1368
   */
 
1369
  if (attributes->wclass == GDK_INPUT_ONLY &&
 
1370
      private->parent->window_type == GDK_WINDOW_ROOT &&
 
1371
      !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
 
1372
    {
 
1373
      g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
 
1374
      attributes->wclass = GDK_INPUT_OUTPUT;
 
1375
    }
 
1376
#endif
 
1377
 
 
1378
  if (attributes->wclass == GDK_INPUT_ONLY)
 
1379
    {
 
1380
      /* Backwards compatiblity - we've always ignored
 
1381
       * attributes->window_type for input-only windows
 
1382
       * before
 
1383
       */
 
1384
      if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
 
1385
        private->window_type = GDK_WINDOW_TEMP;
 
1386
      else
 
1387
        private->window_type = GDK_WINDOW_CHILD;
 
1388
    }
 
1389
  else
 
1390
    private->window_type = attributes->window_type;
 
1391
 
 
1392
  /* Sanity checks */
 
1393
  switch (private->window_type)
 
1394
    {
 
1395
    case GDK_WINDOW_TOPLEVEL:
 
1396
    case GDK_WINDOW_DIALOG:
 
1397
    case GDK_WINDOW_TEMP:
 
1398
    case GDK_WINDOW_OFFSCREEN:
 
1399
      if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
 
1400
        g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
 
1401
                   "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
 
1402
    case GDK_WINDOW_CHILD:
 
1403
      break;
 
1404
      break;
 
1405
    default:
 
1406
      g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
 
1407
      return NULL;
 
1408
    }
 
1409
 
 
1410
  if (attributes_mask & GDK_WA_VISUAL)
 
1411
    visual = attributes->visual;
 
1412
  else
 
1413
    visual = gdk_screen_get_system_visual (screen);
 
1414
 
 
1415
  private->event_mask = attributes->event_mask;
 
1416
 
 
1417
  if (attributes->wclass == GDK_INPUT_OUTPUT)
 
1418
    {
 
1419
      private->input_only = FALSE;
 
1420
      private->depth = visual->depth;
 
1421
 
 
1422
      private->bg_color.pixel = 0; /* TODO: BlackPixel (xdisplay, screen_x11->screen_num); */
 
1423
      private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
 
1424
 
 
1425
      private->bg_pixmap = NULL;
 
1426
    }
 
1427
  else
 
1428
    {
 
1429
      private->depth = 0;
 
1430
      private->input_only = TRUE;
 
1431
    }
 
1432
 
 
1433
  if (private->parent)
 
1434
    private->parent->children = g_list_prepend (private->parent->children, window);
 
1435
 
 
1436
  native = _gdk_native_windows; /* Default */
 
1437
  if (private->parent->window_type == GDK_WINDOW_ROOT)
 
1438
    native = TRUE; /* Always use native windows for toplevels */
 
1439
  else if (!private->input_only &&
 
1440
           ((attributes_mask & GDK_WA_COLORMAP &&
 
1441
             attributes->colormap != gdk_drawable_get_colormap ((GdkDrawable *)private->parent)) ||
 
1442
            (attributes_mask & GDK_WA_VISUAL &&
 
1443
             attributes->visual != gdk_drawable_get_visual ((GdkDrawable *)private->parent))))
 
1444
    native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
 
1445
 
 
1446
  if (gdk_window_is_offscreen (private))
 
1447
    {
 
1448
      _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
 
1449
      private->impl_window = private;
 
1450
    }
 
1451
  else if (native)
 
1452
    {
 
1453
      event_mask = get_native_event_mask (private);
 
1454
 
 
1455
      /* Create the impl */
 
1456
      _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
 
1457
      private->impl_window = private;
 
1458
 
 
1459
      /* This will put the native window topmost in the native parent, which may
 
1460
       * be wrong wrt other native windows in the non-native hierarchy, so restack */
 
1461
      if (!_gdk_window_has_impl (real_parent))
 
1462
        sync_native_window_stack_position (window);
 
1463
    }
 
1464
  else
 
1465
    {
 
1466
      private->impl_window = g_object_ref (private->parent->impl_window);
 
1467
      private->impl = g_object_ref (private->impl_window->impl);
 
1468
    }
 
1469
 
 
1470
  recompute_visible_regions (private, TRUE, FALSE);
 
1471
 
 
1472
  if (private->parent->window_type != GDK_WINDOW_ROOT)
 
1473
    {
 
1474
      /* Inherit redirection from parent */
 
1475
      private->redirect = private->parent->redirect;
 
1476
    }
 
1477
 
 
1478
  gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
 
1479
                                  (attributes->cursor) :
 
1480
                                  NULL));
 
1481
 
 
1482
  return window;
 
1483
}
 
1484
 
 
1485
static gboolean
 
1486
is_parent_of (GdkWindow *parent,
 
1487
              GdkWindow *child)
 
1488
{
 
1489
  GdkWindow *w;
 
1490
 
 
1491
  w = child;
 
1492
  while (w != NULL)
 
1493
    {
 
1494
      if (w == parent)
 
1495
        return TRUE;
 
1496
 
 
1497
      w = gdk_window_get_parent (w);
 
1498
    }
 
1499
 
 
1500
  return FALSE;
 
1501
}
 
1502
 
 
1503
static void
 
1504
change_impl (GdkWindowObject *private,
 
1505
             GdkWindowObject *impl_window,
 
1506
             GdkDrawable *new)
 
1507
{
 
1508
  GList *l;
 
1509
  GdkWindowObject *child;
 
1510
  GdkDrawable *old_impl;
 
1511
  GdkWindowObject *old_impl_window;
 
1512
 
 
1513
  old_impl = private->impl;
 
1514
  old_impl_window = private->impl_window;
 
1515
  if (private != impl_window)
 
1516
    private->impl_window = g_object_ref (impl_window);
 
1517
  else
 
1518
    private->impl_window = private;
 
1519
  private->impl = g_object_ref (new);
 
1520
  if (old_impl_window != private)
 
1521
    g_object_unref (old_impl_window);
 
1522
  g_object_unref (old_impl);
 
1523
 
 
1524
  for (l = private->children; l != NULL; l = l->next)
 
1525
    {
 
1526
      child = l->data;
 
1527
 
 
1528
      if (child->impl == old_impl)
 
1529
        change_impl (child, impl_window, new);
 
1530
    }
 
1531
}
 
1532
 
 
1533
static void
 
1534
reparent_to_impl (GdkWindowObject *private)
 
1535
{
 
1536
  GList *l;
 
1537
  GdkWindowObject *child;
 
1538
  gboolean show;
 
1539
  GdkWindowImplIface *impl_iface;
 
1540
 
 
1541
  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
1542
 
 
1543
  /* Enumerate in reverse order so we get the right order for the native
 
1544
     windows (first in childrens list is topmost, and reparent places on top) */
 
1545
  for (l = g_list_last (private->children); l != NULL; l = l->prev)
 
1546
    {
 
1547
      child = l->data;
 
1548
 
 
1549
      if (child->impl == private->impl)
 
1550
        reparent_to_impl (child);
 
1551
      else
 
1552
        {
 
1553
          show = impl_iface->reparent ((GdkWindow *)child,
 
1554
                                       (GdkWindow *)private,
 
1555
                                       child->x, child->y);
 
1556
          if (show)
 
1557
            gdk_window_show_unraised ((GdkWindow *)child);
 
1558
        }
 
1559
    }
 
1560
}
 
1561
 
 
1562
 
 
1563
/**
 
1564
 * gdk_window_reparent:
 
1565
 * @window: a #GdkWindow
 
1566
 * @new_parent: new parent to move @window into
 
1567
 * @x: X location inside the new parent
 
1568
 * @y: Y location inside the new parent
 
1569
 *
 
1570
 * Reparents @window into the given @new_parent. The window being
 
1571
 * reparented will be unmapped as a side effect.
 
1572
 *
 
1573
 **/
 
1574
void
 
1575
gdk_window_reparent (GdkWindow *window,
 
1576
                     GdkWindow *new_parent,
 
1577
                     gint       x,
 
1578
                     gint       y)
 
1579
{
 
1580
  GdkWindowObject *private;
 
1581
  GdkWindowObject *new_parent_private;
 
1582
  GdkWindowObject *old_parent;
 
1583
  GdkScreen *screen;
 
1584
  gboolean show, was_mapped, applied_clip_as_shape;
 
1585
  gboolean do_reparent_to_impl;
 
1586
  GdkEventMask old_native_event_mask;
 
1587
  GdkWindowImplIface *impl_iface;
 
1588
 
 
1589
  g_return_if_fail (GDK_IS_WINDOW (window));
 
1590
  g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
 
1591
  g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
 
1592
 
 
1593
  if (GDK_WINDOW_DESTROYED (window) ||
 
1594
      (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
 
1595
    return;
 
1596
 
 
1597
  screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
 
1598
  if (!new_parent)
 
1599
    new_parent = gdk_screen_get_root_window (screen);
 
1600
 
 
1601
  private = (GdkWindowObject *) window;
 
1602
  new_parent_private = (GdkWindowObject *)new_parent;
 
1603
 
 
1604
  /* No input-output children of input-only windows */
 
1605
  if (new_parent_private->input_only && !private->input_only)
 
1606
    return;
 
1607
 
 
1608
  /* Don't create loops in hierarchy */
 
1609
  if (is_parent_of (window, new_parent))
 
1610
    return;
 
1611
 
 
1612
  /* This might be wrong in the new parent, e.g. for non-native surfaces.
 
1613
     To make sure we're ok, just wipe it. */
 
1614
  gdk_window_drop_cairo_surface (private);
 
1615
 
 
1616
  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
1617
  old_parent = private->parent;
 
1618
 
 
1619
  /* Break up redirection if inherited */
 
1620
  if (private->redirect && private->redirect->redirected != private)
 
1621
    {
 
1622
      remove_redirect_from_children (private, private->redirect);
 
1623
      private->redirect = NULL;
 
1624
    }
 
1625
 
 
1626
  was_mapped = GDK_WINDOW_IS_MAPPED (window);
 
1627
  show = FALSE;
 
1628
 
 
1629
  /* Reparenting to toplevel. Ensure we have a native window so this can work */
 
1630
  if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
 
1631
      new_parent_private->window_type == GDK_WINDOW_FOREIGN)
 
1632
    gdk_window_ensure_native (window);
 
1633
 
 
1634
  applied_clip_as_shape = should_apply_clip_as_shape (private);
 
1635
 
 
1636
  old_native_event_mask = 0;
 
1637
  do_reparent_to_impl = FALSE;
 
1638
  if (gdk_window_has_impl (private))
 
1639
    {
 
1640
      old_native_event_mask = get_native_event_mask (private);
 
1641
      /* Native window */
 
1642
      show = impl_iface->reparent (window, new_parent, x, y);
 
1643
    }
 
1644
  else
 
1645
    {
 
1646
      /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
 
1647
      g_assert (new_parent_private->window_type != GDK_WINDOW_ROOT &&
 
1648
                new_parent_private->window_type != GDK_WINDOW_FOREIGN);
 
1649
 
 
1650
      show = was_mapped;
 
1651
      gdk_window_hide (window);
 
1652
 
 
1653
      do_reparent_to_impl = TRUE;
 
1654
      change_impl (private,
 
1655
                   new_parent_private->impl_window,
 
1656
                   new_parent_private->impl);
 
1657
    }
 
1658
 
 
1659
  /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
 
1660
   * the root window
 
1661
   */
 
1662
  if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
 
1663
    {
 
1664
      new_parent = gdk_screen_get_root_window (screen);
 
1665
      new_parent_private = (GdkWindowObject *)new_parent;
 
1666
    }
 
1667
 
 
1668
  if (old_parent)
 
1669
    old_parent->children = g_list_remove (old_parent->children, window);
 
1670
 
 
1671
  private->parent = new_parent_private;
 
1672
  private->x = x;
 
1673
  private->y = y;
 
1674
 
 
1675
  new_parent_private->children = g_list_prepend (new_parent_private->children, window);
 
1676
 
 
1677
  /* Switch the window type as appropriate */
 
1678
 
 
1679
  switch (GDK_WINDOW_TYPE (new_parent))
 
1680
    {
 
1681
    case GDK_WINDOW_ROOT:
 
1682
    case GDK_WINDOW_FOREIGN:
 
1683
      if (private->toplevel_window_type != -1)
 
1684
        GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
 
1685
      else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
 
1686
        GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
 
1687
      break;
 
1688
    case GDK_WINDOW_OFFSCREEN:
 
1689
    case GDK_WINDOW_TOPLEVEL:
 
1690
    case GDK_WINDOW_CHILD:
 
1691
    case GDK_WINDOW_DIALOG:
 
1692
    case GDK_WINDOW_TEMP:
 
1693
      if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
 
1694
          GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
 
1695
        {
 
1696
          /* Save the original window type so we can restore it if the
 
1697
           * window is reparented back to be a toplevel
 
1698
           */
 
1699
          private->toplevel_window_type = GDK_WINDOW_TYPE (window);
 
1700
          GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
 
1701
        }
 
1702
    }
 
1703
 
 
1704
  /* We might have changed window type for a native windows, so we
 
1705
     need to change the event mask too. */
 
1706
  if (gdk_window_has_impl (private))
 
1707
    {
 
1708
      GdkEventMask native_event_mask = get_native_event_mask (private);
 
1709
 
 
1710
      if (native_event_mask != old_native_event_mask)
 
1711
        impl_iface->set_events (window, native_event_mask);
 
1712
    }
 
1713
 
 
1714
  /* Inherit parent redirect if we don't have our own */
 
1715
  if (private->parent && private->redirect == NULL)
 
1716
    {
 
1717
      private->redirect = private->parent->redirect;
 
1718
      apply_redirect_to_children (private, private->redirect);
 
1719
    }
 
1720
 
 
1721
  _gdk_window_update_viewable (window);
 
1722
 
 
1723
  recompute_visible_regions (private, TRUE, FALSE);
 
1724
  if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
 
1725
    recompute_visible_regions (old_parent, FALSE, TRUE);
 
1726
 
 
1727
  /* We used to apply the clip as the shape, but no more.
 
1728
     Reset this to the real shape */
 
1729
  if (gdk_window_has_impl (private) &&
 
1730
      applied_clip_as_shape &&
 
1731
      !should_apply_clip_as_shape (private))
 
1732
    apply_shape (private, private->shape);
 
1733
 
 
1734
  if (do_reparent_to_impl)
 
1735
    reparent_to_impl (private);
 
1736
  else
 
1737
    {
 
1738
      /* The reparent will have put the native window topmost in the native parent,
 
1739
       * which may be wrong wrt other native windows in the non-native hierarchy,
 
1740
       * so restack */
 
1741
      if (!gdk_window_has_impl (new_parent_private))
 
1742
        sync_native_window_stack_position (window);
 
1743
    }
 
1744
 
 
1745
  if (show)
 
1746
    gdk_window_show_unraised (window);
 
1747
  else
 
1748
    _gdk_synthesize_crossing_events_for_geometry_change (window);
 
1749
}
 
1750
 
 
1751
static gboolean
 
1752
temporary_disable_extension_events (GdkWindowObject *window)
 
1753
{
 
1754
  GdkWindowObject *child;
 
1755
  GList *l;
 
1756
  gboolean res;
 
1757
 
 
1758
  if (window->extension_events != 0)
 
1759
    {
 
1760
      g_object_set_data (G_OBJECT (window),
 
1761
                         "gdk-window-extension-events",
 
1762
                         GINT_TO_POINTER (window->extension_events));
 
1763
      gdk_input_set_extension_events ((GdkWindow *)window, 0,
 
1764
                                      GDK_EXTENSION_EVENTS_NONE);
 
1765
    }
 
1766
  else
 
1767
    res = FALSE;
 
1768
 
 
1769
  for (l = window->children; l != NULL; l = l->next)
 
1770
    {
 
1771
      child = l->data;
 
1772
 
 
1773
      if (window->impl_window == child->impl_window)
 
1774
        res |= temporary_disable_extension_events (child);
 
1775
    }
 
1776
 
 
1777
  return res;
 
1778
}
 
1779
 
 
1780
static void
 
1781
reenable_extension_events (GdkWindowObject *window)
 
1782
{
 
1783
  GdkWindowObject *child;
 
1784
  GList *l;
 
1785
  int mask;
 
1786
 
 
1787
  mask = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window),
 
1788
                                              "gdk-window-extension-events"));
 
1789
 
 
1790
  if (mask != 0)
 
1791
    {
 
1792
      /* We don't have the mode here, so we pass in cursor.
 
1793
         This works with the current code since mode is not
 
1794
         stored except as part of the mask, and cursor doesn't
 
1795
         change the mask. */
 
1796
      gdk_input_set_extension_events ((GdkWindow *)window, mask,
 
1797
                                      GDK_EXTENSION_EVENTS_CURSOR);
 
1798
      g_object_set_data (G_OBJECT (window),
 
1799
                         "gdk-window-extension-events",
 
1800
                         NULL);
 
1801
    }
 
1802
 
 
1803
  for (l = window->children; l != NULL; l = l->next)
 
1804
    {
 
1805
      child = l->data;
 
1806
 
 
1807
      if (window->impl_window == child->impl_window)
 
1808
        reenable_extension_events (window);
 
1809
    }
 
1810
}
 
1811
 
 
1812
/**
 
1813
 * gdk_window_ensure_native:
 
1814
 * @window: a #GdkWindow
 
1815
 *
 
1816
 * Tries to ensure that there is a window-system native window for this
 
1817
 * GdkWindow. This may fail in some situations, returning %FALSE.
 
1818
 *
 
1819
 * Offscreen window and children of them can never have native windows.
 
1820
 *
 
1821
 * Some backends may not support native child windows.
 
1822
 *
 
1823
 * Returns: %TRUE if the window has a native window, %FALSE otherwise
 
1824
 *
 
1825
 * Since: 2.18
 
1826
 */
 
1827
gboolean
 
1828
gdk_window_ensure_native (GdkWindow *window)
 
1829
{
 
1830
  GdkWindowObject *private;
 
1831
  GdkWindowObject *impl_window;
 
1832
  GdkDrawable *new_impl, *old_impl;
 
1833
  GdkScreen *screen;
 
1834
  GdkVisual *visual;
 
1835
  GdkWindowAttr attributes;
 
1836
  GdkWindowObject *above;
 
1837
  GList listhead;
 
1838
  GdkWindowImplIface *impl_iface;
 
1839
  gboolean disabled_extension_events;
 
1840
 
 
1841
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
1842
 
 
1843
  if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
 
1844
      GDK_WINDOW_DESTROYED (window))
 
1845
    return FALSE;
 
1846
 
 
1847
  private = (GdkWindowObject *) window;
 
1848
 
 
1849
  impl_window = gdk_window_get_impl_window (private);
 
1850
 
 
1851
  if (gdk_window_is_offscreen (impl_window))
 
1852
    return FALSE; /* native in offscreens not supported */
 
1853
 
 
1854
  if (impl_window == private)
 
1855
    /* Already has an impl, and its not offscreen . */
 
1856
    return TRUE;
 
1857
 
 
1858
  /* Need to create a native window */
 
1859
 
 
1860
  /* First we disable any extension events on the window or its
 
1861
     descendants to handle the native input window moving */
 
1862
  disabled_extension_events = FALSE;
 
1863
  if (impl_window->input_window)
 
1864
    disabled_extension_events = temporary_disable_extension_events (private);
 
1865
 
 
1866
  gdk_window_drop_cairo_surface (private);
 
1867
 
 
1868
  screen = gdk_drawable_get_screen (window);
 
1869
  visual = gdk_drawable_get_visual (window);
 
1870
 
 
1871
  /* These fields are required in the attributes struct so we can't
 
1872
     ignore them by clearing a flag in the attributes mask */
 
1873
  attributes.wclass = private->input_only ? GDK_INPUT_ONLY : GDK_INPUT_OUTPUT;
 
1874
  attributes.width = private->width;
 
1875
  attributes.height = private->height;
 
1876
  attributes.window_type = private->window_type;
 
1877
 
 
1878
  attributes.colormap = gdk_drawable_get_colormap (window);
 
1879
 
 
1880
  old_impl = private->impl;
 
1881
  _gdk_window_impl_new (window, (GdkWindow *)private->parent,
 
1882
                        screen, visual,
 
1883
                        get_native_event_mask (private),
 
1884
                        &attributes, GDK_WA_COLORMAP);
 
1885
  new_impl = private->impl;
 
1886
 
 
1887
  private->impl = old_impl;
 
1888
  change_impl (private, private, new_impl);
 
1889
 
 
1890
  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
1891
 
 
1892
  /* Native window creation will put the native window topmost in the
 
1893
   * native parent, which may be wrong wrt the position of the previous
 
1894
   * non-native window wrt to the other non-native children, so correct this.
 
1895
   */
 
1896
  above = find_native_sibling_above (private->parent, private);
 
1897
  if (above)
 
1898
    {
 
1899
      listhead.data = window;
 
1900
      listhead.prev = NULL;
 
1901
      listhead.next = NULL;
 
1902
      impl_iface->restack_under ((GdkWindow *)above, &listhead);
 
1903
    }
 
1904
 
 
1905
  recompute_visible_regions (private, FALSE, FALSE);
 
1906
 
 
1907
  /* The shape may not have been set, as the clip region doesn't actually
 
1908
     change, so do it here manually */
 
1909
  if (should_apply_clip_as_shape (private))
 
1910
    apply_clip_as_shape (private);
 
1911
 
 
1912
  reparent_to_impl (private);
 
1913
 
 
1914
  if (!private->input_only)
 
1915
    {
 
1916
      impl_iface->set_background (window, &private->bg_color);
 
1917
      if (private->bg_pixmap != NULL)
 
1918
        impl_iface->set_back_pixmap (window, private->bg_pixmap);
 
1919
    }
 
1920
 
 
1921
  impl_iface->input_shape_combine_region (window,
 
1922
                                          private->input_shape,
 
1923
                                          0, 0);
 
1924
 
 
1925
  if (gdk_window_is_viewable (window))
 
1926
    impl_iface->show (window, FALSE);
 
1927
 
 
1928
  if (disabled_extension_events)
 
1929
    reenable_extension_events (private);
 
1930
 
 
1931
  return TRUE;
 
1932
}
 
1933
 
 
1934
/**
 
1935
 * _gdk_event_filter_unref:
 
1936
 * @window: (allow-none): A #GdkWindow, or %NULL to be the global window
 
1937
 * @filter: A window filter
 
1938
 *
 
1939
 * Release a reference to @filter.  Note this function may
 
1940
 * mutate the list storage, so you need to handle this
 
1941
 * if iterating over a list of filters.
 
1942
 */
 
1943
void
 
1944
_gdk_event_filter_unref (GdkWindow       *window,
 
1945
                         GdkEventFilter  *filter)
 
1946
{
 
1947
  GList **filters;
 
1948
  GList *tmp_list;
 
1949
 
 
1950
  if (window == NULL)
 
1951
    filters = &_gdk_default_filters;
 
1952
  else
 
1953
    {
 
1954
      GdkWindowObject *private;
 
1955
      private = (GdkWindowObject *) window;
 
1956
      filters = &private->filters;
 
1957
    }
 
1958
 
 
1959
  for (tmp_list = *filters; tmp_list; tmp_list = tmp_list->next)
 
1960
    {
 
1961
      GdkEventFilter *iter_filter = tmp_list->data;
 
1962
      GList *node;
 
1963
 
 
1964
      if (iter_filter != filter)
 
1965
        continue;
 
1966
 
 
1967
      g_assert (iter_filter->ref_count > 0);
 
1968
 
 
1969
      filter->ref_count--;
 
1970
      if (filter->ref_count != 0)
 
1971
        continue;
 
1972
 
 
1973
      node = tmp_list;
 
1974
      tmp_list = tmp_list->next;
 
1975
 
 
1976
      *filters = g_list_remove_link (*filters, node);
 
1977
      g_free (filter);
 
1978
      g_list_free_1 (node);
 
1979
    }
 
1980
}
 
1981
 
 
1982
static void
 
1983
window_remove_filters (GdkWindow *window)
 
1984
{
 
1985
  GdkWindowObject *obj = (GdkWindowObject*) window;
 
1986
  while (obj->filters)
 
1987
    _gdk_event_filter_unref (window, obj->filters->data);
 
1988
}
 
1989
 
 
1990
/**
 
1991
 * _gdk_window_destroy_hierarchy:
 
1992
 * @window: a #GdkWindow
 
1993
 * @recursing: If TRUE, then this is being called because a parent
 
1994
 *            was destroyed.
 
1995
 * @recursing_native: If TRUE, then this is being called because a native parent
 
1996
 *            was destroyed. This generally means that the call to the
 
1997
 *            windowing system to destroy the window can be omitted, since
 
1998
 *            it will be destroyed as a result of the parent being destroyed.
 
1999
 *            Unless @foreign_destroy.
 
2000
 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
 
2001
 *            external agency. The window has already been destroyed and no
 
2002
 *            windowing system calls should be made. (This may never happen
 
2003
 *            for some windowing systems.)
 
2004
 *
 
2005
 * Internal function to destroy a window. Like gdk_window_destroy(),
 
2006
 * but does not drop the reference count created by gdk_window_new().
 
2007
 **/
 
2008
static void
 
2009
_gdk_window_destroy_hierarchy (GdkWindow *window,
 
2010
                               gboolean   recursing,
 
2011
                               gboolean   recursing_native,
 
2012
                               gboolean   foreign_destroy)
 
2013
{
 
2014
  GdkWindowObject *private;
 
2015
  GdkWindowObject *temp_private;
 
2016
  GdkWindowImplIface *impl_iface;
 
2017
  GdkWindow *temp_window;
 
2018
  GdkScreen *screen;
 
2019
  GdkDisplay *display;
 
2020
  GList *children;
 
2021
  GList *tmp;
 
2022
 
 
2023
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2024
 
 
2025
  private = (GdkWindowObject*) window;
 
2026
 
 
2027
  if (GDK_WINDOW_DESTROYED (window))
 
2028
    return;
 
2029
 
 
2030
  display = gdk_drawable_get_display (GDK_DRAWABLE (window));
 
2031
  screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
 
2032
  temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
 
2033
  if (temp_window == window)
 
2034
    g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
 
2035
 
 
2036
 
 
2037
  switch (private->window_type)
 
2038
    {
 
2039
    case GDK_WINDOW_ROOT:
 
2040
      if (!screen->closed)
 
2041
        {
 
2042
          g_error ("attempted to destroy root window");
 
2043
          break;
 
2044
        }
 
2045
      /* else fall thru */
 
2046
    case GDK_WINDOW_TOPLEVEL:
 
2047
    case GDK_WINDOW_CHILD:
 
2048
    case GDK_WINDOW_DIALOG:
 
2049
    case GDK_WINDOW_TEMP:
 
2050
    case GDK_WINDOW_FOREIGN:
 
2051
    case GDK_WINDOW_OFFSCREEN:
 
2052
      if (private->window_type == GDK_WINDOW_FOREIGN && !foreign_destroy)
 
2053
        {
 
2054
          /* Logically, it probably makes more sense to send
 
2055
           * a "destroy yourself" message to the foreign window
 
2056
           * whether or not it's in our hierarchy; but for historical
 
2057
           * reasons, we only send "destroy yourself" messages to
 
2058
           * foreign windows in our hierarchy.
 
2059
           */
 
2060
          if (private->parent)
 
2061
            _gdk_windowing_window_destroy_foreign (window);
 
2062
 
 
2063
          /* Also for historical reasons, we remove any filters
 
2064
           * on a foreign window when it or a parent is destroyed;
 
2065
           * this likely causes problems if two separate portions
 
2066
           * of code are maintaining filter lists on a foreign window.
 
2067
           */
 
2068
          window_remove_filters (window);
 
2069
        }
 
2070
      else
 
2071
        {
 
2072
          if (private->parent)
 
2073
            {
 
2074
              GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
 
2075
 
 
2076
              if (parent_private->children)
 
2077
                parent_private->children = g_list_remove (parent_private->children, window);
 
2078
 
 
2079
              if (!recursing &&
 
2080
                  GDK_WINDOW_IS_MAPPED (window))
 
2081
                {
 
2082
                  recompute_visible_regions (private, TRUE, FALSE);
 
2083
                  gdk_window_invalidate_in_parent (private);
 
2084
                }
 
2085
            }
 
2086
 
 
2087
          gdk_window_free_paint_stack (window);
 
2088
 
 
2089
          if (private->bg_pixmap &&
 
2090
              private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
 
2091
              private->bg_pixmap != GDK_NO_BG)
 
2092
            {
 
2093
              g_object_unref (private->bg_pixmap);
 
2094
              private->bg_pixmap = NULL;
 
2095
            }
 
2096
 
 
2097
          if (private->background)
 
2098
            {
 
2099
              cairo_pattern_destroy (private->background);
 
2100
              private->background = NULL;
 
2101
            }
 
2102
 
 
2103
          if (private->window_type == GDK_WINDOW_FOREIGN)
 
2104
            g_assert (private->children == NULL);
 
2105
          else
 
2106
            {
 
2107
              children = tmp = private->children;
 
2108
              private->children = NULL;
 
2109
 
 
2110
              while (tmp)
 
2111
                {
 
2112
                  temp_window = tmp->data;
 
2113
                  tmp = tmp->next;
 
2114
 
 
2115
                  temp_private = (GdkWindowObject*) temp_window;
 
2116
                  if (temp_private)
 
2117
                    _gdk_window_destroy_hierarchy (temp_window,
 
2118
                                                   TRUE,
 
2119
                                                   recursing_native || gdk_window_has_impl (private),
 
2120
                                                   foreign_destroy);
 
2121
                }
 
2122
 
 
2123
              g_list_free (children);
 
2124
            }
 
2125
 
 
2126
          _gdk_window_clear_update_area (window);
 
2127
 
 
2128
          gdk_window_drop_cairo_surface (private);
 
2129
 
 
2130
          impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
2131
 
 
2132
          if (private->extension_events)
 
2133
            impl_iface->input_window_destroy (window);
 
2134
 
 
2135
          if (gdk_window_has_impl (private))
 
2136
            impl_iface->destroy (window, recursing_native,
 
2137
                                 foreign_destroy);
 
2138
          else
 
2139
            {
 
2140
              /* hide to make sure we repaint and break grabs */
 
2141
              gdk_window_hide (window);
 
2142
            }
 
2143
 
 
2144
          private->state |= GDK_WINDOW_STATE_WITHDRAWN;
 
2145
          private->parent = NULL;
 
2146
          private->destroyed = TRUE;
 
2147
 
 
2148
          window_remove_filters (window);
 
2149
 
 
2150
          gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
 
2151
 
 
2152
          /* If we own the redirect, free it */
 
2153
          if (private->redirect && private->redirect->redirected == private)
 
2154
            gdk_window_redirect_free (private->redirect);
 
2155
 
 
2156
          private->redirect = NULL;
 
2157
 
 
2158
          if (display->pointer_info.toplevel_under_pointer == window)
 
2159
            {
 
2160
              g_object_unref (display->pointer_info.toplevel_under_pointer);
 
2161
              display->pointer_info.toplevel_under_pointer = NULL;
 
2162
            }
 
2163
 
 
2164
          if (private->clip_region)
 
2165
            {
 
2166
              gdk_region_destroy (private->clip_region);
 
2167
              private->clip_region = NULL;
 
2168
            }
 
2169
 
 
2170
          if (private->clip_region_with_children)
 
2171
            {
 
2172
              gdk_region_destroy (private->clip_region_with_children);
 
2173
              private->clip_region_with_children = NULL;
 
2174
            }
 
2175
 
 
2176
          if (private->outstanding_moves)
 
2177
            {
 
2178
              g_list_foreach (private->outstanding_moves, (GFunc)gdk_window_region_move_free, NULL);
 
2179
              g_list_free (private->outstanding_moves);
 
2180
              private->outstanding_moves = NULL;
 
2181
            }
 
2182
        }
 
2183
      break;
 
2184
    }
 
2185
}
 
2186
 
 
2187
/**
 
2188
 * _gdk_window_destroy:
 
2189
 * @window: a #GdkWindow
 
2190
 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
 
2191
 *            external agency. The window has already been destroyed and no
 
2192
 *            windowing system calls should be made. (This may never happen
 
2193
 *            for some windowing systems.)
 
2194
 *
 
2195
 * Internal function to destroy a window. Like gdk_window_destroy(),
 
2196
 * but does not drop the reference count created by gdk_window_new().
 
2197
 **/
 
2198
void
 
2199
_gdk_window_destroy (GdkWindow *window,
 
2200
                     gboolean   foreign_destroy)
 
2201
{
 
2202
  _gdk_window_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
 
2203
}
 
2204
 
 
2205
/**
 
2206
 * gdk_window_destroy:
 
2207
 * @window: a #GdkWindow
 
2208
 *
 
2209
 * Destroys the window system resources associated with @window and decrements @window's
 
2210
 * reference count. The window system resources for all children of @window are also
 
2211
 * destroyed, but the children's reference counts are not decremented.
 
2212
 *
 
2213
 * Note that a window will not be destroyed automatically when its reference count
 
2214
 * reaches zero. You must call this function yourself before that happens.
 
2215
 *
 
2216
 **/
 
2217
void
 
2218
gdk_window_destroy (GdkWindow *window)
 
2219
{
 
2220
  _gdk_window_destroy_hierarchy (window, FALSE, FALSE, FALSE);
 
2221
  g_object_unref (window);
 
2222
}
 
2223
 
 
2224
/**
 
2225
 * gdk_window_set_user_data:
 
2226
 * @window: a #GdkWindow
 
2227
 * @user_data: user data
 
2228
 *
 
2229
 * For most purposes this function is deprecated in favor of
 
2230
 * g_object_set_data(). However, for historical reasons GTK+ stores
 
2231
 * the #GtkWidget that owns a #GdkWindow as user data on the
 
2232
 * #GdkWindow. So, custom widget implementations should use
 
2233
 * this function for that. If GTK+ receives an event for a #GdkWindow,
 
2234
 * and the user data for the window is non-%NULL, GTK+ will assume the
 
2235
 * user data is a #GtkWidget, and forward the event to that widget.
 
2236
 *
 
2237
 **/
 
2238
void
 
2239
gdk_window_set_user_data (GdkWindow *window,
 
2240
                          gpointer   user_data)
 
2241
{
 
2242
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2243
 
 
2244
  ((GdkWindowObject*)window)->user_data = user_data;
 
2245
}
 
2246
 
 
2247
/**
 
2248
 * gdk_window_get_user_data:
 
2249
 * @window: a #GdkWindow
 
2250
 * @data: (out): return location for user data
 
2251
 *
 
2252
 * Retrieves the user data for @window, which is normally the widget
 
2253
 * that @window belongs to. See gdk_window_set_user_data().
 
2254
 *
 
2255
 **/
 
2256
void
 
2257
gdk_window_get_user_data (GdkWindow *window,
 
2258
                          gpointer  *data)
 
2259
{
 
2260
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2261
 
 
2262
  *data = ((GdkWindowObject*)window)->user_data;
 
2263
}
 
2264
 
 
2265
/**
 
2266
 * gdk_window_get_window_type:
 
2267
 * @window: a #GdkWindow
 
2268
 *
 
2269
 * Gets the type of the window. See #GdkWindowType.
 
2270
 *
 
2271
 * Return value: type of window
 
2272
 **/
 
2273
GdkWindowType
 
2274
gdk_window_get_window_type (GdkWindow *window)
 
2275
{
 
2276
  g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
 
2277
 
 
2278
  return GDK_WINDOW_TYPE (window);
 
2279
}
 
2280
 
 
2281
/**
 
2282
 * gdk_window_is_destroyed:
 
2283
 * @window: a #GdkWindow
 
2284
 *
 
2285
 * Check to see if a window is destroyed..
 
2286
 *
 
2287
 * Return value: %TRUE if the window is destroyed
 
2288
 *
 
2289
 * Since: 2.18
 
2290
 **/
 
2291
gboolean
 
2292
gdk_window_is_destroyed (GdkWindow *window)
 
2293
{
 
2294
  return GDK_WINDOW_DESTROYED (window);
 
2295
}
 
2296
 
 
2297
static void
 
2298
to_embedder (GdkWindowObject *window,
 
2299
             gdouble          offscreen_x,
 
2300
             gdouble          offscreen_y,
 
2301
             gdouble         *embedder_x,
 
2302
             gdouble         *embedder_y)
 
2303
{
 
2304
  g_signal_emit (window, signals[TO_EMBEDDER], 0,
 
2305
                 offscreen_x, offscreen_y,
 
2306
                 embedder_x, embedder_y);
 
2307
}
 
2308
 
 
2309
static void
 
2310
from_embedder (GdkWindowObject *window,
 
2311
               gdouble          embedder_x,
 
2312
               gdouble          embedder_y,
 
2313
               gdouble         *offscreen_x,
 
2314
               gdouble         *offscreen_y)
 
2315
{
 
2316
  g_signal_emit (window, signals[FROM_EMBEDDER], 0,
 
2317
                 embedder_x, embedder_y,
 
2318
                 offscreen_x, offscreen_y);
 
2319
}
 
2320
 
 
2321
/**
 
2322
 * gdk_window_has_native:
 
2323
 * @window: a #GdkWindow
 
2324
 *
 
2325
 * Checks whether the window has a native window or not. Note that
 
2326
 * you can use gdk_window_ensure_native() if a native window is needed.
 
2327
 *
 
2328
 * Returns: %TRUE if the %window has a native window, %FALSE otherwise.
 
2329
 *
 
2330
 * Since: 2.22
 
2331
 */
 
2332
gboolean
 
2333
gdk_window_has_native (GdkWindow *window)
 
2334
{
 
2335
  GdkWindowObject *w;
 
2336
 
 
2337
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
2338
 
 
2339
  w = GDK_WINDOW_OBJECT (window);
 
2340
 
 
2341
  return w->parent == NULL || w->parent->impl != w->impl;
 
2342
}
 
2343
 
 
2344
/**
 
2345
 * gdk_window_get_position:
 
2346
 * @window: a #GdkWindow
 
2347
 * @x: (out) (allow-none): X coordinate of window
 
2348
 * @y: (out) (allow-none): Y coordinate of window
 
2349
 *
 
2350
 * Obtains the position of the window as reported in the
 
2351
 * most-recently-processed #GdkEventConfigure. Contrast with
 
2352
 * gdk_window_get_geometry() which queries the X server for the
 
2353
 * current window position, regardless of which events have been
 
2354
 * received or processed.
 
2355
 *
 
2356
 * The position coordinates are relative to the window's parent window.
 
2357
 *
 
2358
 **/
 
2359
void
 
2360
gdk_window_get_position (GdkWindow *window,
 
2361
                         gint      *x,
 
2362
                         gint      *y)
 
2363
{
 
2364
  GdkWindowObject *obj;
 
2365
 
 
2366
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2367
 
 
2368
  obj = (GdkWindowObject*) window;
 
2369
 
 
2370
  if (x)
 
2371
    *x = obj->x;
 
2372
  if (y)
 
2373
    *y = obj->y;
 
2374
}
 
2375
 
 
2376
/**
 
2377
 * gdk_window_get_parent:
 
2378
 * @window: a #GdkWindow
 
2379
 *
 
2380
 * Obtains the parent of @window, as known to GDK. Does not query the
 
2381
 * X server; thus this returns the parent as passed to gdk_window_new(),
 
2382
 * not the actual parent. This should never matter unless you're using
 
2383
 * Xlib calls mixed with GDK calls on the X11 platform. It may also
 
2384
 * matter for toplevel windows, because the window manager may choose
 
2385
 * to reparent them.
 
2386
 *
 
2387
 * Note that you should use gdk_window_get_effective_parent() when
 
2388
 * writing generic code that walks up a window hierarchy, because
 
2389
 * gdk_window_get_parent() will most likely not do what you expect if
 
2390
 * there are offscreen windows in the hierarchy.
 
2391
 *
 
2392
 * Return value: parent of @window
 
2393
 **/
 
2394
GdkWindow*
 
2395
gdk_window_get_parent (GdkWindow *window)
 
2396
{
 
2397
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
2398
 
 
2399
  return (GdkWindow*) ((GdkWindowObject*) window)->parent;
 
2400
}
 
2401
 
 
2402
/**
 
2403
 * gdk_window_get_effective_parent:
 
2404
 * @window: a #GdkWindow
 
2405
 *
 
2406
 * Obtains the parent of @window, as known to GDK. Works like
 
2407
 * gdk_window_get_parent() for normal windows, but returns the
 
2408
 * window's embedder for offscreen windows.
 
2409
 *
 
2410
 * See also: gdk_offscreen_window_get_embedder()
 
2411
 *
 
2412
 * Return value: effective parent of @window
 
2413
 *
 
2414
 * Since: 2.22
 
2415
 **/
 
2416
GdkWindow *
 
2417
gdk_window_get_effective_parent (GdkWindow *window)
 
2418
{
 
2419
  GdkWindowObject *obj;
 
2420
 
 
2421
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
2422
 
 
2423
  obj = (GdkWindowObject *)window;
 
2424
 
 
2425
  if (gdk_window_is_offscreen (obj))
 
2426
    return gdk_offscreen_window_get_embedder (window);
 
2427
  else
 
2428
    return (GdkWindow *) obj->parent;
 
2429
}
 
2430
 
 
2431
/**
 
2432
 * gdk_window_get_toplevel:
 
2433
 * @window: a #GdkWindow
 
2434
 *
 
2435
 * Gets the toplevel window that's an ancestor of @window.
 
2436
 *
 
2437
 * Any window type but %GDK_WINDOW_CHILD is considered a
 
2438
 * toplevel window, as is a %GDK_WINDOW_CHILD window that
 
2439
 * has a root window as parent.
 
2440
 *
 
2441
 * Note that you should use gdk_window_get_effective_toplevel() when
 
2442
 * you want to get to a window's toplevel as seen on screen, because
 
2443
 * gdk_window_get_toplevel() will most likely not do what you expect
 
2444
 * if there are offscreen windows in the hierarchy.
 
2445
 *
 
2446
 * Return value: the toplevel window containing @window
 
2447
 **/
 
2448
GdkWindow *
 
2449
gdk_window_get_toplevel (GdkWindow *window)
 
2450
{
 
2451
  GdkWindowObject *obj;
 
2452
 
 
2453
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
2454
 
 
2455
  obj = (GdkWindowObject *)window;
 
2456
 
 
2457
  while (obj->window_type == GDK_WINDOW_CHILD)
 
2458
    {
 
2459
      if (gdk_window_is_toplevel (obj))
 
2460
        break;
 
2461
      obj = obj->parent;
 
2462
    }
 
2463
 
 
2464
  return GDK_WINDOW (obj);
 
2465
}
 
2466
 
 
2467
/**
 
2468
 * gdk_window_get_effective_toplevel:
 
2469
 * @window: a #GdkWindow
 
2470
 *
 
2471
 * Gets the toplevel window that's an ancestor of @window.
 
2472
 *
 
2473
 * Works like gdk_window_get_toplevel(), but treats an offscreen window's
 
2474
 * embedder as its parent, using gdk_window_get_effective_parent().
 
2475
 *
 
2476
 * See also: gdk_offscreen_window_get_embedder()
 
2477
 *
 
2478
 * Return value: the effective toplevel window containing @window
 
2479
 *
 
2480
 * Since: 2.22
 
2481
 **/
 
2482
GdkWindow *
 
2483
gdk_window_get_effective_toplevel (GdkWindow *window)
 
2484
{
 
2485
  GdkWindow *parent;
 
2486
 
 
2487
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
2488
 
 
2489
  while ((parent = gdk_window_get_effective_parent (window)) != NULL &&
 
2490
         (gdk_window_get_window_type (parent) != GDK_WINDOW_ROOT))
 
2491
    window = parent;
 
2492
 
 
2493
  return window;
 
2494
}
 
2495
 
 
2496
/**
 
2497
 * gdk_window_get_children:
 
2498
 * @window: a #GdkWindow
 
2499
 *
 
2500
 * Gets the list of children of @window known to GDK.
 
2501
 * This function only returns children created via GDK,
 
2502
 * so for example it's useless when used with the root window;
 
2503
 * it only returns windows an application created itself.
 
2504
 *
 
2505
 * The returned list must be freed, but the elements in the
 
2506
 * list need not be.
 
2507
 *
 
2508
 * Return value: (transfer container) (element-type GdkWindow):
 
2509
 *     list of child windows inside @window
 
2510
 **/
 
2511
GList*
 
2512
gdk_window_get_children (GdkWindow *window)
 
2513
{
 
2514
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
2515
 
 
2516
  if (GDK_WINDOW_DESTROYED (window))
 
2517
    return NULL;
 
2518
 
 
2519
  return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
 
2520
}
 
2521
 
 
2522
/**
 
2523
 * gdk_window_peek_children:
 
2524
 * @window: a #GdkWindow
 
2525
 *
 
2526
 * Like gdk_window_get_children(), but does not copy the list of
 
2527
 * children, so the list does not need to be freed.
 
2528
 *
 
2529
 * Return value: (transfer none) (element-type GdkWindow):
 
2530
 *     a reference to the list of child windows in @window
 
2531
 **/
 
2532
GList *
 
2533
gdk_window_peek_children (GdkWindow *window)
 
2534
{
 
2535
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
2536
 
 
2537
  if (GDK_WINDOW_DESTROYED (window))
 
2538
    return NULL;
 
2539
 
 
2540
  return GDK_WINDOW_OBJECT (window)->children;
 
2541
}
 
2542
 
 
2543
/**
 
2544
 * gdk_window_add_filter:
 
2545
 * @window: a #GdkWindow
 
2546
 * @function: filter callback
 
2547
 * @data: data to pass to filter callback
 
2548
 *
 
2549
 * Adds an event filter to @window, allowing you to intercept events
 
2550
 * before they reach GDK. This is a low-level operation and makes it
 
2551
 * easy to break GDK and/or GTK+, so you have to know what you're
 
2552
 * doing. Pass %NULL for @window to get all events for all windows,
 
2553
 * instead of events for a specific window.
 
2554
 *
 
2555
 * See gdk_display_add_client_message_filter() if you are interested
 
2556
 * in X ClientMessage events.
 
2557
 **/
 
2558
void
 
2559
gdk_window_add_filter (GdkWindow     *window,
 
2560
                       GdkFilterFunc  function,
 
2561
                       gpointer       data)
 
2562
{
 
2563
  GdkWindowObject *private;
 
2564
  GList *tmp_list;
 
2565
  GdkEventFilter *filter;
 
2566
 
 
2567
  g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
 
2568
 
 
2569
  private = (GdkWindowObject*) window;
 
2570
  if (private && GDK_WINDOW_DESTROYED (window))
 
2571
    return;
 
2572
 
 
2573
  /* Filters are for the native events on the native window, so
 
2574
     ensure there is a native window. */
 
2575
  if (window)
 
2576
    gdk_window_ensure_native (window);
 
2577
 
 
2578
  if (private)
 
2579
    tmp_list = private->filters;
 
2580
  else
 
2581
    tmp_list = _gdk_default_filters;
 
2582
 
 
2583
  while (tmp_list)
 
2584
    {
 
2585
      filter = (GdkEventFilter *)tmp_list->data;
 
2586
      if ((filter->function == function) && (filter->data == data))
 
2587
        {
 
2588
          filter->ref_count++;
 
2589
          return;
 
2590
        }
 
2591
      tmp_list = tmp_list->next;
 
2592
    }
 
2593
 
 
2594
  filter = g_new (GdkEventFilter, 1);
 
2595
  filter->function = function;
 
2596
  filter->data = data;
 
2597
  filter->ref_count = 1;
 
2598
  filter->flags = 0;
 
2599
 
 
2600
  if (private)
 
2601
    private->filters = g_list_append (private->filters, filter);
 
2602
  else
 
2603
    _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
 
2604
}
 
2605
 
 
2606
/**
 
2607
 * gdk_window_remove_filter:
 
2608
 * @window: a #GdkWindow
 
2609
 * @function: previously-added filter function
 
2610
 * @data: user data for previously-added filter function
 
2611
 *
 
2612
 * Remove a filter previously added with gdk_window_add_filter().
 
2613
 *
 
2614
 **/
 
2615
void
 
2616
gdk_window_remove_filter (GdkWindow     *window,
 
2617
                          GdkFilterFunc  function,
 
2618
                          gpointer       data)
 
2619
{
 
2620
  GdkWindowObject *private;
 
2621
  GList *tmp_list, *node;
 
2622
  GdkEventFilter *filter;
 
2623
 
 
2624
  g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
 
2625
 
 
2626
  private = (GdkWindowObject*) window;
 
2627
 
 
2628
  if (private)
 
2629
    tmp_list = private->filters;
 
2630
  else
 
2631
    tmp_list = _gdk_default_filters;
 
2632
 
 
2633
  while (tmp_list)
 
2634
    {
 
2635
      filter = (GdkEventFilter *)tmp_list->data;
 
2636
      node = tmp_list;
 
2637
      tmp_list = tmp_list->next;
 
2638
 
 
2639
      if ((filter->function == function) && (filter->data == data))
 
2640
        {
 
2641
          filter->flags |= GDK_EVENT_FILTER_REMOVED;
 
2642
          _gdk_event_filter_unref (window, filter);
 
2643
 
 
2644
          return;
 
2645
        }
 
2646
    }
 
2647
}
 
2648
 
 
2649
/**
 
2650
 * gdk_screen_get_toplevel_windows:
 
2651
 * @screen: The #GdkScreen where the toplevels are located.
 
2652
 *
 
2653
 * Obtains a list of all toplevel windows known to GDK on the screen @screen.
 
2654
 * A toplevel window is a child of the root window (see
 
2655
 * gdk_get_default_root_window()).
 
2656
 *
 
2657
 * The returned list should be freed with g_list_free(), but
 
2658
 * its elements need not be freed.
 
2659
 *
 
2660
 * Return value: (transfer container) (element-type GdkWindow):
 
2661
 *     list of toplevel windows, free with g_list_free()
 
2662
 *
 
2663
 * Since: 2.2
 
2664
 **/
 
2665
GList *
 
2666
gdk_screen_get_toplevel_windows (GdkScreen *screen)
 
2667
{
 
2668
  GdkWindow * root_window;
 
2669
  GList *new_list = NULL;
 
2670
  GList *tmp_list;
 
2671
 
 
2672
  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
 
2673
 
 
2674
  root_window = gdk_screen_get_root_window (screen);
 
2675
 
 
2676
  tmp_list = ((GdkWindowObject *)root_window)->children;
 
2677
  while (tmp_list)
 
2678
    {
 
2679
      GdkWindowObject *w = tmp_list->data;
 
2680
 
 
2681
      if (w->window_type != GDK_WINDOW_FOREIGN)
 
2682
        new_list = g_list_prepend (new_list, w);
 
2683
      tmp_list = tmp_list->next;
 
2684
    }
 
2685
 
 
2686
  return new_list;
 
2687
}
 
2688
 
 
2689
/**
 
2690
 * gdk_window_get_toplevels:
 
2691
 *
 
2692
 * Obtains a list of all toplevel windows known to GDK on the default
 
2693
 * screen (see gdk_screen_get_toplevel_windows()).
 
2694
 * A toplevel window is a child of the root window (see
 
2695
 * gdk_get_default_root_window()).
 
2696
 *
 
2697
 * The returned list should be freed with g_list_free(), but
 
2698
 * its elements need not be freed.
 
2699
 *
 
2700
 * Return value: list of toplevel windows, free with g_list_free()
 
2701
 *
 
2702
 * Deprecated: 2.16: Use gdk_screen_get_toplevel_windows() instead.
 
2703
 */
 
2704
GList *
 
2705
gdk_window_get_toplevels (void)
 
2706
{
 
2707
  return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
 
2708
}
 
2709
 
 
2710
/**
 
2711
 * gdk_window_is_visible:
 
2712
 * @window: a #GdkWindow
 
2713
 *
 
2714
 * Checks whether the window has been mapped (with gdk_window_show() or
 
2715
 * gdk_window_show_unraised()).
 
2716
 *
 
2717
 * Return value: %TRUE if the window is mapped
 
2718
 **/
 
2719
gboolean
 
2720
gdk_window_is_visible (GdkWindow *window)
 
2721
{
 
2722
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
2723
 
 
2724
  return GDK_WINDOW_IS_MAPPED (window);
 
2725
}
 
2726
 
 
2727
/**
 
2728
 * gdk_window_is_viewable:
 
2729
 * @window: a #GdkWindow
 
2730
 *
 
2731
 * Check if the window and all ancestors of the window are
 
2732
 * mapped. (This is not necessarily "viewable" in the X sense, since
 
2733
 * we only check as far as we have GDK window parents, not to the root
 
2734
 * window.)
 
2735
 *
 
2736
 * Return value: %TRUE if the window is viewable
 
2737
 **/
 
2738
gboolean
 
2739
gdk_window_is_viewable (GdkWindow *window)
 
2740
{
 
2741
  GdkWindowObject *private = (GdkWindowObject *)window;
 
2742
 
 
2743
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
2744
 
 
2745
  if (private->destroyed)
 
2746
    return FALSE;
 
2747
 
 
2748
  return private->viewable;
 
2749
}
 
2750
 
 
2751
/**
 
2752
 * gdk_window_get_state:
 
2753
 * @window: a #GdkWindow
 
2754
 *
 
2755
 * Gets the bitwise OR of the currently active window state flags,
 
2756
 * from the #GdkWindowState enumeration.
 
2757
 *
 
2758
 * Return value: window state bitfield
 
2759
 **/
 
2760
GdkWindowState
 
2761
gdk_window_get_state (GdkWindow *window)
 
2762
{
 
2763
  GdkWindowObject *private = (GdkWindowObject *)window;
 
2764
 
 
2765
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
2766
 
 
2767
  return private->state;
 
2768
}
 
2769
 
 
2770
 
 
2771
/* This creates an empty "implicit" paint region for the impl window.
 
2772
 * By itself this does nothing, but real paints to this window
 
2773
 * or children of it can use this pixmap as backing to avoid allocating
 
2774
 * multiple pixmaps for subwindow rendering. When doing so they
 
2775
 * add to the region of the implicit paint region, which will be
 
2776
 * pushed to the window when the implicit paint region is ended.
 
2777
 * Such paints should not copy anything to the window on paint end, but
 
2778
 * should rely on the implicit paint end.
 
2779
 * The implicit paint will be automatically ended if someone draws
 
2780
 * directly to the window or a child window.
 
2781
 */
 
2782
static gboolean
 
2783
gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
 
2784
{
 
2785
  GdkWindowObject *private = (GdkWindowObject *)window;
 
2786
  GdkWindowPaint *paint;
 
2787
 
 
2788
  g_assert (gdk_window_has_impl (private));
 
2789
 
 
2790
  if (_gdk_native_windows)
 
2791
    return FALSE; /* No need for implicit paints since we can't merge draws anyway */
 
2792
 
 
2793
  if (GDK_IS_PAINTABLE (private->impl))
 
2794
    return FALSE; /* Implementation does double buffering */
 
2795
 
 
2796
  if (private->paint_stack != NULL ||
 
2797
      private->implicit_paint != NULL)
 
2798
    return FALSE; /* Don't stack implicit paints */
 
2799
 
 
2800
  if (private->outstanding_surfaces != 0)
 
2801
    return FALSE; /* May conflict with direct drawing to cairo surface */
 
2802
 
 
2803
  /* Never do implicit paints for foreign windows, they don't need
 
2804
   * double buffer combination since they have no client side children,
 
2805
   * and creating pixmaps for them is risky since they could disappear
 
2806
   * at any time
 
2807
   */
 
2808
  if (private->window_type == GDK_WINDOW_FOREIGN)
 
2809
    return FALSE;
 
2810
 
 
2811
  paint = g_new (GdkWindowPaint, 1);
 
2812
  paint->region = gdk_region_new (); /* Empty */
 
2813
  paint->x_offset = rect->x;
 
2814
  paint->y_offset = rect->y;
 
2815
  paint->uses_implicit = FALSE;
 
2816
  paint->flushed = FALSE;
 
2817
  paint->surface = NULL;
 
2818
  paint->pixmap =
 
2819
    gdk_pixmap_new (window,
 
2820
                    MAX (rect->width, 1), MAX (rect->height, 1), -1);
 
2821
 
 
2822
  private->implicit_paint = paint;
 
2823
 
 
2824
  return TRUE;
 
2825
}
 
2826
 
 
2827
/* Ensure that all content related to this (sub)window is pushed to the
 
2828
   native region. If there is an active paint then that area is not
 
2829
   pushed, in order to not show partially finished double buffers. */
 
2830
static void
 
2831
gdk_window_flush_implicit_paint (GdkWindow *window)
 
2832
{
 
2833
  GdkWindowObject *private = (GdkWindowObject *)window;
 
2834
  GdkWindowObject *impl_window;
 
2835
  GdkWindowPaint *paint;
 
2836
  GdkRegion *region;
 
2837
  GdkGC *tmp_gc;
 
2838
  GSList *list;
 
2839
 
 
2840
  impl_window = gdk_window_get_impl_window (private);
 
2841
  if (impl_window->implicit_paint == NULL)
 
2842
    return;
 
2843
 
 
2844
  paint = impl_window->implicit_paint;
 
2845
  paint->flushed = TRUE;
 
2846
  region = gdk_region_copy (private->clip_region_with_children);
 
2847
 
 
2848
  /* Don't flush active double buffers, as that may show partially done
 
2849
   * rendering */
 
2850
  for (list = private->paint_stack; list != NULL; list = list->next)
 
2851
    {
 
2852
      GdkWindowPaint *tmp_paint = list->data;
 
2853
 
 
2854
      gdk_region_subtract (region, tmp_paint->region);
 
2855
    }
 
2856
 
 
2857
  gdk_region_offset (region, private->abs_x, private->abs_y);
 
2858
  gdk_region_intersect (region, paint->region);
 
2859
 
 
2860
  if (!GDK_WINDOW_DESTROYED (window) && !gdk_region_empty (region))
 
2861
    {
 
2862
      /* Remove flushed region from the implicit paint */
 
2863
      gdk_region_subtract (paint->region, region);
 
2864
 
 
2865
      /* Some regions are valid, push these to window now */
 
2866
      tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
 
2867
      _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
 
2868
      gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
 
2869
                         0, 0, paint->x_offset, paint->y_offset, -1, -1);
 
2870
      /* Reset clip region of the cached GdkGC */
 
2871
      gdk_gc_set_clip_region (tmp_gc, NULL);
 
2872
    }
 
2873
  else
 
2874
    gdk_region_destroy (region);
 
2875
}
 
2876
 
 
2877
/* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
 
2878
static void
 
2879
gdk_window_end_implicit_paint (GdkWindow *window)
 
2880
{
 
2881
  GdkWindowObject *private = (GdkWindowObject *)window;
 
2882
  GdkWindowPaint *paint;
 
2883
  GdkGC *tmp_gc;
 
2884
 
 
2885
  g_assert (gdk_window_has_impl (private));
 
2886
 
 
2887
  g_assert (private->implicit_paint != NULL);
 
2888
 
 
2889
  paint = private->implicit_paint;
 
2890
 
 
2891
  private->implicit_paint = NULL;
 
2892
 
 
2893
  if (!GDK_WINDOW_DESTROYED (window) && !gdk_region_empty (paint->region))
 
2894
    {
 
2895
      /* Some regions are valid, push these to window now */
 
2896
      tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
 
2897
      _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
 
2898
      gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
 
2899
                         0, 0, paint->x_offset, paint->y_offset, -1, -1);
 
2900
      /* Reset clip region of the cached GdkGC */
 
2901
      gdk_gc_set_clip_region (tmp_gc, NULL);
 
2902
    }
 
2903
  else
 
2904
    gdk_region_destroy (paint->region);
 
2905
 
 
2906
  g_object_unref (paint->pixmap);
 
2907
  g_free (paint);
 
2908
}
 
2909
 
 
2910
/**
 
2911
 * gdk_window_begin_paint_rect:
 
2912
 * @window: a #GdkWindow
 
2913
 * @rectangle: rectangle you intend to draw to
 
2914
 *
 
2915
 * A convenience wrapper around gdk_window_begin_paint_region() which
 
2916
 * creates a rectangular region for you. See
 
2917
 * gdk_window_begin_paint_region() for details.
 
2918
 *
 
2919
 **/
 
2920
void
 
2921
gdk_window_begin_paint_rect (GdkWindow          *window,
 
2922
                             const GdkRectangle *rectangle)
 
2923
{
 
2924
  GdkRegion *region;
 
2925
 
 
2926
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2927
 
 
2928
  region = gdk_region_rectangle (rectangle);
 
2929
  gdk_window_begin_paint_region (window, region);
 
2930
  gdk_region_destroy (region);
 
2931
}
 
2932
 
 
2933
/**
 
2934
 * gdk_window_begin_paint_region:
 
2935
 * @window: a #GdkWindow
 
2936
 * @region: region you intend to draw to
 
2937
 *
 
2938
 * Indicates that you are beginning the process of redrawing @region.
 
2939
 * A backing store (offscreen buffer) large enough to contain @region
 
2940
 * will be created. The backing store will be initialized with the
 
2941
 * background color or background pixmap for @window. Then, all
 
2942
 * drawing operations performed on @window will be diverted to the
 
2943
 * backing store.  When you call gdk_window_end_paint(), the backing
 
2944
 * store will be copied to @window, making it visible onscreen. Only
 
2945
 * the part of @window contained in @region will be modified; that is,
 
2946
 * drawing operations are clipped to @region.
 
2947
 *
 
2948
 * The net result of all this is to remove flicker, because the user
 
2949
 * sees the finished product appear all at once when you call
 
2950
 * gdk_window_end_paint(). If you draw to @window directly without
 
2951
 * calling gdk_window_begin_paint_region(), the user may see flicker
 
2952
 * as individual drawing operations are performed in sequence.  The
 
2953
 * clipping and background-initializing features of
 
2954
 * gdk_window_begin_paint_region() are conveniences for the
 
2955
 * programmer, so you can avoid doing that work yourself.
 
2956
 *
 
2957
 * When using GTK+, the widget system automatically places calls to
 
2958
 * gdk_window_begin_paint_region() and gdk_window_end_paint() around
 
2959
 * emissions of the expose_event signal. That is, if you're writing an
 
2960
 * expose event handler, you can assume that the exposed area in
 
2961
 * #GdkEventExpose has already been cleared to the window background,
 
2962
 * is already set as the clip region, and already has a backing store.
 
2963
 * Therefore in most cases, application code need not call
 
2964
 * gdk_window_begin_paint_region(). (You can disable the automatic
 
2965
 * calls around expose events on a widget-by-widget basis by calling
 
2966
 * gtk_widget_set_double_buffered().)
 
2967
 *
 
2968
 * If you call this function multiple times before calling the
 
2969
 * matching gdk_window_end_paint(), the backing stores are pushed onto
 
2970
 * a stack. gdk_window_end_paint() copies the topmost backing store
 
2971
 * onscreen, subtracts the topmost region from all other regions in
 
2972
 * the stack, and pops the stack. All drawing operations affect only
 
2973
 * the topmost backing store in the stack. One matching call to
 
2974
 * gdk_window_end_paint() is required for each call to
 
2975
 * gdk_window_begin_paint_region().
 
2976
 *
 
2977
 **/
 
2978
void
 
2979
gdk_window_begin_paint_region (GdkWindow       *window,
 
2980
                               const GdkRegion *region)
 
2981
{
 
2982
#ifdef USE_BACKING_STORE
 
2983
  GdkWindowObject *private = (GdkWindowObject *)window;
 
2984
  GdkRectangle clip_box;
 
2985
  GdkWindowPaint *paint, *implicit_paint;
 
2986
  GdkWindowObject *impl_window;
 
2987
  GSList *list;
 
2988
 
 
2989
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2990
 
 
2991
  if (GDK_WINDOW_DESTROYED (window))
 
2992
    return;
 
2993
 
 
2994
  if (GDK_IS_PAINTABLE (private->impl))
 
2995
    {
 
2996
      GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
 
2997
 
 
2998
      if (iface->begin_paint_region)
 
2999
        iface->begin_paint_region ((GdkPaintable*)private->impl, window, region);
 
3000
 
 
3001
      return;
 
3002
    }
 
3003
 
 
3004
  impl_window = gdk_window_get_impl_window (private);
 
3005
  implicit_paint = impl_window->implicit_paint;
 
3006
 
 
3007
  paint = g_new (GdkWindowPaint, 1);
 
3008
  paint->region = gdk_region_copy (region);
 
3009
  paint->region_tag = new_region_tag ();
 
3010
 
 
3011
  gdk_region_intersect (paint->region, private->clip_region_with_children);
 
3012
  gdk_region_get_clipbox (paint->region, &clip_box);
 
3013
 
 
3014
  /* Convert to impl coords */
 
3015
  gdk_region_offset (paint->region, private->abs_x, private->abs_y);
 
3016
 
 
3017
  /* Mark the region as valid on the implicit paint */
 
3018
 
 
3019
  if (implicit_paint)
 
3020
    gdk_region_union (implicit_paint->region, paint->region);
 
3021
 
 
3022
  /* Convert back to normal coords */
 
3023
  gdk_region_offset (paint->region, -private->abs_x, -private->abs_y);
 
3024
 
 
3025
  if (implicit_paint)
 
3026
    {
 
3027
      int width, height;
 
3028
 
 
3029
      paint->uses_implicit = TRUE;
 
3030
      paint->pixmap = g_object_ref (implicit_paint->pixmap);
 
3031
      paint->x_offset = -private->abs_x + implicit_paint->x_offset;
 
3032
      paint->y_offset = -private->abs_y + implicit_paint->y_offset;
 
3033
 
 
3034
      gdk_drawable_get_size (paint->pixmap, &width, &height);
 
3035
      paint->surface = _gdk_drawable_create_cairo_surface (paint->pixmap, width, height);
 
3036
    }
 
3037
  else
 
3038
    {
 
3039
      paint->uses_implicit = FALSE;
 
3040
      paint->x_offset = clip_box.x;
 
3041
      paint->y_offset = clip_box.y;
 
3042
      paint->pixmap =
 
3043
        gdk_pixmap_new (window,
 
3044
                        MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
 
3045
      paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
 
3046
    }
 
3047
 
 
3048
  if (paint->surface)
 
3049
    cairo_surface_set_device_offset (paint->surface,
 
3050
                                     -paint->x_offset, -paint->y_offset);
 
3051
 
 
3052
  for (list = private->paint_stack; list != NULL; list = list->next)
 
3053
    {
 
3054
      GdkWindowPaint *tmp_paint = list->data;
 
3055
 
 
3056
      gdk_region_subtract (tmp_paint->region, paint->region);
 
3057
    }
 
3058
 
 
3059
  private->paint_stack = g_slist_prepend (private->paint_stack, paint);
 
3060
 
 
3061
  if (!gdk_region_empty (paint->region))
 
3062
    {
 
3063
      gdk_window_clear_backing_region (window,
 
3064
                                       paint->region);
 
3065
    }
 
3066
 
 
3067
#endif /* USE_BACKING_STORE */
 
3068
}
 
3069
 
 
3070
static void
 
3071
setup_redirect_clip (GdkWindow      *window,
 
3072
                     GdkGC          *gc,
 
3073
                     int            *x_offset_out,
 
3074
                     int            *y_offset_out)
 
3075
{
 
3076
  GdkWindowObject *private = (GdkWindowObject *)window;
 
3077
  GdkRegion *visible_region;
 
3078
  GdkRectangle dest_rect;
 
3079
  GdkRegion *tmpreg;
 
3080
  GdkWindow *toplevel;
 
3081
  int x_offset, y_offset;
 
3082
 
 
3083
  toplevel = GDK_WINDOW (private->redirect->redirected);
 
3084
 
 
3085
  /* Get the clip region for gc clip rect + window hierarchy in
 
3086
     window relative coords */
 
3087
  visible_region =
 
3088
    _gdk_window_calculate_full_clip_region (window, toplevel,
 
3089
                                            TRUE,
 
3090
                                            &x_offset,
 
3091
                                            &y_offset);
 
3092
 
 
3093
  /* Compensate for the source pos/size */
 
3094
  x_offset -= private->redirect->src_x;
 
3095
  y_offset -= private->redirect->src_y;
 
3096
  dest_rect.x = -x_offset;
 
3097
  dest_rect.y = -y_offset;
 
3098
  dest_rect.width = private->redirect->width;
 
3099
  dest_rect.height = private->redirect->height;
 
3100
  tmpreg = gdk_region_rectangle (&dest_rect);
 
3101
  gdk_region_intersect (visible_region, tmpreg);
 
3102
  gdk_region_destroy (tmpreg);
 
3103
 
 
3104
  /* Compensate for the dest pos */
 
3105
  x_offset += private->redirect->dest_x;
 
3106
  y_offset += private->redirect->dest_y;
 
3107
 
 
3108
  gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
 
3109
 
 
3110
  /* offset clip and tiles from window coords to pixmaps coords */
 
3111
  gdk_gc_offset (gc, -x_offset, -y_offset);
 
3112
 
 
3113
  gdk_region_destroy (visible_region);
 
3114
 
 
3115
  *x_offset_out = x_offset;
 
3116
  *y_offset_out = y_offset;
 
3117
}
 
3118
 
 
3119
/**
 
3120
 * gdk_window_end_paint:
 
3121
 * @window: a #GdkWindow
 
3122
 *
 
3123
 * Indicates that the backing store created by the most recent call to
 
3124
 * gdk_window_begin_paint_region() should be copied onscreen and
 
3125
 * deleted, leaving the next-most-recent backing store or no backing
 
3126
 * store at all as the active paint region. See
 
3127
 * gdk_window_begin_paint_region() for full details. It is an error to
 
3128
 * call this function without a matching
 
3129
 * gdk_window_begin_paint_region() first.
 
3130
 *
 
3131
 **/
 
3132
void
 
3133
gdk_window_end_paint (GdkWindow *window)
 
3134
{
 
3135
#ifdef USE_BACKING_STORE
 
3136
  GdkWindowObject *private = (GdkWindowObject *)window;
 
3137
  GdkWindowObject *composited;
 
3138
  GdkWindowPaint *paint;
 
3139
  GdkGC *tmp_gc;
 
3140
  GdkRectangle clip_box;
 
3141
  gint x_offset, y_offset;
 
3142
  GdkRegion *full_clip;
 
3143
 
 
3144
  g_return_if_fail (GDK_IS_WINDOW (window));
 
3145
 
 
3146
  if (GDK_WINDOW_DESTROYED (window))
 
3147
    return;
 
3148
 
 
3149
  if (GDK_IS_PAINTABLE (private->impl))
 
3150
    {
 
3151
      GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
 
3152
 
 
3153
      if (iface->end_paint)
 
3154
        iface->end_paint ((GdkPaintable*)private->impl);
 
3155
      return;
 
3156
    }
 
3157
 
 
3158
  if (private->paint_stack == NULL)
 
3159
    {
 
3160
      g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
 
3161
      return;
 
3162
    }
 
3163
 
 
3164
  paint = private->paint_stack->data;
 
3165
 
 
3166
  private->paint_stack = g_slist_delete_link (private->paint_stack,
 
3167
                                              private->paint_stack);
 
3168
 
 
3169
  gdk_region_get_clipbox (paint->region, &clip_box);
 
3170
 
 
3171
  tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
 
3172
 
 
3173
  x_offset = -private->abs_x;
 
3174
  y_offset = -private->abs_y;
 
3175
 
 
3176
  if (!paint->uses_implicit)
 
3177
    {
 
3178
      gdk_window_flush_outstanding_moves (window);
 
3179
 
 
3180
      full_clip = gdk_region_copy (private->clip_region_with_children);
 
3181
      gdk_region_intersect (full_clip, paint->region);
 
3182
      _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
 
3183
      gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
 
3184
      gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
 
3185
                         clip_box.x - paint->x_offset,
 
3186
                         clip_box.y - paint->y_offset,
 
3187
                         clip_box.x - x_offset, clip_box.y - y_offset,
 
3188
                         clip_box.width, clip_box.height);
 
3189
    }
 
3190
 
 
3191
  if (private->redirect)
 
3192
    {
 
3193
      int x_offset, y_offset;
 
3194
 
 
3195
      /* TODO: Should also use paint->region for clipping */
 
3196
      setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
 
3197
      gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
 
3198
                         clip_box.x - paint->x_offset,
 
3199
                         clip_box.y - paint->y_offset,
 
3200
                         clip_box.x + x_offset,
 
3201
                         clip_box.y + y_offset,
 
3202
                         clip_box.width, clip_box.height);
 
3203
    }
 
3204
 
 
3205
  /* Reset clip region of the cached GdkGC */
 
3206
  gdk_gc_set_clip_region (tmp_gc, NULL);
 
3207
 
 
3208
  cairo_surface_destroy (paint->surface);
 
3209
  g_object_unref (paint->pixmap);
 
3210
  gdk_region_destroy (paint->region);
 
3211
  g_free (paint);
 
3212
 
 
3213
  /* find a composited window in our hierarchy to signal its
 
3214
   * parent to redraw, calculating the clip box as we go...
 
3215
   *
 
3216
   * stop if parent becomes NULL since then we'd have nowhere
 
3217
   * to draw (ie: 'composited' will always be non-NULL here).
 
3218
   */
 
3219
  for (composited = private;
 
3220
       composited->parent;
 
3221
       composited = composited->parent)
 
3222
    {
 
3223
      int width, height;
 
3224
 
 
3225
      gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
 
3226
                             &width, &height);
 
3227
 
 
3228
      clip_box.x += composited->x;
 
3229
      clip_box.y += composited->y;
 
3230
      clip_box.width = MIN (clip_box.width, width - clip_box.x);
 
3231
      clip_box.height = MIN (clip_box.height, height - clip_box.y);
 
3232
 
 
3233
      if (composited->composited)
 
3234
        {
 
3235
          gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
 
3236
                                      &clip_box, FALSE);
 
3237
          break;
 
3238
        }
 
3239
    }
 
3240
#endif /* USE_BACKING_STORE */
 
3241
}
 
3242
 
 
3243
static void
 
3244
gdk_window_free_paint_stack (GdkWindow *window)
 
3245
{
 
3246
  GdkWindowObject *private = (GdkWindowObject *)window;
 
3247
 
 
3248
  if (private->paint_stack)
 
3249
    {
 
3250
      GSList *tmp_list = private->paint_stack;
 
3251
 
 
3252
      while (tmp_list)
 
3253
        {
 
3254
          GdkWindowPaint *paint = tmp_list->data;
 
3255
 
 
3256
          if (tmp_list == private->paint_stack)
 
3257
            g_object_unref (paint->pixmap);
 
3258
 
 
3259
          gdk_region_destroy (paint->region);
 
3260
          g_free (paint);
 
3261
 
 
3262
          tmp_list = tmp_list->next;
 
3263
        }
 
3264
 
 
3265
      g_slist_free (private->paint_stack);
 
3266
      private->paint_stack = NULL;
 
3267
    }
 
3268
}
 
3269
 
 
3270
static void
 
3271
do_move_region_bits_on_impl (GdkWindowObject *impl_window,
 
3272
                             GdkRegion *dest_region, /* In impl window coords */
 
3273
                             int dx, int dy)
 
3274
{
 
3275
  GdkGC *tmp_gc;
 
3276
  GdkRectangle copy_rect;
 
3277
  GdkWindowObject *private;
 
3278
  GdkWindowImplIface *impl_iface;
 
3279
 
 
3280
  /* We need to get data from subwindows here, because we might have
 
3281
   * shaped a native window over the moving region (with bg none,
 
3282
   * so the pixels are still there). In fact we might need to get data
 
3283
   * from overlapping native window that are not children of this window,
 
3284
   * so we copy from the toplevel with INCLUDE_INFERIORS.
 
3285
   */
 
3286
  private = impl_window;
 
3287
  while (!gdk_window_is_toplevel (private) &&
 
3288
         !private->composited &&
 
3289
         gdk_drawable_get_visual ((GdkDrawable *) private) == gdk_drawable_get_visual ((GdkDrawable *) private->parent))
 
3290
    {
 
3291
      dx -= private->parent->abs_x + private->x;
 
3292
      dy -= private->parent->abs_y + private->y;
 
3293
      private = gdk_window_get_impl_window (private->parent);
 
3294
    }
 
3295
  tmp_gc = _gdk_drawable_get_subwindow_scratch_gc ((GdkWindow *)private);
 
3296
 
 
3297
  gdk_region_get_clipbox (dest_region, &copy_rect);
 
3298
  gdk_gc_set_clip_region (tmp_gc, dest_region);
 
3299
 
 
3300
  /* The region area is moved and we queue translations for all expose events
 
3301
     to the source area that were sent prior to the copy */
 
3302
  gdk_region_offset (dest_region, -dx, -dy); /* Move to source region */
 
3303
  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
3304
 
 
3305
  impl_iface->queue_translation ((GdkWindow *)impl_window,
 
3306
                                 tmp_gc,
 
3307
                                 dest_region, dx, dy);
 
3308
 
 
3309
  gdk_draw_drawable (impl_window->impl,
 
3310
                     tmp_gc,
 
3311
                     private->impl,
 
3312
                     copy_rect.x-dx, copy_rect.y-dy,
 
3313
                     copy_rect.x, copy_rect.y,
 
3314
                     copy_rect.width, copy_rect.height);
 
3315
  gdk_gc_set_clip_region (tmp_gc, NULL);
 
3316
}
 
3317
 
 
3318
static GdkWindowRegionMove *
 
3319
gdk_window_region_move_new (GdkRegion *region,
 
3320
                            int dx, int dy)
 
3321
{
 
3322
  GdkWindowRegionMove *move;
 
3323
 
 
3324
  move = g_slice_new (GdkWindowRegionMove);
 
3325
  move->dest_region  = gdk_region_copy (region);
 
3326
  move->dx = dx;
 
3327
  move->dy = dy;
 
3328
 
 
3329
  return move;
 
3330
}
 
3331
 
 
3332
static void
 
3333
gdk_window_region_move_free (GdkWindowRegionMove *move)
 
3334
{
 
3335
  gdk_region_destroy (move->dest_region);
 
3336
  g_slice_free (GdkWindowRegionMove, move);
 
3337
}
 
3338
 
 
3339
static void
 
3340
append_move_region (GdkWindowObject *impl_window,
 
3341
                    GdkRegion *new_dest_region,
 
3342
                    int dx, int dy)
 
3343
{
 
3344
  GdkWindowRegionMove *move, *old_move;
 
3345
  GdkRegion *new_total_region, *old_total_region;
 
3346
  GdkRegion *source_overlaps_destination;
 
3347
  GdkRegion *non_overwritten;
 
3348
  gboolean added_move;
 
3349
  GList *l, *prev;
 
3350
 
 
3351
  if (gdk_region_empty (new_dest_region))
 
3352
    return;
 
3353
 
 
3354
  /* In principle this could just append the move to the list of outstanding
 
3355
     moves that will be replayed before drawing anything when we're handling
 
3356
     exposes. However, we'd like to do a bit better since its commonly the case
 
3357
     that we get multiple copies where A is copied to B and then B is copied
 
3358
     to C, and we'd like to express this as a simple copy A to C operation. */
 
3359
 
 
3360
  /* We approach this by taking the new move and pushing it ahead of moves
 
3361
     starting at the end of the list and stopping when its not safe to do so.
 
3362
     It's not safe to push past a move if either the source of the new move
 
3363
     is in the destination of the old move, or if the destination of the new
 
3364
     move is in the source of the new move, or if the destination of the new
 
3365
     move overlaps the destination of the old move. We simplify this by
 
3366
     just comparing the total regions (src + dest) */
 
3367
  new_total_region = gdk_region_copy (new_dest_region);
 
3368
  gdk_region_offset (new_total_region, -dx, -dy);
 
3369
  gdk_region_union (new_total_region, new_dest_region);
 
3370
 
 
3371
  added_move = FALSE;
 
3372
  for (l = g_list_last (impl_window->outstanding_moves); l != NULL; l = prev)
 
3373
    {
 
3374
      prev = l->prev;
 
3375
      old_move = l->data;
 
3376
 
 
3377
      old_total_region = gdk_region_copy (old_move->dest_region);
 
3378
      gdk_region_offset (old_total_region, -old_move->dx, -old_move->dy);
 
3379
      gdk_region_union (old_total_region, old_move->dest_region);
 
3380
 
 
3381
      gdk_region_intersect (old_total_region, new_total_region);
 
3382
      /* If these regions intersect then its not safe to push the
 
3383
         new region before the old one */
 
3384
      if (!gdk_region_empty (old_total_region))
 
3385
        {
 
3386
          /* The area where the new moves source overlaps the old ones
 
3387
             destination */
 
3388
          source_overlaps_destination = gdk_region_copy (new_dest_region);
 
3389
          gdk_region_offset (source_overlaps_destination, -dx, -dy);
 
3390
          gdk_region_intersect (source_overlaps_destination, old_move->dest_region);
 
3391
          gdk_region_offset (source_overlaps_destination, dx, dy);
 
3392
 
 
3393
          /* We can do all sort of optimizations here, but to do things safely it becomes
 
3394
             quite complicated. However, a very common case is that you copy something first,
 
3395
             then copy all that or a subset of it to a new location (i.e. if you scroll twice
 
3396
             in the same direction). We'd like to detect this case and optimize it to one
 
3397
             copy. */
 
3398
          if (gdk_region_equal (source_overlaps_destination, new_dest_region))
 
3399
            {
 
3400
              /* This means we might be able to replace the old move and the new one
 
3401
                 with the new one read from the old ones source, and a second copy of
 
3402
                 the non-overwritten parts of the old move. However, such a split
 
3403
                 is only valid if the source in the old move isn't overwritten
 
3404
                 by the destination of the new one */
 
3405
 
 
3406
              /* the new destination of old move if split is ok: */
 
3407
              non_overwritten = gdk_region_copy (old_move->dest_region);
 
3408
              gdk_region_subtract (non_overwritten, new_dest_region);
 
3409
              /* move to source region */
 
3410
              gdk_region_offset (non_overwritten, -old_move->dx, -old_move->dy);
 
3411
 
 
3412
              gdk_region_intersect (non_overwritten, new_dest_region);
 
3413
              if (gdk_region_empty (non_overwritten))
 
3414
                {
 
3415
                  added_move = TRUE;
 
3416
                  move = gdk_window_region_move_new (new_dest_region,
 
3417
                                                     dx + old_move->dx,
 
3418
                                                     dy + old_move->dy);
 
3419
 
 
3420
                  impl_window->outstanding_moves =
 
3421
                    g_list_insert_before (impl_window->outstanding_moves,
 
3422
                                          l, move);
 
3423
                  gdk_region_subtract (old_move->dest_region, new_dest_region);
 
3424
                }
 
3425
              gdk_region_destroy (non_overwritten);
 
3426
            }
 
3427
 
 
3428
          gdk_region_destroy (source_overlaps_destination);
 
3429
          gdk_region_destroy (old_total_region);
 
3430
          break;
 
3431
        }
 
3432
      gdk_region_destroy (old_total_region);
 
3433
    }
 
3434
 
 
3435
  gdk_region_destroy (new_total_region);
 
3436
 
 
3437
  if (!added_move)
 
3438
    {
 
3439
      move = gdk_window_region_move_new (new_dest_region, dx, dy);
 
3440
 
 
3441
      if (l == NULL)
 
3442
        impl_window->outstanding_moves =
 
3443
          g_list_prepend (impl_window->outstanding_moves,
 
3444
                          move);
 
3445
      else
 
3446
        impl_window->outstanding_moves =
 
3447
          g_list_insert_before (impl_window->outstanding_moves,
 
3448
                                l->next, move);
 
3449
    }
 
3450
}
 
3451
 
 
3452
/* Moves bits and update area by dx/dy in impl window.
 
3453
   Takes ownership of region to avoid copy (because we may change it) */
 
3454
static void
 
3455
move_region_on_impl (GdkWindowObject *impl_window,
 
3456
                     GdkRegion *region, /* In impl window coords */
 
3457
                     int dx, int dy)
 
3458
{
 
3459
  if ((dx == 0 && dy == 0) ||
 
3460
      gdk_region_empty (region))
 
3461
    {
 
3462
      gdk_region_destroy (region);
 
3463
      return;
 
3464
    }
 
3465
 
 
3466
  g_assert (impl_window == gdk_window_get_impl_window (impl_window));
 
3467
 
 
3468
  /* Move any old invalid regions in the copy source area by dx/dy */
 
3469
  if (impl_window->update_area)
 
3470
    {
 
3471
      GdkRegion *update_area;
 
3472
 
 
3473
      update_area = gdk_region_copy (region);
 
3474
 
 
3475
      /* Convert from target to source */
 
3476
      gdk_region_offset (update_area, -dx, -dy);
 
3477
      gdk_region_intersect (update_area, impl_window->update_area);
 
3478
      /* We only copy the area, so keep the old update area invalid.
 
3479
         It would be safe to remove it too, as code that uses
 
3480
         move_region_on_impl generally also invalidate the source
 
3481
         area. However, it would just use waste cycles. */
 
3482
 
 
3483
      /* Convert back */
 
3484
      gdk_region_offset (update_area, dx, dy);
 
3485
      gdk_region_union (impl_window->update_area, update_area);
 
3486
 
 
3487
      /* This area of the destination is now invalid,
 
3488
         so no need to copy to it.  */
 
3489
      gdk_region_subtract (region, update_area);
 
3490
 
 
3491
      gdk_region_destroy (update_area);
 
3492
    }
 
3493
 
 
3494
  /* If we're currently exposing this window, don't copy to this
 
3495
     destination, as it will be overdrawn when the expose is done,
 
3496
     instead invalidate it and repaint later. */
 
3497
  if (impl_window->implicit_paint)
 
3498
    {
 
3499
      GdkWindowPaint *implicit_paint = impl_window->implicit_paint;
 
3500
      GdkRegion *exposing;
 
3501
 
 
3502
      exposing = gdk_region_copy (implicit_paint->region);
 
3503
      gdk_region_intersect (exposing, region);
 
3504
      gdk_region_subtract (region, exposing);
 
3505
 
 
3506
      impl_window_add_update_area (impl_window, exposing);
 
3507
      gdk_region_destroy (exposing);
 
3508
    }
 
3509
 
 
3510
  if (impl_window->outstanding_surfaces == 0) /* Enable flicker free handling of moves. */
 
3511
    append_move_region (impl_window, region, dx, dy);
 
3512
  else
 
3513
    do_move_region_bits_on_impl (impl_window,
 
3514
                                 region, dx, dy);
 
3515
 
 
3516
  gdk_region_destroy (region);
 
3517
}
 
3518
 
 
3519
/* Flushes all outstanding changes to the window, call this
 
3520
 * before drawing directly to the window (i.e. outside a begin/end_paint pair).
 
3521
 */
 
3522
static void
 
3523
gdk_window_flush_outstanding_moves (GdkWindow *window)
 
3524
{
 
3525
  GdkWindowObject *private;
 
3526
  GdkWindowObject *impl_window;
 
3527
  GdkWindowRegionMove *move;
 
3528
 
 
3529
  private = (GdkWindowObject *) window;
 
3530
 
 
3531
  impl_window = gdk_window_get_impl_window (private);
 
3532
 
 
3533
  while (impl_window->outstanding_moves)
 
3534
    {
 
3535
      move = impl_window->outstanding_moves->data;
 
3536
      impl_window->outstanding_moves = g_list_delete_link (impl_window->outstanding_moves,
 
3537
                                                           impl_window->outstanding_moves);
 
3538
 
 
3539
      do_move_region_bits_on_impl (impl_window,
 
3540
                                   move->dest_region, move->dx, move->dy);
 
3541
 
 
3542
      gdk_window_region_move_free (move);
 
3543
    }
 
3544
}
 
3545
 
 
3546
/**
 
3547
 * gdk_window_flush:
 
3548
 * @window: a #GdkWindow
 
3549
 *
 
3550
 * Flush all outstanding cached operations on a window, leaving the
 
3551
 * window in a state which reflects all that has been drawn before.
 
3552
 *
 
3553
 * Gdk uses multiple kinds of caching to get better performance and
 
3554
 * nicer drawing. For instance, during exposes all paints to a window
 
3555
 * using double buffered rendering are keep on a pixmap until the last
 
3556
 * window has been exposed. It also delays window moves/scrolls until
 
3557
 * as long as possible until next update to avoid tearing when moving
 
3558
 * windows.
 
3559
 *
 
3560
 * Normally this should be completely invisible to applications, as
 
3561
 * we automatically flush the windows when required, but this might
 
3562
 * be needed if you for instance mix direct native drawing with
 
3563
 * gdk drawing. For Gtk widgets that don't use double buffering this
 
3564
 * will be called automatically before sending the expose event.
 
3565
 *
 
3566
 * Since: 2.18
 
3567
 **/
 
3568
void
 
3569
gdk_window_flush (GdkWindow *window)
 
3570
{
 
3571
  gdk_window_flush_outstanding_moves (window);
 
3572
  gdk_window_flush_implicit_paint (window);
 
3573
}
 
3574
 
 
3575
/* If we're about to move/resize or otherwise change the
 
3576
 * hierarchy of a client side window in an impl and we're
 
3577
 * called from an expose event handler then we need to
 
3578
 * flush any already painted parts of the implicit paint
 
3579
 * that are not part of the current paint, as these may
 
3580
 * be used when scrolling or may overdraw the changes
 
3581
 * caused by the hierarchy change.
 
3582
 */
 
3583
static void
 
3584
gdk_window_flush_if_exposing (GdkWindow *window)
 
3585
{
 
3586
  GdkWindowObject *private;
 
3587
  GdkWindowObject *impl_window;
 
3588
 
 
3589
  private = (GdkWindowObject *) window;
 
3590
  impl_window = gdk_window_get_impl_window (private);
 
3591
 
 
3592
  /* If we're in an implicit paint (i.e. in an expose handler, flush
 
3593
     all the already finished exposes to get things to an uptodate state. */
 
3594
  if (impl_window->implicit_paint)
 
3595
    gdk_window_flush (window);
 
3596
}
 
3597
 
 
3598
 
 
3599
static void
 
3600
gdk_window_flush_recursive_helper (GdkWindowObject *window,
 
3601
                                   GdkWindow *impl)
 
3602
{
 
3603
  GdkWindowObject *child;
 
3604
  GList *l;
 
3605
 
 
3606
  for (l = window->children; l != NULL; l = l->next)
 
3607
    {
 
3608
      child = l->data;
 
3609
 
 
3610
      if (child->impl == impl)
 
3611
        /* Same impl, ignore */
 
3612
        gdk_window_flush_recursive_helper (child, impl);
 
3613
      else
 
3614
        gdk_window_flush_recursive (child);
 
3615
    }
 
3616
}
 
3617
 
 
3618
static void
 
3619
gdk_window_flush_recursive (GdkWindowObject *window)
 
3620
{
 
3621
  gdk_window_flush ((GdkWindow *)window);
 
3622
  gdk_window_flush_recursive_helper (window, window->impl);
 
3623
}
 
3624
 
 
3625
static void
 
3626
gdk_window_get_offsets (GdkWindow *window,
 
3627
                        gint      *x_offset,
 
3628
                        gint      *y_offset)
 
3629
{
 
3630
  GdkWindowObject *private = (GdkWindowObject *)window;
 
3631
 
 
3632
  if (private->paint_stack)
 
3633
    {
 
3634
      GdkWindowPaint *paint = private->paint_stack->data;
 
3635
      *x_offset = paint->x_offset;
 
3636
      *y_offset = paint->y_offset;
 
3637
    }
 
3638
  else
 
3639
    {
 
3640
      *x_offset = -private->abs_x;
 
3641
      *y_offset = -private->abs_y;
 
3642
    }
 
3643
}
 
3644
 
 
3645
/**
 
3646
 * gdk_window_get_internal_paint_info:
 
3647
 * @window: a #GdkWindow
 
3648
 * @real_drawable: (out): location to store the drawable to which drawing should be
 
3649
 *            done.
 
3650
 * @x_offset: (out): location to store the X offset between coordinates in @window,
 
3651
 *            and the underlying window system primitive coordinates for
 
3652
 *            *@real_drawable.
 
3653
 * @y_offset: (out): location to store the Y offset between coordinates in @window,
 
3654
 *            and the underlying window system primitive coordinates for
 
3655
 *            *@real_drawable.
 
3656
 *
 
3657
 * If you bypass the GDK layer and use windowing system primitives to
 
3658
 * draw directly onto a #GdkWindow, then you need to deal with two
 
3659
 * details: there may be an offset between GDK coordinates and windowing
 
3660
 * system coordinates, and GDK may have redirected drawing to a offscreen
 
3661
 * pixmap as the result of a gdk_window_begin_paint_region() calls.
 
3662
 * This function allows retrieving the information you need to compensate
 
3663
 * for these effects.
 
3664
 *
 
3665
 * This function exposes details of the GDK implementation, and is thus
 
3666
 * likely to change in future releases of GDK.
 
3667
 **/
 
3668
void
 
3669
gdk_window_get_internal_paint_info (GdkWindow    *window,
 
3670
                                    GdkDrawable **real_drawable,
 
3671
                                    gint         *x_offset,
 
3672
                                    gint         *y_offset)
 
3673
{
 
3674
  gint x_off, y_off;
 
3675
 
 
3676
  GdkWindowObject *private;
 
3677
 
 
3678
  g_return_if_fail (GDK_IS_WINDOW (window));
 
3679
 
 
3680
  private = (GdkWindowObject *)window;
 
3681
 
 
3682
  if (real_drawable)
 
3683
    {
 
3684
      if (private->paint_stack)
 
3685
        {
 
3686
          GdkWindowPaint *paint = private->paint_stack->data;
 
3687
          *real_drawable = paint->pixmap;
 
3688
        }
 
3689
      else
 
3690
        {
 
3691
          /* This means you're probably gonna be doing some weird shit
 
3692
             directly to the window, so we flush all outstanding stuff */
 
3693
          gdk_window_flush (window);
 
3694
          *real_drawable = window;
 
3695
        }
 
3696
    }
 
3697
 
 
3698
  gdk_window_get_offsets (window, &x_off, &y_off);
 
3699
 
 
3700
  if (x_offset)
 
3701
    *x_offset = x_off;
 
3702
  if (y_offset)
 
3703
    *y_offset = y_off;
 
3704
}
 
3705
 
 
3706
static GdkDrawable *
 
3707
start_draw_helper (GdkDrawable *drawable,
 
3708
                   GdkGC *gc,
 
3709
                   gint *x_offset_out,
 
3710
                   gint *y_offset_out)
 
3711
{
 
3712
  GdkWindowObject *private = (GdkWindowObject *)drawable;
 
3713
  gint x_offset, y_offset;
 
3714
  GdkDrawable *impl;
 
3715
  gint old_clip_x = gc->clip_x_origin;
 
3716
  gint old_clip_y = gc->clip_y_origin;
 
3717
  GdkRegion *clip;
 
3718
  guint32 clip_region_tag;
 
3719
  GdkWindowPaint *paint;
 
3720
 
 
3721
  paint = NULL;
 
3722
  if (private->paint_stack)
 
3723
    paint = private->paint_stack->data;
 
3724
 
 
3725
  if (paint)
 
3726
    {
 
3727
      x_offset = paint->x_offset;
 
3728
      y_offset = paint->y_offset;
 
3729
    }
 
3730
  else
 
3731
    {
 
3732
      x_offset = -private->abs_x;
 
3733
      y_offset = -private->abs_y;
 
3734
    }
 
3735
 
 
3736
  if (x_offset != 0 || y_offset != 0)
 
3737
    {
 
3738
      gdk_gc_set_clip_origin (gc,
 
3739
                              old_clip_x - x_offset,
 
3740
                              old_clip_y - y_offset);
 
3741
      gdk_gc_set_ts_origin (gc,
 
3742
                            gc->ts_x_origin - x_offset,
 
3743
                            gc->ts_y_origin - y_offset);
 
3744
    }
 
3745
 
 
3746
  *x_offset_out = x_offset;
 
3747
  *y_offset_out = y_offset;
 
3748
 
 
3749
  /* Add client side window clip region to gc */
 
3750
  clip = NULL;
 
3751
  if (paint)
 
3752
    {
 
3753
      /* Only need clipping if using implicit paint, otherwise
 
3754
         the pixmap is clipped when copying to the window in end_paint */
 
3755
      if (paint->uses_implicit)
 
3756
        {
 
3757
          /* This includes the window clip */
 
3758
          clip = paint->region;
 
3759
        }
 
3760
      clip_region_tag = paint->region_tag;
 
3761
 
 
3762
      /* After having set up the drawable clip rect on a GC we need to make sure
 
3763
       * that we draw to th the impl, otherwise the pixmap code will reset the
 
3764
       * drawable clip. */
 
3765
      impl = ((GdkPixmapObject *)(paint->pixmap))->impl;
 
3766
    }
 
3767
  else
 
3768
    {
 
3769
      /* Drawing directly to the window, flush anything outstanding to
 
3770
         guarantee ordering. */
 
3771
      gdk_window_flush ((GdkWindow *)drawable);
 
3772
 
 
3773
      /* Don't clip when drawing to root or all native */
 
3774
      if (!_gdk_native_windows && private->window_type != GDK_WINDOW_ROOT)
 
3775
        {
 
3776
          if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
 
3777
            clip = private->clip_region_with_children;
 
3778
          else
 
3779
            clip = private->clip_region;
 
3780
        }
 
3781
      clip_region_tag = private->clip_tag;
 
3782
      impl = private->impl;
 
3783
    }
 
3784
 
 
3785
  if (clip)
 
3786
    _gdk_gc_add_drawable_clip (gc,
 
3787
                               clip_region_tag, clip,
 
3788
                               /* If there was a clip origin set appart from the
 
3789
                                * window offset, need to take that into
 
3790
                                * consideration */
 
3791
                               -old_clip_x, -old_clip_y);
 
3792
 
 
3793
  return impl;
 
3794
}
 
3795
 
 
3796
#define BEGIN_DRAW                                      \
 
3797
  {                                                     \
 
3798
    GdkDrawable *impl;                                  \
 
3799
    gint x_offset, y_offset;                            \
 
3800
    gint old_clip_x = gc->clip_x_origin;                \
 
3801
    gint old_clip_y = gc->clip_y_origin;                \
 
3802
    gint old_ts_x = gc->ts_x_origin;                    \
 
3803
    gint old_ts_y = gc->ts_y_origin;                    \
 
3804
    impl = start_draw_helper (drawable, gc,             \
 
3805
                              &x_offset, &y_offset);
 
3806
 
 
3807
#define END_DRAW                                            \
 
3808
    if (x_offset != 0 || y_offset != 0)                     \
 
3809
     {                                                      \
 
3810
       gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
 
3811
       gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y);       \
 
3812
     }                                                      \
 
3813
  }
 
3814
 
 
3815
#define BEGIN_DRAW_MACRO \
 
3816
  {
 
3817
 
 
3818
#define END_DRAW_MACRO \
 
3819
  }
 
3820
 
 
3821
typedef struct
 
3822
{
 
3823
  GdkDrawable *drawable;
 
3824
  GdkGC *gc;
 
3825
 
 
3826
  gint x_offset;
 
3827
  gint y_offset;
 
3828
 
 
3829
  gint clip_x;
 
3830
  gint clip_y;
 
3831
  gint ts_x;
 
3832
  gint ts_y;
 
3833
} DirectDrawInfo;
 
3834
 
 
3835
GdkDrawable *
 
3836
_gdk_drawable_begin_direct_draw (GdkDrawable *drawable,
 
3837
                                 GdkGC *gc,
 
3838
                                 gpointer *priv_data,
 
3839
                                 gint *x_offset_out,
 
3840
                                 gint *y_offset_out)
 
3841
{
 
3842
  GdkDrawable *out_impl = NULL;
 
3843
 
 
3844
  g_return_val_if_fail (priv_data != NULL, NULL);
 
3845
 
 
3846
  *priv_data = NULL;
 
3847
 
 
3848
  if (GDK_IS_PIXMAP (drawable))
 
3849
    {
 
3850
      /* We bypass the GdkPixmap functions, so do this ourself */
 
3851
      _gdk_gc_remove_drawable_clip (gc);
 
3852
 
 
3853
      out_impl = drawable;
 
3854
 
 
3855
      *x_offset_out = 0;
 
3856
      *y_offset_out = 0;
 
3857
    }
 
3858
  else
 
3859
    {
 
3860
      DirectDrawInfo *priv;
 
3861
 
 
3862
      if (GDK_WINDOW_DESTROYED (drawable))
 
3863
        return NULL;
 
3864
 
 
3865
      BEGIN_DRAW;
 
3866
 
 
3867
      if (impl == NULL)
 
3868
        return NULL;
 
3869
 
 
3870
      out_impl = impl;
 
3871
 
 
3872
      *x_offset_out = x_offset;
 
3873
      *y_offset_out = y_offset;
 
3874
 
 
3875
      priv = g_new (DirectDrawInfo, 1);
 
3876
 
 
3877
      priv->drawable = impl;
 
3878
      priv->gc = gc;
 
3879
 
 
3880
      priv->x_offset = x_offset;
 
3881
      priv->y_offset = y_offset;
 
3882
      priv->clip_x = old_clip_x;
 
3883
      priv->clip_y = old_clip_y;
 
3884
      priv->ts_x = old_ts_x;
 
3885
      priv->ts_y = old_ts_y;
 
3886
 
 
3887
      *priv_data = (gpointer) priv;
 
3888
 
 
3889
      END_DRAW_MACRO;
 
3890
    }
 
3891
 
 
3892
  return out_impl;
 
3893
}
 
3894
 
 
3895
void
 
3896
_gdk_drawable_end_direct_draw (gpointer priv_data)
 
3897
{
 
3898
  DirectDrawInfo *priv;
 
3899
  GdkGC *gc;
 
3900
 
 
3901
  /* Its a GdkPixmap or the call to _gdk_drawable_begin_direct_draw failed. */
 
3902
  if (priv_data == NULL)
 
3903
    return;
 
3904
 
 
3905
  priv = priv_data;
 
3906
  gc = priv->gc;
 
3907
 
 
3908
  /* This is only for GdkWindows - if GdkPixmaps need any handling here in
 
3909
   * the future, then we should keep track of what type of drawable it is in
 
3910
   * DirectDrawInfo. */
 
3911
  BEGIN_DRAW_MACRO;
 
3912
 
 
3913
  {
 
3914
    gint x_offset = priv->x_offset;
 
3915
    gint y_offset = priv->y_offset;
 
3916
    gint old_clip_x = priv->clip_x;
 
3917
    gint old_clip_y = priv->clip_y;
 
3918
    gint old_ts_x = priv->ts_x;
 
3919
    gint old_ts_y = priv->ts_y;
 
3920
 
 
3921
    END_DRAW;
 
3922
  }
 
3923
 
 
3924
  g_free (priv_data);
 
3925
}
 
3926
 
 
3927
static GdkGC *
 
3928
gdk_window_create_gc (GdkDrawable     *drawable,
 
3929
                      GdkGCValues     *values,
 
3930
                      GdkGCValuesMask  mask)
 
3931
{
 
3932
  g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
 
3933
 
 
3934
  if (GDK_WINDOW_DESTROYED (drawable))
 
3935
    return NULL;
 
3936
 
 
3937
  return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
 
3938
                                 values, mask);
 
3939
}
 
3940
 
 
3941
static void
 
3942
gdk_window_draw_rectangle (GdkDrawable *drawable,
 
3943
                           GdkGC       *gc,
 
3944
                           gboolean     filled,
 
3945
                           gint         x,
 
3946
                           gint         y,
 
3947
                           gint         width,
 
3948
                           gint         height)
 
3949
{
 
3950
  if (GDK_WINDOW_DESTROYED (drawable))
 
3951
    return;
 
3952
 
 
3953
  BEGIN_DRAW;
 
3954
  gdk_draw_rectangle (impl, gc, filled,
 
3955
                      x - x_offset, y - y_offset, width, height);
 
3956
  END_DRAW;
 
3957
}
 
3958
 
 
3959
static void
 
3960
gdk_window_draw_arc (GdkDrawable *drawable,
 
3961
                     GdkGC       *gc,
 
3962
                     gboolean     filled,
 
3963
                     gint         x,
 
3964
                     gint         y,
 
3965
                     gint         width,
 
3966
                     gint         height,
 
3967
                     gint         angle1,
 
3968
                     gint         angle2)
 
3969
{
 
3970
  if (GDK_WINDOW_DESTROYED (drawable))
 
3971
    return;
 
3972
 
 
3973
  BEGIN_DRAW;
 
3974
  gdk_draw_arc (impl, gc, filled,
 
3975
                x - x_offset, y - y_offset,
 
3976
                width, height, angle1, angle2);
 
3977
  END_DRAW;
 
3978
}
 
3979
 
 
3980
static void
 
3981
gdk_window_draw_polygon (GdkDrawable *drawable,
 
3982
                         GdkGC       *gc,
 
3983
                         gboolean     filled,
 
3984
                         GdkPoint    *points,
 
3985
                         gint         npoints)
 
3986
{
 
3987
  GdkPoint *new_points;
 
3988
 
 
3989
  if (GDK_WINDOW_DESTROYED (drawable))
 
3990
    return;
 
3991
 
 
3992
  BEGIN_DRAW;
 
3993
 
 
3994
  if (x_offset != 0 || y_offset != 0)
 
3995
    {
 
3996
      int i;
 
3997
 
 
3998
      new_points = g_new (GdkPoint, npoints);
 
3999
      for (i=0; i<npoints; i++)
 
4000
        {
 
4001
          new_points[i].x = points[i].x - x_offset;
 
4002
          new_points[i].y = points[i].y - y_offset;
 
4003
        }
 
4004
    }
 
4005
  else
 
4006
    new_points = points;
 
4007
 
 
4008
  gdk_draw_polygon (impl, gc, filled, new_points, npoints);
 
4009
 
 
4010
  if (new_points != points)
 
4011
    g_free (new_points);
 
4012
 
 
4013
  END_DRAW;
 
4014
}
 
4015
 
 
4016
static void
 
4017
gdk_window_draw_text (GdkDrawable *drawable,
 
4018
                      GdkFont     *font,
 
4019
                      GdkGC       *gc,
 
4020
                      gint         x,
 
4021
                      gint         y,
 
4022
                      const gchar *text,
 
4023
                      gint         text_length)
 
4024
{
 
4025
  if (GDK_WINDOW_DESTROYED (drawable))
 
4026
    return;
 
4027
 
 
4028
  BEGIN_DRAW;
 
4029
  gdk_draw_text (impl, font, gc,
 
4030
                 x - x_offset, y - y_offset, text, text_length);
 
4031
  END_DRAW;
 
4032
}
 
4033
 
 
4034
static void
 
4035
gdk_window_draw_text_wc (GdkDrawable    *drawable,
 
4036
                         GdkFont        *font,
 
4037
                         GdkGC          *gc,
 
4038
                         gint            x,
 
4039
                         gint            y,
 
4040
                         const GdkWChar *text,
 
4041
                         gint            text_length)
 
4042
{
 
4043
  if (GDK_WINDOW_DESTROYED (drawable))
 
4044
    return;
 
4045
 
 
4046
  BEGIN_DRAW;
 
4047
  gdk_draw_text_wc (impl, font, gc,
 
4048
                    x - x_offset, y - y_offset, text, text_length);
 
4049
  END_DRAW;
 
4050
}
 
4051
 
 
4052
static GdkDrawable *
 
4053
gdk_window_get_source_drawable (GdkDrawable *drawable)
 
4054
{
 
4055
  GdkWindow *window = GDK_WINDOW (drawable);
 
4056
  GdkWindowObject *private;
 
4057
 
 
4058
  private = (GdkWindowObject *) window;
 
4059
  if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
 
4060
    return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
 
4061
 
 
4062
  return drawable;
 
4063
}
 
4064
 
 
4065
static GdkDrawable *
 
4066
gdk_window_get_composite_drawable (GdkDrawable *drawable,
 
4067
                                   gint         x,
 
4068
                                   gint         y,
 
4069
                                   gint         width,
 
4070
                                   gint         height,
 
4071
                                   gint        *composite_x_offset,
 
4072
                                   gint        *composite_y_offset)
 
4073
{
 
4074
  GdkWindowObject *private = (GdkWindowObject *)drawable;
 
4075
  GSList *list;
 
4076
  GdkPixmap *tmp_pixmap;
 
4077
  GdkRectangle rect;
 
4078
  GdkGC *tmp_gc;
 
4079
  gboolean overlap_buffer;
 
4080
  GdkDrawable *source;
 
4081
  GdkWindowObject *impl_window;
 
4082
  GdkWindowPaint *implicit_paint;
 
4083
 
 
4084
  *composite_x_offset = -private->abs_x;
 
4085
  *composite_y_offset = -private->abs_y;
 
4086
 
 
4087
  if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
 
4088
    return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
 
4089
 
 
4090
  /* See if any buffered part is overlapping the part we want
 
4091
   * to get
 
4092
   */
 
4093
  rect.x = x;
 
4094
  rect.y = y;
 
4095
  rect.width = width;
 
4096
  rect.height = height;
 
4097
 
 
4098
  overlap_buffer = FALSE;
 
4099
 
 
4100
  for (list = private->paint_stack; list != NULL; list = list->next)
 
4101
    {
 
4102
      GdkWindowPaint *paint = list->data;
 
4103
      GdkOverlapType overlap;
 
4104
 
 
4105
      overlap = gdk_region_rect_in (paint->region, &rect);
 
4106
 
 
4107
      if (overlap == GDK_OVERLAP_RECTANGLE_IN)
 
4108
        {
 
4109
          *composite_x_offset = paint->x_offset;
 
4110
          *composite_y_offset = paint->y_offset;
 
4111
 
 
4112
          return g_object_ref (paint->pixmap);
 
4113
        }
 
4114
      else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
 
4115
        {
 
4116
          overlap_buffer = TRUE;
 
4117
          break;
 
4118
        }
 
4119
    }
 
4120
 
 
4121
  impl_window = gdk_window_get_impl_window (private);
 
4122
  implicit_paint = impl_window->implicit_paint;
 
4123
  if (implicit_paint)
 
4124
    {
 
4125
      GdkOverlapType overlap;
 
4126
 
 
4127
      rect.x += private->abs_x;
 
4128
      rect.y += private->abs_y;
 
4129
 
 
4130
      overlap = gdk_region_rect_in (implicit_paint->region, &rect);
 
4131
      if (overlap == GDK_OVERLAP_RECTANGLE_IN)
 
4132
        {
 
4133
          *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
 
4134
          *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
 
4135
 
 
4136
          return g_object_ref (implicit_paint->pixmap);
 
4137
        }
 
4138
      else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
 
4139
        overlap_buffer = TRUE;
 
4140
    }
 
4141
 
 
4142
  if (!overlap_buffer)
 
4143
    return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
 
4144
 
 
4145
  tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
 
4146
  tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
 
4147
 
 
4148
  source = _gdk_drawable_get_source_drawable (drawable);
 
4149
 
 
4150
  /* Copy the current window contents */
 
4151
  gdk_draw_drawable (tmp_pixmap,
 
4152
                     tmp_gc,
 
4153
                     GDK_WINDOW_OBJECT (source)->impl,
 
4154
                     x - *composite_x_offset,
 
4155
                     y - *composite_y_offset,
 
4156
                     0, 0,
 
4157
                     width, height);
 
4158
 
 
4159
  /* paint the backing stores */
 
4160
  if (implicit_paint)
 
4161
    {
 
4162
      GdkWindowPaint *paint = list->data;
 
4163
 
 
4164
      gdk_gc_set_clip_region (tmp_gc, paint->region);
 
4165
      gdk_gc_set_clip_origin (tmp_gc, -x  - paint->x_offset, -y  - paint->y_offset);
 
4166
 
 
4167
      gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
 
4168
                         x - paint->x_offset,
 
4169
                         y - paint->y_offset,
 
4170
                         0, 0, width, height);
 
4171
    }
 
4172
 
 
4173
  for (list = private->paint_stack; list != NULL; list = list->next)
 
4174
    {
 
4175
      GdkWindowPaint *paint = list->data;
 
4176
 
 
4177
      if (paint->uses_implicit)
 
4178
        continue; /* We already copied this above */
 
4179
 
 
4180
      gdk_gc_set_clip_region (tmp_gc, paint->region);
 
4181
      gdk_gc_set_clip_origin (tmp_gc, -x, -y);
 
4182
 
 
4183
      gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
 
4184
                         x - paint->x_offset,
 
4185
                         y - paint->y_offset,
 
4186
                         0, 0, width, height);
 
4187
    }
 
4188
 
 
4189
  /* Reset clip region of the cached GdkGC */
 
4190
  gdk_gc_set_clip_region (tmp_gc, NULL);
 
4191
 
 
4192
  /* Set these to location of tmp_pixmap within the window */
 
4193
  *composite_x_offset = x;
 
4194
  *composite_y_offset = y;
 
4195
 
 
4196
  return tmp_pixmap;
 
4197
}
 
4198
 
 
4199
static GdkRegion*
 
4200
gdk_window_get_clip_region (GdkDrawable *drawable)
 
4201
{
 
4202
  GdkWindowObject *private = (GdkWindowObject *)drawable;
 
4203
  GdkRegion *result;
 
4204
 
 
4205
  result = gdk_region_copy (private->clip_region);
 
4206
 
 
4207
  if (private->paint_stack)
 
4208
    {
 
4209
      GdkRegion *paint_region = gdk_region_new ();
 
4210
      GSList *tmp_list = private->paint_stack;
 
4211
 
 
4212
      while (tmp_list)
 
4213
        {
 
4214
          GdkWindowPaint *paint = tmp_list->data;
 
4215
 
 
4216
          gdk_region_union (paint_region, paint->region);
 
4217
 
 
4218
          tmp_list = tmp_list->next;
 
4219
        }
 
4220
 
 
4221
      gdk_region_intersect (result, paint_region);
 
4222
      gdk_region_destroy (paint_region);
 
4223
    }
 
4224
 
 
4225
  return result;
 
4226
}
 
4227
 
 
4228
static GdkRegion*
 
4229
gdk_window_get_visible_region (GdkDrawable *drawable)
 
4230
{
 
4231
  GdkWindowObject *private = (GdkWindowObject*) drawable;
 
4232
 
 
4233
  return gdk_region_copy (private->clip_region);
 
4234
}
 
4235
 
 
4236
static void
 
4237
gdk_window_draw_drawable (GdkDrawable *drawable,
 
4238
                          GdkGC       *gc,
 
4239
                          GdkPixmap   *src,
 
4240
                          gint         xsrc,
 
4241
                          gint         ysrc,
 
4242
                          gint         xdest,
 
4243
                          gint         ydest,
 
4244
                          gint         width,
 
4245
                          gint         height,
 
4246
                          GdkDrawable *original_src)
 
4247
{
 
4248
  GdkWindowObject *private = (GdkWindowObject *)drawable;
 
4249
 
 
4250
  if (GDK_WINDOW_DESTROYED (drawable))
 
4251
    return;
 
4252
 
 
4253
  BEGIN_DRAW;
 
4254
 
 
4255
  /* Call the method directly to avoid getting the composite drawable again */
 
4256
  GDK_DRAWABLE_GET_CLASS (impl)->draw_drawable_with_src (impl, gc,
 
4257
                                                         src,
 
4258
                                                         xsrc, ysrc,
 
4259
                                                         xdest - x_offset,
 
4260
                                                         ydest - y_offset,
 
4261
                                                         width, height,
 
4262
                                                         original_src);
 
4263
 
 
4264
  if (!private->paint_stack)
 
4265
    {
 
4266
      /* We might have drawn from an obscured part of a client
 
4267
         side window, if so we need to send graphics exposures */
 
4268
      if (_gdk_gc_get_exposures (gc) &&
 
4269
          GDK_IS_WINDOW (original_src))
 
4270
        {
 
4271
          GdkRegion *exposure_region;
 
4272
          GdkRegion *clip;
 
4273
          GdkRectangle r;
 
4274
 
 
4275
          r.x = xdest;
 
4276
          r.y = ydest;
 
4277
          r.width = width;
 
4278
          r.height = height;
 
4279
          exposure_region = gdk_region_rectangle (&r);
 
4280
 
 
4281
          if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
 
4282
            clip = private->clip_region_with_children;
 
4283
          else
 
4284
            clip = private->clip_region;
 
4285
          gdk_region_intersect (exposure_region, clip);
 
4286
 
 
4287
          _gdk_gc_remove_drawable_clip (gc);
 
4288
          clip = _gdk_gc_get_clip_region (gc);
 
4289
          if (clip)
 
4290
            {
 
4291
              gdk_region_offset (exposure_region,
 
4292
                                 old_clip_x,
 
4293
                                 old_clip_y);
 
4294
              gdk_region_intersect (exposure_region, clip);
 
4295
              gdk_region_offset (exposure_region,
 
4296
                                 -old_clip_x,
 
4297
                                 -old_clip_y);
 
4298
            }
 
4299
 
 
4300
          /* Note: We don't clip by the clip mask if set, so this
 
4301
             may invalidate to much */
 
4302
 
 
4303
          /* Remove the area that is correctly copied from the src.
 
4304
           * Note that xsrc/ysrc has been corrected for abs_x/y offsets already,
 
4305
           * which need to be undone */
 
4306
          clip = gdk_drawable_get_visible_region (original_src);
 
4307
          gdk_region_offset (clip,
 
4308
                             xdest - (xsrc - GDK_WINDOW_OBJECT (original_src)->abs_x),
 
4309
                             ydest - (ysrc - GDK_WINDOW_OBJECT (original_src)->abs_y));
 
4310
          gdk_region_subtract (exposure_region, clip);
 
4311
          gdk_region_destroy (clip);
 
4312
 
 
4313
          gdk_window_invalidate_region_full (GDK_WINDOW (private),
 
4314
                                              exposure_region,
 
4315
                                              _gdk_gc_get_subwindow (gc) == GDK_INCLUDE_INFERIORS,
 
4316
                                              CLEAR_BG_ALL);
 
4317
 
 
4318
          gdk_region_destroy (exposure_region);
 
4319
        }
 
4320
    }
 
4321
 
 
4322
  END_DRAW;
 
4323
}
 
4324
 
 
4325
static void
 
4326
gdk_window_draw_points (GdkDrawable *drawable,
 
4327
                        GdkGC       *gc,
 
4328
                        GdkPoint    *points,
 
4329
                        gint         npoints)
 
4330
{
 
4331
  GdkPoint *new_points;
 
4332
 
 
4333
  if (GDK_WINDOW_DESTROYED (drawable))
 
4334
    return;
 
4335
 
 
4336
  BEGIN_DRAW;
 
4337
 
 
4338
  if (x_offset != 0 || y_offset != 0)
 
4339
    {
 
4340
      gint i;
 
4341
 
 
4342
      new_points = g_new (GdkPoint, npoints);
 
4343
      for (i=0; i<npoints; i++)
 
4344
        {
 
4345
          new_points[i].x = points[i].x - x_offset;
 
4346
          new_points[i].y = points[i].y - y_offset;
 
4347
        }
 
4348
    }
 
4349
  else
 
4350
    new_points = points;
 
4351
 
 
4352
  gdk_draw_points (impl, gc, new_points, npoints);
 
4353
 
 
4354
  if (new_points != points)
 
4355
    g_free (new_points);
 
4356
 
 
4357
  END_DRAW;
 
4358
}
 
4359
 
 
4360
static void
 
4361
gdk_window_draw_segments (GdkDrawable *drawable,
 
4362
                          GdkGC       *gc,
 
4363
                          GdkSegment  *segs,
 
4364
                          gint         nsegs)
 
4365
{
 
4366
  GdkSegment *new_segs;
 
4367
 
 
4368
  if (GDK_WINDOW_DESTROYED (drawable))
 
4369
    return;
 
4370
 
 
4371
  BEGIN_DRAW;
 
4372
 
 
4373
  if (x_offset != 0 || y_offset != 0)
 
4374
    {
 
4375
      gint i;
 
4376
 
 
4377
      new_segs = g_new (GdkSegment, nsegs);
 
4378
      for (i=0; i<nsegs; i++)
 
4379
        {
 
4380
          new_segs[i].x1 = segs[i].x1 - x_offset;
 
4381
          new_segs[i].y1 = segs[i].y1 - y_offset;
 
4382
          new_segs[i].x2 = segs[i].x2 - x_offset;
 
4383
          new_segs[i].y2 = segs[i].y2 - y_offset;
 
4384
        }
 
4385
    }
 
4386
  else
 
4387
    new_segs = segs;
 
4388
 
 
4389
  gdk_draw_segments (impl, gc, new_segs, nsegs);
 
4390
 
 
4391
  if (new_segs != segs)
 
4392
    g_free (new_segs);
 
4393
 
 
4394
  END_DRAW;
 
4395
}
 
4396
 
 
4397
static void
 
4398
gdk_window_draw_lines (GdkDrawable *drawable,
 
4399
                       GdkGC       *gc,
 
4400
                       GdkPoint    *points,
 
4401
                       gint         npoints)
 
4402
{
 
4403
  GdkPoint *new_points;
 
4404
 
 
4405
  if (GDK_WINDOW_DESTROYED (drawable))
 
4406
    return;
 
4407
 
 
4408
  BEGIN_DRAW;
 
4409
 
 
4410
  if (x_offset != 0 || y_offset != 0)
 
4411
    {
 
4412
      gint i;
 
4413
 
 
4414
      new_points = g_new (GdkPoint, npoints);
 
4415
      for (i=0; i<npoints; i++)
 
4416
        {
 
4417
          new_points[i].x = points[i].x - x_offset;
 
4418
          new_points[i].y = points[i].y - y_offset;
 
4419
        }
 
4420
    }
 
4421
  else
 
4422
    new_points = points;
 
4423
 
 
4424
  gdk_draw_lines (impl, gc, new_points, npoints);
 
4425
 
 
4426
  if (new_points != points)
 
4427
    g_free (new_points);
 
4428
 
 
4429
  END_DRAW;
 
4430
}
 
4431
 
 
4432
static void
 
4433
gdk_window_draw_glyphs (GdkDrawable      *drawable,
 
4434
                        GdkGC            *gc,
 
4435
                        PangoFont        *font,
 
4436
                        gint              x,
 
4437
                        gint              y,
 
4438
                        PangoGlyphString *glyphs)
 
4439
{
 
4440
  if (GDK_WINDOW_DESTROYED (drawable))
 
4441
    return;
 
4442
 
 
4443
  BEGIN_DRAW;
 
4444
  gdk_draw_glyphs (impl, gc, font,
 
4445
                   x - x_offset, y - y_offset, glyphs);
 
4446
  END_DRAW;
 
4447
}
 
4448
 
 
4449
static void
 
4450
gdk_window_draw_glyphs_transformed (GdkDrawable      *drawable,
 
4451
                                    GdkGC            *gc,
 
4452
                                    PangoMatrix      *matrix,
 
4453
                                    PangoFont        *font,
 
4454
                                    gint              x,
 
4455
                                    gint              y,
 
4456
                                    PangoGlyphString *glyphs)
 
4457
{
 
4458
  PangoMatrix tmp_matrix;
 
4459
 
 
4460
  if (GDK_WINDOW_DESTROYED (drawable))
 
4461
    return;
 
4462
 
 
4463
  BEGIN_DRAW;
 
4464
 
 
4465
  if (x_offset != 0 || y_offset != 0)
 
4466
    {
 
4467
      if (matrix)
 
4468
        {
 
4469
          tmp_matrix = *matrix;
 
4470
          tmp_matrix.x0 -= x_offset;
 
4471
          tmp_matrix.y0 -= y_offset;
 
4472
          matrix = &tmp_matrix;
 
4473
        }
 
4474
      else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
 
4475
        {
 
4476
          PangoMatrix identity = PANGO_MATRIX_INIT;
 
4477
 
 
4478
          tmp_matrix = identity;
 
4479
          tmp_matrix.x0 -= x_offset;
 
4480
          tmp_matrix.y0 -= y_offset;
 
4481
          matrix = &tmp_matrix;
 
4482
        }
 
4483
      else
 
4484
        {
 
4485
          x -= x_offset * PANGO_SCALE;
 
4486
          y -= y_offset * PANGO_SCALE;
 
4487
        }
 
4488
    }
 
4489
 
 
4490
  gdk_draw_glyphs_transformed (impl, gc, matrix, font, x, y, glyphs);
 
4491
 
 
4492
  END_DRAW;
 
4493
}
 
4494
 
 
4495
typedef struct {
 
4496
  cairo_t *cr; /* if non-null, it means use this cairo context */
 
4497
  GdkGC *gc;   /* if non-null, it means use this GC instead */
 
4498
} BackingRectMethod;
 
4499
 
 
4500
static void
 
4501
setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
 
4502
{
 
4503
  GdkWindowObject *private = (GdkWindowObject *)window;
 
4504
 
 
4505
  if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
 
4506
    {
 
4507
      GdkWindowPaint tmp_paint;
 
4508
 
 
4509
      tmp_paint = *paint;
 
4510
      tmp_paint.x_offset += private->x;
 
4511
      tmp_paint.y_offset += private->y;
 
4512
 
 
4513
      x_offset_cairo += private->x;
 
4514
      y_offset_cairo += private->y;
 
4515
 
 
4516
      setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
 
4517
    }
 
4518
  else if (private->bg_pixmap &&
 
4519
           private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
 
4520
           private->bg_pixmap != GDK_NO_BG)
 
4521
    {
 
4522
/* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
 
4523
 * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
 
4524
 * pixmap destination surface, can be very slow (on the order of seconds for a
 
4525
 * whole-screen copy).  The workaround is to use pretty much the same code that
 
4526
 * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
 
4527
 * a tiled GC XFillRectangle().
 
4528
 */
 
4529
 
 
4530
/* Actually computing this flag is left as an exercise for the reader */
 
4531
#if defined (G_OS_UNIX)
 
4532
#  define GDK_CAIRO_REPEAT_IS_FAST 0
 
4533
#else
 
4534
#  define GDK_CAIRO_REPEAT_IS_FAST 1
 
4535
#endif
 
4536
 
 
4537
#if GDK_CAIRO_REPEAT_IS_FAST
 
4538
      cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
 
4539
      cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
 
4540
      cairo_surface_destroy (surface);
 
4541
 
 
4542
      if (x_offset_cairo != 0 || y_offset_cairo != 0)
 
4543
        {
 
4544
          cairo_matrix_t matrix;
 
4545
          cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
 
4546
          cairo_pattern_set_matrix (pattern, &matrix);
 
4547
        }
 
4548
 
 
4549
      cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
 
4550
 
 
4551
      method->cr = cairo_create (paint->surface);
 
4552
      method->gc = NULL;
 
4553
 
 
4554
      cairo_set_source (method->cr, pattern);
 
4555
      cairo_pattern_destroy (pattern);
 
4556
#else
 
4557
      guint gc_mask;
 
4558
      GdkGCValues gc_values;
 
4559
 
 
4560
      gc_values.fill = GDK_TILED;
 
4561
      gc_values.tile = private->bg_pixmap;
 
4562
      gc_values.ts_x_origin = -x_offset_cairo;
 
4563
      gc_values.ts_y_origin = -y_offset_cairo;
 
4564
 
 
4565
      gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
 
4566
 
 
4567
      method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
 
4568
#endif
 
4569
    }
 
4570
  else
 
4571
    {
 
4572
      method->cr = cairo_create (paint->surface);
 
4573
 
 
4574
      gdk_cairo_set_source_color (method->cr, &private->bg_color);
 
4575
    }
 
4576
}
 
4577
 
 
4578
static void
 
4579
gdk_window_clear_backing_region (GdkWindow *window,
 
4580
                                 GdkRegion *region)
 
4581
{
 
4582
  GdkWindowObject *private = (GdkWindowObject *)window;
 
4583
  GdkWindowPaint *paint = private->paint_stack->data;
 
4584
  BackingRectMethod method;
 
4585
  GdkRegion *clip;
 
4586
  GdkRectangle clipbox;
 
4587
#if 0
 
4588
  GTimer *timer;
 
4589
  double elapsed;
 
4590
#endif
 
4591
 
 
4592
  if (GDK_WINDOW_DESTROYED (window))
 
4593
    return;
 
4594
 
 
4595
#if 0
 
4596
  timer = g_timer_new ();
 
4597
#endif
 
4598
 
 
4599
  method.cr = NULL;
 
4600
  method.gc = NULL;
 
4601
  setup_backing_rect_method (&method, window, paint, 0, 0);
 
4602
 
 
4603
  clip = gdk_region_copy (paint->region);
 
4604
  gdk_region_intersect (clip, region);
 
4605
  gdk_region_get_clipbox (clip, &clipbox);
 
4606
 
 
4607
 
 
4608
  if (method.cr)
 
4609
    {
 
4610
      g_assert (method.gc == NULL);
 
4611
 
 
4612
      gdk_cairo_region (method.cr, clip);
 
4613
      cairo_fill (method.cr);
 
4614
 
 
4615
      cairo_destroy (method.cr);
 
4616
#if 0
 
4617
      elapsed = g_timer_elapsed (timer, NULL);
 
4618
      g_print ("Draw the background with Cairo: %fs\n", elapsed);
 
4619
#endif
 
4620
    }
 
4621
  else
 
4622
    {
 
4623
      g_assert (method.gc != NULL);
 
4624
 
 
4625
      gdk_gc_set_clip_region (method.gc, clip);
 
4626
      gdk_draw_rectangle (window, method.gc, TRUE,
 
4627
                          clipbox.x, clipbox.y,
 
4628
                          clipbox.width, clipbox.height);
 
4629
      g_object_unref (method.gc);
 
4630
 
 
4631
#if 0
 
4632
      elapsed = g_timer_elapsed (timer, NULL);
 
4633
      g_print ("Draw the background with GDK: %fs\n", elapsed);
 
4634
#endif
 
4635
    }
 
4636
 
 
4637
  gdk_region_destroy (clip);
 
4638
 
 
4639
#if 0
 
4640
  g_timer_destroy (timer);
 
4641
#endif
 
4642
}
 
4643
 
 
4644
static void
 
4645
gdk_window_clear_backing_region_redirect (GdkWindow *window,
 
4646
                                          GdkRegion *region)
 
4647
{
 
4648
  GdkWindowObject *private = (GdkWindowObject *)window;
 
4649
  GdkWindowRedirect *redirect = private->redirect;
 
4650
  GdkRegion *clip_region;
 
4651
  GdkRectangle clipbox;
 
4652
  gint x_offset, y_offset;
 
4653
  BackingRectMethod method;
 
4654
  GdkWindowPaint paint;
 
4655
 
 
4656
  if (GDK_WINDOW_DESTROYED (window))
 
4657
    return;
 
4658
 
 
4659
  clip_region = _gdk_window_calculate_full_clip_region (window,
 
4660
                                                        GDK_WINDOW (redirect->redirected),
 
4661
                                                        TRUE,
 
4662
                                                        &x_offset, &y_offset);
 
4663
  gdk_region_intersect (clip_region, region);
 
4664
 
 
4665
  /* offset is from redirected window origin to window origin, convert to
 
4666
     the offset from the redirected pixmap origin to the window origin */
 
4667
  x_offset += redirect->dest_x - redirect->src_x;
 
4668
  y_offset += redirect->dest_y - redirect->src_y;
 
4669
 
 
4670
  /* Convert region to pixmap coords */
 
4671
  gdk_region_offset (clip_region, x_offset, y_offset);
 
4672
 
 
4673
  paint.x_offset = 0;
 
4674
  paint.y_offset = 0;
 
4675
  paint.pixmap = redirect->pixmap;
 
4676
  paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
 
4677
 
 
4678
  method.cr = NULL;
 
4679
  method.gc = NULL;
 
4680
  setup_backing_rect_method (&method, window, &paint, -x_offset, -y_offset);
 
4681
 
 
4682
  if (method.cr)
 
4683
    {
 
4684
      g_assert (method.gc == NULL);
 
4685
 
 
4686
      gdk_cairo_region (method.cr, clip_region);
 
4687
      cairo_fill (method.cr);
 
4688
 
 
4689
      cairo_destroy (method.cr);
 
4690
    }
 
4691
  else
 
4692
    {
 
4693
      g_assert (method.gc != NULL);
 
4694
 
 
4695
      gdk_region_get_clipbox (clip_region, &clipbox);
 
4696
      gdk_gc_set_clip_region (method.gc, clip_region);
 
4697
      gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE,
 
4698
                          clipbox.x, clipbox.y,
 
4699
                          clipbox.width, clipbox.height);
 
4700
      g_object_unref (method.gc);
 
4701
 
 
4702
    }
 
4703
 
 
4704
  gdk_region_destroy (clip_region);
 
4705
  cairo_surface_destroy (paint.surface);
 
4706
}
 
4707
 
 
4708
static void
 
4709
gdk_window_clear_backing_region_direct (GdkWindow *window,
 
4710
                                        GdkRegion *region)
 
4711
{
 
4712
  GdkWindowObject *private = (GdkWindowObject *)window;
 
4713
  BackingRectMethod method;
 
4714
  GdkWindowPaint paint;
 
4715
  GdkRegion *clip;
 
4716
  GdkRectangle clipbox;
 
4717
 
 
4718
  if (GDK_WINDOW_DESTROYED (window))
 
4719
    return;
 
4720
 
 
4721
  paint.x_offset = 0;
 
4722
  paint.y_offset = 0;
 
4723
  paint.pixmap = window;
 
4724
  paint.surface = _gdk_drawable_ref_cairo_surface (window);
 
4725
 
 
4726
  method.cr = NULL;
 
4727
  method.gc = NULL;
 
4728
  setup_backing_rect_method (&method, window, &paint, 0, 0);
 
4729
 
 
4730
  clip = gdk_region_copy (private->clip_region_with_children);
 
4731
  gdk_region_intersect (clip, region);
 
4732
  gdk_region_get_clipbox (clip, &clipbox);
 
4733
 
 
4734
  if (method.cr)
 
4735
    {
 
4736
      g_assert (method.gc == NULL);
 
4737
 
 
4738
      gdk_cairo_region (method.cr, clip);
 
4739
      cairo_fill (method.cr);
 
4740
 
 
4741
      cairo_destroy (method.cr);
 
4742
    }
 
4743
  else
 
4744
    {
 
4745
      g_assert (method.gc != NULL);
 
4746
 
 
4747
      gdk_gc_set_clip_region (method.gc, clip);
 
4748
      gdk_draw_rectangle (window, method.gc, TRUE,
 
4749
                          clipbox.x, clipbox.y,
 
4750
                          clipbox.width, clipbox.height);
 
4751
      g_object_unref (method.gc);
 
4752
 
 
4753
    }
 
4754
 
 
4755
  gdk_region_destroy (clip);
 
4756
  cairo_surface_destroy (paint.surface);
 
4757
}
 
4758
 
 
4759
 
 
4760
/**
 
4761
 * gdk_window_clear:
 
4762
 * @window: a #GdkWindow
 
4763
 *
 
4764
 * Clears an entire @window to the background color or background pixmap.
 
4765
 **/
 
4766
void
 
4767
gdk_window_clear (GdkWindow *window)
 
4768
{
 
4769
  gint width, height;
 
4770
 
 
4771
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4772
 
 
4773
  gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
 
4774
 
 
4775
  gdk_window_clear_area (window, 0, 0,
 
4776
                         width, height);
 
4777
}
 
4778
 
 
4779
/* TRUE if the window clears to the same pixels as a native
 
4780
   window clear. This means you can use the native window
 
4781
   clearing operation, and additionally it means any clearing
 
4782
   done by the native window system for you will already be right */
 
4783
static gboolean
 
4784
clears_as_native (GdkWindowObject *private)
 
4785
{
 
4786
  GdkWindowObject *next;
 
4787
 
 
4788
  next = private;
 
4789
  do
 
4790
    {
 
4791
      private = next;
 
4792
      if (gdk_window_has_impl (private))
 
4793
        return TRUE;
 
4794
      next = private->parent;
 
4795
    }
 
4796
  while (private->bg_pixmap == GDK_PARENT_RELATIVE_BG &&
 
4797
         next && next->window_type != GDK_WINDOW_ROOT);
 
4798
  return FALSE;
 
4799
}
 
4800
 
 
4801
static void
 
4802
gdk_window_clear_region_internal (GdkWindow *window,
 
4803
                                  GdkRegion *region,
 
4804
                                  gboolean   send_expose)
 
4805
{
 
4806
  GdkWindowObject *private = (GdkWindowObject *)window;
 
4807
  GdkWindowImplIface *impl_iface;
 
4808
 
 
4809
  if (private->paint_stack)
 
4810
    gdk_window_clear_backing_region (window, region);
 
4811
  else
 
4812
    {
 
4813
      if (private->redirect)
 
4814
        gdk_window_clear_backing_region_redirect (window, region);
 
4815
 
 
4816
      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
4817
 
 
4818
      if (impl_iface->clear_region && clears_as_native (private))
 
4819
        {
 
4820
          GdkRegion *copy;
 
4821
          copy = gdk_region_copy (region);
 
4822
          gdk_region_intersect (copy,
 
4823
                                private->clip_region_with_children);
 
4824
 
 
4825
 
 
4826
          /* Drawing directly to the window, flush anything outstanding to
 
4827
             guarantee ordering. */
 
4828
          gdk_window_flush (window);
 
4829
          impl_iface->clear_region (window, copy, send_expose);
 
4830
 
 
4831
          gdk_region_destroy (copy);
 
4832
        }
 
4833
      else
 
4834
        {
 
4835
          gdk_window_clear_backing_region_direct (window, region);
 
4836
          if (send_expose)
 
4837
            gdk_window_invalidate_region (window, region, FALSE);
 
4838
        }
 
4839
    }
 
4840
}
 
4841
 
 
4842
static void
 
4843
gdk_window_clear_area_internal (GdkWindow *window,
 
4844
                                gint       x,
 
4845
                                gint       y,
 
4846
                                gint       width,
 
4847
                                gint       height,
 
4848
                                gboolean   send_expose)
 
4849
{
 
4850
  GdkRectangle rect;
 
4851
  GdkRegion *region;
 
4852
 
 
4853
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4854
 
 
4855
  if (GDK_WINDOW_DESTROYED (window))
 
4856
    return;
 
4857
 
 
4858
  /* Terminate early to avoid weird interpretation of
 
4859
     zero width/height by XClearArea */
 
4860
  if (width == 0 || height == 0)
 
4861
    return;
 
4862
 
 
4863
  rect.x = x;
 
4864
  rect.y = y;
 
4865
  rect.width = width;
 
4866
  rect.height = height;
 
4867
 
 
4868
  region = gdk_region_rectangle (&rect);
 
4869
  gdk_window_clear_region_internal (window,
 
4870
                                    region,
 
4871
                                    send_expose);
 
4872
  gdk_region_destroy (region);
 
4873
 
 
4874
}
 
4875
 
 
4876
/**
 
4877
 * gdk_window_clear_area:
 
4878
 * @window: a #GdkWindow
 
4879
 * @x: x coordinate of rectangle to clear
 
4880
 * @y: y coordinate of rectangle to clear
 
4881
 * @width: width of rectangle to clear
 
4882
 * @height: height of rectangle to clear
 
4883
 *
 
4884
 * Clears an area of @window to the background color or background pixmap.
 
4885
 *
 
4886
 **/
 
4887
void
 
4888
gdk_window_clear_area (GdkWindow *window,
 
4889
                       gint       x,
 
4890
                       gint       y,
 
4891
                       gint       width,
 
4892
                       gint       height)
 
4893
{
 
4894
  gdk_window_clear_area_internal (window,
 
4895
                                  x, y,
 
4896
                                  width, height,
 
4897
                                  FALSE);
 
4898
}
 
4899
 
 
4900
/**
 
4901
 * gdk_window_clear_area_e:
 
4902
 * @window: a #GdkWindow
 
4903
 * @x: x coordinate of rectangle to clear
 
4904
 * @y: y coordinate of rectangle to clear
 
4905
 * @width: width of rectangle to clear
 
4906
 * @height: height of rectangle to clear
 
4907
 *
 
4908
 * Like gdk_window_clear_area(), but also generates an expose event for
 
4909
 * the cleared area.
 
4910
 *
 
4911
 * This function has a stupid name because it dates back to the mists
 
4912
 * time, pre-GDK-1.0.
 
4913
 *
 
4914
 **/
 
4915
void
 
4916
gdk_window_clear_area_e (GdkWindow *window,
 
4917
                         gint       x,
 
4918
                         gint       y,
 
4919
                         gint       width,
 
4920
                         gint       height)
 
4921
{
 
4922
  gdk_window_clear_area_internal (window,
 
4923
                                  x, y,
 
4924
                                  width, height,
 
4925
                                  TRUE);
 
4926
}
 
4927
 
 
4928
static void
 
4929
gdk_window_draw_image (GdkDrawable *drawable,
 
4930
                       GdkGC       *gc,
 
4931
                       GdkImage    *image,
 
4932
                       gint         xsrc,
 
4933
                       gint         ysrc,
 
4934
                       gint         xdest,
 
4935
                       gint         ydest,
 
4936
                       gint         width,
 
4937
                       gint         height)
 
4938
{
 
4939
  if (GDK_WINDOW_DESTROYED (drawable))
 
4940
    return;
 
4941
 
 
4942
  BEGIN_DRAW;
 
4943
  gdk_draw_image (impl, gc, image, xsrc, ysrc,
 
4944
                  xdest - x_offset, ydest - y_offset,
 
4945
                  width, height);
 
4946
  END_DRAW;
 
4947
}
 
4948
 
 
4949
static void
 
4950
gdk_window_draw_pixbuf (GdkDrawable     *drawable,
 
4951
                        GdkGC           *gc,
 
4952
                        GdkPixbuf       *pixbuf,
 
4953
                        gint             src_x,
 
4954
                        gint             src_y,
 
4955
                        gint             dest_x,
 
4956
                        gint             dest_y,
 
4957
                        gint             width,
 
4958
                        gint             height,
 
4959
                        GdkRgbDither     dither,
 
4960
                        gint             x_dither,
 
4961
                        gint             y_dither)
 
4962
{
 
4963
  GdkWindowObject *private = (GdkWindowObject *)drawable;
 
4964
  GdkDrawableClass *klass;
 
4965
 
 
4966
  if (GDK_WINDOW_DESTROYED (drawable))
 
4967
    return;
 
4968
 
 
4969
  /* If no gc => no user clipping, but we need clipping
 
4970
     for window emulation, so use a scratch gc */
 
4971
  if (!gc)
 
4972
    gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
 
4973
 
 
4974
  BEGIN_DRAW;
 
4975
 
 
4976
  klass = GDK_DRAWABLE_GET_CLASS (impl);
 
4977
 
 
4978
  if (private->paint_stack)
 
4979
    klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
 
4980
                        dest_x - x_offset, dest_y - y_offset,
 
4981
                        width, height,
 
4982
                        dither, x_dither - x_offset, y_dither - y_offset);
 
4983
  else
 
4984
    klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
 
4985
                        dest_x - x_offset, dest_y - y_offset,
 
4986
                        width, height,
 
4987
                        dither, x_dither, y_dither);
 
4988
  END_DRAW;
 
4989
}
 
4990
 
 
4991
static void
 
4992
gdk_window_draw_trapezoids (GdkDrawable   *drawable,
 
4993
                            GdkGC         *gc,
 
4994
                            GdkTrapezoid  *trapezoids,
 
4995
                            gint           n_trapezoids)
 
4996
{
 
4997
  GdkTrapezoid *new_trapezoids = NULL;
 
4998
 
 
4999
  if (GDK_WINDOW_DESTROYED (drawable))
 
5000
    return;
 
5001
 
 
5002
  BEGIN_DRAW;
 
5003
 
 
5004
  if (x_offset != 0 || y_offset != 0)
 
5005
    {
 
5006
      gint i;
 
5007
 
 
5008
      new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
 
5009
      for (i=0; i < n_trapezoids; i++)
 
5010
        {
 
5011
          new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
 
5012
          new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
 
5013
          new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
 
5014
          new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
 
5015
          new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
 
5016
          new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
 
5017
        }
 
5018
 
 
5019
      trapezoids = new_trapezoids;
 
5020
    }
 
5021
 
 
5022
  gdk_draw_trapezoids (impl, gc, trapezoids, n_trapezoids);
 
5023
 
 
5024
  g_free (new_trapezoids);
 
5025
 
 
5026
  END_DRAW;
 
5027
}
 
5028
 
 
5029
static void
 
5030
gdk_window_real_get_size (GdkDrawable *drawable,
 
5031
                          gint *width,
 
5032
                          gint *height)
 
5033
{
 
5034
  GdkWindowObject *private = (GdkWindowObject *)drawable;
 
5035
 
 
5036
  if (width)
 
5037
    *width = private->width;
 
5038
  if (height)
 
5039
    *height = private->height;
 
5040
}
 
5041
 
 
5042
static GdkVisual*
 
5043
gdk_window_real_get_visual (GdkDrawable *drawable)
 
5044
{
 
5045
  GdkColormap *colormap;
 
5046
 
 
5047
  g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
 
5048
 
 
5049
  colormap = gdk_drawable_get_colormap (drawable);
 
5050
  return colormap ? gdk_colormap_get_visual (colormap) : NULL;
 
5051
}
 
5052
 
 
5053
static gint
 
5054
gdk_window_real_get_depth (GdkDrawable *drawable)
 
5055
{
 
5056
  g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
 
5057
 
 
5058
  return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
 
5059
}
 
5060
 
 
5061
static GdkScreen*
 
5062
gdk_window_real_get_screen (GdkDrawable *drawable)
 
5063
{
 
5064
  return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
 
5065
}
 
5066
 
 
5067
static void
 
5068
gdk_window_real_set_colormap (GdkDrawable *drawable,
 
5069
                              GdkColormap *cmap)
 
5070
{
 
5071
  GdkWindowObject *private;
 
5072
 
 
5073
  g_return_if_fail (GDK_IS_WINDOW (drawable));
 
5074
 
 
5075
  if (GDK_WINDOW_DESTROYED (drawable))
 
5076
    return;
 
5077
 
 
5078
  private = (GdkWindowObject *)drawable;
 
5079
 
 
5080
  /* different colormap than parent, requires native window */
 
5081
  if (!private->input_only &&
 
5082
      cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
 
5083
    gdk_window_ensure_native ((GdkWindow *)drawable);
 
5084
 
 
5085
  gdk_drawable_set_colormap (private->impl, cmap);
 
5086
}
 
5087
 
 
5088
static GdkColormap*
 
5089
gdk_window_real_get_colormap (GdkDrawable *drawable)
 
5090
{
 
5091
  g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
 
5092
 
 
5093
  if (GDK_WINDOW_DESTROYED (drawable))
 
5094
    return NULL;
 
5095
 
 
5096
  return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
 
5097
}
 
5098
 
 
5099
static GdkImage*
 
5100
gdk_window_copy_to_image (GdkDrawable     *drawable,
 
5101
                          GdkImage        *image,
 
5102
                          gint             src_x,
 
5103
                          gint             src_y,
 
5104
                          gint             dest_x,
 
5105
                          gint             dest_y,
 
5106
                          gint             width,
 
5107
                          gint             height)
 
5108
{
 
5109
  GdkWindowObject *private = (GdkWindowObject *) drawable;
 
5110
  gint x_offset, y_offset;
 
5111
 
 
5112
  g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
 
5113
 
 
5114
  if (GDK_WINDOW_DESTROYED (drawable))
 
5115
    return NULL;
 
5116
 
 
5117
  /* If we're here, a composite image was not necessary, so
 
5118
   * we can ignore the paint stack.
 
5119
   */
 
5120
 
 
5121
  /* TODO: Is this right? */
 
5122
  x_offset = 0;
 
5123
  y_offset = 0;
 
5124
 
 
5125
  return gdk_drawable_copy_to_image (private->impl,
 
5126
                                     image,
 
5127
                                     src_x - x_offset,
 
5128
                                     src_y - y_offset,
 
5129
                                     dest_x, dest_y,
 
5130
                                     width, height);
 
5131
}
 
5132
 
 
5133
static void
 
5134
gdk_window_drop_cairo_surface (GdkWindowObject *private)
 
5135
{
 
5136
  if (private->cairo_surface)
 
5137
    {
 
5138
      cairo_surface_finish (private->cairo_surface);
 
5139
      cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
 
5140
                                   NULL, NULL);
 
5141
    }
 
5142
}
 
5143
 
 
5144
static void
 
5145
gdk_window_cairo_surface_destroy (void *data)
 
5146
{
 
5147
  GdkWindowObject *private = (GdkWindowObject*) data;
 
5148
 
 
5149
  private->cairo_surface = NULL;
 
5150
  private->impl_window->outstanding_surfaces--;
 
5151
}
 
5152
 
 
5153
static cairo_surface_t *
 
5154
gdk_window_create_cairo_surface (GdkDrawable *drawable,
 
5155
                                 int width,
 
5156
                                 int height)
 
5157
{
 
5158
  return _gdk_windowing_create_cairo_surface (GDK_WINDOW_OBJECT(drawable)->impl,
 
5159
                                              width, height);
 
5160
}
 
5161
 
 
5162
 
 
5163
static cairo_surface_t *
 
5164
gdk_window_ref_cairo_surface (GdkDrawable *drawable)
 
5165
{
 
5166
  GdkWindowObject *private = (GdkWindowObject*) drawable;
 
5167
  cairo_surface_t *surface;
 
5168
 
 
5169
  if (private->paint_stack)
 
5170
    {
 
5171
      GdkWindowPaint *paint = private->paint_stack->data;
 
5172
 
 
5173
      surface = paint->surface;
 
5174
      cairo_surface_reference (surface);
 
5175
    }
 
5176
  else
 
5177
    {
 
5178
 
 
5179
      /* This will be drawing directly to the window, so flush implicit paint */
 
5180
      gdk_window_flush ((GdkWindow *)drawable);
 
5181
 
 
5182
      if (!private->cairo_surface)
 
5183
        {
 
5184
          int width, height;
 
5185
          GdkDrawable *source;
 
5186
 
 
5187
          gdk_drawable_get_size ((GdkWindow *) private->impl_window,
 
5188
                                 &width, &height);
 
5189
 
 
5190
          source = _gdk_drawable_get_source_drawable (drawable);
 
5191
 
 
5192
          private->cairo_surface = _gdk_drawable_create_cairo_surface (source, width, height);
 
5193
 
 
5194
          if (private->cairo_surface)
 
5195
            {
 
5196
              private->impl_window->outstanding_surfaces++;
 
5197
 
 
5198
              cairo_surface_set_device_offset (private->cairo_surface,
 
5199
                                               private->abs_x,
 
5200
                                               private->abs_y);
 
5201
 
 
5202
              cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
 
5203
                                           drawable, gdk_window_cairo_surface_destroy);
 
5204
            }
 
5205
        }
 
5206
      else
 
5207
        cairo_surface_reference (private->cairo_surface);
 
5208
 
 
5209
      surface = private->cairo_surface;
 
5210
    }
 
5211
 
 
5212
  return surface;
 
5213
}
 
5214
 
 
5215
static void
 
5216
gdk_window_set_cairo_clip (GdkDrawable *drawable,
 
5217
                           cairo_t *cr)
 
5218
{
 
5219
  GdkWindowObject *private = (GdkWindowObject*) drawable;
 
5220
 
 
5221
  if (!private->paint_stack)
 
5222
    {
 
5223
      cairo_reset_clip (cr);
 
5224
 
 
5225
      cairo_save (cr);
 
5226
      cairo_identity_matrix (cr);
 
5227
 
 
5228
      cairo_new_path (cr);
 
5229
      gdk_cairo_region (cr, private->clip_region_with_children);
 
5230
 
 
5231
      cairo_restore (cr);
 
5232
      cairo_clip (cr);
 
5233
    }
 
5234
  else
 
5235
    {
 
5236
      GdkWindowPaint *paint = private->paint_stack->data;
 
5237
 
 
5238
      /* Only needs to clip to region if piggybacking
 
5239
         on an implicit paint pixmap */
 
5240
      cairo_reset_clip (cr);
 
5241
      if (paint->uses_implicit)
 
5242
        {
 
5243
          cairo_save (cr);
 
5244
          cairo_identity_matrix (cr);
 
5245
 
 
5246
          cairo_new_path (cr);
 
5247
          gdk_cairo_region (cr, paint->region);
 
5248
          cairo_restore (cr);
 
5249
 
 
5250
          cairo_clip (cr);
 
5251
        }
 
5252
    }
 
5253
}
 
5254
 
 
5255
/* Code for dirty-region queueing
 
5256
 */
 
5257
static GSList *update_windows = NULL;
 
5258
static guint update_idle = 0;
 
5259
static gboolean debug_updates = FALSE;
 
5260
 
 
5261
static inline gboolean
 
5262
gdk_window_is_ancestor (GdkWindow *window,
 
5263
                        GdkWindow *ancestor)
 
5264
{
 
5265
  while (window)
 
5266
    {
 
5267
      GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
 
5268
 
 
5269
      if (parent == ancestor)
 
5270
        return TRUE;
 
5271
 
 
5272
      window = parent;
 
5273
    }
 
5274
 
 
5275
  return FALSE;
 
5276
}
 
5277
 
 
5278
static void
 
5279
gdk_window_add_update_window (GdkWindow *window)
 
5280
{
 
5281
  GSList *tmp;
 
5282
  GSList *prev = NULL;
 
5283
  gboolean has_ancestor_in_list = FALSE;
 
5284
 
 
5285
  /*  Check whether "window" is already in "update_windows" list.
 
5286
   *  It could be added during execution of gtk_widget_destroy() when
 
5287
   *  setting focus widget to NULL and redrawing old focus widget.
 
5288
   *  See bug 711552.
 
5289
   */
 
5290
  tmp = g_slist_find (update_windows, window);
 
5291
  if (tmp != NULL)
 
5292
    return;
 
5293
 
 
5294
  for (tmp = update_windows; tmp; tmp = tmp->next)
 
5295
    {
 
5296
      GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
 
5297
 
 
5298
      /*  check if tmp is an ancestor of "window"; if it is, set a
 
5299
       *  flag indicating that all following windows are either
 
5300
       *  children of "window" or from a differen hierarchy
 
5301
       */
 
5302
      if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
 
5303
        has_ancestor_in_list = TRUE;
 
5304
 
 
5305
      /* insert in reverse stacking order when adding around siblings,
 
5306
       * so processing updates properly paints over lower stacked windows
 
5307
       */
 
5308
      if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
 
5309
        {
 
5310
          gint index = g_list_index (parent->children, window);
 
5311
          for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
 
5312
            {
 
5313
              gint sibling_index = g_list_index (parent->children, tmp->data);
 
5314
              if (index > sibling_index)
 
5315
                break;
 
5316
              prev = tmp;
 
5317
            }
 
5318
          /* here, tmp got advanced past all lower stacked siblings */
 
5319
          tmp = g_slist_prepend (tmp, g_object_ref (window));
 
5320
          if (prev)
 
5321
            prev->next = tmp;
 
5322
          else
 
5323
            update_windows = tmp;
 
5324
          return;
 
5325
        }
 
5326
 
 
5327
      /*  if "window" has an ancestor in the list and tmp is one of
 
5328
       *  "window's" children, insert "window" before tmp
 
5329
       */
 
5330
      if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
 
5331
        {
 
5332
          tmp = g_slist_prepend (tmp, g_object_ref (window));
 
5333
 
 
5334
          if (prev)
 
5335
            prev->next = tmp;
 
5336
          else
 
5337
            update_windows = tmp;
 
5338
          return;
 
5339
        }
 
5340
 
 
5341
      /*  if we're at the end of the list and had an ancestor it it,
 
5342
       *  append to the list
 
5343
       */
 
5344
      if (! tmp->next && has_ancestor_in_list)
 
5345
        {
 
5346
          tmp = g_slist_append (tmp, g_object_ref (window));
 
5347
          return;
 
5348
        }
 
5349
 
 
5350
      prev = tmp;
 
5351
    }
 
5352
 
 
5353
  /*  if all above checks failed ("window" is from a different
 
5354
   *  hierarchy than what is already in the list) or the list is
 
5355
   *  empty, prepend
 
5356
   */
 
5357
  update_windows = g_slist_prepend (update_windows, g_object_ref (window));
 
5358
}
 
5359
 
 
5360
static void
 
5361
gdk_window_remove_update_window (GdkWindow *window)
 
5362
{
 
5363
  GSList *link;
 
5364
 
 
5365
  link = g_slist_find (update_windows, window);
 
5366
  if (link != NULL)
 
5367
    {
 
5368
      update_windows = g_slist_delete_link (update_windows, link);
 
5369
      g_object_unref (window);
 
5370
    }
 
5371
}
 
5372
 
 
5373
static gboolean
 
5374
gdk_window_update_idle (gpointer data)
 
5375
{
 
5376
  gdk_window_process_all_updates ();
 
5377
 
 
5378
  return FALSE;
 
5379
}
 
5380
 
 
5381
static gboolean
 
5382
gdk_window_is_toplevel_frozen (GdkWindow *window)
 
5383
{
 
5384
  GdkWindowObject *toplevel;
 
5385
 
 
5386
  toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
 
5387
 
 
5388
  return toplevel->update_and_descendants_freeze_count > 0;
 
5389
}
 
5390
 
 
5391
static void
 
5392
gdk_window_schedule_update (GdkWindow *window)
 
5393
{
 
5394
  if (window &&
 
5395
      (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
 
5396
       gdk_window_is_toplevel_frozen (window)))
 
5397
    return;
 
5398
 
 
5399
  if (!update_idle)
 
5400
    update_idle =
 
5401
      gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
 
5402
                                 gdk_window_update_idle,
 
5403
                                 NULL, NULL);
 
5404
}
 
5405
 
 
5406
void
 
5407
_gdk_window_process_updates_recurse (GdkWindow *window,
 
5408
                                     GdkRegion *expose_region)
 
5409
{
 
5410
  GdkWindowObject *private = (GdkWindowObject *)window;
 
5411
  GdkWindowObject *child;
 
5412
  GdkRegion *child_region;
 
5413
  GdkRectangle r;
 
5414
  GList *l, *children;
 
5415
 
 
5416
  if (gdk_region_empty (expose_region))
 
5417
    return;
 
5418
 
 
5419
  /* Make this reentrancy safe for expose handlers freeing windows */
 
5420
  children = g_list_copy (private->children);
 
5421
  g_list_foreach (children, (GFunc)g_object_ref, NULL);
 
5422
 
 
5423
  /* Iterate over children, starting at topmost */
 
5424
  for (l = children; l != NULL; l = l->next)
 
5425
    {
 
5426
      child = l->data;
 
5427
 
 
5428
      if (child->destroyed || !GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
 
5429
        continue;
 
5430
 
 
5431
      /* Ignore offscreen children, as they don't draw in their parent and
 
5432
       * don't take part in the clipping */
 
5433
      if (gdk_window_is_offscreen (child))
 
5434
        continue;
 
5435
 
 
5436
      r.x = child->x;
 
5437
      r.y = child->y;
 
5438
      r.width = child->width;
 
5439
      r.height = child->height;
 
5440
 
 
5441
      child_region = gdk_region_rectangle (&r);
 
5442
      if (child->shape)
 
5443
        {
 
5444
          /* Adjust shape region to parent window coords */
 
5445
          gdk_region_offset (child->shape, child->x, child->y);
 
5446
          gdk_region_intersect (child_region, child->shape);
 
5447
          gdk_region_offset (child->shape, -child->x, -child->y);
 
5448
        }
 
5449
 
 
5450
      if (child->impl == private->impl)
 
5451
        {
 
5452
          /* Client side child, expose */
 
5453
          gdk_region_intersect (child_region, expose_region);
 
5454
          gdk_region_subtract (expose_region, child_region);
 
5455
          gdk_region_offset (child_region, -child->x, -child->y);
 
5456
          _gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
 
5457
        }
 
5458
      else
 
5459
        {
 
5460
          /* Native child, just remove area from expose region */
 
5461
          gdk_region_subtract (expose_region, child_region);
 
5462
        }
 
5463
      gdk_region_destroy (child_region);
 
5464
    }
 
5465
 
 
5466
  g_list_foreach (children, (GFunc)g_object_unref, NULL);
 
5467
  g_list_free (children);
 
5468
 
 
5469
  if (!gdk_region_empty (expose_region) &&
 
5470
      !private->destroyed)
 
5471
    {
 
5472
      if (private->event_mask & GDK_EXPOSURE_MASK)
 
5473
        {
 
5474
          GdkEvent event;
 
5475
 
 
5476
          event.expose.type = GDK_EXPOSE;
 
5477
          event.expose.window = g_object_ref (window);
 
5478
          event.expose.send_event = FALSE;
 
5479
          event.expose.count = 0;
 
5480
          event.expose.region = expose_region;
 
5481
          gdk_region_get_clipbox (expose_region, &event.expose.area);
 
5482
 
 
5483
          (*_gdk_event_func) (&event, _gdk_event_data);
 
5484
 
 
5485
          g_object_unref (window);
 
5486
        }
 
5487
      else if (private->bg_pixmap != GDK_NO_BG &&
 
5488
               private->window_type != GDK_WINDOW_FOREIGN)
 
5489
        {
 
5490
          /* No exposure mask set, so nothing will be drawn, the
 
5491
           * app relies on the background being what it specified
 
5492
           * for the window. So, we need to clear this manually.
 
5493
           *
 
5494
           * For foreign windows if expose is not set that generally
 
5495
           * means some other client paints them, so don't clear
 
5496
           * there.
 
5497
           *
 
5498
           * We use begin/end_paint around the clear so that we can
 
5499
           * piggyback on the implicit paint */
 
5500
 
 
5501
          gdk_window_begin_paint_region (window, expose_region);
 
5502
          gdk_window_clear_region_internal (window, expose_region, FALSE);
 
5503
          gdk_window_end_paint (window);
 
5504
        }
 
5505
    }
 
5506
}
 
5507
 
 
5508
/* Process and remove any invalid area on the native window by creating
 
5509
 * expose events for the window and all non-native descendants.
 
5510
 * Also processes any outstanding moves on the window before doing
 
5511
 * any drawing. Note that its possible to have outstanding moves without
 
5512
 * any invalid area as we use the update idle mechanism to coalesce
 
5513
 * multiple moves as well as multiple invalidations.
 
5514
 */
 
5515
static void
 
5516
gdk_window_process_updates_internal (GdkWindow *window)
 
5517
{
 
5518
  GdkWindowObject *private = (GdkWindowObject *)window;
 
5519
  GdkWindowImplIface *impl_iface;
 
5520
  gboolean save_region = FALSE;
 
5521
  GdkRectangle clip_box;
 
5522
  int iteration;
 
5523
 
 
5524
  /* Ensure the window lives while updating it */
 
5525
  g_object_ref (window);
 
5526
 
 
5527
  /* If an update got queued during update processing, we can get a
 
5528
   * window in the update queue that has an empty update_area.
 
5529
   * just ignore it.
 
5530
   *
 
5531
   * We run this multiple times if needed because on win32 the
 
5532
   * first run can cause new (synchronous) updates from
 
5533
   * gdk_window_flush_outstanding_moves(). However, we
 
5534
   * limit it to two iterations to avoid any potential loops.
 
5535
   */
 
5536
  iteration = 0;
 
5537
  while (private->update_area &&
 
5538
         iteration++ < 2)
 
5539
    {
 
5540
      GdkRegion *update_area = private->update_area;
 
5541
      private->update_area = NULL;
 
5542
 
 
5543
      if (_gdk_event_func && gdk_window_is_viewable (window))
 
5544
        {
 
5545
          GdkRegion *expose_region;
 
5546
          gboolean end_implicit;
 
5547
 
 
5548
          /* Clip to part visible in toplevel */
 
5549
          gdk_region_intersect (update_area, private->clip_region);
 
5550
 
 
5551
          if (debug_updates)
 
5552
            {
 
5553
              /* Make sure we see the red invalid area before redrawing. */
 
5554
              gdk_display_sync (gdk_drawable_get_display (window));
 
5555
              g_usleep (70000);
 
5556
            }
 
5557
 
 
5558
          /* At this point we will be completely redrawing all of update_area.
 
5559
           * If we have any outstanding moves that end up moving stuff inside
 
5560
           * this area we don't actually need to move that as that part would
 
5561
           * be overdrawn by the expose anyway. So, in order to copy less data
 
5562
           * we remove these areas from the outstanding moves.
 
5563
           */
 
5564
          if (private->outstanding_moves)
 
5565
            {
 
5566
              GdkWindowRegionMove *move;
 
5567
              GdkRegion *remove;
 
5568
              GList *l, *prev;
 
5569
 
 
5570
              remove = gdk_region_copy (update_area);
 
5571
              /* We iterate backwards, starting from the state that would be
 
5572
                 if we had applied all the moves. */
 
5573
              for (l = g_list_last (private->outstanding_moves); l != NULL; l = prev)
 
5574
                {
 
5575
                  prev = l->prev;
 
5576
                  move = l->data;
 
5577
 
 
5578
                  /* Don't need this area */
 
5579
                  gdk_region_subtract (move->dest_region, remove);
 
5580
 
 
5581
                  /* However if any of the destination we do need has a source
 
5582
                     in the updated region we do need that as a destination for
 
5583
                     the earlier moves */
 
5584
                  gdk_region_offset (move->dest_region, -move->dx, -move->dy);
 
5585
                  gdk_region_subtract (remove, move->dest_region);
 
5586
 
 
5587
                  if (gdk_region_empty (move->dest_region))
 
5588
                    {
 
5589
                      gdk_window_region_move_free (move);
 
5590
                      private->outstanding_moves =
 
5591
                        g_list_delete_link (private->outstanding_moves, l);
 
5592
                    }
 
5593
                  else /* move back */
 
5594
                    gdk_region_offset (move->dest_region, move->dx, move->dy);
 
5595
                }
 
5596
              gdk_region_destroy (remove);
 
5597
            }
 
5598
 
 
5599
          /* By now we a set of window moves that should be applied, and then
 
5600
           * an update region that should be repainted. A trivial implementation
 
5601
           * would just do that in order, however in order to get nicer drawing
 
5602
           * we do some tricks:
 
5603
           *
 
5604
           * First of all, each subwindow expose may be double buffered by
 
5605
           * itself (depending on widget setting) via
 
5606
           * gdk_window_begin/end_paint(). But we also do an "implicit" paint,
 
5607
           * creating a single pixmap the size of the invalid area on the
 
5608
           * native window which all the individual normal paints will draw
 
5609
           * into. This way in the normal case there will be only one pixmap
 
5610
           * allocated and only once pixmap draw done for all the windows
 
5611
           * in this native window.
 
5612
           * There are a couple of reasons this may fail, for instance, some
 
5613
           * backends (like quartz) do its own double buffering, so we disable
 
5614
           * gdk double buffering there. Secondly, some subwindow could be
 
5615
           * non-double buffered and draw directly to the window outside a
 
5616
           * begin/end_paint pair. That will be lead to a gdk_window_flush
 
5617
           * which immediately executes all outstanding moves and paints+removes
 
5618
           * the implicit paint (further paints will allocate their own pixmap).
 
5619
           *
 
5620
           * Secondly, in the case of implicit double buffering we expose all
 
5621
           * the child windows into the implicit pixmap before we execute
 
5622
           * the outstanding moves. This way we minimize the time between
 
5623
           * doing the moves and rendering the new update area, thus minimizing
 
5624
           * flashing. Of course, if any subwindow is non-double buffered we
 
5625
           * well flush earlier than that.
 
5626
           *
 
5627
           * Thirdly, after having done the outstanding moves we queue an
 
5628
           * "antiexpose" on the area that will be drawn by the expose, which
 
5629
           * means that any invalid region on the native window side before
 
5630
           * the first expose drawing operation will be discarded, as it
 
5631
           * has by then been overdrawn with valid data. This means we can
 
5632
           * avoid doing the unnecessary repaint any outstanding expose events.
 
5633
           */
 
5634
 
 
5635
          gdk_region_get_clipbox (update_area, &clip_box);
 
5636
          end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
 
5637
          expose_region = gdk_region_copy (update_area);
 
5638
          if (!end_implicit)
 
5639
            {
 
5640
              /* Rendering is not double buffered by gdk, do outstanding
 
5641
               * moves and queue antiexposure immediately. No need to do
 
5642
               * any tricks */
 
5643
              gdk_window_flush_outstanding_moves (window);
 
5644
              impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
5645
              save_region = impl_iface->queue_antiexpose (window, update_area);
 
5646
            }
 
5647
 
 
5648
          /* Render the invalid areas to the implicit paint, by sending exposes.
 
5649
           * May flush if non-double buffered widget draw. */
 
5650
          _gdk_windowing_window_process_updates_recurse (window, expose_region);
 
5651
 
 
5652
          if (end_implicit)
 
5653
            {
 
5654
              /* Do moves right before exposes are rendered to the window */
 
5655
              gdk_window_flush_outstanding_moves (window);
 
5656
 
 
5657
              /* By this time we know that any outstanding expose for this
 
5658
               * area is invalid and we can avoid it, so queue an antiexpose.
 
5659
               * However, it may be that due to an non-double buffered expose
 
5660
               * we have already started drawing to the window, so it would
 
5661
               * be to late to anti-expose now. Since this is merely an
 
5662
               * optimization we just avoid doing it at all in that case.
 
5663
               */
 
5664
              if (private->implicit_paint != NULL &&
 
5665
                  !private->implicit_paint->flushed)
 
5666
                {
 
5667
                  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
5668
                  save_region = impl_iface->queue_antiexpose (window, update_area);
 
5669
                }
 
5670
 
 
5671
              gdk_window_end_implicit_paint (window);
 
5672
            }
 
5673
          gdk_region_destroy (expose_region);
 
5674
        }
 
5675
      if (!save_region)
 
5676
        gdk_region_destroy (update_area);
 
5677
    }
 
5678
 
 
5679
  if (private->outstanding_moves)
 
5680
    {
 
5681
      /* Flush any outstanding moves, may happen if we moved a window but got
 
5682
         no actual invalid area */
 
5683
      gdk_window_flush_outstanding_moves (window);
 
5684
    }
 
5685
 
 
5686
  g_object_unref (window);
 
5687
}
 
5688
 
 
5689
static void
 
5690
flush_all_displays (void)
 
5691
{
 
5692
  GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
 
5693
  GSList *tmp_list;
 
5694
 
 
5695
  for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
 
5696
    gdk_display_flush (tmp_list->data);
 
5697
 
 
5698
  g_slist_free (displays);
 
5699
}
 
5700
 
 
5701
/* Currently it is not possible to override
 
5702
 * gdk_window_process_all_updates in the same manner as
 
5703
 * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
 
5704
 * by implementing the GdkPaintable interface.  If in the future a
 
5705
 * backend would need this, the right solution would be to add a
 
5706
 * method to GdkDisplay that can be optionally
 
5707
 * NULL. gdk_window_process_all_updates can then walk the list of open
 
5708
 * displays and call the mehod.
 
5709
 */
 
5710
 
 
5711
/**
 
5712
 * gdk_window_process_all_updates:
 
5713
 *
 
5714
 * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
 
5715
 * in the application.
 
5716
 *
 
5717
 **/
 
5718
void
 
5719
gdk_window_process_all_updates (void)
 
5720
{
 
5721
  GSList *old_update_windows = update_windows;
 
5722
  GSList *tmp_list = update_windows;
 
5723
  static gboolean in_process_all_updates = FALSE;
 
5724
  static gboolean got_recursive_update = FALSE;
 
5725
 
 
5726
  if (in_process_all_updates)
 
5727
    {
 
5728
      /* We can't do this now since that would recurse, so
 
5729
         delay it until after the recursion is done. */
 
5730
      got_recursive_update = TRUE;
 
5731
      update_idle = 0;
 
5732
      return;
 
5733
    }
 
5734
 
 
5735
  in_process_all_updates = TRUE;
 
5736
  got_recursive_update = FALSE;
 
5737
 
 
5738
  if (update_idle)
 
5739
    g_source_remove (update_idle);
 
5740
 
 
5741
  update_windows = NULL;
 
5742
  update_idle = 0;
 
5743
 
 
5744
  _gdk_windowing_before_process_all_updates ();
 
5745
 
 
5746
  while (tmp_list)
 
5747
    {
 
5748
      GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
 
5749
 
 
5750
      if (!GDK_WINDOW_DESTROYED (tmp_list->data))
 
5751
        {
 
5752
          if (private->update_freeze_count ||
 
5753
              gdk_window_is_toplevel_frozen (tmp_list->data))
 
5754
            gdk_window_add_update_window ((GdkWindow *) private);
 
5755
          else
 
5756
            gdk_window_process_updates_internal (tmp_list->data);
 
5757
        }
 
5758
 
 
5759
      g_object_unref (tmp_list->data);
 
5760
      tmp_list = tmp_list->next;
 
5761
    }
 
5762
 
 
5763
  g_slist_free (old_update_windows);
 
5764
 
 
5765
  flush_all_displays ();
 
5766
 
 
5767
  _gdk_windowing_after_process_all_updates ();
 
5768
 
 
5769
  in_process_all_updates = FALSE;
 
5770
 
 
5771
  /* If we ignored a recursive call, schedule a
 
5772
     redraw now so that it eventually happens,
 
5773
     otherwise we could miss an update if nothing
 
5774
     else schedules an update. */
 
5775
  if (got_recursive_update && !update_idle)
 
5776
    update_idle =
 
5777
      gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
 
5778
                                 gdk_window_update_idle,
 
5779
                                 NULL, NULL);
 
5780
}
 
5781
 
 
5782
/**
 
5783
 * gdk_window_process_updates:
 
5784
 * @window: a #GdkWindow
 
5785
 * @update_children: whether to also process updates for child windows
 
5786
 *
 
5787
 * Sends one or more expose events to @window. The areas in each
 
5788
 * expose event will cover the entire update area for the window (see
 
5789
 * gdk_window_invalidate_region() for details). Normally GDK calls
 
5790
 * gdk_window_process_all_updates() on your behalf, so there's no
 
5791
 * need to call this function unless you want to force expose events
 
5792
 * to be delivered immediately and synchronously (vs. the usual
 
5793
 * case, where GDK delivers them in an idle handler). Occasionally
 
5794
 * this is useful to produce nicer scrolling behavior, for example.
 
5795
 *
 
5796
 **/
 
5797
void
 
5798
gdk_window_process_updates (GdkWindow *window,
 
5799
                            gboolean   update_children)
 
5800
{
 
5801
  GdkWindowObject *private = (GdkWindowObject *)window;
 
5802
  GdkWindowObject *impl_window;
 
5803
 
 
5804
  g_return_if_fail (GDK_IS_WINDOW (window));
 
5805
 
 
5806
  if (GDK_WINDOW_DESTROYED (window))
 
5807
    return;
 
5808
 
 
5809
  /* Make sure the window lives during the expose callouts */
 
5810
  g_object_ref (window);
 
5811
 
 
5812
  impl_window = gdk_window_get_impl_window (private);
 
5813
  if ((impl_window->update_area ||
 
5814
       impl_window->outstanding_moves) &&
 
5815
      !impl_window->update_freeze_count &&
 
5816
      !gdk_window_is_toplevel_frozen (window) &&
 
5817
 
 
5818
      /* Don't recurse into process_updates_internal, we'll
 
5819
       * do the update later when idle instead. */
 
5820
      impl_window->implicit_paint == NULL)
 
5821
    {
 
5822
      gdk_window_process_updates_internal ((GdkWindow *)impl_window);
 
5823
      gdk_window_remove_update_window ((GdkWindow *)impl_window);
 
5824
    }
 
5825
 
 
5826
  if (update_children)
 
5827
    {
 
5828
      /* process updates in reverse stacking order so composition or
 
5829
       * painting over achieves the desired effect for offscreen windows
 
5830
       */
 
5831
      GList *node, *children;
 
5832
 
 
5833
      children = g_list_copy (private->children);
 
5834
      g_list_foreach (children, (GFunc)g_object_ref, NULL);
 
5835
 
 
5836
      for (node = g_list_last (children); node; node = node->prev)
 
5837
        {
 
5838
          gdk_window_process_updates (node->data, TRUE);
 
5839
          g_object_unref (node->data);
 
5840
        }
 
5841
 
 
5842
      g_list_free (children);
 
5843
    }
 
5844
 
 
5845
  g_object_unref (window);
 
5846
}
 
5847
 
 
5848
static void
 
5849
gdk_window_invalidate_rect_full (GdkWindow          *window,
 
5850
                                  const GdkRectangle *rect,
 
5851
                                  gboolean            invalidate_children,
 
5852
                                  ClearBg             clear_bg)
 
5853
{
 
5854
  GdkRectangle window_rect;
 
5855
  GdkRegion *region;
 
5856
  GdkWindowObject *private = (GdkWindowObject *)window;
 
5857
 
 
5858
  g_return_if_fail (GDK_IS_WINDOW (window));
 
5859
 
 
5860
  if (GDK_WINDOW_DESTROYED (window))
 
5861
    return;
 
5862
 
 
5863
  if (private->input_only || !private->viewable)
 
5864
    return;
 
5865
 
 
5866
  if (!rect)
 
5867
    {
 
5868
      window_rect.x = 0;
 
5869
      window_rect.y = 0;
 
5870
      gdk_drawable_get_size (GDK_DRAWABLE (window),
 
5871
                             &window_rect.width,
 
5872
                             &window_rect.height);
 
5873
      rect = &window_rect;
 
5874
    }
 
5875
 
 
5876
  region = gdk_region_rectangle (rect);
 
5877
  gdk_window_invalidate_region_full (window, region, invalidate_children, clear_bg);
 
5878
  gdk_region_destroy (region);
 
5879
}
 
5880
 
 
5881
/**
 
5882
 * gdk_window_invalidate_rect:
 
5883
 * @window: a #GdkWindow
 
5884
 * @rect: (allow-none): rectangle to invalidate or %NULL to invalidate the whole
 
5885
 *      window
 
5886
 * @invalidate_children: whether to also invalidate child windows
 
5887
 *
 
5888
 * A convenience wrapper around gdk_window_invalidate_region() which
 
5889
 * invalidates a rectangular region. See
 
5890
 * gdk_window_invalidate_region() for details.
 
5891
 **/
 
5892
void
 
5893
gdk_window_invalidate_rect (GdkWindow          *window,
 
5894
                            const GdkRectangle *rect,
 
5895
                            gboolean            invalidate_children)
 
5896
{
 
5897
  gdk_window_invalidate_rect_full (window, rect, invalidate_children, CLEAR_BG_NONE);
 
5898
}
 
5899
 
 
5900
static void
 
5901
draw_ugly_color (GdkWindow       *window,
 
5902
                 const GdkRegion *region)
 
5903
{
 
5904
  /* Draw ugly color all over the newly-invalid region */
 
5905
  GdkColor ugly_color = { 0, 50000, 10000, 10000 };
 
5906
  GdkGC *ugly_gc;
 
5907
  GdkRectangle clipbox;
 
5908
 
 
5909
  ugly_gc = gdk_gc_new (window);
 
5910
  gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
 
5911
  gdk_gc_set_clip_region (ugly_gc, region);
 
5912
 
 
5913
  gdk_region_get_clipbox (region, &clipbox);
 
5914
 
 
5915
  gdk_draw_rectangle (window,
 
5916
                      ugly_gc,
 
5917
                      TRUE,
 
5918
                      clipbox.x, clipbox.y,
 
5919
                      clipbox.width, clipbox.height);
 
5920
 
 
5921
  g_object_unref (ugly_gc);
 
5922
}
 
5923
 
 
5924
static void
 
5925
impl_window_add_update_area (GdkWindowObject *impl_window,
 
5926
                             GdkRegion *region)
 
5927
{
 
5928
  if (impl_window->update_area)
 
5929
    gdk_region_union (impl_window->update_area, region);
 
5930
  else
 
5931
    {
 
5932
      gdk_window_add_update_window ((GdkWindow *)impl_window);
 
5933
      impl_window->update_area = gdk_region_copy (region);
 
5934
      gdk_window_schedule_update ((GdkWindow *)impl_window);
 
5935
    }
 
5936
}
 
5937
 
 
5938
/* clear_bg controls if the region will be cleared to
 
5939
 * the background color/pixmap if the exposure mask is not
 
5940
 * set for the window, whereas this might not otherwise be
 
5941
 * done (unless necessary to emulate background settings).
 
5942
 * Set this to CLEAR_BG_WINCLEARED or CLEAR_BG_ALL if you
 
5943
 * need to clear the background, such as when exposing the area beneath a
 
5944
 * hidden or moved window, but not when an app requests repaint or when the
 
5945
 * windowing system exposes a newly visible area (because then the windowing
 
5946
 * system has already cleared the area).
 
5947
 */
 
5948
static void
 
5949
gdk_window_invalidate_maybe_recurse_full (GdkWindow       *window,
 
5950
                                          const GdkRegion *region,
 
5951
                                          ClearBg          clear_bg,
 
5952
                                          gboolean       (*child_func) (GdkWindow *,
 
5953
                                                                        gpointer),
 
5954
                                          gpointer   user_data)
 
5955
{
 
5956
  GdkWindowObject *private = (GdkWindowObject *)window;
 
5957
  GdkWindowObject *impl_window;
 
5958
  GdkRegion *visible_region;
 
5959
  GList *tmp_list;
 
5960
 
 
5961
  g_return_if_fail (GDK_IS_WINDOW (window));
 
5962
 
 
5963
  if (GDK_WINDOW_DESTROYED (window))
 
5964
    return;
 
5965
 
 
5966
  if (private->input_only ||
 
5967
      !private->viewable ||
 
5968
      gdk_region_empty (region) ||
 
5969
      private->window_type == GDK_WINDOW_ROOT)
 
5970
    return;
 
5971
 
 
5972
  visible_region = gdk_drawable_get_visible_region (window);
 
5973
  gdk_region_intersect (visible_region, region);
 
5974
 
 
5975
  tmp_list = private->children;
 
5976
  while (tmp_list)
 
5977
    {
 
5978
      GdkWindowObject *child = tmp_list->data;
 
5979
 
 
5980
      if (!child->input_only)
 
5981
        {
 
5982
          GdkRegion *child_region;
 
5983
          GdkRectangle child_rect;
 
5984
 
 
5985
          child_rect.x = child->x;
 
5986
          child_rect.y = child->y;
 
5987
          child_rect.width = child->width;
 
5988
          child_rect.height = child->height;
 
5989
          child_region = gdk_region_rectangle (&child_rect);
 
5990
 
 
5991
          /* remove child area from the invalid area of the parent */
 
5992
          if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
 
5993
              !child->composited &&
 
5994
              !gdk_window_is_offscreen (child))
 
5995
            gdk_region_subtract (visible_region, child_region);
 
5996
 
 
5997
          if (child_func && (*child_func) ((GdkWindow *)child, user_data))
 
5998
            {
 
5999
              GdkRegion *tmp = gdk_region_copy (region);
 
6000
 
 
6001
              gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
 
6002
              gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
 
6003
              gdk_region_intersect (child_region, tmp);
 
6004
 
 
6005
              gdk_window_invalidate_maybe_recurse_full ((GdkWindow *)child,
 
6006
                                                        child_region, clear_bg, child_func, user_data);
 
6007
 
 
6008
              gdk_region_destroy (tmp);
 
6009
            }
 
6010
 
 
6011
          gdk_region_destroy (child_region);
 
6012
        }
 
6013
 
 
6014
      tmp_list = tmp_list->next;
 
6015
    }
 
6016
 
 
6017
  impl_window = gdk_window_get_impl_window (private);
 
6018
 
 
6019
  if (!gdk_region_empty (visible_region)  ||
 
6020
      /* Even if we're not exposing anything, make sure we process
 
6021
         idles for windows with outstanding moves */
 
6022
      (impl_window->outstanding_moves != NULL &&
 
6023
       impl_window->update_area == NULL))
 
6024
    {
 
6025
      if (debug_updates)
 
6026
        draw_ugly_color (window, region);
 
6027
 
 
6028
      /* Convert to impl coords */
 
6029
      gdk_region_offset (visible_region, private->abs_x, private->abs_y);
 
6030
 
 
6031
      /* Only invalidate area if app requested expose events or if
 
6032
         we need to clear the area (by request or to emulate background
 
6033
         clearing for non-native windows or native windows with no support
 
6034
         for window backgrounds */
 
6035
      if (private->event_mask & GDK_EXPOSURE_MASK ||
 
6036
          clear_bg == CLEAR_BG_ALL ||
 
6037
          (clear_bg == CLEAR_BG_WINCLEARED &&
 
6038
           (!clears_as_native (private) ||
 
6039
            !GDK_WINDOW_IMPL_GET_IFACE (private->impl)->supports_native_bg)))
 
6040
        impl_window_add_update_area (impl_window, visible_region);
 
6041
    }
 
6042
 
 
6043
  gdk_region_destroy (visible_region);
 
6044
}
 
6045
 
 
6046
/**
 
6047
 * gdk_window_invalidate_maybe_recurse:
 
6048
 * @window: a #GdkWindow
 
6049
 * @region: a #GdkRegion
 
6050
 * @child_func: function to use to decide if to recurse to a child,
 
6051
 *              %NULL means never recurse.
 
6052
 * @user_data: data passed to @child_func
 
6053
 *
 
6054
 * Adds @region to the update area for @window. The update area is the
 
6055
 * region that needs to be redrawn, or "dirty region." The call
 
6056
 * gdk_window_process_updates() sends one or more expose events to the
 
6057
 * window, which together cover the entire update area. An
 
6058
 * application would normally redraw the contents of @window in
 
6059
 * response to those expose events.
 
6060
 *
 
6061
 * GDK will call gdk_window_process_all_updates() on your behalf
 
6062
 * whenever your program returns to the main loop and becomes idle, so
 
6063
 * normally there's no need to do that manually, you just need to
 
6064
 * invalidate regions that you know should be redrawn.
 
6065
 *
 
6066
 * The @child_func parameter controls whether the region of
 
6067
 * each child window that intersects @region will also be invalidated.
 
6068
 * Only children for which @child_func returns TRUE will have the area
 
6069
 * invalidated.
 
6070
 **/
 
6071
void
 
6072
gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
 
6073
                                     const GdkRegion *region,
 
6074
                                     gboolean       (*child_func) (GdkWindow *,
 
6075
                                                                   gpointer),
 
6076
                                     gpointer   user_data)
 
6077
{
 
6078
  gdk_window_invalidate_maybe_recurse_full (window, region, CLEAR_BG_NONE,
 
6079
                                            child_func, user_data);
 
6080
}
 
6081
 
 
6082
static gboolean
 
6083
true_predicate (GdkWindow *window,
 
6084
                gpointer   user_data)
 
6085
{
 
6086
  return TRUE;
 
6087
}
 
6088
 
 
6089
static void
 
6090
gdk_window_invalidate_region_full (GdkWindow       *window,
 
6091
                                    const GdkRegion *region,
 
6092
                                    gboolean         invalidate_children,
 
6093
                                    ClearBg          clear_bg)
 
6094
{
 
6095
  gdk_window_invalidate_maybe_recurse_full (window, region, clear_bg,
 
6096
                                            invalidate_children ?
 
6097
                                            true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
 
6098
                                       NULL);
 
6099
}
 
6100
 
 
6101
/**
 
6102
 * gdk_window_invalidate_region:
 
6103
 * @window: a #GdkWindow
 
6104
 * @region: a #GdkRegion
 
6105
 * @invalidate_children: %TRUE to also invalidate child windows
 
6106
 *
 
6107
 * Adds @region to the update area for @window. The update area is the
 
6108
 * region that needs to be redrawn, or "dirty region." The call
 
6109
 * gdk_window_process_updates() sends one or more expose events to the
 
6110
 * window, which together cover the entire update area. An
 
6111
 * application would normally redraw the contents of @window in
 
6112
 * response to those expose events.
 
6113
 *
 
6114
 * GDK will call gdk_window_process_all_updates() on your behalf
 
6115
 * whenever your program returns to the main loop and becomes idle, so
 
6116
 * normally there's no need to do that manually, you just need to
 
6117
 * invalidate regions that you know should be redrawn.
 
6118
 *
 
6119
 * The @invalidate_children parameter controls whether the region of
 
6120
 * each child window that intersects @region will also be invalidated.
 
6121
 * If %FALSE, then the update area for child windows will remain
 
6122
 * unaffected. See gdk_window_invalidate_maybe_recurse if you need
 
6123
 * fine grained control over which children are invalidated.
 
6124
 **/
 
6125
void
 
6126
gdk_window_invalidate_region (GdkWindow       *window,
 
6127
                              const GdkRegion *region,
 
6128
                              gboolean         invalidate_children)
 
6129
{
 
6130
  gdk_window_invalidate_maybe_recurse (window, region,
 
6131
                                       invalidate_children ?
 
6132
                                         true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
 
6133
                                       NULL);
 
6134
}
 
6135
 
 
6136
/**
 
6137
 * _gdk_window_invalidate_for_expose:
 
6138
 * @window: a #GdkWindow
 
6139
 * @region: a #GdkRegion
 
6140
 *
 
6141
 * Adds @region to the update area for @window. The update area is the
 
6142
 * region that needs to be redrawn, or "dirty region." The call
 
6143
 * gdk_window_process_updates() sends one or more expose events to the
 
6144
 * window, which together cover the entire update area. An
 
6145
 * application would normally redraw the contents of @window in
 
6146
 * response to those expose events.
 
6147
 *
 
6148
 * GDK will call gdk_window_process_all_updates() on your behalf
 
6149
 * whenever your program returns to the main loop and becomes idle, so
 
6150
 * normally there's no need to do that manually, you just need to
 
6151
 * invalidate regions that you know should be redrawn.
 
6152
 *
 
6153
 * This version of invalidation is used when you recieve expose events
 
6154
 * from the native window system. It exposes the native window, plus
 
6155
 * any non-native child windows (but not native child windows, as those would
 
6156
 * have gotten their own expose events).
 
6157
 **/
 
6158
void
 
6159
_gdk_window_invalidate_for_expose (GdkWindow       *window,
 
6160
                                   GdkRegion       *region)
 
6161
{
 
6162
  GdkWindowObject *private = (GdkWindowObject *) window;
 
6163
  GdkWindowRegionMove *move;
 
6164
  GdkRegion *move_region;
 
6165
  GList *l;
 
6166
 
 
6167
  /* Any invalidations comming from the windowing system will
 
6168
     be in areas that may be moved by outstanding moves,
 
6169
     so we need to modify the expose region correspondingly,
 
6170
     otherwise we would expose in the wrong place, as the
 
6171
     outstanding moves will be copied before we draw the
 
6172
     exposes. */
 
6173
  for (l = private->outstanding_moves; l != NULL; l = l->next)
 
6174
    {
 
6175
      move = l->data;
 
6176
 
 
6177
      /* covert to move source region */
 
6178
      move_region = gdk_region_copy (move->dest_region);
 
6179
      gdk_region_offset (move_region, -move->dx, -move->dy);
 
6180
 
 
6181
      /* Move area of region that intersects with move source
 
6182
         by dx, dy of the move*/
 
6183
      gdk_region_intersect (move_region, region);
 
6184
      gdk_region_subtract (region, move_region);
 
6185
      gdk_region_offset (move_region, move->dx, move->dy);
 
6186
      gdk_region_union (region, move_region);
 
6187
 
 
6188
      gdk_region_destroy (move_region);
 
6189
    }
 
6190
 
 
6191
  gdk_window_invalidate_maybe_recurse_full (window, region, CLEAR_BG_WINCLEARED,
 
6192
                                            (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
 
6193
                                            NULL);
 
6194
}
 
6195
 
 
6196
 
 
6197
/**
 
6198
 * gdk_window_get_update_area:
 
6199
 * @window: a #GdkWindow
 
6200
 *
 
6201
 * Transfers ownership of the update area from @window to the caller
 
6202
 * of the function. That is, after calling this function, @window will
 
6203
 * no longer have an invalid/dirty region; the update area is removed
 
6204
 * from @window and handed to you. If a window has no update area,
 
6205
 * gdk_window_get_update_area() returns %NULL. You are responsible for
 
6206
 * calling gdk_region_destroy() on the returned region if it's non-%NULL.
 
6207
 *
 
6208
 * Return value: the update area for @window
 
6209
 **/
 
6210
GdkRegion *
 
6211
gdk_window_get_update_area (GdkWindow *window)
 
6212
{
 
6213
  GdkWindowObject *private = (GdkWindowObject *)window;
 
6214
  GdkWindowObject *impl_window;
 
6215
  GdkRegion *tmp_region;
 
6216
 
 
6217
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
6218
 
 
6219
  impl_window = gdk_window_get_impl_window (private);
 
6220
 
 
6221
  if (impl_window->update_area)
 
6222
    {
 
6223
      tmp_region = gdk_region_copy (private->clip_region_with_children);
 
6224
      /* Convert to impl coords */
 
6225
      gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
 
6226
      gdk_region_intersect (tmp_region, impl_window->update_area);
 
6227
 
 
6228
      if (gdk_region_empty (tmp_region))
 
6229
        {
 
6230
          gdk_region_destroy (tmp_region);
 
6231
          return NULL;
 
6232
        }
 
6233
      else
 
6234
        {
 
6235
          gdk_region_subtract (impl_window->update_area, tmp_region);
 
6236
 
 
6237
          if (gdk_region_empty (impl_window->update_area) &&
 
6238
              impl_window->outstanding_moves == NULL)
 
6239
            {
 
6240
              gdk_region_destroy (impl_window->update_area);
 
6241
              impl_window->update_area = NULL;
 
6242
 
 
6243
              gdk_window_remove_update_window ((GdkWindow *)impl_window);
 
6244
            }
 
6245
 
 
6246
          /* Convert from impl coords */
 
6247
          gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
 
6248
          return tmp_region;
 
6249
 
 
6250
        }
 
6251
    }
 
6252
  else
 
6253
    return NULL;
 
6254
}
 
6255
 
 
6256
/**
 
6257
 * _gdk_window_clear_update_area:
 
6258
 * @window: a #GdkWindow.
 
6259
 *
 
6260
 * Internal function to clear the update area for a window. This
 
6261
 * is called when the window is hidden or destroyed.
 
6262
 **/
 
6263
void
 
6264
_gdk_window_clear_update_area (GdkWindow *window)
 
6265
{
 
6266
  GdkWindowObject *private = (GdkWindowObject *)window;
 
6267
 
 
6268
  g_return_if_fail (GDK_IS_WINDOW (window));
 
6269
 
 
6270
  if (private->update_area)
 
6271
    {
 
6272
      gdk_window_remove_update_window (window);
 
6273
 
 
6274
      gdk_region_destroy (private->update_area);
 
6275
      private->update_area = NULL;
 
6276
    }
 
6277
}
 
6278
 
 
6279
/**
 
6280
 * gdk_window_freeze_updates:
 
6281
 * @window: a #GdkWindow
 
6282
 *
 
6283
 * Temporarily freezes a window such that it won't receive expose
 
6284
 * events.  The window will begin receiving expose events again when
 
6285
 * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
 
6286
 * has been called more than once, gdk_window_thaw_updates() must be called
 
6287
 * an equal number of times to begin processing exposes.
 
6288
 **/
 
6289
void
 
6290
gdk_window_freeze_updates (GdkWindow *window)
 
6291
{
 
6292
  GdkWindowObject *private = (GdkWindowObject *)window;
 
6293
  GdkWindowObject *impl_window;
 
6294
 
 
6295
  g_return_if_fail (GDK_IS_WINDOW (window));
 
6296
 
 
6297
  impl_window = gdk_window_get_impl_window (private);
 
6298
  impl_window->update_freeze_count++;
 
6299
}
 
6300
 
 
6301
/**
 
6302
 * gdk_window_thaw_updates:
 
6303
 * @window: a #GdkWindow
 
6304
 *
 
6305
 * Thaws a window frozen with gdk_window_freeze_updates().
 
6306
 **/
 
6307
void
 
6308
gdk_window_thaw_updates (GdkWindow *window)
 
6309
{
 
6310
  GdkWindowObject *private = (GdkWindowObject *)window;
 
6311
  GdkWindowObject *impl_window;
 
6312
 
 
6313
  g_return_if_fail (GDK_IS_WINDOW (window));
 
6314
 
 
6315
  impl_window = gdk_window_get_impl_window (private);
 
6316
 
 
6317
  g_return_if_fail (impl_window->update_freeze_count > 0);
 
6318
 
 
6319
  if (--impl_window->update_freeze_count == 0)
 
6320
    gdk_window_schedule_update (GDK_WINDOW (impl_window));
 
6321
}
 
6322
 
 
6323
/**
 
6324
 * gdk_window_freeze_toplevel_updates_libgtk_only:
 
6325
 * @window: a #GdkWindow
 
6326
 *
 
6327
 * Temporarily freezes a window and all its descendants such that it won't
 
6328
 * receive expose events.  The window will begin receiving expose events
 
6329
 * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
 
6330
 * gdk_window_freeze_toplevel_updates_libgtk_only()
 
6331
 * has been called more than once,
 
6332
 * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
 
6333
 * an equal number of times to begin processing exposes.
 
6334
 *
 
6335
 * This function is not part of the GDK public API and is only
 
6336
 * for use by GTK+.
 
6337
 **/
 
6338
void
 
6339
gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
 
6340
{
 
6341
  GdkWindowObject *private = (GdkWindowObject *)window;
 
6342
 
 
6343
  g_return_if_fail (GDK_IS_WINDOW (window));
 
6344
  g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
 
6345
 
 
6346
  private->update_and_descendants_freeze_count++;
 
6347
}
 
6348
 
 
6349
/**
 
6350
 * gdk_window_thaw_toplevel_updates_libgtk_only:
 
6351
 * @window: a #GdkWindow
 
6352
 *
 
6353
 * Thaws a window frozen with
 
6354
 * gdk_window_freeze_toplevel_updates_libgtk_only().
 
6355
 *
 
6356
 * This function is not part of the GDK public API and is only
 
6357
 * for use by GTK+.
 
6358
 **/
 
6359
void
 
6360
gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
 
6361
{
 
6362
  GdkWindowObject *private = (GdkWindowObject *)window;
 
6363
 
 
6364
  g_return_if_fail (GDK_IS_WINDOW (window));
 
6365
  g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
 
6366
  g_return_if_fail (private->update_and_descendants_freeze_count > 0);
 
6367
 
 
6368
  private->update_and_descendants_freeze_count--;
 
6369
 
 
6370
  gdk_window_schedule_update (window);
 
6371
}
 
6372
 
 
6373
/**
 
6374
 * gdk_window_set_debug_updates:
 
6375
 * @setting: %TRUE to turn on update debugging
 
6376
 *
 
6377
 * With update debugging enabled, calls to
 
6378
 * gdk_window_invalidate_region() clear the invalidated region of the
 
6379
 * screen to a noticeable color, and GDK pauses for a short time
 
6380
 * before sending exposes to windows during
 
6381
 * gdk_window_process_updates().  The net effect is that you can see
 
6382
 * the invalid region for each window and watch redraws as they
 
6383
 * occur. This allows you to diagnose inefficiencies in your application.
 
6384
 *
 
6385
 * In essence, because the GDK rendering model prevents all flicker,
 
6386
 * if you are redrawing the same region 400 times you may never
 
6387
 * notice, aside from noticing a speed problem. Enabling update
 
6388
 * debugging causes GTK to flicker slowly and noticeably, so you can
 
6389
 * see exactly what's being redrawn when, in what order.
 
6390
 *
 
6391
 * The --gtk-debug=updates command line option passed to GTK+ programs
 
6392
 * enables this debug option at application startup time. That's
 
6393
 * usually more useful than calling gdk_window_set_debug_updates()
 
6394
 * yourself, though you might want to use this function to enable
 
6395
 * updates sometime after application startup time.
 
6396
 *
 
6397
 **/
 
6398
void
 
6399
gdk_window_set_debug_updates (gboolean setting)
 
6400
{
 
6401
  debug_updates = setting;
 
6402
}
 
6403
 
 
6404
/**
 
6405
 * gdk_window_constrain_size:
 
6406
 * @geometry: a #GdkGeometry structure
 
6407
 * @flags: a mask indicating what portions of @geometry are set
 
6408
 * @width: desired width of window
 
6409
 * @height: desired height of the window
 
6410
 * @new_width: (out): location to store resulting width
 
6411
 * @new_height: (out): location to store resulting height
 
6412
 *
 
6413
 * Constrains a desired width and height according to a
 
6414
 * set of geometry hints (such as minimum and maximum size).
 
6415
 */
 
6416
void
 
6417
gdk_window_constrain_size (GdkGeometry *geometry,
 
6418
                           guint        flags,
 
6419
                           gint         width,
 
6420
                           gint         height,
 
6421
                           gint        *new_width,
 
6422
                           gint        *new_height)
 
6423
{
 
6424
  /* This routine is partially borrowed from fvwm.
 
6425
   *
 
6426
   * Copyright 1993, Robert Nation
 
6427
   *     You may use this code for any purpose, as long as the original
 
6428
   *     copyright remains in the source code and all documentation
 
6429
   *
 
6430
   * which in turn borrows parts of the algorithm from uwm
 
6431
   */
 
6432
  gint min_width = 0;
 
6433
  gint min_height = 0;
 
6434
  gint base_width = 0;
 
6435
  gint base_height = 0;
 
6436
  gint xinc = 1;
 
6437
  gint yinc = 1;
 
6438
  gint max_width = G_MAXINT;
 
6439
  gint max_height = G_MAXINT;
 
6440
 
 
6441
#define FLOOR(value, base)      ( ((gint) ((value) / (base))) * (base) )
 
6442
 
 
6443
  if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
 
6444
    {
 
6445
      base_width = geometry->base_width;
 
6446
      base_height = geometry->base_height;
 
6447
      min_width = geometry->min_width;
 
6448
      min_height = geometry->min_height;
 
6449
    }
 
6450
  else if (flags & GDK_HINT_BASE_SIZE)
 
6451
    {
 
6452
      base_width = geometry->base_width;
 
6453
      base_height = geometry->base_height;
 
6454
      min_width = geometry->base_width;
 
6455
      min_height = geometry->base_height;
 
6456
    }
 
6457
  else if (flags & GDK_HINT_MIN_SIZE)
 
6458
    {
 
6459
      base_width = geometry->min_width;
 
6460
      base_height = geometry->min_height;
 
6461
      min_width = geometry->min_width;
 
6462
      min_height = geometry->min_height;
 
6463
    }
 
6464
 
 
6465
  if (flags & GDK_HINT_MAX_SIZE)
 
6466
    {
 
6467
      max_width = geometry->max_width ;
 
6468
      max_height = geometry->max_height;
 
6469
    }
 
6470
 
 
6471
  if (flags & GDK_HINT_RESIZE_INC)
 
6472
    {
 
6473
      xinc = MAX (xinc, geometry->width_inc);
 
6474
      yinc = MAX (yinc, geometry->height_inc);
 
6475
    }
 
6476
 
 
6477
  /* clamp width and height to min and max values
 
6478
   */
 
6479
  width = CLAMP (width, min_width, max_width);
 
6480
  height = CLAMP (height, min_height, max_height);
 
6481
 
 
6482
  /* shrink to base + N * inc
 
6483
   */
 
6484
  width = base_width + FLOOR (width - base_width, xinc);
 
6485
  height = base_height + FLOOR (height - base_height, yinc);
 
6486
 
 
6487
  /* constrain aspect ratio, according to:
 
6488
   *
 
6489
   *                width
 
6490
   * min_aspect <= -------- <= max_aspect
 
6491
   *                height
 
6492
   */
 
6493
 
 
6494
  if (flags & GDK_HINT_ASPECT &&
 
6495
      geometry->min_aspect > 0 &&
 
6496
      geometry->max_aspect > 0)
 
6497
    {
 
6498
      gint delta;
 
6499
 
 
6500
      if (geometry->min_aspect * height > width)
 
6501
        {
 
6502
          delta = FLOOR (height - width / geometry->min_aspect, yinc);
 
6503
          if (height - delta >= min_height)
 
6504
            height -= delta;
 
6505
          else
 
6506
            {
 
6507
              delta = FLOOR (height * geometry->min_aspect - width, xinc);
 
6508
              if (width + delta <= max_width)
 
6509
                width += delta;
 
6510
            }
 
6511
        }
 
6512
 
 
6513
      if (geometry->max_aspect * height < width)
 
6514
        {
 
6515
          delta = FLOOR (width - height * geometry->max_aspect, xinc);
 
6516
          if (width - delta >= min_width)
 
6517
            width -= delta;
 
6518
          else
 
6519
            {
 
6520
              delta = FLOOR (width / geometry->max_aspect - height, yinc);
 
6521
              if (height + delta <= max_height)
 
6522
                height += delta;
 
6523
            }
 
6524
        }
 
6525
    }
 
6526
 
 
6527
#undef FLOOR
 
6528
 
 
6529
  *new_width = width;
 
6530
  *new_height = height;
 
6531
}
 
6532
 
 
6533
/**
 
6534
 * gdk_window_get_pointer:
 
6535
 * @window: a #GdkWindow
 
6536
 * @x: (out) (allow-none): return location for X coordinate of pointer or %NULL to not
 
6537
 *      return the X coordinate
 
6538
 * @y: (out) (allow-none):  return location for Y coordinate of pointer or %NULL to not
 
6539
 *      return the Y coordinate
 
6540
 * @mask: (out) (allow-none): return location for modifier mask or %NULL to not return the
 
6541
 *      modifier mask
 
6542
 *
 
6543
 * Obtains the current pointer position and modifier state.
 
6544
 * The position is given in coordinates relative to the upper left
 
6545
 * corner of @window.
 
6546
 *
 
6547
 * Return value: (transfer none): the window containing the pointer (as with
 
6548
 * gdk_window_at_pointer()), or %NULL if the window containing the
 
6549
 * pointer isn't known to GDK
 
6550
 **/
 
6551
GdkWindow*
 
6552
gdk_window_get_pointer (GdkWindow         *window,
 
6553
                        gint              *x,
 
6554
                        gint              *y,
 
6555
                        GdkModifierType   *mask)
 
6556
{
 
6557
  GdkDisplay *display;
 
6558
  gint tmp_x, tmp_y;
 
6559
  GdkModifierType tmp_mask;
 
6560
  GdkWindow *child;
 
6561
 
 
6562
  g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
 
6563
 
 
6564
  if (window)
 
6565
    {
 
6566
      display = gdk_drawable_get_display (window);
 
6567
    }
 
6568
  else
 
6569
    {
 
6570
      GdkScreen *screen = gdk_screen_get_default ();
 
6571
 
 
6572
      display = gdk_screen_get_display (screen);
 
6573
      window = gdk_screen_get_root_window (screen);
 
6574
 
 
6575
      GDK_NOTE (MULTIHEAD,
 
6576
                g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
 
6577
                           "is not multihead safe"));
 
6578
    }
 
6579
 
 
6580
  child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
 
6581
 
 
6582
  if (x)
 
6583
    *x = tmp_x;
 
6584
  if (y)
 
6585
    *y = tmp_y;
 
6586
  if (mask)
 
6587
    *mask = tmp_mask;
 
6588
 
 
6589
  _gdk_display_enable_motion_hints (display);
 
6590
 
 
6591
  return child;
 
6592
}
 
6593
 
 
6594
/**
 
6595
 * gdk_window_at_pointer:
 
6596
 * @win_x: (out) (allow-none): return location for origin of the window under the pointer
 
6597
 * @win_y: (out) (allow-none): return location for origin of the window under the pointer
 
6598
 *
 
6599
 * Obtains the window underneath the mouse pointer, returning the
 
6600
 * location of that window in @win_x, @win_y. Returns %NULL if the
 
6601
 * window under the mouse pointer is not known to GDK (if the window
 
6602
 * belongs to another application and a #GdkWindow hasn't been created
 
6603
 * for it with gdk_window_foreign_new())
 
6604
 *
 
6605
 * NOTE: For multihead-aware widgets or applications use
 
6606
 * gdk_display_get_window_at_pointer() instead.
 
6607
 *
 
6608
 * Return value: (transfer none): window under the mouse pointer
 
6609
 **/
 
6610
GdkWindow*
 
6611
gdk_window_at_pointer (gint *win_x,
 
6612
                       gint *win_y)
 
6613
{
 
6614
  return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
 
6615
}
 
6616
 
 
6617
/**
 
6618
 * gdk_get_default_root_window:
 
6619
 *
 
6620
 * Obtains the root window (parent all other windows are inside)
 
6621
 * for the default display and screen.
 
6622
 *
 
6623
 * Return value: the default root window
 
6624
 **/
 
6625
GdkWindow *
 
6626
gdk_get_default_root_window (void)
 
6627
{
 
6628
  return gdk_screen_get_root_window (gdk_screen_get_default ());
 
6629
}
 
6630
 
 
6631
/**
 
6632
 * gdk_window_foreign_new:
 
6633
 * @anid: a native window handle.
 
6634
 *
 
6635
 * Wraps a native window for the default display in a #GdkWindow.
 
6636
 * This may fail if the window has been destroyed.
 
6637
 *
 
6638
 * For example in the X backend, a native window handle is an Xlib
 
6639
 * <type>XID</type>.
 
6640
 *
 
6641
 * Return value: the newly-created #GdkWindow wrapper for the
 
6642
 *    native window or %NULL if the window has been destroyed.
 
6643
 **/
 
6644
GdkWindow *
 
6645
gdk_window_foreign_new (GdkNativeWindow anid)
 
6646
{
 
6647
  return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
 
6648
}
 
6649
 
 
6650
static void
 
6651
get_all_native_children (GdkWindowObject *private,
 
6652
                         GList **native)
 
6653
{
 
6654
  GdkWindowObject *child;
 
6655
  GList *l;
 
6656
 
 
6657
  for (l = private->children; l != NULL; l = l->next)
 
6658
    {
 
6659
      child = l->data;
 
6660
 
 
6661
      if (gdk_window_has_impl (child))
 
6662
        *native = g_list_prepend (*native, child);
 
6663
      else
 
6664
        get_all_native_children (child, native);
 
6665
    }
 
6666
}
 
6667
 
 
6668
 
 
6669
static inline void
 
6670
gdk_window_raise_internal (GdkWindow *window)
 
6671
{
 
6672
  GdkWindowObject *private = (GdkWindowObject *)window;
 
6673
  GdkWindowObject *parent = private->parent;
 
6674
  GdkWindowObject *above;
 
6675
  GList *native_children;
 
6676
  GList *l, listhead;
 
6677
  GdkWindowImplIface *impl_iface;
 
6678
 
 
6679
  if (parent)
 
6680
    {
 
6681
      parent->children = g_list_remove (parent->children, window);
 
6682
      parent->children = g_list_prepend (parent->children, window);
 
6683
    }
 
6684
 
 
6685
  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
6686
  /* Just do native raise for toplevels */
 
6687
  if (gdk_window_is_toplevel (private) ||
 
6688
      /* The restack_under codepath should work correctly even if the parent
 
6689
         is native, but it relies on the order of ->children to be correct,
 
6690
         and some apps like SWT reorder the x windows without gdks knowledge,
 
6691
         so we use raise directly in order to make these behave as before
 
6692
         when using native windows */
 
6693
      (gdk_window_has_impl (private) && gdk_window_has_impl (parent)))
 
6694
    {
 
6695
      impl_iface->raise (window);
 
6696
    }
 
6697
  else if (gdk_window_has_impl (private))
 
6698
    {
 
6699
      above = find_native_sibling_above (parent, private);
 
6700
      if (above)
 
6701
        {
 
6702
          listhead.data = window;
 
6703
          listhead.next = NULL;
 
6704
          listhead.prev = NULL;
 
6705
          impl_iface->restack_under ((GdkWindow *)above,
 
6706
                                     &listhead);
 
6707
        }
 
6708
      else
 
6709
        impl_iface->raise (window);
 
6710
    }
 
6711
  else
 
6712
    {
 
6713
      native_children = NULL;
 
6714
      get_all_native_children (private, &native_children);
 
6715
      if (native_children != NULL)
 
6716
        {
 
6717
          above = find_native_sibling_above (parent, private);
 
6718
 
 
6719
          if (above)
 
6720
            impl_iface->restack_under ((GdkWindow *)above,
 
6721
                                       native_children);
 
6722
          else
 
6723
            {
 
6724
              /* Right order, since native_children is bottom-topmost first */
 
6725
              for (l = native_children; l != NULL; l = l->next)
 
6726
                impl_iface->raise (l->data);
 
6727
            }
 
6728
 
 
6729
          g_list_free (native_children);
 
6730
        }
 
6731
 
 
6732
    }
 
6733
}
 
6734
 
 
6735
/* Returns TRUE If the native window was mapped or unmapped */
 
6736
static gboolean
 
6737
set_viewable (GdkWindowObject *w,
 
6738
              gboolean val)
 
6739
{
 
6740
  GdkWindowObject *child;
 
6741
  GdkWindowImplIface *impl_iface;
 
6742
  GList *l;
 
6743
 
 
6744
  if (w->viewable == val)
 
6745
    return FALSE;
 
6746
 
 
6747
  w->viewable = val;
 
6748
 
 
6749
  if (val)
 
6750
    recompute_visible_regions (w, FALSE, FALSE);
 
6751
 
 
6752
  for (l = w->children; l != NULL; l = l->next)
 
6753
    {
 
6754
      child = l->data;
 
6755
 
 
6756
      if (GDK_WINDOW_IS_MAPPED (child) &&
 
6757
          child->window_type != GDK_WINDOW_FOREIGN)
 
6758
        set_viewable (child, val);
 
6759
    }
 
6760
 
 
6761
  if (!_gdk_native_windows &&
 
6762
      gdk_window_has_impl (w)  &&
 
6763
      w->window_type != GDK_WINDOW_FOREIGN &&
 
6764
      !gdk_window_is_toplevel (w))
 
6765
    {
 
6766
      /* For most native windows we show/hide them not when they are
 
6767
       * mapped/unmapped, because that may not produce the correct results.
 
6768
       * For instance, if a native window have a non-native parent which is
 
6769
       * hidden, but its native parent is viewable then showing the window
 
6770
       * would make it viewable to X but its not viewable wrt the non-native
 
6771
       * hierarchy. In order to handle this we track the gdk side viewability
 
6772
       * and only map really viewable windows.
 
6773
       *
 
6774
       * There are two exceptions though:
 
6775
       *
 
6776
       * For foreign windows we don't want ever change the mapped state
 
6777
       * except when explicitly done via gdk_window_show/hide, as this may
 
6778
       * cause problems for client owning the foreign window when its window
 
6779
       * is suddenly mapped or unmapped.
 
6780
       *
 
6781
       * For toplevel windows embedded in a foreign window (e.g. a plug)
 
6782
       * we sometimes synthesize a map of a window, but the native
 
6783
       * window is really shown by the embedder, so we don't want to
 
6784
       * do the show ourselves. We can't really tell this case from the normal
 
6785
       * toplevel show as such toplevels are seen by gdk as parents of the
 
6786
       * root window, so we make an exception for all toplevels.
 
6787
       *
 
6788
       * Also, when in GDK_NATIVE_WINDOW mode we never need to play games
 
6789
       * like this, so we just always show/hide directly.
 
6790
       */
 
6791
 
 
6792
      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (w->impl);
 
6793
      if (val)
 
6794
        impl_iface->show ((GdkWindow *)w, FALSE);
 
6795
      else
 
6796
        impl_iface->hide ((GdkWindow *)w);
 
6797
 
 
6798
      return TRUE;
 
6799
    }
 
6800
 
 
6801
  return FALSE;
 
6802
}
 
6803
 
 
6804
/* Returns TRUE If the native window was mapped or unmapped */
 
6805
gboolean
 
6806
_gdk_window_update_viewable (GdkWindow *window)
 
6807
{
 
6808
  GdkWindowObject *priv = (GdkWindowObject *)window;
 
6809
  gboolean viewable;
 
6810
 
 
6811
  if (priv->window_type == GDK_WINDOW_FOREIGN ||
 
6812
      priv->window_type == GDK_WINDOW_ROOT)
 
6813
    viewable = TRUE;
 
6814
  else if (gdk_window_is_toplevel (priv) ||
 
6815
           priv->parent->viewable)
 
6816
    viewable = GDK_WINDOW_IS_MAPPED (priv);
 
6817
  else
 
6818
    viewable = FALSE;
 
6819
 
 
6820
  return set_viewable (priv, viewable);
 
6821
}
 
6822
 
 
6823
static void
 
6824
gdk_window_show_internal (GdkWindow *window, gboolean raise)
 
6825
{
 
6826
  GdkWindowObject *private;
 
6827
  GdkWindowImplIface *impl_iface;
 
6828
  gboolean was_mapped, was_viewable;
 
6829
  gboolean did_show;
 
6830
 
 
6831
  g_return_if_fail (GDK_IS_WINDOW (window));
 
6832
 
 
6833
  private = (GdkWindowObject *) window;
 
6834
  if (private->destroyed)
 
6835
    return;
 
6836
 
 
6837
  was_mapped = GDK_WINDOW_IS_MAPPED (window);
 
6838
  was_viewable = private->viewable;
 
6839
 
 
6840
  if (raise)
 
6841
    /* Keep children in (reverse) stacking order */
 
6842
    gdk_window_raise_internal (window);
 
6843
 
 
6844
  if (gdk_window_has_impl (private))
 
6845
    {
 
6846
      if (!was_mapped)
 
6847
        gdk_synthesize_window_state (window,
 
6848
                                     GDK_WINDOW_STATE_WITHDRAWN,
 
6849
                                     0);
 
6850
    }
 
6851
  else
 
6852
    {
 
6853
      private->state = 0;
 
6854
    }
 
6855
 
 
6856
  did_show = _gdk_window_update_viewable (window);
 
6857
 
 
6858
  /* If it was already viewable the backend show op won't be called, call it
 
6859
     again to ensure things happen right if the mapped tracking was not right
 
6860
     for e.g. a foreign window.
 
6861
     Dunno if this is strictly needed but its what happened pre-csw.
 
6862
     Also show if not done by gdk_window_update_viewable. */
 
6863
  if (gdk_window_has_impl (private) && (was_viewable || !did_show))
 
6864
    {
 
6865
      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
6866
      impl_iface->show ((GdkWindow *)private,
 
6867
                        !did_show ? was_mapped : TRUE);
 
6868
    }
 
6869
 
 
6870
  if (!was_mapped && !gdk_window_has_impl (private))
 
6871
    {
 
6872
      if (private->event_mask & GDK_STRUCTURE_MASK)
 
6873
        _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
 
6874
 
 
6875
      if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
 
6876
        _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
 
6877
    }
 
6878
 
 
6879
  if (!was_mapped || raise)
 
6880
    {
 
6881
      recompute_visible_regions (private, TRUE, FALSE);
 
6882
 
 
6883
      /* If any decendants became visible we need to send visibility notify */
 
6884
      gdk_window_update_visibility_recursively (private, NULL);
 
6885
 
 
6886
      if (gdk_window_is_viewable (window))
 
6887
        {
 
6888
          _gdk_synthesize_crossing_events_for_geometry_change (window);
 
6889
          gdk_window_invalidate_rect_full (window, NULL, TRUE, CLEAR_BG_ALL);
 
6890
        }
 
6891
    }
 
6892
}
 
6893
 
 
6894
/**
 
6895
 * gdk_window_show_unraised:
 
6896
 * @window: a #GdkWindow
 
6897
 *
 
6898
 * Shows a #GdkWindow onscreen, but does not modify its stacking
 
6899
 * order. In contrast, gdk_window_show() will raise the window
 
6900
 * to the top of the window stack.
 
6901
 *
 
6902
 * On the X11 platform, in Xlib terms, this function calls
 
6903
 * XMapWindow() (it also updates some internal GDK state, which means
 
6904
 * that you can't really use XMapWindow() directly on a GDK window).
 
6905
 */
 
6906
void
 
6907
gdk_window_show_unraised (GdkWindow *window)
 
6908
{
 
6909
  gdk_window_show_internal (window, FALSE);
 
6910
}
 
6911
 
 
6912
/**
 
6913
 * gdk_window_raise:
 
6914
 * @window: a #GdkWindow
 
6915
 *
 
6916
 * Raises @window to the top of the Z-order (stacking order), so that
 
6917
 * other windows with the same parent window appear below @window.
 
6918
 * This is true whether or not the windows are visible.
 
6919
 *
 
6920
 * If @window is a toplevel, the window manager may choose to deny the
 
6921
 * request to move the window in the Z-order, gdk_window_raise() only
 
6922
 * requests the restack, does not guarantee it.
 
6923
 */
 
6924
void
 
6925
gdk_window_raise (GdkWindow *window)
 
6926
{
 
6927
  GdkWindowObject *private;
 
6928
  GdkRegion *old_region, *new_region;
 
6929
 
 
6930
  g_return_if_fail (GDK_IS_WINDOW (window));
 
6931
 
 
6932
  private = (GdkWindowObject *) window;
 
6933
  if (private->destroyed)
 
6934
    return;
 
6935
 
 
6936
  gdk_window_flush_if_exposing (window);
 
6937
 
 
6938
  old_region = NULL;
 
6939
  if (gdk_window_is_viewable (window) &&
 
6940
      !private->input_only)
 
6941
    old_region = gdk_region_copy (private->clip_region);
 
6942
 
 
6943
  /* Keep children in (reverse) stacking order */
 
6944
  gdk_window_raise_internal (window);
 
6945
 
 
6946
  recompute_visible_regions (private, TRUE, FALSE);
 
6947
 
 
6948
  if (old_region)
 
6949
    {
 
6950
      new_region = gdk_region_copy (private->clip_region);
 
6951
 
 
6952
      gdk_region_subtract (new_region, old_region);
 
6953
      gdk_window_invalidate_region_full (window, new_region, TRUE, CLEAR_BG_ALL);
 
6954
 
 
6955
      gdk_region_destroy (old_region);
 
6956
      gdk_region_destroy (new_region);
 
6957
    }
 
6958
}
 
6959
 
 
6960
static void
 
6961
gdk_window_lower_internal (GdkWindow *window)
 
6962
{
 
6963
  GdkWindowObject *private = (GdkWindowObject *)window;
 
6964
  GdkWindowObject *parent = private->parent;
 
6965
  GdkWindowImplIface *impl_iface;
 
6966
  GdkWindowObject *above;
 
6967
  GList *native_children;
 
6968
  GList *l, listhead;
 
6969
 
 
6970
  if (parent)
 
6971
    {
 
6972
      parent->children = g_list_remove (parent->children, window);
 
6973
      parent->children = g_list_append (parent->children, window);
 
6974
    }
 
6975
 
 
6976
  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
6977
  /* Just do native lower for toplevels */
 
6978
  if (gdk_window_is_toplevel (private) ||
 
6979
      /* The restack_under codepath should work correctly even if the parent
 
6980
         is native, but it relies on the order of ->children to be correct,
 
6981
         and some apps like SWT reorder the x windows without gdks knowledge,
 
6982
         so we use lower directly in order to make these behave as before
 
6983
         when using native windows */
 
6984
      (gdk_window_has_impl (private) && gdk_window_has_impl (parent)))
 
6985
    {
 
6986
      impl_iface->lower (window);
 
6987
    }
 
6988
  else if (gdk_window_has_impl (private))
 
6989
    {
 
6990
      above = find_native_sibling_above (parent, private);
 
6991
      if (above)
 
6992
        {
 
6993
          listhead.data = window;
 
6994
          listhead.next = NULL;
 
6995
          listhead.prev = NULL;
 
6996
          impl_iface->restack_under ((GdkWindow *)above, &listhead);
 
6997
        }
 
6998
      else
 
6999
        impl_iface->raise (window);
 
7000
    }
 
7001
  else
 
7002
    {
 
7003
      native_children = NULL;
 
7004
      get_all_native_children (private, &native_children);
 
7005
      if (native_children != NULL)
 
7006
        {
 
7007
          above = find_native_sibling_above (parent, private);
 
7008
 
 
7009
          if (above)
 
7010
            impl_iface->restack_under ((GdkWindow *)above,
 
7011
                                       native_children);
 
7012
          else
 
7013
            {
 
7014
              /* Right order, since native_children is bottom-topmost first */
 
7015
              for (l = native_children; l != NULL; l = l->next)
 
7016
                impl_iface->raise (l->data);
 
7017
            }
 
7018
 
 
7019
          g_list_free (native_children);
 
7020
        }
 
7021
 
 
7022
    }
 
7023
}
 
7024
 
 
7025
static void
 
7026
gdk_window_invalidate_in_parent (GdkWindowObject *private)
 
7027
{
 
7028
  GdkRectangle r, child;
 
7029
 
 
7030
  if (gdk_window_is_toplevel (private))
 
7031
    return;
 
7032
 
 
7033
  /* get the visible rectangle of the parent */
 
7034
  r.x = r.y = 0;
 
7035
  r.width = private->parent->width;
 
7036
  r.height = private->parent->height;
 
7037
 
 
7038
  child.x = private->x;
 
7039
  child.y = private->y;
 
7040
  child.width = private->width;
 
7041
  child.height = private->height;
 
7042
  gdk_rectangle_intersect (&r, &child, &r);
 
7043
 
 
7044
  gdk_window_invalidate_rect_full (GDK_WINDOW (private->parent), &r, TRUE, CLEAR_BG_ALL);
 
7045
}
 
7046
 
 
7047
 
 
7048
/**
 
7049
 * gdk_window_lower:
 
7050
 * @window: a #GdkWindow
 
7051
 *
 
7052
 * Lowers @window to the bottom of the Z-order (stacking order), so that
 
7053
 * other windows with the same parent window appear above @window.
 
7054
 * This is true whether or not the other windows are visible.
 
7055
 *
 
7056
 * If @window is a toplevel, the window manager may choose to deny the
 
7057
 * request to move the window in the Z-order, gdk_window_lower() only
 
7058
 * requests the restack, does not guarantee it.
 
7059
 *
 
7060
 * Note that gdk_window_show() raises the window again, so don't call this
 
7061
 * function before gdk_window_show(). (Try gdk_window_show_unraised().)
 
7062
 */
 
7063
void
 
7064
gdk_window_lower (GdkWindow *window)
 
7065
{
 
7066
  GdkWindowObject *private;
 
7067
 
 
7068
  g_return_if_fail (GDK_IS_WINDOW (window));
 
7069
 
 
7070
  private = (GdkWindowObject *) window;
 
7071
  if (private->destroyed)
 
7072
    return;
 
7073
 
 
7074
  gdk_window_flush_if_exposing (window);
 
7075
 
 
7076
  /* Keep children in (reverse) stacking order */
 
7077
  gdk_window_lower_internal (window);
 
7078
 
 
7079
  recompute_visible_regions (private, TRUE, FALSE);
 
7080
 
 
7081
  _gdk_synthesize_crossing_events_for_geometry_change (window);
 
7082
  gdk_window_invalidate_in_parent (private);
 
7083
}
 
7084
 
 
7085
/**
 
7086
 * gdk_window_restack:
 
7087
 * @window: a #GdkWindow
 
7088
 * @sibling: (allow-none): a #GdkWindow that is a sibling of @window, or %NULL
 
7089
 * @above: a boolean
 
7090
 *
 
7091
 * Changes the position of  @window in the Z-order (stacking order), so that
 
7092
 * it is above @sibling (if @above is %TRUE) or below @sibling (if @above is
 
7093
 * %FALSE).
 
7094
 *
 
7095
 * If @sibling is %NULL, then this either raises (if @above is %TRUE) or
 
7096
 * lowers the window.
 
7097
 *
 
7098
 * If @window is a toplevel, the window manager may choose to deny the
 
7099
 * request to move the window in the Z-order, gdk_window_restack() only
 
7100
 * requests the restack, does not guarantee it.
 
7101
 *
 
7102
 * Since: 2.18
 
7103
 */
 
7104
void
 
7105
gdk_window_restack (GdkWindow     *window,
 
7106
                    GdkWindow     *sibling,
 
7107
                    gboolean       above)
 
7108
{
 
7109
  GdkWindowObject *private;
 
7110
  GdkWindowImplIface *impl_iface;
 
7111
  GdkWindowObject *parent;
 
7112
  GdkWindowObject *above_native;
 
7113
  GList *sibling_link;
 
7114
  GList *native_children;
 
7115
  GList *l, listhead;
 
7116
 
 
7117
  g_return_if_fail (GDK_IS_WINDOW (window));
 
7118
  g_return_if_fail (sibling == NULL || GDK_IS_WINDOW (sibling));
 
7119
 
 
7120
  private = (GdkWindowObject *) window;
 
7121
  if (private->destroyed)
 
7122
    return;
 
7123
 
 
7124
  if (sibling == NULL)
 
7125
    {
 
7126
      if (above)
 
7127
        gdk_window_raise (window);
 
7128
      else
 
7129
        gdk_window_lower (window);
 
7130
      return;
 
7131
    }
 
7132
 
 
7133
  gdk_window_flush_if_exposing (window);
 
7134
 
 
7135
  if (gdk_window_is_toplevel (private))
 
7136
    {
 
7137
      g_return_if_fail (gdk_window_is_toplevel (GDK_WINDOW_OBJECT (sibling)));
 
7138
      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
7139
      impl_iface->restack_toplevel (window, sibling, above);
 
7140
      return;
 
7141
    }
 
7142
 
 
7143
  parent = private->parent;
 
7144
  if (parent)
 
7145
    {
 
7146
      sibling_link = g_list_find (parent->children, sibling);
 
7147
      g_return_if_fail (sibling_link != NULL);
 
7148
      if (sibling_link == NULL)
 
7149
        return;
 
7150
 
 
7151
      parent->children = g_list_remove (parent->children, window);
 
7152
      if (above)
 
7153
        parent->children = g_list_insert_before (parent->children,
 
7154
                                                 sibling_link,
 
7155
                                                 window);
 
7156
      else
 
7157
        parent->children = g_list_insert_before (parent->children,
 
7158
                                                 sibling_link->next,
 
7159
                                                 window);
 
7160
 
 
7161
      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
7162
      if (gdk_window_has_impl (private))
 
7163
        {
 
7164
          above_native = find_native_sibling_above (parent, private);
 
7165
          if (above_native)
 
7166
            {
 
7167
              listhead.data = window;
 
7168
              listhead.next = NULL;
 
7169
              listhead.prev = NULL;
 
7170
              impl_iface->restack_under ((GdkWindow *)above_native, &listhead);
 
7171
            }
 
7172
          else
 
7173
            impl_iface->raise (window);
 
7174
        }
 
7175
      else
 
7176
        {
 
7177
          native_children = NULL;
 
7178
          get_all_native_children (private, &native_children);
 
7179
          if (native_children != NULL)
 
7180
            {
 
7181
              above_native = find_native_sibling_above (parent, private);
 
7182
              if (above_native)
 
7183
                impl_iface->restack_under ((GdkWindow *)above_native,
 
7184
                                           native_children);
 
7185
              else
 
7186
                {
 
7187
                  /* Right order, since native_children is bottom-topmost first */
 
7188
                  for (l = native_children; l != NULL; l = l->next)
 
7189
                    impl_iface->raise (l->data);
 
7190
                }
 
7191
 
 
7192
              g_list_free (native_children);
 
7193
            }
 
7194
        }
 
7195
    }
 
7196
 
 
7197
  recompute_visible_regions (private, TRUE, FALSE);
 
7198
 
 
7199
  _gdk_synthesize_crossing_events_for_geometry_change (window);
 
7200
  gdk_window_invalidate_in_parent (private);
 
7201
}
 
7202
 
 
7203
 
 
7204
/**
 
7205
 * gdk_window_show:
 
7206
 * @window: a #GdkWindow
 
7207
 *
 
7208
 * Like gdk_window_show_unraised(), but also raises the window to the
 
7209
 * top of the window stack (moves the window to the front of the
 
7210
 * Z-order).
 
7211
 *
 
7212
 * This function maps a window so it's visible onscreen. Its opposite
 
7213
 * is gdk_window_hide().
 
7214
 *
 
7215
 * When implementing a #GtkWidget, you should call this function on the widget's
 
7216
 * #GdkWindow as part of the "map" method.
 
7217
 */
 
7218
void
 
7219
gdk_window_show (GdkWindow *window)
 
7220
{
 
7221
  gdk_window_show_internal (window, TRUE);
 
7222
}
 
7223
 
 
7224
/**
 
7225
 * gdk_window_hide:
 
7226
 * @window: a #GdkWindow
 
7227
 *
 
7228
 * For toplevel windows, withdraws them, so they will no longer be
 
7229
 * known to the window manager; for all windows, unmaps them, so
 
7230
 * they won't be displayed. Normally done automatically as
 
7231
 * part of gtk_widget_hide().
 
7232
 */
 
7233
void
 
7234
gdk_window_hide (GdkWindow *window)
 
7235
{
 
7236
  GdkWindowObject *private;
 
7237
  GdkWindowImplIface *impl_iface;
 
7238
  gboolean was_mapped, did_hide;
 
7239
 
 
7240
  g_return_if_fail (GDK_IS_WINDOW (window));
 
7241
 
 
7242
  private = (GdkWindowObject *) window;
 
7243
  if (private->destroyed)
 
7244
    return;
 
7245
 
 
7246
  was_mapped = GDK_WINDOW_IS_MAPPED (private);
 
7247
 
 
7248
  if (gdk_window_has_impl (private))
 
7249
    {
 
7250
 
 
7251
      if (GDK_WINDOW_IS_MAPPED (window))
 
7252
        gdk_synthesize_window_state (window,
 
7253
                                     0,
 
7254
                                     GDK_WINDOW_STATE_WITHDRAWN);
 
7255
    }
 
7256
  else if (was_mapped)
 
7257
    {
 
7258
      GdkDisplay *display;
 
7259
 
 
7260
      /* May need to break grabs on children */
 
7261
      display = gdk_drawable_get_display (window);
 
7262
 
 
7263
      if (_gdk_display_end_pointer_grab (display,
 
7264
                                         _gdk_windowing_window_get_next_serial (display),
 
7265
                                         window,
 
7266
                                         TRUE))
 
7267
        gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
 
7268
 
 
7269
      if (display->keyboard_grab.window != NULL)
 
7270
        {
 
7271
          if (is_parent_of (window, display->keyboard_grab.window))
 
7272
            {
 
7273
              /* Call this ourselves, even though gdk_display_keyboard_ungrab
 
7274
                 does so too, since we want to pass implicit == TRUE so the
 
7275
                 broken grab event is generated */
 
7276
              _gdk_display_unset_has_keyboard_grab (display,
 
7277
                                                    TRUE);
 
7278
              gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
 
7279
            }
 
7280
        }
 
7281
 
 
7282
      private->state = GDK_WINDOW_STATE_WITHDRAWN;
 
7283
    }
 
7284
 
 
7285
  did_hide = _gdk_window_update_viewable (window);
 
7286
 
 
7287
  /* Hide foreign window as those are not handled by update_viewable. */
 
7288
  if (gdk_window_has_impl (private) && (!did_hide))
 
7289
    {
 
7290
      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
7291
      impl_iface->hide (window);
 
7292
    }
 
7293
 
 
7294
  recompute_visible_regions (private, TRUE, FALSE);
 
7295
 
 
7296
  /* all decendants became non-visible, we need to send visibility notify */
 
7297
  gdk_window_update_visibility_recursively (private, NULL);
 
7298
 
 
7299
  if (was_mapped && !gdk_window_has_impl (private))
 
7300
    {
 
7301
      if (private->event_mask & GDK_STRUCTURE_MASK)
 
7302
        _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
 
7303
 
 
7304
      if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
 
7305
        _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
 
7306
 
 
7307
      _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
 
7308
    }
 
7309
 
 
7310
  /* Invalidate the rect */
 
7311
  if (was_mapped)
 
7312
    gdk_window_invalidate_in_parent (private);
 
7313
}
 
7314
 
 
7315
/**
 
7316
 * gdk_window_withdraw:
 
7317
 * @window: a toplevel #GdkWindow
 
7318
 *
 
7319
 * Withdraws a window (unmaps it and asks the window manager to forget about it).
 
7320
 * This function is not really useful as gdk_window_hide() automatically
 
7321
 * withdraws toplevel windows before hiding them.
 
7322
 **/
 
7323
void
 
7324
gdk_window_withdraw (GdkWindow *window)
 
7325
{
 
7326
  GdkWindowObject *private;
 
7327
  GdkWindowImplIface *impl_iface;
 
7328
  gboolean was_mapped;
 
7329
 
 
7330
  g_return_if_fail (GDK_IS_WINDOW (window));
 
7331
 
 
7332
  private = (GdkWindowObject *) window;
 
7333
  if (private->destroyed)
 
7334
    return;
 
7335
 
 
7336
  was_mapped = GDK_WINDOW_IS_MAPPED (private);
 
7337
 
 
7338
  if (gdk_window_has_impl (private))
 
7339
    {
 
7340
      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
7341
      impl_iface->withdraw (window);
 
7342
 
 
7343
      if (was_mapped)
 
7344
        {
 
7345
          if (private->event_mask & GDK_STRUCTURE_MASK)
 
7346
            _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
 
7347
 
 
7348
          if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
 
7349
            _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
 
7350
 
 
7351
          _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
 
7352
        }
 
7353
 
 
7354
      recompute_visible_regions (private, TRUE, FALSE);
 
7355
    }
 
7356
}
 
7357
 
 
7358
/**
 
7359
 * gdk_window_set_events:
 
7360
 * @window: a #GdkWindow
 
7361
 * @event_mask: event mask for @window
 
7362
 *
 
7363
 * The event mask for a window determines which events will be reported
 
7364
 * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
 
7365
 * means the window should report button press events. The event mask
 
7366
 * is the bitwise OR of values from the #GdkEventMask enumeration.
 
7367
 **/
 
7368
void
 
7369
gdk_window_set_events (GdkWindow       *window,
 
7370
                       GdkEventMask     event_mask)
 
7371
{
 
7372
  GdkWindowObject *private;
 
7373
  GdkWindowImplIface *impl_iface;
 
7374
  GdkDisplay *display;
 
7375
 
 
7376
  g_return_if_fail (GDK_IS_WINDOW (window));
 
7377
 
 
7378
  private = (GdkWindowObject *) window;
 
7379
  if (private->destroyed)
 
7380
    return;
 
7381
 
 
7382
  /* If motion hint is disabled, enable motion events again */
 
7383
  display = gdk_drawable_get_display (window);
 
7384
  if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
 
7385
      !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
 
7386
    _gdk_display_enable_motion_hints (display);
 
7387
 
 
7388
  private->event_mask = event_mask;
 
7389
 
 
7390
  if (gdk_window_has_impl (private))
 
7391
    {
 
7392
      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
7393
      impl_iface->set_events (window,
 
7394
                              get_native_event_mask (private));
 
7395
    }
 
7396
 
 
7397
}
 
7398
 
 
7399
/**
 
7400
 * gdk_window_get_events:
 
7401
 * @window: a #GdkWindow
 
7402
 *
 
7403
 * Gets the event mask for @window. See gdk_window_set_events().
 
7404
 *
 
7405
 * Return value: event mask for @window
 
7406
 **/
 
7407
GdkEventMask
 
7408
gdk_window_get_events (GdkWindow *window)
 
7409
{
 
7410
  GdkWindowObject *private;
 
7411
 
 
7412
  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
7413
 
 
7414
  private = (GdkWindowObject *) window;
 
7415
  if (private->destroyed)
 
7416
    return 0;
 
7417
 
 
7418
  return private->event_mask;
 
7419
}
 
7420
 
 
7421
static void
 
7422
gdk_window_move_resize_toplevel (GdkWindow *window,
 
7423
                                 gboolean   with_move,
 
7424
                                 gint       x,
 
7425
                                 gint       y,
 
7426
                                 gint       width,
 
7427
                                 gint       height)
 
7428
{
 
7429
  GdkWindowObject *private;
 
7430
  GdkRegion *old_region, *new_region;
 
7431
  GdkWindowImplIface *impl_iface;
 
7432
  gboolean expose;
 
7433
  int old_x, old_y, old_abs_x, old_abs_y;
 
7434
  int dx, dy;
 
7435
  gboolean is_resize;
 
7436
 
 
7437
  private = (GdkWindowObject *) window;
 
7438
 
 
7439
  expose = FALSE;
 
7440
  old_region = NULL;
 
7441
 
 
7442
  old_x = private->x;
 
7443
  old_y = private->y;
 
7444
 
 
7445
  is_resize = (width != -1) || (height != -1);
 
7446
 
 
7447
  if (gdk_window_is_viewable (window) &&
 
7448
      !private->input_only)
 
7449
    {
 
7450
      expose = TRUE;
 
7451
      old_region = gdk_region_copy (private->clip_region);
 
7452
    }
 
7453
 
 
7454
  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
7455
  impl_iface->move_resize (window, with_move, x, y, width, height);
 
7456
 
 
7457
  dx = private->x - old_x;
 
7458
  dy = private->y - old_y;
 
7459
 
 
7460
  old_abs_x = private->abs_x;
 
7461
  old_abs_y = private->abs_y;
 
7462
 
 
7463
  /* Avoid recomputing for pure toplevel moves, for performance reasons */
 
7464
  if (is_resize)
 
7465
    recompute_visible_regions (private, TRUE, FALSE);
 
7466
 
 
7467
  if (expose)
 
7468
    {
 
7469
      new_region = gdk_region_copy (private->clip_region);
 
7470
 
 
7471
      /* This is the newly exposed area (due to any resize),
 
7472
       * X will expose it, but lets do that without the
 
7473
       * roundtrip
 
7474
       */
 
7475
      gdk_region_subtract (new_region, old_region);
 
7476
      gdk_window_invalidate_region_full (window, new_region, TRUE, CLEAR_BG_WINCLEARED);
 
7477
 
 
7478
      gdk_region_destroy (old_region);
 
7479
      gdk_region_destroy (new_region);
 
7480
    }
 
7481
 
 
7482
  _gdk_synthesize_crossing_events_for_geometry_change (window);
 
7483
}
 
7484
 
 
7485
 
 
7486
static void
 
7487
move_native_children (GdkWindowObject *private)
 
7488
{
 
7489
  GList *l;
 
7490
  GdkWindowObject *child;
 
7491
  GdkWindowImplIface *impl_iface;
 
7492
 
 
7493
  for (l = private->children; l; l = l->next)
 
7494
    {
 
7495
      child = l->data;
 
7496
 
 
7497
      if (child->impl != private->impl)
 
7498
        {
 
7499
          impl_iface = GDK_WINDOW_IMPL_GET_IFACE (child->impl);
 
7500
          impl_iface->move_resize ((GdkWindow *)child, TRUE,
 
7501
                                   child->x, child->y,
 
7502
                                   child->width, child->height);
 
7503
        }
 
7504
      else
 
7505
        move_native_children  (child);
 
7506
    }
 
7507
}
 
7508
 
 
7509
static gboolean
 
7510
collect_native_child_region_helper (GdkWindowObject *window,
 
7511
                                    GdkWindow *impl,
 
7512
                                    GdkRegion **region,
 
7513
                                    int x_offset,
 
7514
                                    int y_offset)
 
7515
{
 
7516
  GdkWindowObject *child;
 
7517
  GdkRegion *tmp;
 
7518
  GList *l;
 
7519
 
 
7520
  for (l = window->children; l != NULL; l = l->next)
 
7521
    {
 
7522
      child = l->data;
 
7523
 
 
7524
      if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
 
7525
        continue;
 
7526
 
 
7527
      if (child->impl != impl)
 
7528
        {
 
7529
          tmp = gdk_region_copy (child->clip_region);
 
7530
          gdk_region_offset (tmp,
 
7531
                             x_offset + child->x,
 
7532
                             y_offset + child->y);
 
7533
          if (*region == NULL)
 
7534
            *region = tmp;
 
7535
          else
 
7536
            {
 
7537
              gdk_region_union (*region, tmp);
 
7538
              gdk_region_destroy (tmp);
 
7539
            }
 
7540
        }
 
7541
      else
 
7542
        collect_native_child_region_helper (child, impl, region,
 
7543
                                            x_offset + child->x,
 
7544
                                            y_offset + child->y);
 
7545
    }
 
7546
 
 
7547
  return FALSE;
 
7548
}
 
7549
 
 
7550
static GdkRegion *
 
7551
collect_native_child_region (GdkWindowObject *window,
 
7552
                             gboolean include_this)
 
7553
{
 
7554
  GdkRegion *region;
 
7555
 
 
7556
  if (include_this && gdk_window_has_impl (window) && window->viewable)
 
7557
    return gdk_region_copy (window->clip_region);
 
7558
 
 
7559
  region = NULL;
 
7560
 
 
7561
  collect_native_child_region_helper (window, window->impl, &region, 0, 0);
 
7562
 
 
7563
  return region;
 
7564
}
 
7565
 
 
7566
 
 
7567
static void
 
7568
gdk_window_move_resize_internal (GdkWindow *window,
 
7569
                                 gboolean   with_move,
 
7570
                                 gint       x,
 
7571
                                 gint       y,
 
7572
                                 gint       width,
 
7573
                                 gint       height)
 
7574
{
 
7575
  GdkWindowObject *private;
 
7576
  GdkRegion *old_region, *new_region, *copy_area;
 
7577
  GdkRegion *old_native_child_region, *new_native_child_region;
 
7578
  GdkWindowObject *impl_window;
 
7579
  GdkWindowImplIface *impl_iface;
 
7580
  gboolean expose;
 
7581
  int old_x, old_y, old_abs_x, old_abs_y;
 
7582
  int dx, dy;
 
7583
 
 
7584
  g_return_if_fail (GDK_IS_WINDOW (window));
 
7585
 
 
7586
  private = (GdkWindowObject *) window;
 
7587
  if (private->destroyed)
 
7588
    return;
 
7589
 
 
7590
  if (gdk_window_is_toplevel (private))
 
7591
    {
 
7592
      gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
 
7593
      return;
 
7594
    }
 
7595
 
 
7596
  /* Bail early if no change */
 
7597
  if (private->width == width &&
 
7598
      private->height == height &&
 
7599
      (!with_move ||
 
7600
       (private->x == x &&
 
7601
        private->y == y)))
 
7602
    return;
 
7603
 
 
7604
  gdk_window_flush_if_exposing (window);
 
7605
 
 
7606
  /* Handle child windows */
 
7607
 
 
7608
  expose = FALSE;
 
7609
  old_region = NULL;
 
7610
 
 
7611
  impl_window = gdk_window_get_impl_window (private);
 
7612
 
 
7613
  old_x = private->x;
 
7614
  old_y = private->y;
 
7615
 
 
7616
  old_native_child_region = NULL;
 
7617
  if (gdk_window_is_viewable (window) &&
 
7618
      !private->input_only)
 
7619
    {
 
7620
      expose = TRUE;
 
7621
 
 
7622
      old_region = gdk_region_copy (private->clip_region);
 
7623
      /* Adjust region to parent window coords */
 
7624
      gdk_region_offset (old_region, private->x, private->y);
 
7625
 
 
7626
      old_native_child_region = collect_native_child_region (private, TRUE);
 
7627
      if (old_native_child_region)
 
7628
        {
 
7629
          /* Adjust region to parent window coords */
 
7630
          gdk_region_offset (old_native_child_region, private->x, private->y);
 
7631
 
 
7632
          /* Any native window move will immediately copy stuff to the destination, which may overwrite a
 
7633
           * source or destination for a delayed GdkWindowRegionMove. So, we need
 
7634
           * to flush those here for the parent window and all overlapped subwindows
 
7635
           * of it. And we need to do this before setting the new clips as those will be
 
7636
           * affecting this.
 
7637
           */
 
7638
          gdk_window_flush_recursive (private->parent);
 
7639
        }
 
7640
    }
 
7641
 
 
7642
  /* Set the new position and size */
 
7643
  if (with_move)
 
7644
    {
 
7645
      private->x = x;
 
7646
      private->y = y;
 
7647
    }
 
7648
  if (!(width < 0 && height < 0))
 
7649
    {
 
7650
      if (width < 1)
 
7651
        width = 1;
 
7652
      private->width = width;
 
7653
      if (height < 1)
 
7654
        height = 1;
 
7655
      private->height = height;
 
7656
    }
 
7657
 
 
7658
  dx = private->x - old_x;
 
7659
  dy = private->y - old_y;
 
7660
 
 
7661
  old_abs_x = private->abs_x;
 
7662
  old_abs_y = private->abs_y;
 
7663
 
 
7664
  recompute_visible_regions (private, TRUE, FALSE);
 
7665
 
 
7666
  new_native_child_region = NULL;
 
7667
  if (old_native_child_region)
 
7668
    {
 
7669
      new_native_child_region = collect_native_child_region (private, TRUE);
 
7670
      /* Adjust region to parent window coords */
 
7671
      gdk_region_offset (new_native_child_region, private->x, private->y);
 
7672
    }
 
7673
 
 
7674
  if (gdk_window_has_impl (private))
 
7675
    {
 
7676
      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
7677
 
 
7678
      /* Do the actual move after recomputing things, as this will have set the shape to
 
7679
         the now correct one, thus avoiding copying regions that should not be copied. */
 
7680
      impl_iface->move_resize (window, TRUE,
 
7681
                               private->x, private->y,
 
7682
                               private->width, private->height);
 
7683
    }
 
7684
  else if (old_abs_x != private->abs_x ||
 
7685
           old_abs_y != private->abs_y)
 
7686
    move_native_children (private);
 
7687
 
 
7688
  if (expose)
 
7689
    {
 
7690
      new_region = gdk_region_copy (private->clip_region);
 
7691
      /* Adjust region to parent window coords */
 
7692
      gdk_region_offset (new_region, private->x, private->y);
 
7693
 
 
7694
      /* copy_area:
 
7695
       * Part of the data at the new location can be copied from the
 
7696
       * old location, this area is the intersection of the old region
 
7697
       * moved as the copy will move it and then intersected with
 
7698
       * the new region.
 
7699
       *
 
7700
       * new_region:
 
7701
       * Everything in the old and new regions that is not copied must be
 
7702
       * invalidated (including children) as this is newly exposed
 
7703
       */
 
7704
      copy_area = gdk_region_copy (new_region);
 
7705
 
 
7706
      gdk_region_union (new_region, old_region);
 
7707
 
 
7708
      if (old_native_child_region)
 
7709
        {
 
7710
          /* Don't copy from inside native children, as this is copied by
 
7711
           * the native window move.
 
7712
           */
 
7713
          gdk_region_subtract (old_region, old_native_child_region);
 
7714
        }
 
7715
      gdk_region_offset (old_region, dx, dy);
 
7716
 
 
7717
      gdk_region_intersect (copy_area, old_region);
 
7718
 
 
7719
      if (new_native_child_region)
 
7720
        {
 
7721
          /* Don't copy any bits that would cause a read from the moved
 
7722
             native windows, as we can't read that data */
 
7723
          gdk_region_offset (new_native_child_region, dx, dy);
 
7724
          gdk_region_subtract (copy_area, new_native_child_region);
 
7725
          gdk_region_offset (new_native_child_region, -dx, -dy);
 
7726
        }
 
7727
 
 
7728
      gdk_region_subtract (new_region, copy_area);
 
7729
 
 
7730
      /* Convert old region to impl coords */
 
7731
      gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
 
7732
 
 
7733
      /* convert from parent coords to impl */
 
7734
      gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
 
7735
 
 
7736
      move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
 
7737
 
 
7738
      /* Invalidate affected part in the parent window
 
7739
       *  (no higher window should be affected)
 
7740
       * We also invalidate any children in that area, which could include
 
7741
       * this window if it still overlaps that area.
 
7742
       */
 
7743
      if (old_native_child_region)
 
7744
        {
 
7745
          /* No need to expose the region that the native window move copies */
 
7746
          gdk_region_offset (old_native_child_region, dx, dy);
 
7747
          gdk_region_intersect (old_native_child_region, new_native_child_region);
 
7748
          gdk_region_subtract (new_region, old_native_child_region);
 
7749
        }
 
7750
      gdk_window_invalidate_region_full (GDK_WINDOW (private->parent), new_region, TRUE, CLEAR_BG_ALL);
 
7751
 
 
7752
      gdk_region_destroy (old_region);
 
7753
      gdk_region_destroy (new_region);
 
7754
    }
 
7755
 
 
7756
  if (old_native_child_region)
 
7757
    {
 
7758
      gdk_region_destroy (old_native_child_region);
 
7759
      gdk_region_destroy (new_native_child_region);
 
7760
    }
 
7761
 
 
7762
  _gdk_synthesize_crossing_events_for_geometry_change (window);
 
7763
}
 
7764
 
 
7765
 
 
7766
 
 
7767
/**
 
7768
 * gdk_window_move:
 
7769
 * @window: a #GdkWindow
 
7770
 * @x: X coordinate relative to window's parent
 
7771
 * @y: Y coordinate relative to window's parent
 
7772
 *
 
7773
 * Repositions a window relative to its parent window.
 
7774
 * For toplevel windows, window managers may ignore or modify the move;
 
7775
 * you should probably use gtk_window_move() on a #GtkWindow widget
 
7776
 * anyway, instead of using GDK functions. For child windows,
 
7777
 * the move will reliably succeed.
 
7778
 *
 
7779
 * If you're also planning to resize the window, use gdk_window_move_resize()
 
7780
 * to both move and resize simultaneously, for a nicer visual effect.
 
7781
 **/
 
7782
void
 
7783
gdk_window_move (GdkWindow *window,
 
7784
                 gint       x,
 
7785
                 gint       y)
 
7786
{
 
7787
  gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
 
7788
}
 
7789
 
 
7790
/**
 
7791
 * gdk_window_resize:
 
7792
 * @window: a #GdkWindow
 
7793
 * @width: new width of the window
 
7794
 * @height: new height of the window
 
7795
 *
 
7796
 * Resizes @window; for toplevel windows, asks the window manager to resize
 
7797
 * the window. The window manager may not allow the resize. When using GTK+,
 
7798
 * use gtk_window_resize() instead of this low-level GDK function.
 
7799
 *
 
7800
 * Windows may not be resized below 1x1.
 
7801
 *
 
7802
 * If you're also planning to move the window, use gdk_window_move_resize()
 
7803
 * to both move and resize simultaneously, for a nicer visual effect.
 
7804
 **/
 
7805
void
 
7806
gdk_window_resize (GdkWindow *window,
 
7807
                   gint       width,
 
7808
                   gint       height)
 
7809
{
 
7810
  gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
 
7811
}
 
7812
 
 
7813
 
 
7814
/**
 
7815
 * gdk_window_move_resize:
 
7816
 * @window: a #GdkWindow
 
7817
 * @x: new X position relative to window's parent
 
7818
 * @y: new Y position relative to window's parent
 
7819
 * @width: new width
 
7820
 * @height: new height
 
7821
 *
 
7822
 * Equivalent to calling gdk_window_move() and gdk_window_resize(),
 
7823
 * except that both operations are performed at once, avoiding strange
 
7824
 * visual effects. (i.e. the user may be able to see the window first
 
7825
 * move, then resize, if you don't use gdk_window_move_resize().)
 
7826
 **/
 
7827
void
 
7828
gdk_window_move_resize (GdkWindow *window,
 
7829
                        gint       x,
 
7830
                        gint       y,
 
7831
                        gint       width,
 
7832
                        gint       height)
 
7833
{
 
7834
  gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
 
7835
}
 
7836
 
 
7837
 
 
7838
/**
 
7839
 * gdk_window_scroll:
 
7840
 * @window: a #GdkWindow
 
7841
 * @dx: Amount to scroll in the X direction
 
7842
 * @dy: Amount to scroll in the Y direction
 
7843
 *
 
7844
 * Scroll the contents of @window, both pixels and children, by the
 
7845
 * given amount. @window itself does not move. Portions of the window
 
7846
 * that the scroll operation brings in from offscreen areas are
 
7847
 * invalidated. The invalidated region may be bigger than what would
 
7848
 * strictly be necessary.
 
7849
 *
 
7850
 * For X11, a minimum area will be invalidated if the window has no
 
7851
 * subwindows, or if the edges of the window's parent do not extend
 
7852
 * beyond the edges of the window. In other cases, a multi-step process
 
7853
 * is used to scroll the window which may produce temporary visual
 
7854
 * artifacts and unnecessary invalidations.
 
7855
 **/
 
7856
void
 
7857
gdk_window_scroll (GdkWindow *window,
 
7858
                   gint       dx,
 
7859
                   gint       dy)
 
7860
{
 
7861
  GdkWindowObject *private = (GdkWindowObject *) window;
 
7862
  GdkWindowObject *impl_window;
 
7863
  GdkRegion *copy_area, *noncopy_area;
 
7864
  GdkRegion *old_native_child_region, *new_native_child_region;
 
7865
  GList *tmp_list;
 
7866
 
 
7867
  g_return_if_fail (GDK_IS_WINDOW (window));
 
7868
 
 
7869
  if (dx == 0 && dy == 0)
 
7870
    return;
 
7871
 
 
7872
  if (private->destroyed)
 
7873
    return;
 
7874
 
 
7875
  gdk_window_flush_if_exposing (window);
 
7876
 
 
7877
  old_native_child_region = collect_native_child_region (private, FALSE);
 
7878
  if (old_native_child_region)
 
7879
    {
 
7880
      /* Any native window move will immediately copy stuff to the destination, which may overwrite a
 
7881
       * source or destination for a delayed GdkWindowRegionMove. So, we need
 
7882
       * to flush those here for the window and all overlapped subwindows
 
7883
       * of it. And we need to do this before setting the new clips as those will be
 
7884
       * affecting this.
 
7885
       */
 
7886
      gdk_window_flush_recursive (private);
 
7887
    }
 
7888
 
 
7889
 
 
7890
  /* First move all child windows, without causing invalidation */
 
7891
 
 
7892
  tmp_list = private->children;
 
7893
  while (tmp_list)
 
7894
    {
 
7895
      GdkWindow *child = GDK_WINDOW (tmp_list->data);
 
7896
      GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
 
7897
 
 
7898
      /* Just update the positions, the bits will move with the copy */
 
7899
      child_obj->x += dx;
 
7900
      child_obj->y += dy;
 
7901
 
 
7902
      tmp_list = tmp_list->next;
 
7903
    }
 
7904
 
 
7905
  recompute_visible_regions (private, FALSE, TRUE);
 
7906
 
 
7907
  new_native_child_region = NULL;
 
7908
  if (old_native_child_region)
 
7909
    new_native_child_region = collect_native_child_region (private, FALSE);
 
7910
 
 
7911
  move_native_children (private);
 
7912
 
 
7913
  /* Then copy the actual bits of the window w/ child windows */
 
7914
 
 
7915
  impl_window = gdk_window_get_impl_window (private);
 
7916
 
 
7917
  /* Calculate the area that can be gotten by copying the old area */
 
7918
  copy_area = gdk_region_copy (private->clip_region);
 
7919
  if (old_native_child_region)
 
7920
    {
 
7921
      /* Don't copy from inside native children, as this is copied by
 
7922
       * the native window move.
 
7923
       */
 
7924
      gdk_region_subtract (copy_area, old_native_child_region);
 
7925
 
 
7926
      /* Don't copy any bits that would cause a read from the moved
 
7927
         native windows, as we can't read that data */
 
7928
      gdk_region_subtract (copy_area, new_native_child_region);
 
7929
    }
 
7930
  gdk_region_offset (copy_area, dx, dy);
 
7931
  gdk_region_intersect (copy_area, private->clip_region);
 
7932
 
 
7933
  /* And the rest need to be invalidated */
 
7934
  noncopy_area = gdk_region_copy (private->clip_region);
 
7935
  gdk_region_subtract (noncopy_area, copy_area);
 
7936
 
 
7937
  /* convert from window coords to impl */
 
7938
  gdk_region_offset (copy_area, private->abs_x, private->abs_y);
 
7939
 
 
7940
  move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
 
7941
 
 
7942
  /* Invalidate not copied regions */
 
7943
  if (old_native_child_region)
 
7944
    {
 
7945
      /* No need to expose the region that the native window move copies */
 
7946
      gdk_region_offset (old_native_child_region, dx, dy);
 
7947
      gdk_region_intersect (old_native_child_region, new_native_child_region);
 
7948
      gdk_region_subtract (noncopy_area, old_native_child_region);
 
7949
    }
 
7950
  gdk_window_invalidate_region_full (window, noncopy_area, TRUE, CLEAR_BG_ALL);
 
7951
 
 
7952
  gdk_region_destroy (noncopy_area);
 
7953
 
 
7954
  if (old_native_child_region)
 
7955
    {
 
7956
      gdk_region_destroy (old_native_child_region);
 
7957
      gdk_region_destroy (new_native_child_region);
 
7958
    }
 
7959
 
 
7960
  _gdk_synthesize_crossing_events_for_geometry_change (window);
 
7961
}
 
7962
 
 
7963
/**
 
7964
 * gdk_window_move_region:
 
7965
 * @window: a #GdkWindow
 
7966
 * @region: The #GdkRegion to move
 
7967
 * @dx: Amount to move in the X direction
 
7968
 * @dy: Amount to move in the Y direction
 
7969
 *
 
7970
 * Move the part of @window indicated by @region by @dy pixels in the Y
 
7971
 * direction and @dx pixels in the X direction. The portions of @region
 
7972
 * that not covered by the new position of @region are invalidated.
 
7973
 *
 
7974
 * Child windows are not moved.
 
7975
 *
 
7976
 * Since: 2.8
 
7977
 */
 
7978
void
 
7979
gdk_window_move_region (GdkWindow       *window,
 
7980
                        const GdkRegion *region,
 
7981
                        gint             dx,
 
7982
                        gint             dy)
 
7983
{
 
7984
  GdkWindowObject *private = (GdkWindowObject *) window;
 
7985
  GdkWindowObject *impl_window;
 
7986
  GdkRegion *nocopy_area;
 
7987
  GdkRegion *copy_area;
 
7988
 
 
7989
  g_return_if_fail (GDK_IS_WINDOW (window));
 
7990
  g_return_if_fail (region != NULL);
 
7991
 
 
7992
  if (dx == 0 && dy == 0)
 
7993
    return;
 
7994
 
 
7995
  if (private->destroyed)
 
7996
    return;
 
7997
 
 
7998
  impl_window = gdk_window_get_impl_window (private);
 
7999
 
 
8000
  /* compute source regions */
 
8001
  copy_area = gdk_region_copy (region);
 
8002
  gdk_region_intersect (copy_area, private->clip_region_with_children);
 
8003
 
 
8004
  /* compute destination regions */
 
8005
  gdk_region_offset (copy_area, dx, dy);
 
8006
  gdk_region_intersect (copy_area, private->clip_region_with_children);
 
8007
 
 
8008
  /* Invalidate parts of the region (source and dest) not covered
 
8009
     by the copy */
 
8010
  nocopy_area = gdk_region_copy (region);
 
8011
  gdk_region_offset (nocopy_area, dx, dy);
 
8012
  gdk_region_union (nocopy_area, region);
 
8013
  gdk_region_subtract (nocopy_area, copy_area);
 
8014
 
 
8015
  /* convert from window coords to impl */
 
8016
  gdk_region_offset (copy_area, private->abs_x, private->abs_y);
 
8017
  move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
 
8018
 
 
8019
  gdk_window_invalidate_region_full (window, nocopy_area, FALSE, CLEAR_BG_ALL);
 
8020
  gdk_region_destroy (nocopy_area);
 
8021
}
 
8022
 
 
8023
/**
 
8024
 * gdk_window_set_background:
 
8025
 * @window: a #GdkWindow
 
8026
 * @color: an allocated #GdkColor
 
8027
 *
 
8028
 * Sets the background color of @window. (However, when using GTK+,
 
8029
 * set the background of a widget with gtk_widget_modify_bg() - if
 
8030
 * you're an application - or gtk_style_set_background() - if you're
 
8031
 * implementing a custom widget.)
 
8032
 *
 
8033
 * The @color must be allocated; gdk_rgb_find_color() is the best way
 
8034
 * to allocate a color.
 
8035
 *
 
8036
 * See also gdk_window_set_back_pixmap().
 
8037
 */
 
8038
void
 
8039
gdk_window_set_background (GdkWindow      *window,
 
8040
                           const GdkColor *color)
 
8041
{
 
8042
  GdkWindowObject *private;
 
8043
  GdkColormap *colormap = gdk_drawable_get_colormap (window);
 
8044
  GdkWindowImplIface *impl_iface;
 
8045
 
 
8046
  g_return_if_fail (GDK_IS_WINDOW (window));
 
8047
 
 
8048
  private = (GdkWindowObject *) window;
 
8049
 
 
8050
  private->bg_color = *color;
 
8051
  gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
 
8052
 
 
8053
  if (private->bg_pixmap &&
 
8054
      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
 
8055
      private->bg_pixmap != GDK_NO_BG)
 
8056
    g_object_unref (private->bg_pixmap);
 
8057
 
 
8058
  private->bg_pixmap = NULL;
 
8059
 
 
8060
  if (private->background)
 
8061
    {
 
8062
      cairo_pattern_destroy (private->background);
 
8063
      private->background = NULL;
 
8064
    }
 
8065
 
 
8066
  if (!GDK_WINDOW_DESTROYED (window) &&
 
8067
      gdk_window_has_impl (private) &&
 
8068
      !private->input_only)
 
8069
    {
 
8070
      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
8071
      impl_iface->set_background (window, &private->bg_color);
 
8072
    }
 
8073
}
 
8074
 
 
8075
/**
 
8076
 * gdk_window_set_back_pixmap:
 
8077
 * @window: a #GdkWindow
 
8078
 * @pixmap: (allow-none): a #GdkPixmap, or %NULL
 
8079
 * @parent_relative: whether the tiling origin is at the origin of
 
8080
 *   @window's parent
 
8081
 *
 
8082
 * Sets the background pixmap of @window. May also be used to set a
 
8083
 * background of "None" on @window, by setting a background pixmap
 
8084
 * of %NULL.
 
8085
 *
 
8086
 * A background pixmap will be tiled, positioning the first tile at
 
8087
 * the origin of @window, or if @parent_relative is %TRUE, the tiling
 
8088
 * will be done based on the origin of the parent window (useful to
 
8089
 * align tiles in a parent with tiles in a child).
 
8090
 *
 
8091
 * A background pixmap of %NULL means that the window will have no
 
8092
 * background.  A window with no background will never have its
 
8093
 * background filled by the windowing system, instead the window will
 
8094
 * contain whatever pixels were already in the corresponding area of
 
8095
 * the display.
 
8096
 *
 
8097
 * The windowing system will normally fill a window with its background
 
8098
 * when the window is obscured then exposed, and when you call
 
8099
 * gdk_window_clear().
 
8100
 */
 
8101
void
 
8102
gdk_window_set_back_pixmap (GdkWindow *window,
 
8103
                            GdkPixmap *pixmap,
 
8104
                            gboolean   parent_relative)
 
8105
{
 
8106
  GdkWindowObject *private;
 
8107
  GdkWindowImplIface *impl_iface;
 
8108
 
 
8109
  g_return_if_fail (GDK_IS_WINDOW (window));
 
8110
  g_return_if_fail (pixmap == NULL || !parent_relative);
 
8111
  g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
 
8112
 
 
8113
  private = (GdkWindowObject *) window;
 
8114
 
 
8115
  if (pixmap && !gdk_drawable_get_colormap (pixmap))
 
8116
    {
 
8117
      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
 
8118
      return;
 
8119
    }
 
8120
 
 
8121
  if (private->bg_pixmap &&
 
8122
      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
 
8123
      private->bg_pixmap != GDK_NO_BG)
 
8124
    g_object_unref (private->bg_pixmap);
 
8125
 
 
8126
  if (private->background)
 
8127
    {
 
8128
      cairo_pattern_destroy (private->background);
 
8129
      private->background = NULL;
 
8130
    }
 
8131
 
 
8132
  if (parent_relative)
 
8133
    private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
 
8134
  else if (pixmap)
 
8135
    private->bg_pixmap = g_object_ref (pixmap);
 
8136
  else
 
8137
    private->bg_pixmap = GDK_NO_BG;
 
8138
 
 
8139
  if (!GDK_WINDOW_DESTROYED (window) &&
 
8140
      gdk_window_has_impl (private) &&
 
8141
      !private->input_only)
 
8142
    {
 
8143
      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
8144
      impl_iface->set_back_pixmap (window, private->bg_pixmap);
 
8145
    }
 
8146
}
 
8147
 
 
8148
/**
 
8149
 * gdk_window_get_background_pattern:
 
8150
 * @window: a window
 
8151
 *
 
8152
 * Gets the pattern used to clear the background on @window. If @window
 
8153
 * does not have its own background and reuses the parent's, %NULL is
 
8154
 * returned and you'll have to query it yourself.
 
8155
 *
 
8156
 * Returns: (transfer none): The pattern to use for the background or
 
8157
 *     %NULL to use the parent's background.
 
8158
 *
 
8159
 * Since: 2.22
 
8160
 **/
 
8161
cairo_pattern_t *
 
8162
gdk_window_get_background_pattern (GdkWindow *window)
 
8163
{
 
8164
  GdkWindowObject *private = (GdkWindowObject *) window;
 
8165
 
 
8166
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
8167
 
 
8168
  if (private->background == NULL)
 
8169
    {
 
8170
      if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG)
 
8171
        private->background = NULL;
 
8172
      else if (private->bg_pixmap != GDK_NO_BG &&
 
8173
               private->bg_pixmap != NULL)
 
8174
        {
 
8175
          static cairo_user_data_key_t key;
 
8176
          cairo_surface_t *surface;
 
8177
 
 
8178
          surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
 
8179
          private->background = cairo_pattern_create_for_surface (surface);
 
8180
          cairo_surface_destroy (surface);
 
8181
 
 
8182
          cairo_pattern_set_extend (private->background, CAIRO_EXTEND_REPEAT);
 
8183
          cairo_pattern_set_user_data (private->background,
 
8184
                                       &key,
 
8185
                                       g_object_ref (private->bg_pixmap),
 
8186
                                       g_object_unref);
 
8187
        }
 
8188
      else
 
8189
        private->background =
 
8190
            cairo_pattern_create_rgb (private->bg_color.red   / 65535.,
 
8191
                                      private->bg_color.green / 65535.,
 
8192
                                      private->bg_color.blue / 65535.);
 
8193
    }   
 
8194
 
 
8195
  return private->background;
 
8196
}
 
8197
 
 
8198
/**
 
8199
 * gdk_window_get_cursor:
 
8200
 * @window: a #GdkWindow
 
8201
 *
 
8202
 * Retrieves a #GdkCursor pointer for the cursor currently set on the
 
8203
 * specified #GdkWindow, or %NULL.  If the return value is %NULL then
 
8204
 * there is no custom cursor set on the specified window, and it is
 
8205
 * using the cursor for its parent window.
 
8206
 *
 
8207
 * Return value: (transfer none): a #GdkCursor, or %NULL. The returned
 
8208
 *   object is owned by the #GdkWindow and should not be unreferenced
 
8209
 *   directly. Use gdk_window_set_cursor() to unset the cursor of the
 
8210
 *   window
 
8211
 *
 
8212
 * Since: 2.18
 
8213
 */
 
8214
GdkCursor *
 
8215
gdk_window_get_cursor (GdkWindow *window)
 
8216
{
 
8217
  GdkWindowObject *private;
 
8218
 
 
8219
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
8220
 
 
8221
  private = (GdkWindowObject *) window;
 
8222
 
 
8223
  return private->cursor;
 
8224
}
 
8225
 
 
8226
/**
 
8227
 * gdk_window_set_cursor:
 
8228
 * @window: a #GdkWindow
 
8229
 * @cursor: (allow-none): a cursor
 
8230
 *
 
8231
 * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
 
8232
 * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
 
8233
 * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
 
8234
 * to gdk_window_set_cursor() means that @window will use the cursor of its
 
8235
 * parent window. Most windows should use this default.
 
8236
 */
 
8237
void
 
8238
gdk_window_set_cursor (GdkWindow *window,
 
8239
                       GdkCursor *cursor)
 
8240
{
 
8241
  GdkWindowObject *private;
 
8242
  GdkWindowImplIface *impl_iface;
 
8243
  GdkDisplay *display;
 
8244
 
 
8245
  g_return_if_fail (GDK_IS_WINDOW (window));
 
8246
 
 
8247
  private = (GdkWindowObject *) window;
 
8248
  display = gdk_drawable_get_display (window);
 
8249
 
 
8250
  if (private->cursor)
 
8251
    {
 
8252
      gdk_cursor_unref (private->cursor);
 
8253
      private->cursor = NULL;
 
8254
    }
 
8255
 
 
8256
  if (!GDK_WINDOW_DESTROYED (window))
 
8257
    {
 
8258
      if (cursor)
 
8259
        private->cursor = gdk_cursor_ref (cursor);
 
8260
 
 
8261
      if (_gdk_native_windows ||
 
8262
          private->window_type == GDK_WINDOW_ROOT ||
 
8263
          private->window_type == GDK_WINDOW_FOREIGN)
 
8264
        {
 
8265
          impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
8266
          impl_iface->set_cursor (window, cursor);
 
8267
        }
 
8268
      else if (_gdk_window_event_parent_of (window, display->pointer_info.window_under_pointer))
 
8269
        update_cursor (display);
 
8270
 
 
8271
      g_object_notify (G_OBJECT (window), "cursor");
 
8272
    }
 
8273
}
 
8274
 
 
8275
/**
 
8276
 * gdk_window_get_geometry:
 
8277
 * @window: a #GdkWindow
 
8278
 * @x: return location for X coordinate of window (relative to its parent)
 
8279
 * @y: return location for Y coordinate of window (relative to its parent)
 
8280
 * @width: return location for width of window
 
8281
 * @height: return location for height of window
 
8282
 * @depth: return location for bit depth of window
 
8283
 *
 
8284
 * Any of the return location arguments to this function may be %NULL,
 
8285
 * if you aren't interested in getting the value of that field.
 
8286
 *
 
8287
 * The X and Y coordinates returned are relative to the parent window
 
8288
 * of @window, which for toplevels usually means relative to the
 
8289
 * window decorations (titlebar, etc.) rather than relative to the
 
8290
 * root window (screen-size background window).
 
8291
 *
 
8292
 * On the X11 platform, the geometry is obtained from the X server,
 
8293
 * so reflects the latest position of @window; this may be out-of-sync
 
8294
 * with the position of @window delivered in the most-recently-processed
 
8295
 * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
 
8296
 * position from the most recent configure event.
 
8297
 *
 
8298
 * <note>
 
8299
 * If @window is not a toplevel, it is <emphasis>much</emphasis> better
 
8300
 * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
 
8301
 * because it avoids the roundtrip to the X server and because
 
8302
 * gdk_drawable_get_size() supports the full 32-bit coordinate space,
 
8303
 * whereas gdk_window_get_geometry() is restricted to the 16-bit
 
8304
 * coordinates of X11.
 
8305
 *</note>
 
8306
 **/
 
8307
void
 
8308
gdk_window_get_geometry (GdkWindow *window,
 
8309
                         gint      *x,
 
8310
                         gint      *y,
 
8311
                         gint      *width,
 
8312
                         gint      *height,
 
8313
                         gint      *depth)
 
8314
{
 
8315
  GdkWindowObject *private, *parent;
 
8316
  GdkWindowImplIface *impl_iface;
 
8317
 
 
8318
  if (!window)
 
8319
    {
 
8320
      GDK_NOTE (MULTIHEAD,
 
8321
                g_message ("gdk_window_get_geometry(): Window needs "
 
8322
                           "to be non-NULL to be multi head safe"));
 
8323
      window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
 
8324
    }
 
8325
 
 
8326
  g_return_if_fail (GDK_IS_WINDOW (window));
 
8327
 
 
8328
  private = (GdkWindowObject *) window;
 
8329
 
 
8330
  if (!GDK_WINDOW_DESTROYED (window))
 
8331
    {
 
8332
      if (gdk_window_has_impl (private))
 
8333
        {
 
8334
          impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
8335
          impl_iface->get_geometry (window, x, y,
 
8336
                                    width, height,
 
8337
                                    depth);
 
8338
          /* This reports the position wrt to the native parent, we need to convert
 
8339
             it to be relative to the client side parent */
 
8340
          parent = private->parent;
 
8341
          if (parent && !gdk_window_has_impl (parent))
 
8342
            {
 
8343
              if (x)
 
8344
                *x -= parent->abs_x;
 
8345
              if (y)
 
8346
                *y -= parent->abs_y;
 
8347
            }
 
8348
        }
 
8349
      else
 
8350
        {
 
8351
          if (x)
 
8352
            *x = private->x;
 
8353
          if (y)
 
8354
            *y = private->y;
 
8355
          if (width)
 
8356
            *width = private->width;
 
8357
          if (height)
 
8358
            *height = private->height;
 
8359
          if (depth)
 
8360
            *depth = private->depth;
 
8361
        }
 
8362
    }
 
8363
}
 
8364
 
 
8365
/**
 
8366
 * gdk_window_get_origin:
 
8367
 * @window: a #GdkWindow
 
8368
 * @x: return location for X coordinate
 
8369
 * @y: return location for Y coordinate
 
8370
 *
 
8371
 * Obtains the position of a window in root window coordinates.
 
8372
 * (Compare with gdk_window_get_position() and
 
8373
 * gdk_window_get_geometry() which return the position of a window
 
8374
 * relative to its parent window.)
 
8375
 *
 
8376
 * Return value: not meaningful, ignore
 
8377
 */
 
8378
gint
 
8379
gdk_window_get_origin (GdkWindow *window,
 
8380
                       gint      *x,
 
8381
                       gint      *y)
 
8382
{
 
8383
  GdkWindowObject *private;
 
8384
  GdkWindowImplIface *impl_iface;
 
8385
 
 
8386
  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
8387
 
 
8388
  if (GDK_WINDOW_DESTROYED (window))
 
8389
    {
 
8390
      if (x)
 
8391
        *x = 0;
 
8392
      if (y)
 
8393
        *y = 0;
 
8394
      return 0;
 
8395
    }
 
8396
  
 
8397
  private = (GdkWindowObject *) window;
 
8398
 
 
8399
  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
8400
  impl_iface->get_root_coords (window,
 
8401
                               private->abs_x,
 
8402
                               private->abs_y,
 
8403
                               x, y);
 
8404
 
 
8405
  return TRUE;
 
8406
}
 
8407
 
 
8408
/**
 
8409
 * gdk_window_get_root_coords:
 
8410
 * @window: a #GdkWindow
 
8411
 * @x: X coordinate in window
 
8412
 * @y: Y coordinate in window
 
8413
 * @root_x: (out): return location for X coordinate
 
8414
 * @root_y: (out): return location for Y coordinate
 
8415
 *
 
8416
 * Obtains the position of a window position in root
 
8417
 * window coordinates. This is similar to
 
8418
 * gdk_window_get_origin() but allows you go pass
 
8419
 * in any position in the window, not just the origin.
 
8420
 *
 
8421
 * Since: 2.18
 
8422
 */
 
8423
void
 
8424
gdk_window_get_root_coords (GdkWindow *window,
 
8425
                            gint       x,
 
8426
                            gint       y,
 
8427
                            gint      *root_x,
 
8428
                            gint      *root_y)
 
8429
{
 
8430
  GdkWindowObject *private;
 
8431
  GdkWindowImplIface *impl_iface;
 
8432
 
 
8433
  g_return_if_fail (GDK_IS_WINDOW (window));
 
8434
 
 
8435
  private = (GdkWindowObject *) window;
 
8436
 
 
8437
  if (GDK_WINDOW_DESTROYED (window))
 
8438
    {
 
8439
      if (x)
 
8440
        *root_x = x;
 
8441
      if (y)
 
8442
        *root_y = y;
 
8443
      return;
 
8444
    }
 
8445
  
 
8446
  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
8447
  impl_iface->get_root_coords (window,
 
8448
                               x + private->abs_x,
 
8449
                               y + private->abs_y,
 
8450
                               root_x, root_y);
 
8451
}
 
8452
 
 
8453
/**
 
8454
 * gdk_window_coords_to_parent:
 
8455
 * @window: a child window
 
8456
 * @x: X coordinate in child's coordinate system
 
8457
 * @y: Y coordinate in child's coordinate system
 
8458
 * @parent_x: (out) (allow-none): return location for X coordinate
 
8459
 * in parent's coordinate system, or %NULL
 
8460
 * @parent_y: (out) (allow-none): return location for Y coordinate
 
8461
 * in parent's coordinate system, or %NULL
 
8462
 *
 
8463
 * Transforms window coordinates from a child window to its parent
 
8464
 * window, where the parent window is the normal parent as returned by
 
8465
 * gdk_window_get_parent() for normal windows, and the window's
 
8466
 * embedder as returned by gdk_offscreen_window_get_embedder() for
 
8467
 * offscreen windows.
 
8468
 *
 
8469
 * For normal windows, calling this function is equivalent to adding
 
8470
 * the return values of gdk_window_get_position() to the child coordinates.
 
8471
 * For offscreen windows however (which can be arbitrarily transformed),
 
8472
 * this function calls the GdkWindow::to-embedder: signal to translate
 
8473
 * the coordinates.
 
8474
 *
 
8475
 * You should always use this function when writing generic code that
 
8476
 * walks up a window hierarchy.
 
8477
 *
 
8478
 * See also: gdk_window_coords_from_parent()
 
8479
 *
 
8480
 * Since: 2.22
 
8481
 **/
 
8482
void
 
8483
gdk_window_coords_to_parent (GdkWindow *window,
 
8484
                             gdouble    x,
 
8485
                             gdouble    y,
 
8486
                             gdouble   *parent_x,
 
8487
                             gdouble   *parent_y)
 
8488
{
 
8489
  GdkWindowObject *obj;
 
8490
 
 
8491
  g_return_if_fail (GDK_IS_WINDOW (window));
 
8492
 
 
8493
  obj = (GdkWindowObject *) window;
 
8494
 
 
8495
  if (gdk_window_is_offscreen (obj))
 
8496
    {
 
8497
      gdouble px, py;
 
8498
 
 
8499
      to_embedder (obj, x, y, &px, &py);
 
8500
 
 
8501
      if (parent_x)
 
8502
        *parent_x = px;
 
8503
 
 
8504
      if (parent_y)
 
8505
        *parent_y = py;
 
8506
    }
 
8507
  else
 
8508
    {
 
8509
      if (parent_x)
 
8510
        *parent_x = x + obj->x;
 
8511
 
 
8512
      if (parent_y)
 
8513
        *parent_y = y + obj->y;
 
8514
    }
 
8515
}
 
8516
 
 
8517
/**
 
8518
 * gdk_window_coords_from_parent:
 
8519
 * @window: a child window
 
8520
 * @parent_x: X coordinate in parent's coordinate system
 
8521
 * @parent_y: Y coordinate in parent's coordinate system
 
8522
 * @x: (out) (allow-none): return location for X coordinate in child's coordinate system
 
8523
 * @y: (out) (allow-none): return location for Y coordinate in child's coordinate system
 
8524
 *
 
8525
 * Transforms window coordinates from a parent window to a child
 
8526
 * window, where the parent window is the normal parent as returned by
 
8527
 * gdk_window_get_parent() for normal windows, and the window's
 
8528
 * embedder as returned by gdk_offscreen_window_get_embedder() for
 
8529
 * offscreen windows.
 
8530
 *
 
8531
 * For normal windows, calling this function is equivalent to subtracting
 
8532
 * the return values of gdk_window_get_position() from the parent coordinates.
 
8533
 * For offscreen windows however (which can be arbitrarily transformed),
 
8534
 * this function calls the GdkWindow::from-embedder: signal to translate
 
8535
 * the coordinates.
 
8536
 *
 
8537
 * You should always use this function when writing generic code that
 
8538
 * walks down a window hierarchy.
 
8539
 *
 
8540
 * See also: gdk_window_coords_to_parent()
 
8541
 *
 
8542
 * Since: 2.22
 
8543
 **/
 
8544
void
 
8545
gdk_window_coords_from_parent (GdkWindow *window,
 
8546
                               gdouble    parent_x,
 
8547
                               gdouble    parent_y,
 
8548
                               gdouble   *x,
 
8549
                               gdouble   *y)
 
8550
{
 
8551
  GdkWindowObject *obj;
 
8552
 
 
8553
  g_return_if_fail (GDK_IS_WINDOW (window));
 
8554
 
 
8555
  obj = (GdkWindowObject *) window;
 
8556
 
 
8557
  if (gdk_window_is_offscreen (obj))
 
8558
    {
 
8559
      gdouble cx, cy;
 
8560
 
 
8561
      from_embedder (obj, parent_x, parent_y, &cx, &cy);
 
8562
 
 
8563
      if (x)
 
8564
        *x = cx;
 
8565
 
 
8566
      if (y)
 
8567
        *y = cy;
 
8568
    }
 
8569
  else
 
8570
    {
 
8571
      if (x)
 
8572
        *x = parent_x - obj->x;
 
8573
 
 
8574
      if (y)
 
8575
        *y = parent_y - obj->y;
 
8576
    }
 
8577
}
 
8578
 
 
8579
/**
 
8580
 * gdk_window_get_deskrelative_origin:
 
8581
 * @window: a toplevel #GdkWindow
 
8582
 * @x: return location for X coordinate
 
8583
 * @y: return location for Y coordinate
 
8584
 *
 
8585
 * This gets the origin of a #GdkWindow relative to
 
8586
 * an Enlightenment-window-manager desktop. As long as you don't
 
8587
 * assume that the user's desktop/workspace covers the entire
 
8588
 * root window (i.e. you don't assume that the desktop begins
 
8589
 * at root window coordinate 0,0) this function is not necessary.
 
8590
 * It's deprecated for that reason.
 
8591
 *
 
8592
 * Return value: not meaningful
 
8593
 **/
 
8594
gboolean
 
8595
gdk_window_get_deskrelative_origin (GdkWindow *window,
 
8596
                                    gint      *x,
 
8597
                                    gint      *y)
 
8598
{
 
8599
  GdkWindowObject *private;
 
8600
  GdkWindowImplIface *impl_iface;
 
8601
  gboolean return_val = FALSE;
 
8602
  gint tx = 0;
 
8603
  gint ty = 0;
 
8604
 
 
8605
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
8606
 
 
8607
  private = (GdkWindowObject *) window;
 
8608
 
 
8609
  if (!GDK_WINDOW_DESTROYED (window))
 
8610
    {
 
8611
      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
8612
      return_val = impl_iface->get_deskrelative_origin (window, &tx, &ty);
 
8613
 
 
8614
      if (x)
 
8615
        *x = tx + private->abs_x;
 
8616
      if (y)
 
8617
        *y = ty + private->abs_y;
 
8618
    }
 
8619
 
 
8620
  return return_val;
 
8621
}
 
8622
 
 
8623
/**
 
8624
 * gdk_window_shape_combine_mask:
 
8625
 * @window: a #GdkWindow
 
8626
 * @mask: shape mask
 
8627
 * @x: X position of shape mask with respect to @window
 
8628
 * @y: Y position of shape mask with respect to @window
 
8629
 *
 
8630
 * Applies a shape mask to @window. Pixels in @window corresponding to
 
8631
 * set bits in the @mask will be visible; pixels in @window
 
8632
 * corresponding to unset bits in the @mask will be transparent. This
 
8633
 * gives a non-rectangular window.
 
8634
 *
 
8635
 * If @mask is %NULL, the shape mask will be unset, and the @x/@y
 
8636
 * parameters are not used.
 
8637
 *
 
8638
 * On the X11 platform, this uses an X server extension which is
 
8639
 * widely available on most common platforms, but not available on
 
8640
 * very old X servers, and occasionally the implementation will be
 
8641
 * buggy. On servers without the shape extension, this function
 
8642
 * will do nothing.
 
8643
 *
 
8644
 * This function works on both toplevel and child windows.
 
8645
 */
 
8646
void
 
8647
gdk_window_shape_combine_mask (GdkWindow *window,
 
8648
                               GdkBitmap *mask,
 
8649
                               gint       x,
 
8650
                               gint       y)
 
8651
{
 
8652
  GdkWindowObject *private;
 
8653
  GdkRegion *region;
 
8654
 
 
8655
  g_return_if_fail (GDK_IS_WINDOW (window));
 
8656
 
 
8657
  private = (GdkWindowObject *) window;
 
8658
 
 
8659
  if (mask)
 
8660
    region = _gdk_windowing_get_shape_for_mask (mask);
 
8661
  else
 
8662
    region = NULL;
 
8663
 
 
8664
  gdk_window_shape_combine_region (window,
 
8665
                                   region,
 
8666
                                   x, y);
 
8667
 
 
8668
  if (region)
 
8669
    gdk_region_destroy (region);
 
8670
}
 
8671
 
 
8672
/**
 
8673
 * gdk_window_shape_combine_region:
 
8674
 * @window: a #GdkWindow
 
8675
 * @shape_region: region of window to be non-transparent
 
8676
 * @offset_x: X position of @shape_region in @window coordinates
 
8677
 * @offset_y: Y position of @shape_region in @window coordinates
 
8678
 *
 
8679
 * Makes pixels in @window outside @shape_region be transparent,
 
8680
 * so that the window may be nonrectangular. See also
 
8681
 * gdk_window_shape_combine_mask() to use a bitmap as the mask.
 
8682
 *
 
8683
 * If @shape_region is %NULL, the shape will be unset, so the whole
 
8684
 * window will be opaque again. @offset_x and @offset_y are ignored
 
8685
 * if @shape_region is %NULL.
 
8686
 *
 
8687
 * On the X11 platform, this uses an X server extension which is
 
8688
 * widely available on most common platforms, but not available on
 
8689
 * very old X servers, and occasionally the implementation will be
 
8690
 * buggy. On servers without the shape extension, this function
 
8691
 * will do nothing.
 
8692
 *
 
8693
 * This function works on both toplevel and child windows.
 
8694
 */
 
8695
void
 
8696
gdk_window_shape_combine_region (GdkWindow       *window,
 
8697
                                 const GdkRegion *shape_region,
 
8698
                                 gint             offset_x,
 
8699
                                 gint             offset_y)
 
8700
{
 
8701
  GdkWindowObject *private;
 
8702
  GdkRegion *old_region, *new_region, *diff;
 
8703
 
 
8704
  g_return_if_fail (GDK_IS_WINDOW (window));
 
8705
 
 
8706
  private = (GdkWindowObject *) window;
 
8707
 
 
8708
  if (GDK_WINDOW_DESTROYED (window))
 
8709
    return;
 
8710
 
 
8711
  if (!private->shaped && shape_region == NULL)
 
8712
    return;
 
8713
 
 
8714
  private->shaped = (shape_region != NULL);
 
8715
 
 
8716
  if (private->shape)
 
8717
    gdk_region_destroy (private->shape);
 
8718
 
 
8719
  old_region = NULL;
 
8720
  if (GDK_WINDOW_IS_MAPPED (window))
 
8721
    old_region = gdk_region_copy (private->clip_region);
 
8722
 
 
8723
  if (shape_region)
 
8724
    {
 
8725
      private->shape = gdk_region_copy (shape_region);
 
8726
      gdk_region_offset (private->shape, offset_x, offset_y);
 
8727
    }
 
8728
  else
 
8729
    private->shape = NULL;
 
8730
 
 
8731
  recompute_visible_regions (private, TRUE, FALSE);
 
8732
 
 
8733
  if (gdk_window_has_impl (private) &&
 
8734
      !should_apply_clip_as_shape (private))
 
8735
    apply_shape (private, private->shape);
 
8736
 
 
8737
  if (old_region)
 
8738
    {
 
8739
      new_region = gdk_region_copy (private->clip_region);
 
8740
 
 
8741
      /* New area in the window, needs invalidation */
 
8742
      diff = gdk_region_copy (new_region);
 
8743
      gdk_region_subtract (diff, old_region);
 
8744
 
 
8745
      gdk_window_invalidate_region_full (window, diff, TRUE, CLEAR_BG_ALL);
 
8746
 
 
8747
      gdk_region_destroy (diff);
 
8748
 
 
8749
      if (!gdk_window_is_toplevel (private))
 
8750
        {
 
8751
          /* New area in the non-root parent window, needs invalidation */
 
8752
          diff = gdk_region_copy (old_region);
 
8753
          gdk_region_subtract (diff, new_region);
 
8754
 
 
8755
          /* Adjust region to parent window coords */
 
8756
          gdk_region_offset (diff, private->x, private->y);
 
8757
 
 
8758
          gdk_window_invalidate_region_full (GDK_WINDOW (private->parent), diff, TRUE, CLEAR_BG_ALL);
 
8759
 
 
8760
          gdk_region_destroy (diff);
 
8761
        }
 
8762
 
 
8763
      gdk_region_destroy (new_region);
 
8764
      gdk_region_destroy (old_region);
 
8765
    }
 
8766
}
 
8767
 
 
8768
static void
 
8769
do_child_shapes (GdkWindow *window,
 
8770
                 gboolean merge)
 
8771
{
 
8772
  GdkWindowObject *private;
 
8773
  GdkRectangle r;
 
8774
  GdkRegion *region;
 
8775
 
 
8776
  private = (GdkWindowObject *) window;
 
8777
 
 
8778
  r.x = 0;
 
8779
  r.y = 0;
 
8780
  r.width = private->width;
 
8781
  r.height = private->height;
 
8782
 
 
8783
  region = gdk_region_rectangle (&r);
 
8784
  remove_child_area (private, NULL, FALSE, region);
 
8785
 
 
8786
  if (merge && private->shape)
 
8787
    gdk_region_subtract (region, private->shape);
 
8788
 
 
8789
  gdk_window_shape_combine_region (window, region, 0, 0);
 
8790
}
 
8791
 
 
8792
/**
 
8793
 * gdk_window_set_child_shapes:
 
8794
 * @window: a #GdkWindow
 
8795
 *
 
8796
 * Sets the shape mask of @window to the union of shape masks
 
8797
 * for all children of @window, ignoring the shape mask of @window
 
8798
 * itself. Contrast with gdk_window_merge_child_shapes() which includes
 
8799
 * the shape mask of @window in the masks to be merged.
 
8800
 **/
 
8801
void
 
8802
gdk_window_set_child_shapes (GdkWindow *window)
 
8803
{
 
8804
  g_return_if_fail (GDK_IS_WINDOW (window));
 
8805
 
 
8806
  do_child_shapes (window, FALSE);
 
8807
}
 
8808
 
 
8809
/**
 
8810
 * gdk_window_merge_child_shapes:
 
8811
 * @window: a #GdkWindow
 
8812
 *
 
8813
 * Merges the shape masks for any child windows into the
 
8814
 * shape mask for @window. i.e. the union of all masks
 
8815
 * for @window and its children will become the new mask
 
8816
 * for @window. See gdk_window_shape_combine_mask().
 
8817
 *
 
8818
 * This function is distinct from gdk_window_set_child_shapes()
 
8819
 * because it includes @window's shape mask in the set of shapes to
 
8820
 * be merged.
 
8821
 */
 
8822
void
 
8823
gdk_window_merge_child_shapes (GdkWindow *window)
 
8824
{
 
8825
  g_return_if_fail (GDK_IS_WINDOW (window));
 
8826
 
 
8827
  do_child_shapes (window, TRUE);
 
8828
}
 
8829
 
 
8830
/**
 
8831
 * gdk_window_input_shape_combine_mask:
 
8832
 * @window: a #GdkWindow
 
8833
 * @mask: (allow-none): shape mask, or %NULL
 
8834
 * @x: X position of shape mask with respect to @window
 
8835
 * @y: Y position of shape mask with respect to @window
 
8836
 *
 
8837
 * Like gdk_window_shape_combine_mask(), but the shape applies
 
8838
 * only to event handling. Mouse events which happen while
 
8839
 * the pointer position corresponds to an unset bit in the
 
8840
 * mask will be passed on the window below @window.
 
8841
 *
 
8842
 * An input shape is typically used with RGBA windows.
 
8843
 * The alpha channel of the window defines which pixels are
 
8844
 * invisible and allows for nicely antialiased borders,
 
8845
 * and the input shape controls where the window is
 
8846
 * "clickable".
 
8847
 *
 
8848
 * On the X11 platform, this requires version 1.1 of the
 
8849
 * shape extension.
 
8850
 *
 
8851
 * On the Win32 platform, this functionality is not present and the
 
8852
 * function does nothing.
 
8853
 *
 
8854
 * Since: 2.10
 
8855
 */
 
8856
void
 
8857
gdk_window_input_shape_combine_mask (GdkWindow *window,
 
8858
                                     GdkBitmap *mask,
 
8859
                                     gint       x,
 
8860
                                     gint       y)
 
8861
{
 
8862
  GdkWindowObject *private;
 
8863
  GdkRegion *region;
 
8864
 
 
8865
  g_return_if_fail (GDK_IS_WINDOW (window));
 
8866
 
 
8867
  private = (GdkWindowObject *) window;
 
8868
 
 
8869
  if (mask)
 
8870
    region = _gdk_windowing_get_shape_for_mask (mask);
 
8871
  else
 
8872
    region = NULL;
 
8873
 
 
8874
  gdk_window_input_shape_combine_region (window,
 
8875
                                         region,
 
8876
                                         x, y);
 
8877
 
 
8878
  if (region != NULL)
 
8879
    gdk_region_destroy (region);
 
8880
}
 
8881
 
 
8882
/**
 
8883
 * gdk_window_input_shape_combine_region:
 
8884
 * @window: a #GdkWindow
 
8885
 * @shape_region: region of window to be non-transparent
 
8886
 * @offset_x: X position of @shape_region in @window coordinates
 
8887
 * @offset_y: Y position of @shape_region in @window coordinates
 
8888
 *
 
8889
 * Like gdk_window_shape_combine_region(), but the shape applies
 
8890
 * only to event handling. Mouse events which happen while
 
8891
 * the pointer position corresponds to an unset bit in the
 
8892
 * mask will be passed on the window below @window.
 
8893
 *
 
8894
 * An input shape is typically used with RGBA windows.
 
8895
 * The alpha channel of the window defines which pixels are
 
8896
 * invisible and allows for nicely antialiased borders,
 
8897
 * and the input shape controls where the window is
 
8898
 * "clickable".
 
8899
 *
 
8900
 * On the X11 platform, this requires version 1.1 of the
 
8901
 * shape extension.
 
8902
 *
 
8903
 * On the Win32 platform, this functionality is not present and the
 
8904
 * function does nothing.
 
8905
 *
 
8906
 * Since: 2.10
 
8907
 */
 
8908
void
 
8909
gdk_window_input_shape_combine_region (GdkWindow       *window,
 
8910
                                       const GdkRegion *shape_region,
 
8911
                                       gint             offset_x,
 
8912
                                       gint             offset_y)
 
8913
{
 
8914
  GdkWindowObject *private;
 
8915
  GdkWindowImplIface *impl_iface;
 
8916
 
 
8917
  g_return_if_fail (GDK_IS_WINDOW (window));
 
8918
 
 
8919
  private = (GdkWindowObject *) window;
 
8920
 
 
8921
  if (GDK_WINDOW_DESTROYED (window))
 
8922
    return;
 
8923
 
 
8924
  if (private->input_shape)
 
8925
    gdk_region_destroy (private->input_shape);
 
8926
 
 
8927
  if (shape_region)
 
8928
    {
 
8929
      private->input_shape = gdk_region_copy (shape_region);
 
8930
      gdk_region_offset (private->input_shape, offset_x, offset_y);
 
8931
    }
 
8932
  else
 
8933
    private->input_shape = NULL;
 
8934
 
 
8935
  if (gdk_window_has_impl (private))
 
8936
    {
 
8937
      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
8938
      impl_iface->input_shape_combine_region (window, private->input_shape, 0, 0);
 
8939
    }
 
8940
 
 
8941
  /* Pointer may have e.g. moved outside window due to the input mask change */
 
8942
  _gdk_synthesize_crossing_events_for_geometry_change (window);
 
8943
}
 
8944
 
 
8945
static void
 
8946
do_child_input_shapes (GdkWindow *window,
 
8947
                       gboolean merge)
 
8948
{
 
8949
  GdkWindowObject *private;
 
8950
  GdkRectangle r;
 
8951
  GdkRegion *region;
 
8952
 
 
8953
  private = (GdkWindowObject *) window;
 
8954
 
 
8955
  r.x = 0;
 
8956
  r.y = 0;
 
8957
  r.width = private->width;
 
8958
  r.height = private->height;
 
8959
 
 
8960
  region = gdk_region_rectangle (&r);
 
8961
  remove_child_area (private, NULL, TRUE, region);
 
8962
 
 
8963
  if (merge && private->shape)
 
8964
    gdk_region_subtract (region, private->shape);
 
8965
  if (merge && private->input_shape)
 
8966
    gdk_region_subtract (region, private->input_shape);
 
8967
 
 
8968
  gdk_window_input_shape_combine_region (window, region, 0, 0);
 
8969
}
 
8970
 
 
8971
 
 
8972
/**
 
8973
 * gdk_window_set_child_input_shapes:
 
8974
 * @window: a #GdkWindow
 
8975
 *
 
8976
 * Sets the input shape mask of @window to the union of input shape masks
 
8977
 * for all children of @window, ignoring the input shape mask of @window
 
8978
 * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
 
8979
 * the input shape mask of @window in the masks to be merged.
 
8980
 *
 
8981
 * Since: 2.10
 
8982
 **/
 
8983
void
 
8984
gdk_window_set_child_input_shapes (GdkWindow *window)
 
8985
{
 
8986
  g_return_if_fail (GDK_IS_WINDOW (window));
 
8987
 
 
8988
  do_child_input_shapes (window, FALSE);
 
8989
}
 
8990
 
 
8991
/**
 
8992
 * gdk_window_merge_child_input_shapes:
 
8993
 * @window: a #GdkWindow
 
8994
 *
 
8995
 * Merges the input shape masks for any child windows into the
 
8996
 * input shape mask for @window. i.e. the union of all input masks
 
8997
 * for @window and its children will become the new input mask
 
8998
 * for @window. See gdk_window_input_shape_combine_mask().
 
8999
 *
 
9000
 * This function is distinct from gdk_window_set_child_input_shapes()
 
9001
 * because it includes @window's input shape mask in the set of
 
9002
 * shapes to be merged.
 
9003
 *
 
9004
 * Since: 2.10
 
9005
 **/
 
9006
void
 
9007
gdk_window_merge_child_input_shapes (GdkWindow *window)
 
9008
{
 
9009
  g_return_if_fail (GDK_IS_WINDOW (window));
 
9010
 
 
9011
  do_child_input_shapes (window, TRUE);
 
9012
}
 
9013
 
 
9014
 
 
9015
/**
 
9016
 * gdk_window_set_static_gravities:
 
9017
 * @window: a #GdkWindow
 
9018
 * @use_static: %TRUE to turn on static gravity
 
9019
 *
 
9020
 * Set the bit gravity of the given window to static, and flag it so
 
9021
 * all children get static subwindow gravity. This is used if you are
 
9022
 * implementing scary features that involve deep knowledge of the
 
9023
 * windowing system. Don't worry about it unless you have to.
 
9024
 *
 
9025
 * Return value: %TRUE if the server supports static gravity
 
9026
 */
 
9027
gboolean
 
9028
gdk_window_set_static_gravities (GdkWindow *window,
 
9029
                                 gboolean   use_static)
 
9030
{
 
9031
  GdkWindowObject *private;
 
9032
  GdkWindowImplIface *impl_iface;
 
9033
 
 
9034
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
9035
 
 
9036
  private = (GdkWindowObject *) window;
 
9037
 
 
9038
  if (gdk_window_has_impl (private))
 
9039
    {
 
9040
      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
 
9041
      return impl_iface->set_static_gravities (window, use_static);
 
9042
    }
 
9043
 
 
9044
  return FALSE;
 
9045
}
 
9046
 
 
9047
/**
 
9048
 * gdk_window_get_composited:
 
9049
 * @window: a #GdkWindow
 
9050
 *
 
9051
 * Determines whether @window is composited.
 
9052
 *
 
9053
 * See gdk_window_set_composited().
 
9054
 *
 
9055
 * Returns: %TRUE if the window is composited.
 
9056
 *
 
9057
 * Since: 2.22
 
9058
 **/
 
9059
gboolean
 
9060
gdk_window_get_composited (GdkWindow *window)
 
9061
{
 
9062
  GdkWindowObject *private;
 
9063
 
 
9064
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
9065
 
 
9066
  private = (GdkWindowObject *)window;
 
9067
 
 
9068
  return private->composited;
 
9069
}
 
9070
 
 
9071
/**
 
9072
 * gdk_window_set_composited:
 
9073
 * @window: a #GdkWindow
 
9074
 * @composited: %TRUE to set the window as composited
 
9075
 *
 
9076
 * Sets a #GdkWindow as composited, or unsets it. Composited
 
9077
 * windows do not automatically have their contents drawn to
 
9078
 * the screen. Drawing is redirected to an offscreen buffer
 
9079
 * and an expose event is emitted on the parent of the composited
 
9080
 * window. It is the responsibility of the parent's expose handler
 
9081
 * to manually merge the off-screen content onto the screen in
 
9082
 * whatever way it sees fit. See <xref linkend="composited-window-example"/>
 
9083
 * for an example.
 
9084
 *
 
9085
 * It only makes sense for child windows to be composited; see
 
9086
 * gdk_window_set_opacity() if you need translucent toplevel
 
9087
 * windows.
 
9088
 *
 
9089
 * An additional effect of this call is that the area of this
 
9090
 * window is no longer clipped from regions marked for
 
9091
 * invalidation on its parent. Draws done on the parent
 
9092
 * window are also no longer clipped by the child.
 
9093
 *
 
9094
 * This call is only supported on some systems (currently,
 
9095
 * only X11 with new enough Xcomposite and Xdamage extensions).
 
9096
 * You must call gdk_display_supports_composite() to check if
 
9097
 * setting a window as composited is supported before
 
9098
 * attempting to do so.
 
9099
 *
 
9100
 * Since: 2.12
 
9101
 */
 
9102
void
 
9103
gdk_window_set_composited (GdkWindow *window,
 
9104
                           gboolean   composited)
 
9105
{
 
9106
  GdkWindowObject *private = (GdkWindowObject *)window;
 
9107
  GdkDisplay *display;
 
9108
 
 
9109
  g_return_if_fail (GDK_IS_WINDOW (window));
 
9110
 
 
9111
  composited = composited != FALSE;
 
9112
 
 
9113
  if (private->composited == composited)
 
9114
    return;
 
9115
 
 
9116
  if (composited)
 
9117
    gdk_window_ensure_native (window);
 
9118
 
 
9119
  display = gdk_drawable_get_display (GDK_DRAWABLE (window));
 
9120
 
 
9121
  if (!gdk_display_supports_composite (display) && composited)
 
9122
    {
 
9123
      g_warning ("gdk_window_set_composited called but "
 
9124
                 "compositing is not supported");
 
9125
      return;
 
9126
    }
 
9127
 
 
9128
  _gdk_windowing_window_set_composited (window, composited);
 
9129
 
 
9130
  recompute_visible_regions (private, TRUE, FALSE);
 
9131
 
 
9132
  if (GDK_WINDOW_IS_MAPPED (window))
 
9133
    gdk_window_invalidate_in_parent (private);
 
9134
 
 
9135
  private->composited = composited;
 
9136
}
 
9137
 
 
9138
 
 
9139
static void
 
9140
remove_redirect_from_children (GdkWindowObject   *private,
 
9141
                               GdkWindowRedirect *redirect)
 
9142
{
 
9143
  GList *l;
 
9144
  GdkWindowObject *child;
 
9145
 
 
9146
  for (l = private->children; l != NULL; l = l->next)
 
9147
    {
 
9148
      child = l->data;
 
9149
 
 
9150
      /* Don't redirect this child if it already has another redirect */
 
9151
      if (child->redirect == redirect)
 
9152
        {
 
9153
          child->redirect = NULL;
 
9154
          remove_redirect_from_children (child, redirect);
 
9155
        }
 
9156
    }
 
9157
}
 
9158
 
 
9159
/**
 
9160
 * gdk_window_remove_redirection:
 
9161
 * @window: a #GdkWindow
 
9162
 *
 
9163
 * Removes any active redirection started by
 
9164
 * gdk_window_redirect_to_drawable().
 
9165
 *
 
9166
 * Since: 2.14
 
9167
 **/
 
9168
void
 
9169
gdk_window_remove_redirection (GdkWindow *window)
 
9170
{
 
9171
  GdkWindowObject *private;
 
9172
 
 
9173
  g_return_if_fail (GDK_IS_WINDOW (window));
 
9174
 
 
9175
  private = (GdkWindowObject *) window;
 
9176
 
 
9177
  if (private->redirect &&
 
9178
      private->redirect->redirected == private)
 
9179
    {
 
9180
      remove_redirect_from_children (private, private->redirect);
 
9181
      gdk_window_redirect_free (private->redirect);
 
9182
      private->redirect = NULL;
 
9183
    }
 
9184
}
 
9185
 
 
9186
/**
 
9187
 * gdk_window_get_modal_hint:
 
9188
 * @window: A toplevel #GdkWindow.
 
9189
 *
 
9190
 * Determines whether or not the window manager is hinted that @window
 
9191
 * has modal behaviour.
 
9192
 *
 
9193
 * Return value: whether or not the window has the modal hint set.
 
9194
 *
 
9195
 * Since: 2.22
 
9196
 */
 
9197
gboolean
 
9198
gdk_window_get_modal_hint (GdkWindow *window)
 
9199
{
 
9200
  GdkWindowObject *private;
 
9201
 
 
9202
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
9203
 
 
9204
  private = (GdkWindowObject*) window;
 
9205
 
 
9206
  return private->modal_hint;
 
9207
}
 
9208
 
 
9209
/**
 
9210
 * gdk_window_get_accept_focus:
 
9211
 * @window: a toplevel #GdkWindow.
 
9212
 *
 
9213
 * Determines whether or not the desktop environment shuld be hinted that
 
9214
 * the window does not want to receive input focus.
 
9215
 *
 
9216
 * Return value: whether or not the window should receive input focus.
 
9217
 *
 
9218
 * Since: 2.22
 
9219
 */
 
9220
gboolean
 
9221
gdk_window_get_accept_focus (GdkWindow *window)
 
9222
{
 
9223
  GdkWindowObject *private;
 
9224
 
 
9225
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
9226
 
 
9227
  private = (GdkWindowObject *)window;
 
9228
 
 
9229
  return private->accept_focus;
 
9230
}
 
9231
 
 
9232
/**
 
9233
 * gdk_window_get_focus_on_map:
 
9234
 * @window: a toplevel #GdkWindow.
 
9235
 *
 
9236
 * Determines whether or not the desktop environment should be hinted that the
 
9237
 * window does not want to receive input focus when it is mapped.
 
9238
 *
 
9239
 * Return value: whether or not the window wants to receive input focus when
 
9240
 * it is mapped.
 
9241
 *
 
9242
 * Since: 2.22
 
9243
 */
 
9244
gboolean
 
9245
gdk_window_get_focus_on_map (GdkWindow *window)
 
9246
{
 
9247
  GdkWindowObject *private;
 
9248
 
 
9249
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
9250
 
 
9251
  private = (GdkWindowObject *)window;
 
9252
 
 
9253
  return private->focus_on_map;
 
9254
}
 
9255
 
 
9256
/**
 
9257
 * gdk_window_is_input_only:
 
9258
 * @window: a toplevel #GdkWindow
 
9259
 *
 
9260
 * Determines whether or not the window is an input only window.
 
9261
 *
 
9262
 * Return value: %TRUE if @window is input only
 
9263
 *
 
9264
 * Since: 2.22
 
9265
 */
 
9266
gboolean
 
9267
gdk_window_is_input_only (GdkWindow *window)
 
9268
{
 
9269
  GdkWindowObject *private;
 
9270
 
 
9271
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
9272
 
 
9273
  private = (GdkWindowObject *)window;
 
9274
 
 
9275
  return private->input_only;
 
9276
}
 
9277
 
 
9278
/**
 
9279
 * gdk_window_is_shaped:
 
9280
 * @window: a toplevel #GdkWindow
 
9281
 *
 
9282
 * Determines whether or not the window is shaped.
 
9283
 *
 
9284
 * Return value: %TRUE if @window is shaped
 
9285
 *
 
9286
 * Since: 2.22
 
9287
 */
 
9288
gboolean
 
9289
gdk_window_is_shaped (GdkWindow *window)
 
9290
{
 
9291
  GdkWindowObject *private;
 
9292
 
 
9293
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
9294
 
 
9295
  private = (GdkWindowObject *)window;
 
9296
 
 
9297
  return private->shaped;
 
9298
}
 
9299
 
 
9300
static void
 
9301
apply_redirect_to_children (GdkWindowObject   *private,
 
9302
                            GdkWindowRedirect *redirect)
 
9303
{
 
9304
  GList *l;
 
9305
  GdkWindowObject *child;
 
9306
 
 
9307
  for (l = private->children; l != NULL; l = l->next)
 
9308
    {
 
9309
      child = l->data;
 
9310
 
 
9311
      /* Don't redirect this child if it already has another redirect */
 
9312
      if (!child->redirect)
 
9313
        {
 
9314
          child->redirect = redirect;
 
9315
          apply_redirect_to_children (child, redirect);
 
9316
        }
 
9317
    }
 
9318
}
 
9319
 
 
9320
/**
 
9321
 * gdk_window_redirect_to_drawable:
 
9322
 * @window: a #GdkWindow
 
9323
 * @drawable: a #GdkDrawable
 
9324
 * @src_x: x position in @window
 
9325
 * @src_y: y position in @window
 
9326
 * @dest_x: x position in @drawable
 
9327
 * @dest_y: y position in @drawable
 
9328
 * @width: width of redirection, or -1 to use the width of @window
 
9329
 * @height: height of redirection or -1 to use the height of @window
 
9330
 *
 
9331
 * Redirects drawing into @window so that drawing to the
 
9332
 * window in the rectangle specified by @src_x, @src_y,
 
9333
 * @width and @height is also drawn into @drawable at
 
9334
 * @dest_x, @dest_y.
 
9335
 *
 
9336
 * Only drawing between gdk_window_begin_paint_region() or
 
9337
 * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
 
9338
 * redirected.
 
9339
 *
 
9340
 * Redirection is active until gdk_window_remove_redirection()
 
9341
 * is called.
 
9342
 *
 
9343
 * Since: 2.14
 
9344
 **/
 
9345
void
 
9346
gdk_window_redirect_to_drawable (GdkWindow   *window,
 
9347
                                 GdkDrawable *drawable,
 
9348
                                 gint         src_x,
 
9349
                                 gint         src_y,
 
9350
                                 gint         dest_x,
 
9351
                                 gint         dest_y,
 
9352
                                 gint         width,
 
9353
                                 gint         height)
 
9354
{
 
9355
  GdkWindowObject *private;
 
9356
 
 
9357
  g_return_if_fail (GDK_IS_WINDOW (window));
 
9358
  g_return_if_fail (GDK_IS_DRAWABLE (drawable));
 
9359
  g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
 
9360
 
 
9361
  private = (GdkWindowObject *) window;
 
9362
 
 
9363
  if (private->redirect)
 
9364
    gdk_window_remove_redirection (window);
 
9365
 
 
9366
  if (width == -1 || height == -1)
 
9367
    {
 
9368
      gint w, h;
 
9369
      gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
 
9370
      if (width == -1)
 
9371
        width = w;
 
9372
      if (height == -1)
 
9373
        height = h;
 
9374
    }
 
9375
 
 
9376
  private->redirect = g_new0 (GdkWindowRedirect, 1);
 
9377
  private->redirect->redirected = private;
 
9378
  private->redirect->pixmap = g_object_ref (drawable);
 
9379
  private->redirect->src_x = src_x;
 
9380
  private->redirect->src_y = src_y;
 
9381
  private->redirect->dest_x = dest_x;
 
9382
  private->redirect->dest_y = dest_y;
 
9383
  private->redirect->width = width;
 
9384
  private->redirect->height = height;
 
9385
 
 
9386
  apply_redirect_to_children (private, private->redirect);
 
9387
}
 
9388
 
 
9389
static void
 
9390
window_get_size_rectangle (GdkWindow    *window,
 
9391
                           GdkRectangle *rect)
 
9392
{
 
9393
  GdkWindowObject *private = (GdkWindowObject *) window;
 
9394
 
 
9395
  rect->x = rect->y = 0;
 
9396
  rect->width = private->width;
 
9397
  rect->height = private->height;
 
9398
}
 
9399
 
 
9400
/* Calculates the real clipping region for a window, in window coordinates,
 
9401
 * taking into account other windows, gc clip region and gc clip mask.
 
9402
 */
 
9403
GdkRegion *
 
9404
_gdk_window_calculate_full_clip_region (GdkWindow *window,
 
9405
                                        GdkWindow *base_window,
 
9406
                                        gboolean   do_children,
 
9407
                                        gint      *base_x_offset,
 
9408
                                        gint      *base_y_offset)
 
9409
{
 
9410
  GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
 
9411
  GdkRectangle visible_rect;
 
9412
  GdkRegion *real_clip_region, *tmpreg;
 
9413
  gint x_offset, y_offset;
 
9414
  GdkWindowObject *parentwin, *lastwin;
 
9415
 
 
9416
  if (base_x_offset)
 
9417
    *base_x_offset = 0;
 
9418
  if (base_y_offset)
 
9419
    *base_y_offset = 0;
 
9420
 
 
9421
  if (!private->viewable || private->input_only)
 
9422
    return gdk_region_new ();
 
9423
 
 
9424
  window_get_size_rectangle (window, &visible_rect);
 
9425
 
 
9426
  /* real_clip_region is in window coordinates */
 
9427
  real_clip_region = gdk_region_rectangle (&visible_rect);
 
9428
 
 
9429
  x_offset = y_offset = 0;
 
9430
 
 
9431
  lastwin = private;
 
9432
  if (do_children)
 
9433
    parentwin = lastwin;
 
9434
  else
 
9435
    parentwin = lastwin->parent;
 
9436
 
 
9437
  /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
 
9438
  for (; parentwin != NULL &&
 
9439
         (parentwin == private || lastwin != (GdkWindowObject*) base_window);
 
9440
       lastwin = parentwin, parentwin = lastwin->parent)
 
9441
    {
 
9442
      GList *cur;
 
9443
      GdkRectangle real_clip_rect;
 
9444
 
 
9445
      if (parentwin != private)
 
9446
        {
 
9447
          x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
 
9448
          y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
 
9449
        }
 
9450
 
 
9451
      /* children is ordered in reverse stack order */
 
9452
      for (cur = parentwin->children;
 
9453
           cur && cur->data != lastwin;
 
9454
           cur = cur->next)
 
9455
        {
 
9456
          GdkWindow *child = cur->data;
 
9457
          GdkWindowObject *child_private = (GdkWindowObject *)child;
 
9458
 
 
9459
          if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
 
9460
            continue;
 
9461
 
 
9462
          /* Ignore offscreen children, as they don't draw in their parent and
 
9463
           * don't take part in the clipping */
 
9464
          if (gdk_window_is_offscreen (child_private))
 
9465
            continue;
 
9466
 
 
9467
          window_get_size_rectangle (child, &visible_rect);
 
9468
 
 
9469
          /* Convert rect to "window" coords */
 
9470
          visible_rect.x += child_private->x - x_offset;
 
9471
          visible_rect.y += child_private->y - y_offset;
 
9472
 
 
9473
          /* This shortcut is really necessary for performance when there are a lot of windows */
 
9474
          gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
 
9475
          if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
 
9476
              visible_rect.x + visible_rect.width <= real_clip_rect.x ||
 
9477
              visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
 
9478
              visible_rect.y + visible_rect.height <= real_clip_rect.y)
 
9479
            continue;
 
9480
 
 
9481
          tmpreg = gdk_region_rectangle (&visible_rect);
 
9482
          gdk_region_subtract (real_clip_region, tmpreg);
 
9483
          gdk_region_destroy (tmpreg);
 
9484
        }
 
9485
 
 
9486
      /* Clip to the parent */
 
9487
      window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
 
9488
      /* Convert rect to "window" coords */
 
9489
      visible_rect.x += - x_offset;
 
9490
      visible_rect.y += - y_offset;
 
9491
 
 
9492
      tmpreg = gdk_region_rectangle (&visible_rect);
 
9493
      gdk_region_intersect (real_clip_region, tmpreg);
 
9494
      gdk_region_destroy (tmpreg);
 
9495
    }
 
9496
 
 
9497
  if (base_x_offset)
 
9498
    *base_x_offset = x_offset;
 
9499
  if (base_y_offset)
 
9500
    *base_y_offset = y_offset;
 
9501
 
 
9502
  return real_clip_region;
 
9503
}
 
9504
 
 
9505
void
 
9506
_gdk_window_add_damage (GdkWindow *toplevel,
 
9507
                        GdkRegion *damaged_region)
 
9508
{
 
9509
  GdkDisplay *display;
 
9510
  GdkEvent event = { 0, };
 
9511
  event.expose.type = GDK_DAMAGE;
 
9512
  event.expose.window = toplevel;
 
9513
  event.expose.send_event = FALSE;
 
9514
  event.expose.region = damaged_region;
 
9515
  gdk_region_get_clipbox (event.expose.region, &event.expose.area);
 
9516
  display = gdk_drawable_get_display (event.expose.window);
 
9517
  _gdk_event_queue_append (display, gdk_event_copy (&event));
 
9518
}
 
9519
 
 
9520
static void
 
9521
gdk_window_redirect_free (GdkWindowRedirect *redirect)
 
9522
{
 
9523
  g_object_unref (redirect->pixmap);
 
9524
  g_free (redirect);
 
9525
}
 
9526
 
 
9527
/* Gets the toplevel for a window as used for events,
 
9528
   i.e. including offscreen parents */
 
9529
static GdkWindowObject *
 
9530
get_event_parent (GdkWindowObject *window)
 
9531
{
 
9532
  if (gdk_window_is_offscreen (window))
 
9533
    return (GdkWindowObject *)gdk_offscreen_window_get_embedder ((GdkWindow *)window);
 
9534
  else
 
9535
    return window->parent;
 
9536
}
 
9537
 
 
9538
/* Gets the toplevel for a window as used for events,
 
9539
   i.e. including offscreen parents going up to the native
 
9540
   toplevel */
 
9541
static GdkWindow *
 
9542
get_event_toplevel (GdkWindow *w)
 
9543
{
 
9544
  GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
 
9545
  GdkWindowObject *parent;
 
9546
 
 
9547
  while ((parent = get_event_parent (private)) != NULL &&
 
9548
         (parent->window_type != GDK_WINDOW_ROOT))
 
9549
    private = parent;
 
9550
 
 
9551
  return GDK_WINDOW (private);
 
9552
}
 
9553
 
 
9554
gboolean
 
9555
_gdk_window_event_parent_of (GdkWindow *parent,
 
9556
                             GdkWindow *child)
 
9557
{
 
9558
  GdkWindow *w;
 
9559
 
 
9560
  w = child;
 
9561
  while (w != NULL)
 
9562
    {
 
9563
      if (w == parent)
 
9564
        return TRUE;
 
9565
 
 
9566
      w = (GdkWindow *)get_event_parent ((GdkWindowObject *)w);
 
9567
    }
 
9568
 
 
9569
  return FALSE;
 
9570
}
 
9571
 
 
9572
static void
 
9573
update_cursor (GdkDisplay *display)
 
9574
{
 
9575
  GdkWindowObject *cursor_window, *parent, *toplevel;
 
9576
  GdkWindow *pointer_window;
 
9577
  GdkWindowImplIface *impl_iface;
 
9578
  GdkPointerGrabInfo *grab;
 
9579
 
 
9580
  pointer_window = display->pointer_info.window_under_pointer;
 
9581
 
 
9582
  /* We ignore the serials here and just pick the last grab
 
9583
     we've sent, as that would shortly be used anyway. */
 
9584
  grab = _gdk_display_get_last_pointer_grab (display);
 
9585
  if (/* have grab */
 
9586
      grab != NULL &&
 
9587
      /* the pointer is not in a descendant of the grab window */
 
9588
      !_gdk_window_event_parent_of (grab->window, pointer_window))
 
9589
    /* use the cursor from the grab window */
 
9590
    cursor_window = (GdkWindowObject *)grab->window;
 
9591
  else
 
9592
    /* otherwise use the cursor from the pointer window */
 
9593
    cursor_window = (GdkWindowObject *)pointer_window;
 
9594
 
 
9595
  /* Find the first window with the cursor actually set, as
 
9596
     the cursor is inherited from the parent */
 
9597
  while (cursor_window->cursor == NULL &&
 
9598
         (parent = get_event_parent (cursor_window)) != NULL &&
 
9599
         parent->window_type != GDK_WINDOW_ROOT)
 
9600
    cursor_window = parent;
 
9601
 
 
9602
  /* Set all cursors on toplevel, otherwise its tricky to keep track of
 
9603
   * which native window has what cursor set. */
 
9604
  toplevel = (GdkWindowObject *)get_event_toplevel (pointer_window);
 
9605
  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (toplevel->impl);
 
9606
  impl_iface->set_cursor ((GdkWindow *)toplevel, cursor_window->cursor);
 
9607
}
 
9608
 
 
9609
static gboolean
 
9610
point_in_window (GdkWindowObject *window,
 
9611
                 gdouble          x,
 
9612
                 gdouble          y)
 
9613
{
 
9614
  return
 
9615
    x >= 0 && x < window->width &&
 
9616
    y >= 0 && y < window->height &&
 
9617
    (window->shape == NULL ||
 
9618
     gdk_region_point_in (window->shape,
 
9619
                          x, y)) &&
 
9620
    (window->input_shape == NULL ||
 
9621
     gdk_region_point_in (window->input_shape,
 
9622
                          x, y));
 
9623
}
 
9624
 
 
9625
static GdkWindow *
 
9626
convert_native_coords_to_toplevel (GdkWindow *window,
 
9627
                                   gdouble    child_x,
 
9628
                                   gdouble    child_y,
 
9629
                                   gdouble   *toplevel_x,
 
9630
                                   gdouble   *toplevel_y)
 
9631
{
 
9632
  GdkWindowObject *private = (GdkWindowObject *)window;
 
9633
  gdouble x, y;
 
9634
 
 
9635
  x = child_x;
 
9636
  y = child_y;
 
9637
 
 
9638
  while (!gdk_window_is_toplevel (private))
 
9639
    {
 
9640
      x += private->x;
 
9641
      y += private->y;
 
9642
      private = private->parent;
 
9643
    }
 
9644
 
 
9645
  *toplevel_x = x;
 
9646
  *toplevel_y = y;
 
9647
 
 
9648
  return (GdkWindow *)private;
 
9649
}
 
9650
 
 
9651
static void
 
9652
convert_toplevel_coords_to_window (GdkWindow *window,
 
9653
                                   gdouble    toplevel_x,
 
9654
                                   gdouble    toplevel_y,
 
9655
                                   gdouble   *window_x,
 
9656
                                   gdouble   *window_y)
 
9657
{
 
9658
  GdkWindowObject *private;
 
9659
  GdkWindowObject *parent;
 
9660
  gdouble x, y;
 
9661
  GList *children, *l;
 
9662
 
 
9663
  private = GDK_WINDOW_OBJECT (window);
 
9664
 
 
9665
  x = toplevel_x;
 
9666
  y = toplevel_y;
 
9667
 
 
9668
  children = NULL;
 
9669
  while ((parent = get_event_parent (private)) != NULL &&
 
9670
         (parent->window_type != GDK_WINDOW_ROOT))
 
9671
    {
 
9672
      children = g_list_prepend (children, private);
 
9673
      private = parent;
 
9674
    }
 
9675
 
 
9676
  for (l = children; l != NULL; l = l->next)
 
9677
    gdk_window_coords_from_parent (l->data, x, y, &x, &y);
 
9678
 
 
9679
  g_list_free (children);
 
9680
 
 
9681
  *window_x = x;
 
9682
  *window_y = y;
 
9683
}
 
9684
 
 
9685
static GdkWindowObject *
 
9686
pick_embedded_child (GdkWindowObject *window,
 
9687
                     gdouble          x,
 
9688
                     gdouble          y)
 
9689
{
 
9690
  GdkWindowObject *res;
 
9691
 
 
9692
  res = NULL;
 
9693
  g_signal_emit (window,
 
9694
                 signals[PICK_EMBEDDED_CHILD], 0,
 
9695
                 x, y, &res);
 
9696
 
 
9697
  return res;
 
9698
}
 
9699
 
 
9700
GdkWindow *
 
9701
_gdk_window_find_child_at (GdkWindow *window,
 
9702
                           int        x,
 
9703
                           int        y)
 
9704
{
 
9705
  GdkWindowObject *private, *sub;
 
9706
  double child_x, child_y;
 
9707
  GList *l;
 
9708
 
 
9709
  private = (GdkWindowObject *)window;
 
9710
 
 
9711
  if (point_in_window (private, x, y))
 
9712
    {
 
9713
      /* Children is ordered in reverse stack order, i.e. first is topmost */
 
9714
      for (l = private->children; l != NULL; l = l->next)
 
9715
        {
 
9716
          sub = l->data;
 
9717
 
 
9718
          if (!GDK_WINDOW_IS_MAPPED (sub))
 
9719
            continue;
 
9720
 
 
9721
          gdk_window_coords_from_parent ((GdkWindow *)sub,
 
9722
                                         x, y,
 
9723
                                         &child_x, &child_y);
 
9724
          if (point_in_window (sub, child_x, child_y))
 
9725
            return (GdkWindow *)sub;
 
9726
        }
 
9727
 
 
9728
      if (private->num_offscreen_children > 0)
 
9729
        {
 
9730
          sub = pick_embedded_child (private,
 
9731
                                     x, y);
 
9732
          if (sub)
 
9733
            return (GdkWindow *)sub;
 
9734
        }
 
9735
    }
 
9736
 
 
9737
  return NULL;
 
9738
}
 
9739
 
 
9740
GdkWindow *
 
9741
_gdk_window_find_descendant_at (GdkWindow *toplevel,
 
9742
                                gdouble    x,
 
9743
                                gdouble    y,
 
9744
                                gdouble   *found_x,
 
9745
                                gdouble   *found_y)
 
9746
{
 
9747
  GdkWindowObject *private, *sub;
 
9748
  gdouble child_x, child_y;
 
9749
  GList *l;
 
9750
  gboolean found;
 
9751
 
 
9752
  private = (GdkWindowObject *)toplevel;
 
9753
 
 
9754
  if (point_in_window (private, x, y))
 
9755
    {
 
9756
      do
 
9757
        {
 
9758
          found = FALSE;
 
9759
          /* Children is ordered in reverse stack order, i.e. first is topmost */
 
9760
          for (l = private->children; l != NULL; l = l->next)
 
9761
            {
 
9762
              sub = l->data;
 
9763
 
 
9764
              if (!GDK_WINDOW_IS_MAPPED (sub))
 
9765
                continue;
 
9766
 
 
9767
              gdk_window_coords_from_parent ((GdkWindow *)sub,
 
9768
                                             x, y,
 
9769
                                             &child_x, &child_y);
 
9770
              if (point_in_window (sub, child_x, child_y))
 
9771
                {
 
9772
                  x = child_x;
 
9773
                  y = child_y;
 
9774
                  private = sub;
 
9775
                  found = TRUE;
 
9776
                  break;
 
9777
                }
 
9778
            }
 
9779
          if (!found &&
 
9780
              private->num_offscreen_children > 0)
 
9781
            {
 
9782
              sub = pick_embedded_child (private,
 
9783
                                         x, y);
 
9784
              if (sub)
 
9785
                {
 
9786
                  found = TRUE;
 
9787
                  private = sub;
 
9788
                  from_embedder (sub, x, y, &x, &y);
 
9789
                }
 
9790
            }
 
9791
        }
 
9792
      while (found);
 
9793
    }
 
9794
  else
 
9795
    {
 
9796
      /* Not in window at all */
 
9797
      private = NULL;
 
9798
    }
 
9799
 
 
9800
  if (found_x)
 
9801
    *found_x = x;
 
9802
  if (found_y)
 
9803
    *found_y = y;
 
9804
 
 
9805
  return (GdkWindow *)private;
 
9806
}
 
9807
 
 
9808
/**
 
9809
 * gdk_window_beep:
 
9810
 * @window: a toplevel #GdkWindow
 
9811
 *
 
9812
 * Emits a short beep associated to @window in the appropriate
 
9813
 * display, if supported. Otherwise, emits a short beep on
 
9814
 * the display just as gdk_display_beep().
 
9815
 *
 
9816
 * Since: 2.12
 
9817
 **/
 
9818
void
 
9819
gdk_window_beep (GdkWindow *window)
 
9820
{
 
9821
  GdkDisplay *display;
 
9822
  GdkWindow *toplevel;
 
9823
 
 
9824
  g_return_if_fail (GDK_IS_WINDOW (window));
 
9825
 
 
9826
  if (GDK_WINDOW_DESTROYED (window))
 
9827
    return;
 
9828
 
 
9829
  toplevel = get_event_toplevel (window);
 
9830
  display = gdk_drawable_get_display (GDK_DRAWABLE (window));
 
9831
 
 
9832
  if (toplevel && !gdk_window_is_offscreen ((GdkWindowObject *)toplevel))
 
9833
    _gdk_windowing_window_beep (toplevel);
 
9834
  else
 
9835
    gdk_display_beep (display);
 
9836
}
 
9837
 
 
9838
static const guint type_masks[] = {
 
9839
  GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE                 = 0  */
 
9840
  GDK_STRUCTURE_MASK, /* GDK_DESTROY                   = 1  */
 
9841
  GDK_EXPOSURE_MASK, /* GDK_EXPOSE                     = 2  */
 
9842
  GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY        = 3  */
 
9843
  GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS           = 4  */
 
9844
  GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS          = 5  */
 
9845
  GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS          = 6  */
 
9846
  GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE       = 7  */
 
9847
  GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS                 = 8  */
 
9848
  GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE             = 9  */
 
9849
  GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY           = 10 */
 
9850
  GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY           = 11 */
 
9851
  GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE           = 12 */
 
9852
  GDK_STRUCTURE_MASK, /* GDK_CONFIGURE                 = 13 */
 
9853
  GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP               = 14 */
 
9854
  GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP             = 15 */
 
9855
  GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY     = 16 */
 
9856
  GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR     = 17 */
 
9857
  GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST   = 18 */
 
9858
  GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY    = 19 */
 
9859
  GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN           = 20 */
 
9860
  GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT         = 21 */
 
9861
  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER               = 22 */
 
9862
  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE               = 23 */
 
9863
  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION              = 24 */
 
9864
  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS              = 25 */
 
9865
  GDK_ALL_EVENTS_MASK, /* GDK_DROP_START               = 26 */
 
9866
  GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED            = 27 */
 
9867
  GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT             = 28 */
 
9868
  GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
 
9869
  GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE                  = 30 */
 
9870
  GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
 
9871
  0, /* GDK_WINDOW_STATE = 32 */
 
9872
  0, /* GDK_SETTING = 33 */
 
9873
  0, /* GDK_OWNER_CHANGE = 34 */
 
9874
  0, /* GDK_GRAB_BROKEN = 35 */
 
9875
  0, /* GDK_DAMAGE = 36 */
 
9876
};
 
9877
G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
 
9878
 
 
9879
/* send motion events if the right buttons are down */
 
9880
static guint
 
9881
update_evmask_for_button_motion (guint           evmask,
 
9882
                                 GdkModifierType mask)
 
9883
{
 
9884
  if (evmask & GDK_BUTTON_MOTION_MASK &&
 
9885
      mask & (GDK_BUTTON1_MASK |
 
9886
              GDK_BUTTON2_MASK |
 
9887
              GDK_BUTTON3_MASK |
 
9888
              GDK_BUTTON4_MASK |
 
9889
              GDK_BUTTON5_MASK))
 
9890
    evmask |= GDK_POINTER_MOTION_MASK;
 
9891
 
 
9892
  if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
 
9893
      (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
 
9894
      (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
 
9895
    evmask |= GDK_POINTER_MOTION_MASK;
 
9896
 
 
9897
  return evmask;
 
9898
}
 
9899
 
 
9900
static gboolean
 
9901
is_button_type (GdkEventType type)
 
9902
{
 
9903
  return type == GDK_BUTTON_PRESS ||
 
9904
         type == GDK_2BUTTON_PRESS ||
 
9905
         type == GDK_3BUTTON_PRESS ||
 
9906
         type == GDK_BUTTON_RELEASE ||
 
9907
         type == GDK_SCROLL;
 
9908
}
 
9909
 
 
9910
static gboolean
 
9911
is_motion_type (GdkEventType type)
 
9912
{
 
9913
  return type == GDK_MOTION_NOTIFY ||
 
9914
         type == GDK_ENTER_NOTIFY ||
 
9915
         type == GDK_LEAVE_NOTIFY;
 
9916
}
 
9917
 
 
9918
static GdkWindowObject *
 
9919
find_common_ancestor (GdkWindowObject *win1,
 
9920
                      GdkWindowObject *win2)
 
9921
{
 
9922
  GdkWindowObject *tmp;
 
9923
  GList *path1 = NULL, *path2 = NULL;
 
9924
  GList *list1, *list2;
 
9925
 
 
9926
  tmp = win1;
 
9927
  while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
 
9928
    {
 
9929
      path1 = g_list_prepend (path1, tmp);
 
9930
      tmp = get_event_parent (tmp);
 
9931
    }
 
9932
 
 
9933
  tmp = win2;
 
9934
  while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
 
9935
    {
 
9936
      path2 = g_list_prepend (path2, tmp);
 
9937
      tmp = get_event_parent (tmp);
 
9938
    }
 
9939
 
 
9940
  list1 = path1;
 
9941
  list2 = path2;
 
9942
  tmp = NULL;
 
9943
  while (list1 && list2 && (list1->data == list2->data))
 
9944
    {
 
9945
      tmp = (GdkWindowObject *)list1->data;
 
9946
      list1 = g_list_next (list1);
 
9947
      list2 = g_list_next (list2);
 
9948
    }
 
9949
  g_list_free (path1);
 
9950
  g_list_free (path2);
 
9951
 
 
9952
  return tmp;
 
9953
}
 
9954
 
 
9955
GdkEvent *
 
9956
_gdk_make_event (GdkWindow    *window,
 
9957
                 GdkEventType  type,
 
9958
                 GdkEvent     *event_in_queue,
 
9959
                 gboolean      before_event)
 
9960
{
 
9961
  GdkEvent *event = gdk_event_new (type);
 
9962
  guint32 the_time;
 
9963
  GdkModifierType the_state;
 
9964
 
 
9965
  the_time = gdk_event_get_time (event_in_queue);
 
9966
  gdk_event_get_state (event_in_queue, &the_state);
 
9967
 
 
9968
  event->any.window = g_object_ref (window);
 
9969
  event->any.send_event = FALSE;
 
9970
  if (event_in_queue && event_in_queue->any.send_event)
 
9971
    event->any.send_event = TRUE;
 
9972
 
 
9973
  switch (type)
 
9974
    {
 
9975
    case GDK_MOTION_NOTIFY:
 
9976
      event->motion.time = the_time;
 
9977
      event->motion.axes = NULL;
 
9978
      event->motion.state = the_state;
 
9979
      break;
 
9980
 
 
9981
    case GDK_BUTTON_PRESS:
 
9982
    case GDK_2BUTTON_PRESS:
 
9983
    case GDK_3BUTTON_PRESS:
 
9984
    case GDK_BUTTON_RELEASE:
 
9985
      event->button.time = the_time;
 
9986
      event->button.axes = NULL;
 
9987
      event->button.state = the_state;
 
9988
      break;
 
9989
 
 
9990
    case GDK_SCROLL:
 
9991
      event->scroll.time = the_time;
 
9992
      event->scroll.state = the_state;
 
9993
      break;
 
9994
 
 
9995
    case GDK_KEY_PRESS:
 
9996
    case GDK_KEY_RELEASE:
 
9997
      event->key.time = the_time;
 
9998
      event->key.state = the_state;
 
9999
      break;
 
10000
 
 
10001
    case GDK_ENTER_NOTIFY:
 
10002
    case GDK_LEAVE_NOTIFY:
 
10003
      event->crossing.time = the_time;
 
10004
      event->crossing.state = the_state;
 
10005
      break;
 
10006
 
 
10007
    case GDK_PROPERTY_NOTIFY:
 
10008
      event->property.time = the_time;
 
10009
      event->property.state = the_state;
 
10010
      break;
 
10011
 
 
10012
    case GDK_SELECTION_CLEAR:
 
10013
    case GDK_SELECTION_REQUEST:
 
10014
    case GDK_SELECTION_NOTIFY:
 
10015
      event->selection.time = the_time;
 
10016
      break;
 
10017
 
 
10018
    case GDK_PROXIMITY_IN:
 
10019
    case GDK_PROXIMITY_OUT:
 
10020
      event->proximity.time = the_time;
 
10021
      break;
 
10022
 
 
10023
    case GDK_DRAG_ENTER:
 
10024
    case GDK_DRAG_LEAVE:
 
10025
    case GDK_DRAG_MOTION:
 
10026
    case GDK_DRAG_STATUS:
 
10027
    case GDK_DROP_START:
 
10028
    case GDK_DROP_FINISHED:
 
10029
      event->dnd.time = the_time;
 
10030
      break;
 
10031
 
 
10032
    case GDK_FOCUS_CHANGE:
 
10033
    case GDK_CONFIGURE:
 
10034
    case GDK_MAP:
 
10035
    case GDK_UNMAP:
 
10036
    case GDK_CLIENT_EVENT:
 
10037
    case GDK_VISIBILITY_NOTIFY:
 
10038
    case GDK_NO_EXPOSE:
 
10039
    case GDK_DELETE:
 
10040
    case GDK_DESTROY:
 
10041
    case GDK_EXPOSE:
 
10042
    default:
 
10043
      break;
 
10044
    }
 
10045
 
 
10046
  if (event_in_queue)
 
10047
    {
 
10048
    if (before_event)
 
10049
      _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
 
10050
    else
 
10051
      _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
 
10052
    }
 
10053
  else
 
10054
    _gdk_event_queue_append (gdk_drawable_get_display (window), event);
 
10055
 
 
10056
  return event;
 
10057
}
 
10058
 
 
10059
static void
 
10060
send_crossing_event (GdkDisplay                 *display,
 
10061
                     GdkWindowObject            *toplevel,
 
10062
                     GdkWindowObject            *window,
 
10063
                     GdkEventType                type,
 
10064
                     GdkCrossingMode             mode,
 
10065
                     GdkNotifyType               notify_type,
 
10066
                     GdkWindow                  *subwindow,
 
10067
                     gint                        toplevel_x,
 
10068
                     gint                        toplevel_y,
 
10069
                     GdkModifierType             mask,
 
10070
                     guint32                     time_,
 
10071
                     GdkEvent                   *event_in_queue,
 
10072
                     gulong                      serial)
 
10073
{
 
10074
  GdkEvent *event;
 
10075
  guint32 window_event_mask, type_event_mask;
 
10076
  GdkPointerGrabInfo *grab;
 
10077
  GdkWindowImplIface *impl_iface;
 
10078
 
 
10079
  grab = _gdk_display_has_pointer_grab (display, serial);
 
10080
 
 
10081
  if (grab != NULL &&
 
10082
      !grab->owner_events)
 
10083
    {
 
10084
      /* !owner_event => only report events wrt grab window, ignore rest */
 
10085
      if ((GdkWindow *)window != grab->window)
 
10086
        return;
 
10087
      window_event_mask = grab->event_mask;
 
10088
    }
 
10089
  else
 
10090
    window_event_mask = window->event_mask;
 
10091
 
 
10092
  if (type == GDK_LEAVE_NOTIFY)
 
10093
    type_event_mask = GDK_LEAVE_NOTIFY_MASK;
 
10094
  else
 
10095
    type_event_mask = GDK_ENTER_NOTIFY_MASK;
 
10096
 
 
10097
  if (window->extension_events != 0)
 
10098
    {
 
10099
      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (window->impl);
 
10100
      impl_iface->input_window_crossing ((GdkWindow *)window,
 
10101
                                         type == GDK_ENTER_NOTIFY);
 
10102
    }
 
10103
 
 
10104
  if (window_event_mask & type_event_mask)
 
10105
    {
 
10106
      event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
 
10107
      event->crossing.time = time_;
 
10108
      event->crossing.subwindow = subwindow;
 
10109
      if (subwindow)
 
10110
        g_object_ref (subwindow);
 
10111
      convert_toplevel_coords_to_window ((GdkWindow *)window,
 
10112
                                         toplevel_x, toplevel_y,
 
10113
                                         &event->crossing.x, &event->crossing.y);
 
10114
      event->crossing.x_root = toplevel_x + toplevel->x;
 
10115
      event->crossing.y_root = toplevel_y + toplevel->y;
 
10116
      event->crossing.mode = mode;
 
10117
      event->crossing.detail = notify_type;
 
10118
      event->crossing.focus = FALSE;
 
10119
      event->crossing.state = mask;
 
10120
    }
 
10121
}
 
10122
 
 
10123
 
 
10124
/* The coordinates are in the toplevel window that src/dest are in.
 
10125
 * src and dest are always (if != NULL) in the same toplevel, as
 
10126
 * we get a leave-notify and set the window_under_pointer to null
 
10127
 * before crossing to another toplevel.
 
10128
 */
 
10129
void
 
10130
_gdk_synthesize_crossing_events (GdkDisplay                 *display,
 
10131
                                 GdkWindow                  *src,
 
10132
                                 GdkWindow                  *dest,
 
10133
                                 GdkCrossingMode             mode,
 
10134
                                 gint                        toplevel_x,
 
10135
                                 gint                        toplevel_y,
 
10136
                                 GdkModifierType             mask,
 
10137
                                 guint32                     time_,
 
10138
                                 GdkEvent                   *event_in_queue,
 
10139
                                 gulong                      serial,
 
10140
                                 gboolean                    non_linear)
 
10141
{
 
10142
  GdkWindowObject *c;
 
10143
  GdkWindowObject *win, *last, *next;
 
10144
  GList *path, *list;
 
10145
  GdkWindowObject *a;
 
10146
  GdkWindowObject *b;
 
10147
  GdkWindowObject *toplevel;
 
10148
  GdkNotifyType notify_type;
 
10149
 
 
10150
  /* TODO: Don't send events to toplevel, as we get those from the windowing system */
 
10151
 
 
10152
  a = (GdkWindowObject *)src;
 
10153
  b = (GdkWindowObject *)dest;
 
10154
  if (a == b)
 
10155
    return; /* No crossings generated between src and dest */
 
10156
 
 
10157
  c = find_common_ancestor (a, b);
 
10158
 
 
10159
  non_linear |= (c != a) && (c != b);
 
10160
 
 
10161
  if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
 
10162
    {
 
10163
      toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
 
10164
 
 
10165
      /* Traverse up from a to (excluding) c sending leave events */
 
10166
      if (non_linear)
 
10167
        notify_type = GDK_NOTIFY_NONLINEAR;
 
10168
      else if (c == a)
 
10169
        notify_type = GDK_NOTIFY_INFERIOR;
 
10170
      else
 
10171
        notify_type = GDK_NOTIFY_ANCESTOR;
 
10172
      send_crossing_event (display, toplevel,
 
10173
                           a, GDK_LEAVE_NOTIFY,
 
10174
                           mode,
 
10175
                           notify_type,
 
10176
                           NULL,
 
10177
                           toplevel_x, toplevel_y,
 
10178
                           mask, time_,
 
10179
                           event_in_queue,
 
10180
                           serial);
 
10181
 
 
10182
      if (c != a)
 
10183
        {
 
10184
          if (non_linear)
 
10185
            notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
 
10186
          else
 
10187
            notify_type = GDK_NOTIFY_VIRTUAL;
 
10188
 
 
10189
          last = a;
 
10190
          win = get_event_parent (a);
 
10191
          while (win != c && win->window_type != GDK_WINDOW_ROOT)
 
10192
            {
 
10193
              send_crossing_event (display, toplevel,
 
10194
                                   win, GDK_LEAVE_NOTIFY,
 
10195
                                   mode,
 
10196
                                   notify_type,
 
10197
                                   (GdkWindow *)last,
 
10198
                                   toplevel_x, toplevel_y,
 
10199
                                   mask, time_,
 
10200
                                   event_in_queue,
 
10201
                                   serial);
 
10202
 
 
10203
              last = win;
 
10204
              win = get_event_parent (win);
 
10205
            }
 
10206
        }
 
10207
    }
 
10208
 
 
10209
  if (b) /* Might not be a dest, e.g. if we're moving out of the window */
 
10210
    {
 
10211
      toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
 
10212
 
 
10213
      /* Traverse down from c to b */
 
10214
      if (c != b)
 
10215
        {
 
10216
          path = NULL;
 
10217
          win = get_event_parent (b);
 
10218
          while (win != c && win->window_type != GDK_WINDOW_ROOT)
 
10219
            {
 
10220
              path = g_list_prepend (path, win);
 
10221
              win = get_event_parent (win);
 
10222
            }
 
10223
 
 
10224
          if (non_linear)
 
10225
            notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
 
10226
          else
 
10227
            notify_type = GDK_NOTIFY_VIRTUAL;
 
10228
 
 
10229
          list = path;
 
10230
          while (list)
 
10231
            {
 
10232
              win = (GdkWindowObject *)list->data;
 
10233
              list = g_list_next (list);
 
10234
              if (list)
 
10235
                next = (GdkWindowObject *)list->data;
 
10236
              else
 
10237
                next = b;
 
10238
 
 
10239
              send_crossing_event (display, toplevel,
 
10240
                                   win, GDK_ENTER_NOTIFY,
 
10241
                                   mode,
 
10242
                                   notify_type,
 
10243
                                   (GdkWindow *)next,
 
10244
                                   toplevel_x, toplevel_y,
 
10245
                                   mask, time_,
 
10246
                                   event_in_queue,
 
10247
                                   serial);
 
10248
            }
 
10249
          g_list_free (path);
 
10250
        }
 
10251
 
 
10252
 
 
10253
      if (non_linear)
 
10254
        notify_type = GDK_NOTIFY_NONLINEAR;
 
10255
      else if (c == a)
 
10256
        notify_type = GDK_NOTIFY_ANCESTOR;
 
10257
      else
 
10258
        notify_type = GDK_NOTIFY_INFERIOR;
 
10259
 
 
10260
      send_crossing_event (display, toplevel,
 
10261
                           b, GDK_ENTER_NOTIFY,
 
10262
                           mode,
 
10263
                           notify_type,
 
10264
                           NULL,
 
10265
                           toplevel_x, toplevel_y,
 
10266
                           mask, time_,
 
10267
                           event_in_queue,
 
10268
                           serial);
 
10269
    }
 
10270
}
 
10271
 
 
10272
/* Returns the window inside the event window with the pointer in it
 
10273
 * at the specified coordinates, or NULL if its not in any child of
 
10274
 * the toplevel. It also takes into account !owner_events grabs.
 
10275
 */
 
10276
static GdkWindow *
 
10277
get_pointer_window (GdkDisplay *display,
 
10278
                    GdkWindow *event_window,
 
10279
                    gdouble toplevel_x,
 
10280
                    gdouble toplevel_y,
 
10281
                    gulong serial)
 
10282
{
 
10283
  GdkWindow *pointer_window;
 
10284
  GdkPointerGrabInfo *grab;
 
10285
 
 
10286
  if (event_window == display->pointer_info.toplevel_under_pointer)
 
10287
    pointer_window =
 
10288
      _gdk_window_find_descendant_at (event_window,
 
10289
                                      toplevel_x, toplevel_y,
 
10290
                                      NULL, NULL);
 
10291
  else
 
10292
    pointer_window = NULL;
 
10293
 
 
10294
  grab = _gdk_display_has_pointer_grab (display, serial);
 
10295
  if (grab != NULL &&
 
10296
      !grab->owner_events &&
 
10297
      pointer_window != grab->window)
 
10298
    pointer_window = NULL;
 
10299
 
 
10300
  return pointer_window;
 
10301
}
 
10302
 
 
10303
void
 
10304
_gdk_display_set_window_under_pointer (GdkDisplay *display,
 
10305
                                       GdkWindow *window)
 
10306
{
 
10307
  /* We don't track this if all native, and it can cause issues
 
10308
     with the update_cursor call below */
 
10309
  if (_gdk_native_windows)
 
10310
    return;
 
10311
 
 
10312
  if (display->pointer_info.window_under_pointer)
 
10313
    g_object_unref (display->pointer_info.window_under_pointer);
 
10314
  display->pointer_info.window_under_pointer = window;
 
10315
  if (window)
 
10316
    g_object_ref (window);
 
10317
 
 
10318
  if (window)
 
10319
    update_cursor (display);
 
10320
 
 
10321
  _gdk_display_enable_motion_hints (display);
 
10322
}
 
10323
 
 
10324
/*
 
10325
 *--------------------------------------------------------------
 
10326
 * gdk_pointer_grab
 
10327
 *
 
10328
 *   Grabs the pointer to a specific window
 
10329
 *
 
10330
 * Arguments:
 
10331
 *   "window" is the window which will receive the grab
 
10332
 *   "owner_events" specifies whether events will be reported as is,
 
10333
 *     or relative to "window"
 
10334
 *   "event_mask" masks only interesting events
 
10335
 *   "confine_to" limits the cursor movement to the specified window
 
10336
 *   "cursor" changes the cursor for the duration of the grab
 
10337
 *   "time" specifies the time
 
10338
 *
 
10339
 * Results:
 
10340
 *
 
10341
 * Side effects:
 
10342
 *   requires a corresponding call to gdk_pointer_ungrab
 
10343
 *
 
10344
 *--------------------------------------------------------------
 
10345
 */
 
10346
GdkGrabStatus
 
10347
gdk_pointer_grab (GdkWindow *     window,
 
10348
                  gboolean        owner_events,
 
10349
                  GdkEventMask    event_mask,
 
10350
                  GdkWindow *     confine_to,
 
10351
                  GdkCursor *     cursor,
 
10352
                  guint32         time)
 
10353
{
 
10354
  GdkWindow *native;
 
10355
  GdkDisplay *display;
 
10356
  GdkGrabStatus res;
 
10357
  gulong serial;
 
10358
 
 
10359
  g_return_val_if_fail (window != NULL, 0);
 
10360
  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
10361
  g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
 
10362
 
 
10363
  /* We need a native window for confine to to work, ensure we have one */
 
10364
  if (confine_to)
 
10365
    {
 
10366
      if (!gdk_window_ensure_native (confine_to))
 
10367
        {
 
10368
          g_warning ("Can't confine to grabbed window, not native");
 
10369
          confine_to = NULL;
 
10370
        }
 
10371
    }
 
10372
 
 
10373
  /* Non-viewable client side window => fail */
 
10374
  if (!_gdk_window_has_impl (window) &&
 
10375
      !gdk_window_is_viewable (window))
 
10376
    return GDK_GRAB_NOT_VIEWABLE;
 
10377
 
 
10378
  if (_gdk_native_windows)
 
10379
    native = window;
 
10380
  else
 
10381
    native = gdk_window_get_toplevel (window);
 
10382
  while (gdk_window_is_offscreen ((GdkWindowObject *)native))
 
10383
    {
 
10384
      native = gdk_offscreen_window_get_embedder (native);
 
10385
 
 
10386
      if (native == NULL ||
 
10387
          (!_gdk_window_has_impl (native) &&
 
10388
           !gdk_window_is_viewable (native)))
 
10389
        return GDK_GRAB_NOT_VIEWABLE;
 
10390
 
 
10391
      native = gdk_window_get_toplevel (native);
 
10392
    }
 
10393
 
 
10394
  display = gdk_drawable_get_display (window);
 
10395
 
 
10396
  serial = _gdk_windowing_window_get_next_serial (display);
 
10397
 
 
10398
  res = _gdk_windowing_pointer_grab (window,
 
10399
                                     native,
 
10400
                                     owner_events,
 
10401
                                     get_native_grab_event_mask (event_mask),
 
10402
                                     confine_to,
 
10403
                                     cursor,
 
10404
                                     time);
 
10405
 
 
10406
  if (res == GDK_GRAB_SUCCESS)
 
10407
    _gdk_display_add_pointer_grab (display,
 
10408
                                   window,
 
10409
                                   native,
 
10410
                                   owner_events,
 
10411
                                   event_mask,
 
10412
                                   serial,
 
10413
                                   time,
 
10414
                                   FALSE);
 
10415
 
 
10416
  return res;
 
10417
}
 
10418
 
 
10419
/**
 
10420
 * gdk_window_geometry_changed:
 
10421
 * @window: an embedded offscreen #GdkWindow
 
10422
 *
 
10423
 * This function informs GDK that the geometry of an embedded
 
10424
 * offscreen window has changed. This is necessary for GDK to keep
 
10425
 * track of which offscreen window the pointer is in.
 
10426
 *
 
10427
 * Since: 2.18
 
10428
 */
 
10429
void
 
10430
gdk_window_geometry_changed (GdkWindow *window)
 
10431
{
 
10432
  _gdk_synthesize_crossing_events_for_geometry_change (window);
 
10433
}
 
10434
 
 
10435
static gboolean
 
10436
do_synthesize_crossing_event (gpointer data)
 
10437
{
 
10438
  GdkDisplay *display;
 
10439
  GdkWindow *changed_toplevel;
 
10440
  GdkWindowObject *changed_toplevel_priv;
 
10441
  GdkWindow *new_window_under_pointer;
 
10442
  gulong serial;
 
10443
 
 
10444
  changed_toplevel = data;
 
10445
  changed_toplevel_priv = (GdkWindowObject *)changed_toplevel;
 
10446
 
 
10447
  changed_toplevel_priv->synthesize_crossing_event_queued = FALSE;
 
10448
 
 
10449
  if (GDK_WINDOW_DESTROYED (changed_toplevel))
 
10450
    return FALSE;
 
10451
 
 
10452
  display = gdk_drawable_get_display (changed_toplevel);
 
10453
  serial = _gdk_windowing_window_get_next_serial (display);
 
10454
 
 
10455
  if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
 
10456
    {
 
10457
      new_window_under_pointer =
 
10458
        get_pointer_window (display, changed_toplevel,
 
10459
                            display->pointer_info.toplevel_x,
 
10460
                            display->pointer_info.toplevel_y,
 
10461
                            serial);
 
10462
      if (new_window_under_pointer !=
 
10463
          display->pointer_info.window_under_pointer)
 
10464
        {
 
10465
          _gdk_synthesize_crossing_events (display,
 
10466
                                           display->pointer_info.window_under_pointer,
 
10467
                                           new_window_under_pointer,
 
10468
                                           GDK_CROSSING_NORMAL,
 
10469
                                           display->pointer_info.toplevel_x,
 
10470
                                           display->pointer_info.toplevel_y,
 
10471
                                           display->pointer_info.state,
 
10472
                                           GDK_CURRENT_TIME,
 
10473
                                           NULL,
 
10474
                                           serial,
 
10475
                                           FALSE);
 
10476
          _gdk_display_set_window_under_pointer (display, new_window_under_pointer);
 
10477
        }
 
10478
    }
 
10479
 
 
10480
  return FALSE;
 
10481
}
 
10482
 
 
10483
void
 
10484
_gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
 
10485
{
 
10486
  GdkDisplay *display;
 
10487
  GdkWindow *toplevel;
 
10488
  GdkWindowObject *toplevel_priv;
 
10489
 
 
10490
  if (_gdk_native_windows)
 
10491
    return; /* We use the native crossing events if all native */
 
10492
 
 
10493
  display = gdk_drawable_get_display (changed_window);
 
10494
 
 
10495
  toplevel = get_event_toplevel (changed_window);
 
10496
  toplevel_priv = (GdkWindowObject *)toplevel;
 
10497
 
 
10498
  if (toplevel == display->pointer_info.toplevel_under_pointer &&
 
10499
      !toplevel_priv->synthesize_crossing_event_queued)
 
10500
    {
 
10501
      toplevel_priv->synthesize_crossing_event_queued = TRUE;
 
10502
      gdk_threads_add_idle_full (GDK_PRIORITY_EVENTS - 1,
 
10503
                                 do_synthesize_crossing_event,
 
10504
                                 g_object_ref (toplevel),
 
10505
                                 g_object_unref);
 
10506
    }
 
10507
}
 
10508
 
 
10509
/* Don't use for crossing events */
 
10510
static GdkWindow *
 
10511
get_event_window (GdkDisplay                 *display,
 
10512
                  GdkWindow                  *pointer_window,
 
10513
                  GdkEventType                type,
 
10514
                  GdkModifierType             mask,
 
10515
                  guint                      *evmask_out,
 
10516
                  gulong                      serial)
 
10517
{
 
10518
  guint evmask;
 
10519
  GdkWindow *grab_window;
 
10520
  GdkWindowObject *w;
 
10521
  GdkPointerGrabInfo *grab;
 
10522
 
 
10523
  grab = _gdk_display_has_pointer_grab (display, serial);
 
10524
 
 
10525
  if (grab != NULL && !grab->owner_events)
 
10526
    {
 
10527
      evmask = grab->event_mask;
 
10528
      evmask = update_evmask_for_button_motion (evmask, mask);
 
10529
 
 
10530
      grab_window = grab->window;
 
10531
 
 
10532
      if (evmask & type_masks[type])
 
10533
        {
 
10534
          if (evmask_out)
 
10535
            *evmask_out = evmask;
 
10536
          return grab_window;
 
10537
        }
 
10538
      else
 
10539
        return NULL;
 
10540
    }
 
10541
 
 
10542
  w = (GdkWindowObject *)pointer_window;
 
10543
  while (w != NULL)
 
10544
    {
 
10545
      evmask = w->event_mask;
 
10546
      evmask = update_evmask_for_button_motion (evmask, mask);
 
10547
 
 
10548
      if (evmask & type_masks[type])
 
10549
        {
 
10550
          if (evmask_out)
 
10551
            *evmask_out = evmask;
 
10552
          return (GdkWindow *)w;
 
10553
        }
 
10554
 
 
10555
      w = get_event_parent (w);
 
10556
    }
 
10557
 
 
10558
  if (grab != NULL &&
 
10559
      grab->owner_events)
 
10560
    {
 
10561
      evmask = grab->event_mask;
 
10562
      evmask = update_evmask_for_button_motion (evmask, mask);
 
10563
 
 
10564
      if (evmask & type_masks[type])
 
10565
        {
 
10566
          if (evmask_out)
 
10567
            *evmask_out = evmask;
 
10568
          return grab->window;
 
10569
        }
 
10570
      else
 
10571
        return NULL;
 
10572
    }
 
10573
 
 
10574
  return NULL;
 
10575
}
 
10576
 
 
10577
static gboolean
 
10578
proxy_pointer_event (GdkDisplay                 *display,
 
10579
                     GdkEvent                   *source_event,
 
10580
                     gulong                      serial)
 
10581
{
 
10582
  GdkWindow *toplevel_window, *event_window;
 
10583
  GdkWindow *pointer_window;
 
10584
  GdkEvent *event;
 
10585
  guint state;
 
10586
  gdouble toplevel_x, toplevel_y;
 
10587
  guint32 time_;
 
10588
  gboolean non_linear;
 
10589
 
 
10590
  event_window = source_event->any.window;
 
10591
  gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
 
10592
  gdk_event_get_state (source_event, &state);
 
10593
  time_ = gdk_event_get_time (source_event);
 
10594
  toplevel_window = convert_native_coords_to_toplevel (event_window,
 
10595
                                                       toplevel_x, toplevel_y,
 
10596
                                                       &toplevel_x, &toplevel_y);
 
10597
 
 
10598
  non_linear = FALSE;
 
10599
  if ((source_event->type == GDK_LEAVE_NOTIFY ||
 
10600
       source_event->type == GDK_ENTER_NOTIFY) &&
 
10601
      (source_event->crossing.detail == GDK_NOTIFY_NONLINEAR ||
 
10602
       source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))
 
10603
    non_linear = TRUE;
 
10604
 
 
10605
  /* If we get crossing events with subwindow unexpectedly being NULL
 
10606
     that means there is a native subwindow that gdk doesn't know about.
 
10607
     We track these and forward them, with the correct virtual window
 
10608
     events inbetween.
 
10609
     This is important to get right, as metacity uses gdk for the frame
 
10610
     windows, but gdk doesn't know about the client windows reparented
 
10611
     into the frame. */
 
10612
  if (((source_event->type == GDK_LEAVE_NOTIFY &&
 
10613
        source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
 
10614
       (source_event->type == GDK_ENTER_NOTIFY &&
 
10615
        (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
 
10616
         source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
 
10617
      source_event->crossing.subwindow == NULL)
 
10618
    {
 
10619
      /* Left for an unknown (to gdk) subwindow */
 
10620
 
 
10621
      /* Send leave events from window under pointer to event window
 
10622
         that will get the subwindow == NULL window */
 
10623
      _gdk_synthesize_crossing_events (display,
 
10624
                                       display->pointer_info.window_under_pointer,
 
10625
                                       event_window,
 
10626
                                       source_event->crossing.mode,
 
10627
                                       toplevel_x, toplevel_y,
 
10628
                                       state, time_,
 
10629
                                       source_event,
 
10630
                                       serial,
 
10631
                                       non_linear);
 
10632
 
 
10633
      /* Send subwindow == NULL event */
 
10634
      send_crossing_event (display,
 
10635
                           (GdkWindowObject *)toplevel_window,
 
10636
                           (GdkWindowObject *)event_window,
 
10637
                           source_event->type,
 
10638
                           source_event->crossing.mode,
 
10639
                           source_event->crossing.detail,
 
10640
                           NULL,
 
10641
                           toplevel_x,   toplevel_y,
 
10642
                           state, time_,
 
10643
                           source_event,
 
10644
                           serial);
 
10645
 
 
10646
      _gdk_display_set_window_under_pointer (display, NULL);
 
10647
      return TRUE;
 
10648
    }
 
10649
 
 
10650
  pointer_window = get_pointer_window (display, toplevel_window,
 
10651
                                       toplevel_x, toplevel_y, serial);
 
10652
 
 
10653
  if (((source_event->type == GDK_ENTER_NOTIFY &&
 
10654
        source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
 
10655
       (source_event->type == GDK_LEAVE_NOTIFY &&
 
10656
        (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
 
10657
         source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
 
10658
      source_event->crossing.subwindow == NULL)
 
10659
    {
 
10660
      /* Entered from an unknown (to gdk) subwindow */
 
10661
 
 
10662
      /* Send subwindow == NULL event */
 
10663
      send_crossing_event (display,
 
10664
                           (GdkWindowObject *)toplevel_window,
 
10665
                           (GdkWindowObject *)event_window,
 
10666
                           source_event->type,
 
10667
                           source_event->crossing.mode,
 
10668
                           source_event->crossing.detail,
 
10669
                           NULL,
 
10670
                           toplevel_x,   toplevel_y,
 
10671
                           state, time_,
 
10672
                           source_event,
 
10673
                           serial);
 
10674
 
 
10675
      /* Send enter events from event window to pointer_window */
 
10676
      _gdk_synthesize_crossing_events (display,
 
10677
                                       event_window,
 
10678
                                       pointer_window,
 
10679
                                       source_event->crossing.mode,
 
10680
                                       toplevel_x, toplevel_y,
 
10681
                                       state, time_,
 
10682
                                       source_event,
 
10683
                                       serial, non_linear);
 
10684
      _gdk_display_set_window_under_pointer (display, pointer_window);
 
10685
      return TRUE;
 
10686
    }
 
10687
 
 
10688
  if (display->pointer_info.window_under_pointer != pointer_window)
 
10689
    {
 
10690
      /* Either a toplevel crossing notify that ended up inside a child window,
 
10691
         or a motion notify that got into another child window  */
 
10692
 
 
10693
      /* Different than last time, send crossing events */
 
10694
      _gdk_synthesize_crossing_events (display,
 
10695
                                       display->pointer_info.window_under_pointer,
 
10696
                                       pointer_window,
 
10697
                                       GDK_CROSSING_NORMAL,
 
10698
                                       toplevel_x, toplevel_y,
 
10699
                                       state, time_,
 
10700
                                       source_event,
 
10701
                                       serial, non_linear);
 
10702
      _gdk_display_set_window_under_pointer (display, pointer_window);
 
10703
    }
 
10704
  else if (source_event->type == GDK_MOTION_NOTIFY)
 
10705
    {
 
10706
      GdkWindow *event_win;
 
10707
      guint evmask;
 
10708
      gboolean is_hint;
 
10709
 
 
10710
      event_win = get_event_window (display,
 
10711
                                    pointer_window,
 
10712
                                    source_event->type,
 
10713
                                    state,
 
10714
                                    &evmask,
 
10715
                                    serial);
 
10716
 
 
10717
      is_hint = FALSE;
 
10718
 
 
10719
      if (event_win &&
 
10720
          (evmask & GDK_POINTER_MOTION_HINT_MASK))
 
10721
        {
 
10722
          if (display->pointer_info.motion_hint_serial != 0 &&
 
10723
              serial < display->pointer_info.motion_hint_serial)
 
10724
            event_win = NULL; /* Ignore event */
 
10725
          else
 
10726
            {
 
10727
              is_hint = TRUE;
 
10728
              display->pointer_info.motion_hint_serial = G_MAXULONG;
 
10729
            }
 
10730
        }
 
10731
 
 
10732
      if (event_win && !display->ignore_core_events)
 
10733
        {
 
10734
          event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
 
10735
          event->motion.time = time_;
 
10736
          convert_toplevel_coords_to_window (event_win,
 
10737
                                             toplevel_x, toplevel_y,
 
10738
                                             &event->motion.x, &event->motion.y);
 
10739
          event->motion.x_root = source_event->motion.x_root;
 
10740
          event->motion.y_root = source_event->motion.y_root;;
 
10741
          event->motion.state = state;
 
10742
          event->motion.is_hint = is_hint;
 
10743
          event->motion.device = NULL;
 
10744
          event->motion.device = source_event->motion.device;
 
10745
        }
 
10746
    }
 
10747
 
 
10748
  /* unlink all move events from queue.
 
10749
     We handle our own, including our emulated masks. */
 
10750
  return TRUE;
 
10751
}
 
10752
 
 
10753
#define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
 
10754
                             GDK_BUTTON2_MASK | \
 
10755
                             GDK_BUTTON3_MASK | \
 
10756
                             GDK_BUTTON4_MASK | \
 
10757
                             GDK_BUTTON5_MASK)
 
10758
 
 
10759
static gboolean
 
10760
proxy_button_event (GdkEvent *source_event,
 
10761
                    gulong serial)
 
10762
{
 
10763
  GdkWindow *toplevel_window, *event_window;
 
10764
  GdkWindow *event_win;
 
10765
  GdkWindow *pointer_window;
 
10766
  GdkWindowObject *parent;
 
10767
  GdkEvent *event;
 
10768
  guint state;
 
10769
  guint32 time_;
 
10770
  GdkEventType type;
 
10771
  gdouble toplevel_x, toplevel_y;
 
10772
  GdkDisplay *display;
 
10773
  GdkWindowObject *w;
 
10774
 
 
10775
  type = source_event->any.type;
 
10776
  event_window = source_event->any.window;
 
10777
  gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
 
10778
  gdk_event_get_state (source_event, &state);
 
10779
  time_ = gdk_event_get_time (source_event);
 
10780
  display = gdk_drawable_get_display (source_event->any.window);
 
10781
  toplevel_window = convert_native_coords_to_toplevel (event_window,
 
10782
                                                       toplevel_x, toplevel_y,
 
10783
                                                       &toplevel_x, &toplevel_y);
 
10784
 
 
10785
  if (type == GDK_BUTTON_PRESS &&
 
10786
      !source_event->any.send_event &&
 
10787
      _gdk_display_has_pointer_grab (display, serial) == NULL)
 
10788
    {
 
10789
      pointer_window =
 
10790
        _gdk_window_find_descendant_at (toplevel_window,
 
10791
                                        toplevel_x, toplevel_y,
 
10792
                                        NULL, NULL);
 
10793
 
 
10794
      /* Find the event window, that gets the grab */
 
10795
      w = (GdkWindowObject *)pointer_window;
 
10796
      while (w != NULL &&
 
10797
             (parent = get_event_parent (w)) != NULL &&
 
10798
             parent->window_type != GDK_WINDOW_ROOT)
 
10799
        {
 
10800
          if (w->event_mask & GDK_BUTTON_PRESS_MASK)
 
10801
            break;
 
10802
          w = parent;
 
10803
        }
 
10804
      pointer_window = (GdkWindow *)w;
 
10805
 
 
10806
      _gdk_display_add_pointer_grab  (display,
 
10807
                                      pointer_window,
 
10808
                                      event_window,
 
10809
                                      FALSE,
 
10810
                                      gdk_window_get_events (pointer_window),
 
10811
                                      serial,
 
10812
                                      time_,
 
10813
                                      TRUE);
 
10814
      _gdk_display_pointer_grab_update (display, serial);
 
10815
    }
 
10816
 
 
10817
  pointer_window = get_pointer_window (display, toplevel_window,
 
10818
                                       toplevel_x, toplevel_y,
 
10819
                                       serial);
 
10820
 
 
10821
  event_win = get_event_window (display,
 
10822
                                pointer_window,
 
10823
                                type, state,
 
10824
                                NULL, serial);
 
10825
 
 
10826
  if (event_win == NULL || display->ignore_core_events)
 
10827
    return TRUE;
 
10828
 
 
10829
  event = _gdk_make_event (event_win, type, source_event, FALSE);
 
10830
 
 
10831
  switch (type)
 
10832
    {
 
10833
    case GDK_BUTTON_PRESS:
 
10834
    case GDK_BUTTON_RELEASE:
 
10835
      event->button.button = source_event->button.button;
 
10836
      convert_toplevel_coords_to_window (event_win,
 
10837
                                         toplevel_x, toplevel_y,
 
10838
                                         &event->button.x, &event->button.y);
 
10839
      event->button.x_root = source_event->button.x_root;
 
10840
      event->button.y_root = source_event->button.y_root;
 
10841
      event->button.state = state;
 
10842
      event->button.device = source_event->button.device;
 
10843
 
 
10844
      if (type == GDK_BUTTON_PRESS)
 
10845
        _gdk_event_button_generate (display, event);
 
10846
      return TRUE;
 
10847
 
 
10848
    case GDK_SCROLL:
 
10849
      event->scroll.direction = source_event->scroll.direction;
 
10850
      convert_toplevel_coords_to_window (event_win,
 
10851
                                         toplevel_x, toplevel_y,
 
10852
                                         &event->scroll.x, &event->scroll.y);
 
10853
      event->scroll.x_root = source_event->scroll.x_root;
 
10854
      event->scroll.y_root = source_event->scroll.y_root;
 
10855
      event->scroll.state = state;
 
10856
      event->scroll.device = source_event->scroll.device;
 
10857
      return TRUE;
 
10858
 
 
10859
    default:
 
10860
      return FALSE;
 
10861
    }
 
10862
 
 
10863
  return TRUE; /* Always unlink original, we want to obey the emulated event mask */
 
10864
}
 
10865
 
 
10866
#ifdef DEBUG_WINDOW_PRINTING
 
10867
static void
 
10868
gdk_window_print (GdkWindowObject *window,
 
10869
                  int indent)
 
10870
{
 
10871
  GdkRectangle r;
 
10872
  const char *window_types[] = {
 
10873
    "root",
 
10874
    "toplevel",
 
10875
    "child",
 
10876
    "dialog",
 
10877
    "temp",
 
10878
    "foreign",
 
10879
    "offscreen"
 
10880
  };
 
10881
 
 
10882
  g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
 
10883
           window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
 
10884
           window->x, window->y,
 
10885
           window->width, window->height
 
10886
           );
 
10887
 
 
10888
  if (gdk_window_has_impl (window))
 
10889
    {
 
10890
#ifdef GDK_WINDOWING_X11
 
10891
      g_print (" impl(0x%lx)", gdk_x11_drawable_get_xid (GDK_DRAWABLE (window)));
 
10892
#endif
 
10893
    }
 
10894
 
 
10895
  if (window->window_type != GDK_WINDOW_CHILD)
 
10896
    g_print (" %s", window_types[window->window_type]);
 
10897
 
 
10898
  if (window->input_only)
 
10899
    g_print (" input-only");
 
10900
 
 
10901
  if (window->shaped)
 
10902
    g_print (" shaped");
 
10903
 
 
10904
  if (!gdk_window_is_visible ((GdkWindow *)window))
 
10905
    g_print (" hidden");
 
10906
 
 
10907
  g_print (" abs[%d,%d]",
 
10908
           window->abs_x, window->abs_y);
 
10909
 
 
10910
  gdk_region_get_clipbox (window->clip_region, &r);
 
10911
  if (gdk_region_empty (window->clip_region))
 
10912
    g_print (" clipbox[empty]");
 
10913
  else
 
10914
    g_print (" clipbox[%d,%d %dx%d]", r.x, r.y, r.width, r.height);
 
10915
 
 
10916
  g_print ("\n");
 
10917
}
 
10918
 
 
10919
 
 
10920
static void
 
10921
gdk_window_print_tree (GdkWindow *window,
 
10922
                       int indent,
 
10923
                       gboolean include_input_only)
 
10924
{
 
10925
  GdkWindowObject *private;
 
10926
  GList *l;
 
10927
 
 
10928
  private = (GdkWindowObject *)window;
 
10929
 
 
10930
  if (private->input_only && !include_input_only)
 
10931
    return;
 
10932
 
 
10933
  gdk_window_print (private, indent);
 
10934
 
 
10935
  for (l = private->children; l != NULL; l = l->next)
 
10936
    gdk_window_print_tree (l->data, indent + 4, include_input_only);
 
10937
}
 
10938
 
 
10939
#endif /* DEBUG_WINDOW_PRINTING */
 
10940
 
 
10941
static gboolean
 
10942
is_input_event (GdkDisplay *display,
 
10943
                GdkEvent *event)
 
10944
{
 
10945
  GdkDevice *core_pointer;
 
10946
 
 
10947
  core_pointer = gdk_display_get_core_pointer (display);
 
10948
  if ((event->type == GDK_MOTION_NOTIFY &&
 
10949
       event->motion.device != core_pointer) ||
 
10950
      ((event->type == GDK_BUTTON_PRESS ||
 
10951
        event->type == GDK_BUTTON_RELEASE) &&
 
10952
       event->button.device != core_pointer))
 
10953
    return TRUE;
 
10954
  return FALSE;
 
10955
}
 
10956
 
 
10957
void
 
10958
_gdk_windowing_got_event (GdkDisplay *display,
 
10959
                          GList      *event_link,
 
10960
                          GdkEvent   *event,
 
10961
                          gulong      serial)
 
10962
{
 
10963
  GdkWindow *event_window;
 
10964
  GdkWindowObject *event_private;
 
10965
  gdouble x, y;
 
10966
  gboolean unlink_event;
 
10967
  guint old_state, old_button;
 
10968
  GdkPointerGrabInfo *button_release_grab;
 
10969
  gboolean is_toplevel;
 
10970
 
 
10971
  if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
 
10972
    display->last_event_time = gdk_event_get_time (event);
 
10973
 
 
10974
  _gdk_display_pointer_grab_update (display,
 
10975
                                    serial);
 
10976
 
 
10977
  event_window = event->any.window;
 
10978
  if (!event_window)
 
10979
    return;
 
10980
 
 
10981
  event_private = GDK_WINDOW_OBJECT (event_window);
 
10982
 
 
10983
#ifdef DEBUG_WINDOW_PRINTING
 
10984
  if (event->type == GDK_KEY_PRESS &&
 
10985
      (event->key.keyval == 0xa7 ||
 
10986
       event->key.keyval == 0xbd))
 
10987
    {
 
10988
      gdk_window_print_tree (event_window, 0,
 
10989
                             event->key.keyval == 0xbd);
 
10990
    }
 
10991
#endif
 
10992
 
 
10993
  if (_gdk_native_windows)
 
10994
    {
 
10995
      if (event->type == GDK_BUTTON_PRESS &&
 
10996
          !event->any.send_event &&
 
10997
          _gdk_display_has_pointer_grab (display, serial) == NULL)
 
10998
        {
 
10999
          _gdk_display_add_pointer_grab  (display,
 
11000
                                          event_window,
 
11001
                                          event_window,
 
11002
                                          FALSE,
 
11003
                                          gdk_window_get_events (event_window),
 
11004
                                          serial,
 
11005
                                          gdk_event_get_time (event),
 
11006
                                          TRUE);
 
11007
          _gdk_display_pointer_grab_update (display,
 
11008
                                            serial);
 
11009
        }
 
11010
      if (event->type == GDK_BUTTON_RELEASE &&
 
11011
          !event->any.send_event)
 
11012
        {
 
11013
          button_release_grab =
 
11014
            _gdk_display_has_pointer_grab (display, serial);
 
11015
          if (button_release_grab &&
 
11016
              button_release_grab->implicit &&
 
11017
              (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
 
11018
            {
 
11019
              button_release_grab->serial_end = serial;
 
11020
              button_release_grab->implicit_ungrab = FALSE;
 
11021
              _gdk_display_pointer_grab_update (display, serial);
 
11022
            }
 
11023
        }
 
11024
 
 
11025
      if (event->type == GDK_BUTTON_PRESS)
 
11026
        _gdk_event_button_generate (display, event);
 
11027
 
 
11028
      return;
 
11029
    }
 
11030
 
 
11031
  if (event->type == GDK_VISIBILITY_NOTIFY)
 
11032
    {
 
11033
      event_private->native_visibility = event->visibility.state;
 
11034
      gdk_window_update_visibility_recursively (event_private,
 
11035
                                                event_private);
 
11036
      return;
 
11037
    }
 
11038
 
 
11039
  if (is_input_event (display, event))
 
11040
    return;
 
11041
 
 
11042
  if (!(is_button_type (event->type) ||
 
11043
        is_motion_type (event->type)) ||
 
11044
      event_private->window_type == GDK_WINDOW_ROOT)
 
11045
    return;
 
11046
 
 
11047
  is_toplevel = gdk_window_is_toplevel (event_private);
 
11048
 
 
11049
  if ((event->type == GDK_ENTER_NOTIFY ||
 
11050
       event->type == GDK_LEAVE_NOTIFY) &&
 
11051
      (event->crossing.mode == GDK_CROSSING_GRAB ||
 
11052
       event->crossing.mode == GDK_CROSSING_UNGRAB) &&
 
11053
      (_gdk_display_has_pointer_grab (display, serial) ||
 
11054
       event->crossing.detail == GDK_NOTIFY_INFERIOR))
 
11055
    {
 
11056
      /* We synthesize all crossing events due to grabs ourselves,
 
11057
       * so we ignore the native ones caused by our native pointer_grab
 
11058
       * calls. Otherwise we would proxy these crossing event and cause
 
11059
       * multiple copies of crossing events for grabs.
 
11060
       *
 
11061
       * We do want to handle grabs from other clients though, as for
 
11062
       * instance alt-tab in metacity causes grabs like these and
 
11063
       * we want to handle those. Thus the has_pointer_grab check.
 
11064
       *
 
11065
       * Implicit grabs on child windows create some grabbing events
 
11066
       * that are sent before the button press. This means we can't
 
11067
       * detect these with the has_pointer_grab check (as the implicit
 
11068
       * grab is only noticed when we get button press event), so we
 
11069
       * detect these events by checking for INFERIOR enter or leave
 
11070
       * events. These should never be a problem to filter out.
 
11071
       */
 
11072
 
 
11073
      /* We ended up in this window after some (perhaps other clients)
 
11074
         grab, so update the toplevel_under_window state */
 
11075
      if (is_toplevel &&
 
11076
          event->type == GDK_ENTER_NOTIFY &&
 
11077
          event->crossing.mode == GDK_CROSSING_UNGRAB)
 
11078
        {
 
11079
          if (display->pointer_info.toplevel_under_pointer)
 
11080
            g_object_unref (display->pointer_info.toplevel_under_pointer);
 
11081
          display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
 
11082
        }
 
11083
 
 
11084
      unlink_event = TRUE;
 
11085
      goto out;
 
11086
    }
 
11087
 
 
11088
  /* Track toplevel_under_pointer */
 
11089
  if (is_toplevel)
 
11090
    {
 
11091
      if (event->type == GDK_ENTER_NOTIFY &&
 
11092
          event->crossing.detail != GDK_NOTIFY_INFERIOR)
 
11093
        {
 
11094
          if (display->pointer_info.toplevel_under_pointer)
 
11095
            g_object_unref (display->pointer_info.toplevel_under_pointer);
 
11096
          display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
 
11097
        }
 
11098
      else if (event->type == GDK_LEAVE_NOTIFY &&
 
11099
               event->crossing.detail != GDK_NOTIFY_INFERIOR &&
 
11100
               display->pointer_info.toplevel_under_pointer == event_window)
 
11101
        {
 
11102
          if (display->pointer_info.toplevel_under_pointer)
 
11103
            g_object_unref (display->pointer_info.toplevel_under_pointer);
 
11104
          display->pointer_info.toplevel_under_pointer = NULL;
 
11105
        }
 
11106
    }
 
11107
 
 
11108
  /* Store last pointer window and position/state */
 
11109
  old_state = display->pointer_info.state;
 
11110
  old_button = display->pointer_info.button;
 
11111
 
 
11112
  gdk_event_get_coords (event, &x, &y);
 
11113
  convert_native_coords_to_toplevel (event_window, x, y,  &x, &y);
 
11114
  display->pointer_info.toplevel_x = x;
 
11115
  display->pointer_info.toplevel_y = y;
 
11116
  gdk_event_get_state (event, &display->pointer_info.state);
 
11117
  if (event->type == GDK_BUTTON_PRESS ||
 
11118
      event->type == GDK_BUTTON_RELEASE)
 
11119
    display->pointer_info.button = event->button.button;
 
11120
 
 
11121
  if (display->pointer_info.state != old_state ||
 
11122
      display->pointer_info.button != old_button)
 
11123
    _gdk_display_enable_motion_hints (display);
 
11124
 
 
11125
  unlink_event = FALSE;
 
11126
  if (is_motion_type (event->type))
 
11127
    unlink_event = proxy_pointer_event (display,
 
11128
                                        event,
 
11129
                                        serial);
 
11130
  else if (is_button_type (event->type))
 
11131
    unlink_event = proxy_button_event (event,
 
11132
                                       serial);
 
11133
 
 
11134
  if (event->type == GDK_BUTTON_RELEASE &&
 
11135
      !event->any.send_event)
 
11136
    {
 
11137
      button_release_grab =
 
11138
        _gdk_display_has_pointer_grab (display, serial);
 
11139
      if (button_release_grab &&
 
11140
          button_release_grab->implicit &&
 
11141
          (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
 
11142
        {
 
11143
          button_release_grab->serial_end = serial;
 
11144
          button_release_grab->implicit_ungrab = FALSE;
 
11145
          _gdk_display_pointer_grab_update (display, serial);
 
11146
        }
 
11147
    }
 
11148
 
 
11149
 out:
 
11150
  if (unlink_event)
 
11151
    {
 
11152
      _gdk_event_queue_remove_link (display, event_link);
 
11153
      g_list_free_1 (event_link);
 
11154
      gdk_event_free (event);
 
11155
    }
 
11156
}
 
11157
 
 
11158
 
 
11159
static GdkWindow *
 
11160
get_extension_event_window (GdkDisplay                 *display,
 
11161
                            GdkWindow                  *pointer_window,
 
11162
                            GdkEventType                type,
 
11163
                            GdkModifierType             mask,
 
11164
                            gulong                      serial)
 
11165
{
 
11166
  guint evmask;
 
11167
  GdkWindow *grab_window;
 
11168
  GdkWindowObject *w;
 
11169
  GdkPointerGrabInfo *grab;
 
11170
 
 
11171
  grab = _gdk_display_has_pointer_grab (display, serial);
 
11172
 
 
11173
  if (grab != NULL && !grab->owner_events)
 
11174
    {
 
11175
      evmask = grab->event_mask;
 
11176
      evmask = update_evmask_for_button_motion (evmask, mask);
 
11177
 
 
11178
      grab_window = grab->window;
 
11179
 
 
11180
      if (evmask & type_masks[type])
 
11181
        return grab_window;
 
11182
      else
 
11183
        return NULL;
 
11184
    }
 
11185
 
 
11186
  w = (GdkWindowObject *)pointer_window;
 
11187
  while (w != NULL)
 
11188
    {
 
11189
      evmask = w->extension_events;
 
11190
      evmask = update_evmask_for_button_motion (evmask, mask);
 
11191
 
 
11192
      if (evmask & type_masks[type])
 
11193
        return (GdkWindow *)w;
 
11194
 
 
11195
      w = get_event_parent (w);
 
11196
    }
 
11197
 
 
11198
  if (grab != NULL &&
 
11199
      grab->owner_events)
 
11200
    {
 
11201
      evmask = grab->event_mask;
 
11202
      evmask = update_evmask_for_button_motion (evmask, mask);
 
11203
 
 
11204
      if (evmask & type_masks[type])
 
11205
        return grab->window;
 
11206
      else
 
11207
        return NULL;
 
11208
    }
 
11209
 
 
11210
  return NULL;
 
11211
}
 
11212
 
 
11213
 
 
11214
GdkWindow *
 
11215
_gdk_window_get_input_window_for_event (GdkWindow *native_window,
 
11216
                                        GdkEventType event_type,
 
11217
                                        GdkModifierType mask,
 
11218
                                        int x, int y,
 
11219
                                        gulong serial)
 
11220
{
 
11221
  GdkDisplay *display;
 
11222
  GdkWindow *toplevel_window;
 
11223
  GdkWindow *pointer_window;
 
11224
  GdkWindow *event_win;
 
11225
  gdouble toplevel_x, toplevel_y;
 
11226
 
 
11227
  toplevel_x = x;
 
11228
  toplevel_y = y;
 
11229
 
 
11230
  display = gdk_drawable_get_display (native_window);
 
11231
  toplevel_window = convert_native_coords_to_toplevel (native_window,
 
11232
                                                       toplevel_x, toplevel_y,
 
11233
                                                       &toplevel_x, &toplevel_y);
 
11234
  pointer_window = get_pointer_window (display, toplevel_window,
 
11235
                                       toplevel_x, toplevel_y, serial);
 
11236
  event_win = get_extension_event_window (display,
 
11237
                                          pointer_window,
 
11238
                                          event_type,
 
11239
                                          mask,
 
11240
                                          serial);
 
11241
 
 
11242
  return event_win;
 
11243
}
 
11244
 
 
11245
/**
 
11246
 * gdk_window_create_similar_surface:
 
11247
 * @window: window to make new surface similar to
 
11248
 * @content: the content for the new surface
 
11249
 * @width: width of the new surface
 
11250
 * @height: height of the new surface
 
11251
 *
 
11252
 * Create a new surface that is as compatible as possible with the
 
11253
 * given @window. For example the new surface will have the same
 
11254
 * fallback resolution and font options as @window. Generally, the new
 
11255
 * surface will also use the same backend as @window, unless that is
 
11256
 * not possible for some reason. The type of the returned surface may
 
11257
 * be examined with cairo_surface_get_type().
 
11258
 *
 
11259
 * Initially the surface contents are all 0 (transparent if contents
 
11260
 * have transparency, black otherwise.)
 
11261
 *
 
11262
 * Returns: a pointer to the newly allocated surface. The caller
 
11263
 * owns the surface and should call cairo_surface_destroy() when done
 
11264
 * with it.
 
11265
 *
 
11266
 * This function always returns a valid pointer, but it will return a
 
11267
 * pointer to a "nil" surface if @other is already in an error state
 
11268
 * or any other error occurs.
 
11269
 *
 
11270
 * Since: 2.22
 
11271
 **/
 
11272
cairo_surface_t *
 
11273
gdk_window_create_similar_surface (GdkWindow *     window,
 
11274
                                   cairo_content_t content,
 
11275
                                   int             width,
 
11276
                                   int             height)
 
11277
{
 
11278
  cairo_surface_t *window_surface, *surface;
 
11279
 
 
11280
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
11281
  
 
11282
  window_surface = _gdk_drawable_ref_cairo_surface (window);
 
11283
 
 
11284
  surface = cairo_surface_create_similar (window_surface,
 
11285
                                          content,
 
11286
                                          width, height);
 
11287
 
 
11288
  cairo_surface_destroy (window_surface);
 
11289
 
 
11290
  return surface;
 
11291
}
 
11292
 
 
11293
/**
 
11294
 * gdk_window_get_screen:
 
11295
 * @window: a #GdkWindow
 
11296
 *
 
11297
 * Gets the #GdkScreen associated with a #GdkWindow.
 
11298
 *
 
11299
 * Return value: the #GdkScreen associated with @window
 
11300
 *
 
11301
 * Since: 2.24
 
11302
 */
 
11303
GdkScreen*
 
11304
gdk_window_get_screen (GdkWindow *window)
 
11305
{
 
11306
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
11307
 
 
11308
  return gdk_drawable_get_screen (GDK_DRAWABLE (window));
 
11309
}
 
11310
 
 
11311
/**
 
11312
 * gdk_window_get_display:
 
11313
 * @window: a #GdkWindow
 
11314
 *
 
11315
 * Gets the #GdkDisplay associated with a #GdkWindow.
 
11316
 *
 
11317
 * Return value: the #GdkDisplay associated with @window
 
11318
 *
 
11319
 * Since: 2.24
 
11320
 */
 
11321
GdkDisplay *
 
11322
gdk_window_get_display (GdkWindow *window)
 
11323
{
 
11324
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
11325
 
 
11326
  return gdk_drawable_get_display (GDK_DRAWABLE (window));
 
11327
}
 
11328
 
 
11329
/**
 
11330
 * gdk_window_get_visual:
 
11331
 * @window: a #GdkWindow
 
11332
 *
 
11333
 * Gets the #GdkVisual describing the pixel format of @window.
 
11334
 *
 
11335
 * Return value: a #GdkVisual
 
11336
 *
 
11337
 * Since: 2.24
 
11338
 */
 
11339
GdkVisual*
 
11340
gdk_window_get_visual (GdkWindow *window)
 
11341
{
 
11342
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
11343
 
 
11344
  return gdk_drawable_get_visual (GDK_DRAWABLE (window));
 
11345
}
 
11346
 
 
11347
/**
 
11348
 * gdk_window_get_width:
 
11349
 * @window: a #GdkWindow
 
11350
 *
 
11351
 * Returns the width of the given @window.
 
11352
 *
 
11353
 * On the X11 platform the returned size is the size reported in the
 
11354
 * most-recently-processed configure event, rather than the current
 
11355
 * size on the X server.
 
11356
 *
 
11357
 * Returns: The width of @window
 
11358
 *
 
11359
 * Since: 2.24
 
11360
 */
 
11361
int
 
11362
gdk_window_get_width (GdkWindow *window)
 
11363
{
 
11364
  gint width, height;
 
11365
 
 
11366
  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
11367
 
 
11368
  gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
 
11369
 
 
11370
  return width;
 
11371
}
 
11372
 
 
11373
/**
 
11374
 * gdk_window_get_height:
 
11375
 * @window: a #GdkWindow
 
11376
 *
 
11377
 * Returns the height of the given @window.
 
11378
 *
 
11379
 * On the X11 platform the returned size is the size reported in the
 
11380
 * most-recently-processed configure event, rather than the current
 
11381
 * size on the X server.
 
11382
 *
 
11383
 * Returns: The height of @window
 
11384
 *
 
11385
 * Since: 2.24
 
11386
 */
 
11387
int
 
11388
gdk_window_get_height (GdkWindow *window)
 
11389
{
 
11390
  gint width, height;
 
11391
 
 
11392
  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
11393
 
 
11394
  gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
 
11395
 
 
11396
  return height;
 
11397
}
 
11398
 
 
11399
 
 
11400
#define __GDK_WINDOW_C__
 
11401
#include "gdkaliasdef.c"