gdkwindow.c 306 KB
Newer Older
Cody Russell's avatar
Cody Russell committed
1
/* GDK - The GIMP Drawing Kit
2 3
 * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
 * Josh MacDonald, Ryan Lortie
Elliot Lee's avatar
Elliot Lee committed
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
Elliot Lee's avatar
Elliot Lee committed
7 8 9 10 11 12
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16 17 18
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
19
 */
20

21
/*
22
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
23 24
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
25
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
26 27
 */

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
#include "config.h"

#include "gdkwindow.h"

#ifdef GDK_WINDOWING_X11
#include "x11/gdkx.h"           /* For workaround */
#endif
#include "math.h"

#include "gdk.h"                /* For gdk_rectangle_union() */
#include "gdkinternals.h"
#include "gdkintl.h"
#include "gdkdrawable.h"
#include "gdkmarshalers.h"
#include "gdkpixmap.h"
#include "gdkscreen.h"
#include "gdkwindowimpl.h"

#include "gdkalias.h"

#undef DEBUG_WINDOW_PRINTING


51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
/**
 * SECTION:windows
 * @Short_description: Onscreen display areas in the target window system
 * @Title: Windows
 *
 * A #GdkWindow is a rectangular region on the screen. It's a low-level object,
 * used to implement high-level objects such as #GtkWidget and #GtkWindow on the
 * GTK+ level. A #GtkWindow is a toplevel window, the thing a user might think
 * of as a "window" with a titlebar and so on; a #GtkWindow may contain many
 * #GdkWindow<!-- -->s. For example, each #GtkButton has a #GdkWindow associated
 * with it.
 *
 * <refsect2 id="COMPOSITED-WINDOWS">
 * <title>Composited Windows</title>
 * <para>
 * Normally, the windowing system takes care of rendering the contents of a
 * child window onto its parent window. This mechanism can be intercepted by
 * calling gdk_window_set_composited() on the child window. For a
 * <firstterm>composited</firstterm> window it is the responsibility of the
 * application to render the window contents at the right spot.
 * </para>
 * <example id="composited-window-example">
 * <title>Composited windows</title>
 * <programlisting>
 * <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../examples/gdk/composited-window-example.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include>
 * </programlisting></example>
 * <para>
 * In the example <xref linkend="composited-window-example"/>, a button is
 * placed inside of an event box inside of a window. The event box is set as
 * composited and therefore is no longer automatically drawn to the screen.
 *
 * When the contents of the event box change, an expose event is generated on
 * it's parent window (which, in this case, belongs to the toplevel #GtkWindow).
 * The expose handler for this widget is responsible for merging the changes
 * back on the screen in the way that it wishes.
 *
 * In our case, we merge the contents with a 50% transparency. We also set the
 * background colour of the window to red. The effect is that the background
 * shows through the button.
 * </para>
 * </refsect2>
 * <refsect2 id="OFFSCREEN-WINDOWS">
 * <title>Offscreen Windows</title>
 * <para>
 * Offscreen windows are more general than composited windows, since they allow
 * not only to modify the rendering of the child window onto its parent, but
 * also to apply coordinate transformations.
 *
 * To integrate an offscreen window into a window hierarchy, one has to call
 * gdk_offscreen_window_set_embedder() and handle a number of signals. The
 * #GdkWindow::pick-embedded-child signal on the embedder window is used to
 * select an offscreen child at given coordinates, and the
 * #GdkWindow::to-embedder and #GdkWindow::from-embedder signals on the
 * offscreen window are used to translate coordinates between the embedder and
 * the offscreen window.
 *
 * For rendering an offscreen window onto its embedder, the contents of the
 * offscreen window are available as a pixmap, via
 * gdk_offscreen_window_get_pixmap().
 * </para>
 * </refsect2>
 */

114

115 116 117 118 119
/* Historically a GdkWindow always matches a platform native window,
 * be it a toplevel window or a child window. In this setup the
 * GdkWindow (and other GdkDrawables) were platform independent classes,
 * and the actual platform specific implementation was in a delegate
 * object availible as "impl" in the window object.
120
 *
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
 * With the addition of client side windows and offscreen windows this
 * changes a bit. The application-visible GdkWindow object behaves as
 * it did before, but not all such windows now have a corresponding native
 * window. Instead windows that are "client side" are emulated by the gdk
 * code such that clipping, drawing, moving, events etc work as expected.
 *
 * For GdkWindows that have a native window the "impl" object is the
 * same as before. However, for all client side windows the impl object
 * is shared with its parent (i.e. all client windows descendants of one
 * native window has the same impl.
 *
 * Additionally there is a new type of platform independent impl object,
 * GdkOffscreenWindow. All windows of type GDK_WINDOW_OFFSCREEN get an impl
 * of this type (while their children are generally GDK_WINDOW_CHILD virtual
 * windows). Such windows work by allocating a GdkPixmap as the backing store
 * for drawing operations, which is resized with the window.
 *
 * GdkWindows have a pointer to the "impl window" they are in, i.e.
 * the topmost GdkWindow which have the same "impl" value. This is stored
 * in impl_window, which is different from the window itself only for client
 * side windows.
 * All GdkWindows (native or not) track the position of the window in the parent
 * (x, y), the size of the window (width, height), the position of the window
 * with respect to the impl window (abs_x, abs_y). We also track the clip
 * region of the window wrt parent windows and siblings, in window-relative
 * coordinates with and without child windows included (clip_region,
 * clip_region_with_children).
 *
 * All toplevel windows are native windows, but also child windows can be
 * native (although not children of offscreens). We always listen to
 * a basic set of events (see get_native_event_mask) for these windows
 * so that we can emulate events for any client side children.
 *
 * For native windows we apply the calculated clip region as a window shape
 * so that eg. client side siblings that overlap the native child properly
 * draws over the native child window.
 *
 * In order to minimize flicker and for performance we use a couple of cacheing
 * tricks. First of all, every time we do a window to window copy area, for instance
 * when moving a client side window or when scrolling/moving a region in a window
 * we store this in outstanding_moves instead of applying immediately. We then
 * delay this move until we really need it (because something depends on being
 * able to read it), or until we're handing a redraw from an expose/invalidation
 * (actually we delay it past redraw, but before blitting the double buffer pixmap
 * to the window). This gives us two advantages. First of all it minimizes the time
 * from the window is moved to the exposes related to that move, secondly it allows
 * us to be smart about how to do the copy. We combine multiple moves into one (when
 * possible) and we don't actually do copies to anything that is or will be
 * invalidated and exposed anyway.
 *
 * Secondly, we use something called a "implicit paint" during repaint handling.
 * An implicit paint is similar to a regular paint for the paint stack, but it is
 * not put on the stack. Instead, it is set on the impl window, and later when
 * regular gdk_window_begin_paint_region()  happen on a window of this impl window
 * we reuse the pixmap from the implicit paint. During repaint we create and at the
 * end flush an implicit paint, which means we can collect all the paints on
 * multiple client side windows in the same backing store pixmap.
 *
 * All drawing to windows are wrapped with macros that set up the GC such that
 * the offsets and clip region is right for drawing to the paint object or
 * directly to the emulated window. It also automatically handles any flushing
 * needed when drawing directly to a window. Adding window/paint clipping is
 * done using _gdk_gc_add_drawable_clip which lets us efficiently add and then
 * remove a custom clip region.
185
 */
186

187
#define USE_BACKING_STORE	/* Appears to work on Win32, too, now. */
188

189 190 191
/* This adds a local value to the GdkVisibilityState enum */
#define GDK_VISIBILITY_NOT_VIEWABLE 3

192
enum {
193 194 195
  PICK_EMBEDDED_CHILD, /* only called if children are embedded */
  TO_EMBEDDER,
  FROM_EMBEDDER,
196 197 198
  LAST_SIGNAL
};

199 200 201 202 203
enum {
  PROP_0,
  PROP_CURSOR
};

204 205 206 207 208 209
typedef enum {
  CLEAR_BG_NONE,
  CLEAR_BG_WINCLEARED, /* Clear backgrounds except those that the window system clears */
  CLEAR_BG_ALL
} ClearBg;

210 211 212 213 214 215
struct _GdkWindowPaint
{
  GdkRegion *region;
  GdkPixmap *pixmap;
  gint x_offset;
  gint y_offset;
216
  cairo_surface_t *surface;
217
  guint uses_implicit : 1;
218
  guint flushed : 1;
219
  guint32 region_tag;
220
};
221

222
typedef struct {
223 224
  GdkRegion *dest_region; /* The destination region */
  int dx, dy; /* The amount that the source was moved to reach dest_region */
225 226 227
} GdkWindowRegionMove;


228
/* Global info */
229

230
static GdkGC *gdk_window_create_gc      (GdkDrawable     *drawable,
231 232
					 GdkGCValues     *values,
					 GdkGCValuesMask  mask);
233
static void   gdk_window_draw_rectangle (GdkDrawable     *drawable,
234 235 236 237 238 239
					 GdkGC           *gc,
					 gboolean         filled,
					 gint             x,
					 gint             y,
					 gint             width,
					 gint             height);
240
static void   gdk_window_draw_arc       (GdkDrawable     *drawable,
241 242 243 244 245 246 247 248
					 GdkGC           *gc,
					 gboolean         filled,
					 gint             x,
					 gint             y,
					 gint             width,
					 gint             height,
					 gint             angle1,
					 gint             angle2);
249
static void   gdk_window_draw_polygon   (GdkDrawable     *drawable,
250 251 252 253
					 GdkGC           *gc,
					 gboolean         filled,
					 GdkPoint        *points,
					 gint             npoints);
254
static void   gdk_window_draw_text      (GdkDrawable     *drawable,
255 256 257 258 259 260
					 GdkFont         *font,
					 GdkGC           *gc,
					 gint             x,
					 gint             y,
					 const gchar     *text,
					 gint             text_length);
261
static void   gdk_window_draw_text_wc   (GdkDrawable     *drawable,
262 263 264 265 266 267
					 GdkFont         *font,
					 GdkGC           *gc,
					 gint             x,
					 gint             y,
					 const GdkWChar  *text,
					 gint             text_length);
268
static void   gdk_window_draw_drawable  (GdkDrawable     *drawable,
269 270 271 272 273 274 275
					 GdkGC           *gc,
					 GdkPixmap       *src,
					 gint             xsrc,
					 gint             ysrc,
					 gint             xdest,
					 gint             ydest,
					 gint             width,
276 277
					 gint             height,
					 GdkDrawable     *original_src);
278
static void   gdk_window_draw_points    (GdkDrawable     *drawable,
279 280 281
					 GdkGC           *gc,
					 GdkPoint        *points,
					 gint             npoints);
282
static void   gdk_window_draw_segments  (GdkDrawable     *drawable,
283 284 285
					 GdkGC           *gc,
					 GdkSegment      *segs,
					 gint             nsegs);
286 287 288 289
static void   gdk_window_draw_lines     (GdkDrawable     *drawable,
					 GdkGC           *gc,
					 GdkPoint        *points,
					 gint             npoints);
290 291 292 293 294 295 296 297 298 299 300 301 302 303

static void gdk_window_draw_glyphs             (GdkDrawable      *drawable,
						GdkGC            *gc,
						PangoFont        *font,
						gint              x,
						gint              y,
						PangoGlyphString *glyphs);
static void gdk_window_draw_glyphs_transformed (GdkDrawable      *drawable,
						GdkGC            *gc,
						PangoMatrix      *matrix,
						PangoFont        *font,
						gint              x,
						gint              y,
						PangoGlyphString *glyphs);
304

305
static void   gdk_window_draw_image     (GdkDrawable     *drawable,
306 307 308 309 310 311 312 313
					 GdkGC           *gc,
					 GdkImage        *image,
					 gint             xsrc,
					 gint             ysrc,
					 gint             xdest,
					 gint             ydest,
					 gint             width,
					 gint             height);
314

315 316 317 318 319 320 321 322 323 324 325 326 327
static void gdk_window_draw_pixbuf (GdkDrawable     *drawable,
				    GdkGC           *gc,
				    GdkPixbuf       *pixbuf,
				    gint             src_x,
				    gint             src_y,
				    gint             dest_x,
				    gint             dest_y,
				    gint             width,
				    gint             height,
				    GdkRgbDither     dither,
				    gint             x_dither,
				    gint             y_dither);

328 329 330 331 332
static void gdk_window_draw_trapezoids (GdkDrawable   *drawable,
					GdkGC	      *gc,
					GdkTrapezoid  *trapezoids,
					gint           n_trapezoids);

333 334 335 336 337 338 339 340
static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
					   GdkImage    *image,
					   gint         src_x,
					   gint         src_y,
					   gint         dest_x,
					   gint         dest_y,
					   gint         width,
					   gint         height);
341

342
static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
343 344 345
static cairo_surface_t *gdk_window_create_cairo_surface (GdkDrawable *drawable,
							 int width,
							 int height);
346
static void             gdk_window_drop_cairo_surface (GdkWindowObject *private);
347 348
static void             gdk_window_set_cairo_clip    (GdkDrawable *drawable,
						      cairo_t *cr);
349

350
static void   gdk_window_real_get_size  (GdkDrawable     *drawable,
351 352
					 gint            *width,
					 gint            *height);
353 354 355

static GdkVisual*   gdk_window_real_get_visual   (GdkDrawable *drawable);
static gint         gdk_window_real_get_depth    (GdkDrawable *drawable);
356
static GdkScreen*   gdk_window_real_get_screen   (GdkDrawable *drawable);
357
static void         gdk_window_real_set_colormap (GdkDrawable *drawable,
358
						  GdkColormap *cmap);
359
static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
360

361
static GdkDrawable* gdk_window_get_source_drawable    (GdkDrawable *drawable);
362
static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
363 364 365 366 367 368 369 370
						       gint         x,
						       gint         y,
						       gint         width,
						       gint         height,
						       gint        *composite_x_offset,
						       gint        *composite_y_offset);
static GdkRegion*   gdk_window_get_clip_region        (GdkDrawable *drawable);
static GdkRegion*   gdk_window_get_visible_region     (GdkDrawable *drawable);
371

Owen Taylor's avatar
Owen Taylor committed
372
static void gdk_window_free_paint_stack (GdkWindow *window);
373

374 375
static void gdk_window_init       (GdkWindowObject      *window);
static void gdk_window_class_init (GdkWindowObjectClass *klass);
376
static void gdk_window_finalize   (GObject              *object);
377 378 379 380 381 382 383 384 385 386

static void gdk_window_set_property (GObject      *object,
                                     guint         prop_id,
                                     const GValue *value,
                                     GParamSpec   *pspec);
static void gdk_window_get_property (GObject      *object,
                                     guint         prop_id,
                                     GValue       *value,
                                     GParamSpec   *pspec);

387 388
static void gdk_window_clear_backing_region (GdkWindow *window,
					     GdkRegion *region);
389 390 391 392 393
static void gdk_window_redirect_free      (GdkWindowRedirect *redirect);
static void apply_redirect_to_children    (GdkWindowObject   *private,
					   GdkWindowRedirect *redirect);
static void remove_redirect_from_children (GdkWindowObject   *private,
					   GdkWindowRedirect *redirect);
394

395 396 397
static void recompute_visible_regions   (GdkWindowObject *private,
					 gboolean recalculate_siblings,
					 gboolean recalculate_children);
398
static void gdk_window_flush_outstanding_moves (GdkWindow *window);
399
static void gdk_window_flush_recursive  (GdkWindowObject *window);
400 401 402
static void do_move_region_bits_on_impl (GdkWindowObject *private,
					 GdkRegion *region, /* In impl window coords */
					 int dx, int dy);
403
static void gdk_window_invalidate_in_parent (GdkWindowObject *private);
404 405 406 407
static void move_native_children        (GdkWindowObject *private);
static void update_cursor               (GdkDisplay *display);
static void impl_window_add_update_area (GdkWindowObject *impl_window,
					 GdkRegion *region);
408
static void gdk_window_region_move_free (GdkWindowRegionMove *move);
409 410 411 412 413 414 415 416
static void gdk_window_invalidate_region_full (GdkWindow       *window,
					       const GdkRegion *region,
					       gboolean         invalidate_children,
					       ClearBg          clear_bg);
static void gdk_window_invalidate_rect_full (GdkWindow          *window,
					     const GdkRectangle *rect,
					     gboolean            invalidate_children,
					     ClearBg             clear_bg);
417

418 419
static guint signals[LAST_SIGNAL] = { 0 };

420 421
static gpointer parent_class = NULL;

422 423
static const cairo_user_data_key_t gdk_window_cairo_key;

424 425 426 427 428 429 430 431
static guint32
new_region_tag (void)
{
  static guint32 tag = 0;

  return ++tag;
}

432 433 434 435 436 437 438 439 440 441 442 443 444
GType
gdk_window_object_get_type (void)
{
  static GType object_type = 0;

  if (!object_type)
    object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
						 "GdkWindow",
						 sizeof (GdkWindowObjectClass),
						 (GClassInitFunc) gdk_window_class_init,
						 sizeof (GdkWindowObject),
						 (GInstanceInitFunc) gdk_window_init,
						 0);
445

446 447
  return object_type;
}
448

449 450 451 452 453 454 455
GType
_gdk_paintable_get_type (void)
{
  static GType paintable_type = 0;

  if (!paintable_type)
    {
456
      const GTypeInfo paintable_info =
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
      {
	sizeof (GdkPaintableIface),  /* class_size */
	NULL,                        /* base_init */
	NULL,                        /* base_finalize */
      };

      paintable_type = g_type_register_static (G_TYPE_INTERFACE,
					       g_intern_static_string ("GdkPaintable"),
					       &paintable_info, 0);

      g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
    }

  return paintable_type;
}

473
static void
474
gdk_window_init (GdkWindowObject *window)
475 476
{
  /* 0-initialization is good for all other fields. */
rhlabs's avatar
rhlabs committed
477

478
  window->window_type = GDK_WINDOW_CHILD;
Elliot Lee's avatar
Elliot Lee committed
479

480
  window->state = GDK_WINDOW_STATE_WITHDRAWN;
481 482 483
  window->width = 1;
  window->height = 1;
  window->toplevel_window_type = -1;
484 485 486 487 488
  /* starts hidden */
  window->effective_visibility = GDK_VISIBILITY_NOT_VIEWABLE;
  window->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
  /* Default to unobscured since some backends don't send visibility events */
  window->native_visibility = GDK_VISIBILITY_UNOBSCURED;
489
}
490

491
/* Stop and return on the first non-NULL parent */
492
static gboolean
493 494 495 496
accumulate_get_window (GSignalInvocationHint *ihint,
		       GValue		       *return_accu,
		       const GValue	       *handler_return,
		       gpointer               data)
497 498 499
{
  g_value_copy (handler_return, return_accu);
  /* Continue while returning NULL */
500
  return g_value_get_object (handler_return) == NULL;
501 502
}

503 504
static GQuark quark_pointer_window = 0;

505
static void
506
gdk_window_class_init (GdkWindowObjectClass *klass)
507 508 509
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
  GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
510

511 512
  parent_class = g_type_class_peek_parent (klass);

513
  object_class->finalize = gdk_window_finalize;
514 515
  object_class->set_property = gdk_window_set_property;
  object_class->get_property = gdk_window_get_property;
516 517 518 519 520 521 522

  drawable_class->create_gc = gdk_window_create_gc;
  drawable_class->draw_rectangle = gdk_window_draw_rectangle;
  drawable_class->draw_arc = gdk_window_draw_arc;
  drawable_class->draw_polygon = gdk_window_draw_polygon;
  drawable_class->draw_text = gdk_window_draw_text;
  drawable_class->draw_text_wc = gdk_window_draw_text_wc;
523
  drawable_class->draw_drawable_with_src = gdk_window_draw_drawable;
524 525 526 527
  drawable_class->draw_points = gdk_window_draw_points;
  drawable_class->draw_segments = gdk_window_draw_segments;
  drawable_class->draw_lines = gdk_window_draw_lines;
  drawable_class->draw_glyphs = gdk_window_draw_glyphs;
528
  drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
529
  drawable_class->draw_image = gdk_window_draw_image;
530
  drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
531
  drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
532
  drawable_class->get_depth = gdk_window_real_get_depth;
533
  drawable_class->get_screen = gdk_window_real_get_screen;
534 535 536 537
  drawable_class->get_size = gdk_window_real_get_size;
  drawable_class->set_colormap = gdk_window_real_set_colormap;
  drawable_class->get_colormap = gdk_window_real_get_colormap;
  drawable_class->get_visual = gdk_window_real_get_visual;
538
  drawable_class->_copy_to_image = gdk_window_copy_to_image;
539
  drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
540
  drawable_class->create_cairo_surface = gdk_window_create_cairo_surface;
541
  drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
542 543
  drawable_class->get_clip_region = gdk_window_get_clip_region;
  drawable_class->get_visible_region = gdk_window_get_visible_region;
544
  drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
545
  drawable_class->get_source_drawable = gdk_window_get_source_drawable;
546 547

  quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
548 549


550
  /* Properties */
551 552 553 554 555 556 557 558 559

  /**
   * GdkWindow:cursor:
   *
   * The mouse pointer for a #GdkWindow. See gdk_window_set_cursor() and
   * gdk_window_get_cursor() for details.
   *
   * Since: 2.18
   */
560 561
  g_object_class_install_property (object_class,
                                   PROP_CURSOR,
562 563 564 565 566
                                   g_param_spec_boxed ("cursor",
                                                       P_("Cursor"),
                                                       P_("Cursor"),
                                                       GDK_TYPE_CURSOR,
                                                       G_PARAM_READWRITE));
567

568 569 570 571 572 573 574 575 576
  /**
   * GdkWindow::pick-embedded-child:
   * @window: the window on which the signal is emitted
   * @x: x coordinate in the window
   * @y: y coordinate in the window
   *
   * The ::pick-embedded-child signal is emitted to find an embedded
   * child at the given position.
   *
Matthias Clasen's avatar
Matthias Clasen committed
577
   * Returns: the #GdkWindow of the embedded child at @x, @y, or %NULL
578 579 580
   *
   * Since: 2.18
   */
581 582
  signals[PICK_EMBEDDED_CHILD] =
    g_signal_new (g_intern_static_string ("pick-embedded-child"),
583 584 585
		  G_OBJECT_CLASS_TYPE (object_class),
		  G_SIGNAL_RUN_LAST,
		  0,
586
		  accumulate_get_window, NULL,
Matthias Clasen's avatar
Matthias Clasen committed
587
		  _gdk_marshal_OBJECT__DOUBLE_DOUBLE,
588 589 590 591
		  GDK_TYPE_WINDOW,
		  2,
		  G_TYPE_DOUBLE,
		  G_TYPE_DOUBLE);
592 593 594 595 596 597 598 599 600 601 602 603

  /**
   * GdkWindow::to-embedder:
   * @window: the offscreen window on which the signal is emitted
   * @offscreen-x: x coordinate in the offscreen window
   * @offscreen-y: y coordinate in the offscreen window
   * @embedder-x: return location for the x coordinate in the embedder window
   * @embedder-y: return location for the y coordinate in the embedder window
   *
   * The ::to-embedder signal is emitted to translate coordinates
   * in an offscreen window to its embedder.
   *
Matthias Clasen's avatar
Matthias Clasen committed
604 605
   * See also #GtkWindow::from-embedder.
   *
606 607
   * Since: 2.18
   */
608 609
  signals[TO_EMBEDDER] =
    g_signal_new (g_intern_static_string ("to-embedder"),
610 611 612 613
		  G_OBJECT_CLASS_TYPE (object_class),
		  G_SIGNAL_RUN_LAST,
		  0,
		  NULL, NULL,
Matthias Clasen's avatar
Matthias Clasen committed
614
		  _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
615 616 617 618 619 620
		  G_TYPE_NONE,
		  4,
		  G_TYPE_DOUBLE,
		  G_TYPE_DOUBLE,
		  G_TYPE_POINTER,
		  G_TYPE_POINTER);
621 622 623 624 625 626 627 628 629 630 631 632

  /**
   * GdkWindow::from-embedder:
   * @window: the offscreen window on which the signal is emitted
   * @embedder-x: x coordinate in the embedder window
   * @embedder-y: y coordinate in the embedder window
   * @offscreen-x: return location for the x coordinate in the offscreen window
   * @offscreen-y: return location for the y coordinate in the offscreen window
   *
   * The ::from-embedder signal is emitted to translate coordinates
   * in the embedder of an offscreen window to the offscreen window.
   *
Matthias Clasen's avatar
Matthias Clasen committed
633 634
   * See also #GtkWindow::to-embedder.
   *
635 636
   * Since: 2.18
   */
637 638
  signals[FROM_EMBEDDER] =
    g_signal_new (g_intern_static_string ("from-embedder"),
639 640 641 642
		  G_OBJECT_CLASS_TYPE (object_class),
		  G_SIGNAL_RUN_LAST,
		  0,
		  NULL, NULL,
Matthias Clasen's avatar
Matthias Clasen committed
643
		  _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
644 645 646 647 648 649
		  G_TYPE_NONE,
		  4,
		  G_TYPE_DOUBLE,
		  G_TYPE_DOUBLE,
		  G_TYPE_POINTER,
		  G_TYPE_POINTER);
650
}
651

652 653 654 655 656
static void
gdk_window_finalize (GObject *object)
{
  GdkWindow *window = GDK_WINDOW (object);
  GdkWindowObject *obj = (GdkWindowObject *) object;
657

658 659 660 661 662 663 664 665 666 667 668 669 670
  if (!GDK_WINDOW_DESTROYED (window))
    {
      if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
	{
	  g_warning ("losing last reference to undestroyed window\n");
	  _gdk_window_destroy (window, FALSE);
	}
      else
	/* We use TRUE here, to keep us from actually calling
	 * XDestroyWindow() on the window
	 */
	_gdk_window_destroy (window, TRUE);
    }
671

672 673 674 675 676 677
  if (obj->impl)
    {
      g_object_unref (obj->impl);
      obj->impl = NULL;
    }

678 679 680 681 682
  if (obj->impl_window != obj)
    {
      g_object_unref (obj->impl_window);
      obj->impl_window = NULL;
    }
683

684 685 686 687 688 689
  if (obj->shape)
    gdk_region_destroy (obj->shape);

  if (obj->input_shape)
    gdk_region_destroy (obj->input_shape);

690 691 692
  if (obj->cursor)
    gdk_cursor_unref (obj->cursor);

693
  G_OBJECT_CLASS (parent_class)->finalize (object);
Elliot Lee's avatar
Elliot Lee committed
694 695
}

696 697 698 699 700 701 702 703 704 705 706
static void
gdk_window_set_property (GObject      *object,
                         guint         prop_id,
                         const GValue *value,
                         GParamSpec   *pspec)
{
  GdkWindow *window = (GdkWindow *)object;

  switch (prop_id)
    {
    case PROP_CURSOR:
707
      gdk_window_set_cursor (window, g_value_get_boxed (value));
708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static void
gdk_window_get_property (GObject    *object,
                         guint       prop_id,
                         GValue     *value,
                         GParamSpec *pspec)
{
  GdkWindow *window = (GdkWindow *) object;

  switch (prop_id)
    {
    case PROP_CURSOR:
727
      g_value_set_boxed (value, gdk_window_get_cursor (window));
728 729 730 731 732 733 734 735
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

736 737 738
static gboolean
gdk_window_is_offscreen (GdkWindowObject *window)
{
739
  return window->window_type == GDK_WINDOW_OFFSCREEN;
740 741 742 743 744
}

static GdkWindowObject *
gdk_window_get_impl_window (GdkWindowObject *window)
{
745
  return window->impl_window;
746 747 748 749 750 751 752 753 754 755 756
}

GdkWindow *
_gdk_window_get_impl_window (GdkWindow *window)
{
  return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
}

static gboolean
gdk_window_has_impl (GdkWindowObject *window)
{
757
  return window->impl_window == window;
758 759
}

760 761 762 763 764 765 766 767
static gboolean
gdk_window_is_toplevel (GdkWindowObject *window)
{
  return
    window->parent == NULL ||
    window->parent->window_type == GDK_WINDOW_ROOT;
}

768 769 770 771 772 773 774 775 776
gboolean
_gdk_window_has_impl (GdkWindow *window)
{
  return gdk_window_has_impl ((GdkWindowObject *)window);
}

static gboolean
gdk_window_has_no_impl (GdkWindowObject *window)
{
777
  return window->impl_window != window;
778 779 780 781 782
}

static void
remove_child_area (GdkWindowObject *private,
		   GdkWindowObject *until,
783
		   gboolean for_input,
784 785 786 787 788 789
		   GdkRegion *region)
{
  GdkWindowObject *child;
  GdkRegion *child_region;
  GdkRectangle r;
  GList *l;
790
  GdkRegion *shape;
791

792 793 794 795 796 797
  for (l = private->children; l; l = l->next)
    {
      child = l->data;

      if (child == until)
	break;
798

799 800 801 802 803
      /* If region is empty already, no need to do
	 anything potentially costly */
      if (gdk_region_empty (region))
	break;

804
      if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
805 806 807 808 809 810 811 812 813 814 815
	continue;

      /* Ignore offscreen children, as they don't draw in their parent and
       * don't take part in the clipping */
      if (gdk_window_is_offscreen (child))
	continue;

      r.x = child->x;
      r.y = child->y;
      r.width = child->width;
      r.height = child->height;
816

817 818 819 820
      /* Bail early if child totally outside region */
      if (gdk_region_rect_in (region, &r) == GDK_OVERLAP_RECTANGLE_OUT)
	continue;

821
      child_region = gdk_region_rectangle (&r);
822

823
      if (child->shape)
824 825 826 827 828 829
	{
	  /* Adjust shape region to parent window coords */
	  gdk_region_offset (child->shape, child->x, child->y);
	  gdk_region_intersect (child_region, child->shape);
	  gdk_region_offset (child->shape, -child->x, -child->y);
	}
830 831 832 833 834 835 836 837 838
      else if (private->window_type == GDK_WINDOW_FOREIGN)
	{
	  shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
	  if (shape)
	    {
	      gdk_region_intersect (child_region, shape);
	      gdk_region_destroy (shape);
	    }
	}
839 840 841 842 843 844 845 846 847 848 849 850 851 852 853

      if (for_input)
	{
	  if (child->input_shape)
	    gdk_region_intersect (child_region, child->input_shape);
	  else if (private->window_type == GDK_WINDOW_FOREIGN)
	    {
	      shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child);
	      if (shape)
		{
		  gdk_region_intersect (child_region, shape);
		  gdk_region_destroy (shape);
		}
	    }
	}
854

855 856
      gdk_region_subtract (region, child_region);
      gdk_region_destroy (child_region);
857

858 859 860
    }
}

861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918
static GdkVisibilityState
effective_visibility (GdkWindowObject *private)
{
  GdkVisibilityState native;

  if (!gdk_window_is_viewable ((GdkWindow *)private))
    return GDK_VISIBILITY_NOT_VIEWABLE;

  native = private->impl_window->native_visibility;

  if (native == GDK_VISIBILITY_FULLY_OBSCURED ||
      private->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
    return GDK_VISIBILITY_FULLY_OBSCURED;
  else if (native == GDK_VISIBILITY_UNOBSCURED)
    return private->visibility;
  else /* native PARTIAL, private partial or unobscured  */
    return GDK_VISIBILITY_PARTIAL;
}

static void
gdk_window_update_visibility (GdkWindowObject *private)
{
  GdkVisibilityState new_visibility;
  GdkEvent *event;

  new_visibility = effective_visibility (private);

  if (new_visibility != private->effective_visibility)
    {
      private->effective_visibility = new_visibility;

      if (new_visibility != GDK_VISIBILITY_NOT_VIEWABLE &&
	  private->event_mask & GDK_VISIBILITY_NOTIFY)
	{
	  event = _gdk_make_event ((GdkWindow *)private, GDK_VISIBILITY_NOTIFY,
				   NULL, FALSE);
	  event->visibility.state = new_visibility;
	}
    }
}

static void
gdk_window_update_visibility_recursively (GdkWindowObject *private,
					  GdkWindowObject *only_for_impl)
{
  GdkWindowObject *child;
  GList *l;

  gdk_window_update_visibility (private);
  for (l = private->children; l != NULL; l = l->next)
    {
      child = l->data;
      if ((only_for_impl == NULL) ||
	  (only_for_impl == child->impl_window))
	gdk_window_update_visibility_recursively (child, only_for_impl);
    }
}

919 920 921 922 923 924
static gboolean
should_apply_clip_as_shape (GdkWindowObject *private)
{
  return
    gdk_window_has_impl (private) &&
    /* Not for offscreens */
925
    !gdk_window_is_offscreen (private) &&
926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973
    /* or for toplevels */
    !gdk_window_is_toplevel (private) &&
    /* or for foreign windows */
    private->window_type != GDK_WINDOW_FOREIGN &&
    /* or for the root window */
    private->window_type != GDK_WINDOW_ROOT;
}

static void
apply_shape (GdkWindowObject *private,
	     GdkRegion *region)
{
  GdkWindowImplIface *impl_iface;

  /* We trash whether we applied a shape so that
     we can avoid unsetting it many times, which
     could happen in e.g. apply_clip_as_shape as
     windows get resized */
  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
  if (region)
    impl_iface->shape_combine_region ((GdkWindow *)private,
				      region, 0, 0);
  else if (private->applied_shape)
    impl_iface->shape_combine_region ((GdkWindow *)private,
				      NULL, 0, 0);

  private->applied_shape = region != NULL;
}

static void
apply_clip_as_shape (GdkWindowObject *private)
{
  GdkRectangle r;

  r.x = r.y = 0;
  r.width = private->width;
  r.height = private->height;

  /* We only apply the clip region if would differ
     from the actual clip region implied by the size
     of the window. This is to avoid unneccessarily
     adding meaningless shapes to all native subwindows */
  if (!gdk_region_rect_equal (private->clip_region, &r))
    apply_shape (private, private->clip_region);
  else
    apply_shape (private, NULL);
}

974 975 976 977 978 979 980 981 982
static void
recompute_visible_regions_internal (GdkWindowObject *private,
				    gboolean recalculate_clip,
				    gboolean recalculate_siblings,
				    gboolean recalculate_children)
{
  GdkRectangle r;
  GList *l;
  GdkWindowObject *child;
983
  GdkRegion *new_clip, *old_clip_region_with_children;
984 985 986 987 988 989
  gboolean clip_region_changed;
  gboolean abs_pos_changed;
  int old_abs_x, old_abs_y;

  old_abs_x = private->abs_x;
  old_abs_y = private->abs_y;
990

991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013
  /* Update absolute position */
  if (gdk_window_has_impl (private))
    {
      /* Native window starts here */
      private->abs_x = 0;
      private->abs_y = 0;
    }
  else
    {
      private->abs_x = private->parent->abs_x + private->x;
      private->abs_y = private->parent->abs_y + private->y;
    }

  abs_pos_changed =
    private->abs_x != old_abs_x ||
    private->abs_y != old_abs_y;

  /* Update clip region based on:
   * parent clip
   * window size
   * siblings in parents above window
   */
  clip_region_changed = FALSE;
1014
  if (recalculate_clip)
1015
    {
1016
      if (private->viewable)
1017
	{
1018 1019 1020 1021 1022 1023 1024
	  /* Calculate visible region (sans children) in parent window coords */
	  r.x = private->x;
	  r.y = private->y;
	  r.width = private->width;
	  r.height = private->height;
	  new_clip = gdk_region_rectangle (&r);

1025
	  if (!gdk_window_is_toplevel (private))
1026 1027
	    {
	      gdk_region_intersect (new_clip, private->parent->clip_region);
1028

1029 1030 1031 1032 1033 1034 1035 1036
	      /* Remove all overlapping children from parent.
	       * Unless we're all native, because then we don't need to take
	       * siblings into account since X does that clipping for us.
	       * This makes things like SWT that modify the raw X stacking
	       * order without GDKs knowledge work.
	       */
	      if (!_gdk_native_windows)
		remove_child_area (private->parent, private, FALSE, new_clip);
1037
	    }
1038

1039 1040
	  /* Convert from parent coords to window coords */
	  gdk_region_offset (new_clip, -private->x, -private->y);
1041

1042 1043 1044 1045 1046
	  if (private->shape)
	    gdk_region_intersect (new_clip, private->shape);
	}
      else
	new_clip = gdk_region_new ();
1047

1048 1049 1050
      if (private->clip_region == NULL ||
	  !gdk_region_equal (private->clip_region, new_clip))
	clip_region_changed = TRUE;
1051

1052 1053 1054 1055
      if (private->clip_region)
	gdk_region_destroy (private->clip_region);
      private->clip_region = new_clip;

1056
      old_clip_region_with_children = private->clip_region_with_children;
1057
      private->clip_region_with_children = gdk_region_copy (private->clip_region);
1058
      if (private->window_type != GDK_WINDOW_ROOT)
1059
	remove_child_area (private, NULL, FALSE, private->clip_region_with_children);
1060 1061 1062 1063 1064 1065 1066

      if (clip_region_changed ||
	  !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
	  private->clip_tag = new_region_tag ();

      if (old_clip_region_with_children)
	gdk_region_destroy (old_clip_region_with_children);
1067 1068
    }

1069 1070 1071 1072 1073 1074 1075
  if (clip_region_changed)
    {
      GdkVisibilityState visibility;
      gboolean fully_visible;

      if (gdk_region_empty (private->clip_region))
	visibility = GDK_VISIBILITY_FULLY_OBSCURED;
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
      else
        {
          if (private->shape)
            {
	      fully_visible = gdk_region_equal (private->clip_region,
	                                        private->shape);
            }
          else
            {
	      r.x = 0;
	      r.y = 0;
	      r.width = private->width;
	      r.height = private->height;
	      fully_visible = gdk_region_rect_equal (private->clip_region, &r);
	    }

	  if (fully_visible)
	    visibility = GDK_VISIBILITY_UNOBSCURED;
	  else
	    visibility = GDK_VISIBILITY_PARTIAL;
1096 1097 1098 1099 1100 1101 1102 1103 1104
	}

      if (private->visibility != visibility)
	{
	  private->visibility = visibility;
	  gdk_window_update_visibility (private);
	}
    }

1105 1106
  /* Update all children, recursively (except for root, where children are not exact). */
  if ((abs_pos_changed || clip_region_changed || recalculate_children) &&
1107
      private->window_type != GDK_WINDOW_ROOT)
1108 1109 1110 1111 1112 1113 1114 1115
    {
      for (l = private->children; l; l = l->next)
	{
	  child = l->data;
	  /* Only recalculate clip if the the clip region changed, otherwise
	   * there is no way the child clip region could change (its has not e.g. moved)
	   * Except if recalculate_children is set to force child updates
	   */
1116 1117 1118
	  recompute_visible_regions_internal (child,
					      recalculate_clip && (clip_region_changed || recalculate_children),
					      FALSE, FALSE);
1119 1120 1121 1122
	}
    }

  if (clip_region_changed &&
1123 1124
      should_apply_clip_as_shape (private))
    apply_clip_as_shape (private);
1125

1126
  if (recalculate_siblings &&
1127
      !gdk_window_is_toplevel (private))
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154
    {
      /* If we moved a child window in parent or changed the stacking order, then we
       * need to recompute the visible area of all the other children in the parent
       */
      for (l = private->parent->children; l; l = l->next)
	{
	  child = l->data;

	  if (child != private)
	    recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
	}

      /* We also need to recompute the _with_children clip for the parent */
      recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
    }

  if (private->cairo_surface)
    {
      int width, height;

      /* It would be nice if we had some cairo support here so we
	 could set the clip rect on the cairo surface */
      width = private->abs_x + private->width;
      height = private->abs_y + private->height;

      _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
					     width, height);
1155
      cairo_surface_set_device_offset (private->cairo_surface,
1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
				       private->abs_x,
				       private->abs_y);
    }
}

/* Call this when private has changed in one or more of these ways:
 *  size changed
 *  window moved
 *  new window added
 *  stacking order of window changed
 *  child deleted
 *
 * It will recalculate abs_x/y and the clip regions
 *
 * Unless the window didn't change stacking order or size/pos, pass in TRUE
 * for recalculate_siblings. (Mostly used internally for the recursion)
1172
 *
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192
 * If a child window was removed (and you can't use that child for
 * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
 */
static void
recompute_visible_regions (GdkWindowObject *private,
			   gboolean recalculate_siblings,
			   gboolean recalculate_children)
{
  recompute_visible_regions_internal (private,
				      TRUE,
				      recalculate_siblings,
				      recalculate_children);
}

void
_gdk_window_update_size (GdkWindow *window)
{
  recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
}

1193 1194 1195 1196 1197 1198 1199
/* Find the native window that would be just above "child"
 * in the native stacking order if "child" was a native window
 * (it doesn't have to be native). If there is no such native
 * window inside this native parent then NULL is returned.
 * If child is NULL, find lowest native window in parent.
 */
static GdkWindowObject *
1200 1201
find_native_sibling_above_helper (GdkWindowObject *parent,
				  GdkWindowObject *child)
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217
{
  GdkWindowObject *w;
  GList *l;

  if (child)
    {
      l = g_list_find (parent->children, child);
      g_assert (l != NULL); /* Better be a child of its parent... */
      l = l->prev; /* Start looking at the one above the child */
    }
  else
    l = g_list_last (parent->children);

  for (; l != NULL; l = l->prev)
    {
      w = l->data;
1218

1219 1220
      if (gdk_window_has_impl (w))
	return w;
1221 1222 1223

      g_assert (parent != w);
      w = find_native_sibling_above_helper (w, NULL);
1224 1225 1226 1227
      if (w)
	return w;
    }

1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241
  return NULL;
}


static GdkWindowObject *
find_native_sibling_above (GdkWindowObject *parent,
			   GdkWindowObject *child)
{
  GdkWindowObject *w;

  w = find_native_sibling_above_helper (parent, child);
  if (w)
    return w;

1242 1243 1244 1245 1246 1247
  if (gdk_window_has_impl (parent))
    return NULL;
  else
    return find_native_sibling_above (parent->parent, parent);
}

1248 1249 1250
static GdkEventMask
get_native_event_mask (GdkWindowObject *private)
{
1251 1252 1253 1254 1255
  if (_gdk_native_windows ||
      private->window_type == GDK_WINDOW_ROOT ||
      private->window_type == GDK_WINDOW_FOREIGN)
    return private->event_mask;
  else
1256
    {
1257 1258 1259 1260
      GdkEventMask mask;

      /* Do whatever the app asks to, since the app
       * may be asking for weird things for native windows,
1261 1262 1263 1264 1265 1266
       * but don't use motion hints as that may affect non-native
       * child windows that don't want it. Also, we need to
       * set all the app-specified masks since they will be picked
       * up by any implicit grabs (i.e. if they were not set as
       * native we would not get the events we need). */
      mask = private->event_mask & ~GDK_POINTER_MOTION_HINT_MASK;
1267 1268 1269 1270

      /* We need thse for all native windows so we can
	 emulate events on children: */
      mask |=
1271
	GDK_EXPOSURE_MASK |
1272
	GDK_VISIBILITY_NOTIFY_MASK |
1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284
	GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK;

      /* Additionally we select for pointer and button events
       * for toplevels as we need to get these to emulate
       * them for non-native subwindows. Even though we don't
       * select on them for all native windows we will get them
       * as the events are propagated out to the first window
       * that select for them.
       * Not selecting for button press on all windows is an
       * important thing, because in X only one client can do
       * so, and we don't want to unexpectedly prevent another
       * client from doing it.
1285 1286 1287 1288 1289 1290
       *
       * We also need to do the same if the app selects for button presses
       * because then we will get implicit grabs for this window, and the
       * event mask used for that grab is based on the rest of the mask
       * for the window, but we might need more events than this window
       * lists due to some non-native child window.
1291
       */
1292 1293
      if (gdk_window_is_toplevel (private) ||
	  mask & GDK_BUTTON_PRESS_MASK)
1294 1295 1296 1297 1298 1299
	mask |=
	  GDK_POINTER_MOTION_MASK |
	  GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
	  GDK_SCROLL_MASK;

      return mask;
1300
    }
1301 1302
}

1303 1304 1305 1306 1307 1308 1309 1310 1311 1312
static GdkEventMask
get_native_grab_event_mask (GdkEventMask grab_mask)
{
  /* Similar to the above but for pointer events only */
  return
    GDK_POINTER_MOTION_MASK |
    GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
    GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
    GDK_SCROLL_MASK |
    (grab_mask &
1313
     ~GDK_POINTER_MOTION_HINT_MASK);
1314 1315
}

1316
/* Puts the native window in the right order wrt the other native windows
1317 1318 1319 1320
 * in the hierarchy, given the position it has in the client side data.
 * This is useful if some operation changed the stacking order.
 * This calls assumes the native window is now topmost in its native parent.
 */
1321 1322 1323 1324 1325
static void
sync_native_window_stack_position (GdkWindow *window)
{
  GdkWindowObject *above;
  GdkWindowObject *private;
1326
  GdkWindowImplIface *impl_iface;
1327 1328 1329
  GList listhead = {0};

  private = (GdkWindowObject *) window;
1330
  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1331 1332 1333 1334 1335

  above = find_native_sibling_above (private->parent, private);
  if (above)
    {
      listhead.data = window;
1336 1337
      impl_iface->restack_under ((GdkWindow *)above,
				 &listhead);
1338 1339 1340
    }
}

1341 1342
/**
 * gdk_window_new:
1343
 * @parent: (allow-none): a #GdkWindow, or %NULL to create the window as a child of
1344 1345 1346
 *   the default root window for the default display.
 * @attributes: attributes of the new window
 * @attributes_mask: mask indicating which fields in @attributes are valid
1347
 *
1348 1349 1350 1351
 * Creates a new #GdkWindow using the attributes from
 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
 * more details.  Note: to use this on displays other than the default
 * display, @parent must be specified.
1352
 *
1353
 * Return value: (transfer none): the new #GdkWindow
1354 1355 1356 1357 1358 1359 1360
 **/
GdkWindow*
gdk_window_new (GdkWindow     *parent,
		GdkWindowAttr *attributes,
		gint           attributes_mask)
{
  GdkWindow *window;
1361 1362 1363
  GdkWindowObject *private;
  GdkScreen *screen;
  GdkVisual *visual;
1364
  int x, y;
1365 1366
  gboolean native;
  GdkEventMask event_mask;
1367
  GdkWindow *real_parent;
1368

1369
  g_return_val_if_fail (attributes != NULL, NULL);
1370

1371 1372 1373 1374
  if (!parent)
    {
      GDK_NOTE (MULTIHEAD,
		g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
1375

1376 1377 1378 1379 1380 1381 1382
      screen = gdk_screen_get_default ();
      parent = gdk_screen_get_root_window (screen);
    }
  else
    screen = gdk_drawable_get_screen (parent);

  g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
1383

1384
  if (GDK_WINDOW_DESTROYED (parent))
1385 1386 1387 1388
    {
      g_warning ("gdk_window_new(): parent is destroyed\n");
      return NULL;
    }
1389

1390 1391 1392 1393 1394 1395 1396
  if (attributes->window_type == GDK_WINDOW_OFFSCREEN &&
      _gdk_native_windows)
    {
      g_warning ("Offscreen windows not supported with native-windows gdk");
      return NULL;
    }

1397 1398
  window = g_object_new (GDK_TYPE_WINDOW, NULL);
  private = (GdkWindowObject *) window;
1399

1400 1401 1402
  /* Windows with a foreign parent are treated as if they are children
   * of the root window, except for actual creation.
   */
1403
  real_parent = parent;
1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415
  if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
    parent = gdk_screen_get_root_window (screen);

  private->parent = (GdkWindowObject *)parent;

  private->accept_focus = TRUE;
  private->focus_on_map = TRUE;

  if (attributes_mask & GDK_WA_X)
    x = attributes->x;
  else
    x = 0;
1416

1417 1418 1419 1420
  if (attributes_mask & GDK_WA_Y)
    y = attributes->y;
  else
    y = 0;
1421

1422 1423 1424 1425 1426 1427
  private->x = x;
  private->y = y;
  private->width = (attributes->width > 1) ? (attributes->width) : (1);
  private->height = (attributes->height > 1) ? (attributes->height) : (1);

#ifdef GDK_WINDOWING_X11
1428
  /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
1429 1430 1431
   * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
   */
  if (attributes->wclass == GDK_INPUT_ONLY &&
1432
      private->parent->window_type == GDK_WINDOW_ROOT &&
1433 1434 1435 1436 1437 1438
      !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
    {
      g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
      attributes->wclass = GDK_INPUT_OUTPUT;
    }
#endif
1439

1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459
  if (attributes->wclass == GDK_INPUT_ONLY)
    {
      /* Backwards compatiblity - we've always ignored
       * attributes->window_type for input-only windows
       * before
       */
      if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
	private->window_type = GDK_WINDOW_TEMP;
      else
	private->window_type = GDK_WINDOW_CHILD;
    }
  else
    private->window_type = attributes->window_type;

  /* Sanity checks */
  switch (private->window_type)
    {
    case GDK_WINDOW_TOPLEVEL:
    case GDK_WINDOW_DIALOG:
    case GDK_WINDOW_TEMP:
1460
    case GDK_WINDOW_OFFSCREEN:
1461 1462 1463 1464
      if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
	g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
		   "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
    case GDK_WINDOW_CHILD:
1465
      break;
1466 1467 1468 1469 1470
      break;
    default:
      g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
      return NULL;
    }
1471

1472 1473 1474 1475 1476 1477 1478 1479 1480 1481
  if (attributes_mask & GDK_WA_VISUAL)
    visual = attributes->visual;
  else
    visual = gdk_screen_get_system_visual (screen);

  private->event_mask = attributes->event_mask;

  if (attributes->wclass == GDK_INPUT_OUTPUT)
    {
      private->input_only = FALSE;
1482
      private->depth = visual->depth;
1483

Alexander Larsson's avatar
Alexander Larsson committed
1484
      private->bg_color.pixel = 0; /* TODO: BlackPixel (xdisplay, screen_x11->screen_num); */
1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497
      private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;

      private->bg_pixmap = NULL;
    }
  else
    {
      private->depth = 0;
      private->input_only = TRUE;
    }

  if (private->parent)
    private->parent->children = g_list_prepend (private->parent->children, window);

1498
  native = _gdk_native_windows; /* Default */
1499
  if (private->parent->window_type == GDK_WINDOW_ROOT)
1500
    native = TRUE; /* Always use native windows for toplevels */
1501 1502 1503 1504 1505 1506
  else if (!private->input_only &&
	   ((attributes_mask & GDK_WA_COLORMAP &&
	     attributes->colormap != gdk_drawable_get_colormap ((GdkDrawable *)private->parent)) ||
	    (attributes_mask & GDK_WA_VISUAL &&
	     attributes->visual != gdk_drawable_get_visual ((GdkDrawable *)private->parent))))
    native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
1507

1508
  if (gdk_window_is_offscreen (private))
1509 1510
    {
      _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
1511
      private->impl_window = private;
1512 1513 1514
    }
  else if (native)
    {
1515
      event_mask = get_native_event_mask (private);
1516

1517
      /* Create the impl */
1518
      _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
1519
      private->impl_window = private;
1520 1521 1522

      /* This will put the native window topmost in the native parent, which may
       * be wrong wrt other native windows in the non-native hierarchy, so restack */
1523 1524
      if (!_gdk_window_has_impl (real_parent))
	sync_native_window_stack_position (window);
1525 1526
    }
  else
1527
    {
1528 1529
      private->impl_window = g_object_ref (private->parent->impl_window);
      private->impl = g_object_ref (private->impl_window->impl);
1530
    }
1531 1532

  recompute_visible_regions (private, TRUE, FALSE);
1533

1534
  if (private->parent->window_type != GDK_WINDOW_ROOT)
1535 1536 1537 1538
    {
      /* Inherit redirection from parent */
      private->redirect = private->parent->redirect;
    }
1539

1540 1541 1542 1543
  gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
				  (attributes->cursor) :
				  NULL));

1544 1545 1546
  return window;
}

1547 1548
static gboolean
is_parent_of (GdkWindow *parent,
1549
	      GdkWindow *child)
1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566
{
  GdkWindow *w;

  w = child;
  while (w != NULL)
    {
      if (w == parent)
	return TRUE;

      w = gdk_window_get_parent (w);
    }

  return FALSE;
}

static void
change_impl (GdkWindowObject *private,
1567
	     GdkWindowObject *impl_window,
1568 1569 1570 1571 1572
	     GdkDrawable *new)
{
  GList *l;
  GdkWindowObject *child;
  GdkDrawable *old_impl;
1573
  GdkWindowObject *old_impl_window;
1574 1575

  old_impl = private->impl;
1576 1577 1578 1579 1580
  old_impl_window = private->impl_window;
  if (private != impl_window)
    private->impl_window = g_object_ref (impl_window);
  else
    private->impl_window = private;
1581
  private->impl = g_object_ref (new);
1582 1583
  if (old_impl_window != private)
    g_object_unref (old_impl_window);
1584
  g_object_unref (old_impl);
1585

1586 1587 1588 1589 1590
  for (l = private->children; l != NULL; l = l->next)
    {
      child = l->data;

      if (child->impl == old_impl)
1591
	change_impl (child, impl_window, new);
1592 1593 1594 1595 1596 1597 1598 1599 1600
    }
}

static void
reparent_to_impl (GdkWindowObject *private)
{
  GList *l;
  GdkWindowObject *child;
  gboolean show;
1601 1602 1603
  GdkWindowImplIface *impl_iface;

  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1604 1605 1606 1607 1608 1609 1610 1611 1612

  /* Enumerate in reverse order so we get the right order for the native
     windows (first in childrens list is topmost, and reparent places on top) */
  for (l = g_list_last (private->children); l != NULL; l = l->prev)
    {
      child = l->data;

      if (child->impl == private->impl)
	reparent_to_impl (child);
1613 1614
      else
	{
1615 1616 1617
	  show = impl_iface->reparent ((GdkWindow *)child,
				       (GdkWindow *)private,
				       child->x, child->y);
1618 1619 1620 1621 1622 1623
	  if (show)
	    gdk_window_show_unraised ((GdkWindow *)child);
	}
    }
}

1624

1625 1626 1627 1628 1629 1630 1631 1632 1633
/**
 * gdk_window_reparent:
 * @window: a #GdkWindow
 * @new_parent: new parent to move @window into
 * @x: X location inside the new parent
 * @y: Y location inside the new parent
 *
 * Reparents @window into the given @new_parent. The window being
 * reparented will be unmapped as a side effect.
1634
 *
1635 1636 1637 1638 1639 1640 1641 1642
 **/
void
gdk_window_reparent (GdkWindow *window,
		     GdkWindow *new_parent,
		     gint       x,
		     gint       y)
{
  GdkWindowObject *private;
1643 1644
  GdkWindowObject *new_parent_private;
  GdkWindowObject *old_parent;
1645
  GdkScreen *screen;
1646
  gboolean show, was_mapped, applied_clip_as_shape;
1647
  gboolean do_reparent_to_impl;
1648
  GdkEventMask old_native_event_mask;
1649
  GdkWindowImplIface *impl_iface;
1650

1651 1652 1653 1654 1655 1656
  g_return_if_fail (GDK_IS_WINDOW (window));
  g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
  g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);

  if (GDK_WINDOW_DESTROYED (window) ||
      (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
1657
    return;
1658

1659
  screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1660
  if (!new_parent)
1661
    new_parent = gdk_screen_get_root_window (screen);
1662

1663
  private = (GdkWindowObject *) window;
1664 1665 1666 1667 1668 1669 1670 1671 1672
  new_parent_private = (GdkWindowObject *)new_parent;

  /* No input-output children of input-only windows */
  if (new_parent_private->input_only && !private->input_only)
    return;

  /* Don't create loops in hierarchy */
  if (is_parent_of (window, new_parent))
    return;
1673

1674 1675 1676
  /* This might be wrong in the new parent, e.g. for non-native surfaces.
     To make sure we're ok, just wipe it. */
  gdk_window_drop_cairo_surface (private);
1677

1678
  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1679
  old_parent = private->parent;
1680 1681 1682 1683 1684 1685 1686 1687

  /* Break up redirection if inherited */
  if (private->redirect && private->redirect->redirected != private)
    {
      remove_redirect_from_children (private, private->redirect);
      private->redirect = NULL;
    }

1688 1689
  was_mapped = GDK_WINDOW_IS_MAPPED (window);
  show = FALSE;
1690 1691 1692 1693

  /* Reparenting to toplevel. Ensure we have a native window so this can work */
  if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
      new_parent_private->window_type == GDK_WINDOW_FOREIGN)
1694
    gdk_window_ensure_native (window);
1695

1696 1697
  applied_clip_as_shape = should_apply_clip_as_shape (private);

1698
  old_native_event_mask = 0;
1699
  do_reparent_to_impl = FALSE;