gdkwindow.c 82.8 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4
/* GDK - The GIMP Drawing Kit
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10 11
 * 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
12
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15 16 17
 * 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
18
 */
19

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

27
#include <config.h>
Owen Taylor's avatar
Started  
Owen Taylor committed
28
#include "gdkwindow.h"
29 30 31
#include "gdkinternals.h"
#include "gdk.h"		/* For gdk_rectangle_union() */
#include "gdkpixmap.h"
Havoc Pennington's avatar
Havoc Pennington committed
32 33
#include "gdkdrawable.h"
#include "gdkpixmap.h"
34
#include "gdkscreen.h"
35
#include "gdkalias.h"
36

Tor Lillqvist's avatar
Tor Lillqvist committed
37
#define USE_BACKING_STORE	/* Appears to work on Win32, too, now. */
38

39 40 41 42 43 44 45 46
typedef struct _GdkWindowPaint GdkWindowPaint;

struct _GdkWindowPaint
{
  GdkRegion *region;
  GdkPixmap *pixmap;
  gint x_offset;
  gint y_offset;
47
  cairo_surface_t *surface;
48
};
49

50 51 52
static GdkGC *gdk_window_create_gc      (GdkDrawable     *drawable,
                                         GdkGCValues     *values,
                                         GdkGCValuesMask  mask);
53
static void   gdk_window_draw_rectangle (GdkDrawable     *drawable,
54
                                         GdkGC           *gc,
55
                                         gboolean         filled,
56 57 58 59
                                         gint             x,
                                         gint             y,
                                         gint             width,
                                         gint             height);
60
static void   gdk_window_draw_arc       (GdkDrawable     *drawable,
61
                                         GdkGC           *gc,
62
                                         gboolean         filled,
63 64 65 66 67 68
                                         gint             x,
                                         gint             y,
                                         gint             width,
                                         gint             height,
                                         gint             angle1,
                                         gint             angle2);
69
static void   gdk_window_draw_polygon   (GdkDrawable     *drawable,
70
                                         GdkGC           *gc,
71
                                         gboolean         filled,
72 73
                                         GdkPoint        *points,
                                         gint             npoints);
74
static void   gdk_window_draw_text      (GdkDrawable     *drawable,
75 76 77 78 79 80
                                         GdkFont         *font,
                                         GdkGC           *gc,
                                         gint             x,
                                         gint             y,
                                         const gchar     *text,
                                         gint             text_length);
81
static void   gdk_window_draw_text_wc   (GdkDrawable     *drawable,
82 83 84 85 86 87
                                         GdkFont         *font,
                                         GdkGC           *gc,
                                         gint             x,
                                         gint             y,
                                         const GdkWChar  *text,
                                         gint             text_length);
88
static void   gdk_window_draw_drawable  (GdkDrawable     *drawable,
89 90 91 92 93 94 95 96
                                         GdkGC           *gc,
                                         GdkPixmap       *src,
                                         gint             xsrc,
                                         gint             ysrc,
                                         gint             xdest,
                                         gint             ydest,
                                         gint             width,
                                         gint             height);
97
static void   gdk_window_draw_points    (GdkDrawable     *drawable,
98 99 100
                                         GdkGC           *gc,
                                         GdkPoint        *points,
                                         gint             npoints);
101
static void   gdk_window_draw_segments  (GdkDrawable     *drawable,
102 103 104
                                         GdkGC           *gc,
                                         GdkSegment      *segs,
                                         gint             nsegs);
105 106 107 108
static void   gdk_window_draw_lines     (GdkDrawable     *drawable,
					 GdkGC           *gc,
					 GdkPoint        *points,
					 gint             npoints);
109 110 111 112 113 114 115 116 117 118 119 120 121 122

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);
123

124 125 126 127 128 129 130 131 132 133
static void   gdk_window_draw_image     (GdkDrawable     *drawable,
                                         GdkGC           *gc,
                                         GdkImage        *image,
                                         gint             xsrc,
                                         gint             ysrc,
                                         gint             xdest,
                                         gint             ydest,
                                         gint             width,
                                         gint             height);

134 135 136 137 138 139 140 141 142 143 144 145 146
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);

147 148 149 150 151
static void gdk_window_draw_trapezoids (GdkDrawable   *drawable,
					GdkGC	      *gc,
					GdkTrapezoid  *trapezoids,
					gint           n_trapezoids);

152 153 154 155 156 157 158 159
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);
160

161
static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
162

163 164 165 166 167 168
static void   gdk_window_real_get_size  (GdkDrawable     *drawable,
                                         gint            *width,
                                         gint            *height);

static GdkVisual*   gdk_window_real_get_visual   (GdkDrawable *drawable);
static gint         gdk_window_real_get_depth    (GdkDrawable *drawable);
169
static GdkScreen*   gdk_window_real_get_screen   (GdkDrawable *drawable);
170
static void         gdk_window_real_set_colormap (GdkDrawable *drawable,
171
						  GdkColormap *cmap);
172
static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
Havoc Pennington's avatar
Havoc Pennington committed
173 174

static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
175 176 177 178 179 180 181 182
						       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);
Havoc Pennington's avatar
Havoc Pennington committed
183

Owen Taylor's avatar
Owen Taylor committed
184
static void gdk_window_free_paint_stack (GdkWindow *window);
185

186
static void gdk_window_finalize   (GObject              *object);
187 188 189 190 191
static void gdk_window_clear_backing_rect (GdkWindow *window,
					   gint       x,
					   gint       y,
					   gint       width,
					   gint       height);
192

Matthias Clasen's avatar
Matthias Clasen committed
193
G_DEFINE_TYPE (GdkWindowObject, gdk_window_object, GDK_TYPE_DRAWABLE);
194

195
static void
Matthias Clasen's avatar
Matthias Clasen committed
196
gdk_window_object_init (GdkWindowObject *window)
197 198
{
  /* 0-initialization is good for all other fields. */
rhlabs's avatar
rhlabs committed
199

200
  window->window_type = GDK_WINDOW_CHILD;
Elliot Lee's avatar
Elliot Lee committed
201

Havoc Pennington's avatar
Havoc Pennington committed
202 203
  window->state = GDK_WINDOW_STATE_WITHDRAWN;
  
204
  window->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
205
}
206

207
static void
Matthias Clasen's avatar
Matthias Clasen committed
208
gdk_window_object_class_init (GdkWindowObjectClass *klass)
209 210 211
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
  GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
212
  
213 214 215 216 217 218 219 220 221 222 223 224 225
  object_class->finalize = gdk_window_finalize;

  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;
  drawable_class->draw_drawable = gdk_window_draw_drawable;
  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;
226
  drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
227
  drawable_class->draw_image = gdk_window_draw_image;
228
  drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
229
  drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
230
  drawable_class->get_depth = gdk_window_real_get_depth;
231
  drawable_class->get_screen = gdk_window_real_get_screen;
232 233 234 235
  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;
236
  drawable_class->_copy_to_image = gdk_window_copy_to_image;
237
  drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
238 239
  drawable_class->get_clip_region = gdk_window_get_clip_region;
  drawable_class->get_visible_region = gdk_window_get_visible_region;
Havoc Pennington's avatar
Havoc Pennington committed
240
  drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
241
}
242

243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
static void
gdk_window_finalize (GObject *object)
{
  GdkWindow *window = GDK_WINDOW (object);
  GdkWindowObject *obj = (GdkWindowObject *) object;
  
  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);
    }
262

263
  g_object_unref (obj->impl);
264
  obj->impl = NULL;
265
  
Matthias Clasen's avatar
Matthias Clasen committed
266
  G_OBJECT_CLASS (gdk_window_object_parent_class)->finalize (object);
Elliot Lee's avatar
Elliot Lee committed
267 268
}

269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
static void
window_remove_filters (GdkWindow *window)
{
  GdkWindowObject *obj = (GdkWindowObject*) window;

  if (obj->filters)
    {
      GList *tmp_list;
      
      for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
	g_free (tmp_list->data);
    
      g_list_free (obj->filters);
      obj->filters = NULL;
    }
}

Owen Taylor's avatar
Owen Taylor committed
286
/**
287
 * _gdk_window_destroy_hierarchy:
Owen Taylor's avatar
Owen Taylor committed
288 289
 * @window: a #GdkWindow
 * @recursing: If TRUE, then this is being called because a parent
Sven Neumann's avatar
Sven Neumann committed
290 291 292 293 294 295 296 297
 *            was destroyed. This generally means that the call to the 
 *            windowing system to destroy the window can be omitted, since
 *            it will be destroyed as a result of the parent being destroyed.
 *            Unless @foreign_destroy.           
 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some 
 *            external agency. The window has already been destroyed and no 
 *            windowing system calls should be made. (This may never happen
 *            for some windowing systems.)
Owen Taylor's avatar
Owen Taylor committed
298
 *
Sven Neumann's avatar
Sven Neumann committed
299 300
 * Internal function to destroy a window. Like gdk_window_destroy(),
 * but does not drop the reference count created by gdk_window_new().
Owen Taylor's avatar
Owen Taylor committed
301 302
 **/
static void
303
_gdk_window_destroy_hierarchy (GdkWindow *window,
Owen Taylor's avatar
Owen Taylor committed
304 305 306
			       gboolean   recursing,
			       gboolean   foreign_destroy)
{
307 308
  GdkWindowObject *private;
  GdkWindowObject *temp_private;
Owen Taylor's avatar
Owen Taylor committed
309
  GdkWindow *temp_window;
310
  GdkScreen *screen;
Owen Taylor's avatar
Owen Taylor committed
311 312 313 314 315
  GList *children;
  GList *tmp;
  
  g_return_if_fail (window != NULL);
  
316
  private = (GdkWindowObject*) window;
Owen Taylor's avatar
Owen Taylor committed
317
  
318 319 320
  if (GDK_WINDOW_DESTROYED (window))
    return;
    
321
  switch (GDK_WINDOW_TYPE (window))
Owen Taylor's avatar
Owen Taylor committed
322
    {
323 324 325 326 327 328 329 330
    case GDK_WINDOW_ROOT:
      screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
      if (!screen->closed)
	{
	  g_error ("attempted to destroy root window");
	  break;
	}
      /* else fall thru */
Owen Taylor's avatar
Owen Taylor committed
331 332 333 334 335
    case GDK_WINDOW_TOPLEVEL:
    case GDK_WINDOW_CHILD:
    case GDK_WINDOW_DIALOG:
    case GDK_WINDOW_TEMP:
    case GDK_WINDOW_FOREIGN:
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354
      if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
	{
	  /* Logically, it probably makes more sense to send
	   * a "destroy yourself" message to the foreign window
	   * whether or not it's in our heirarchy; but for historical
	   * reasons, we only send "destroy yourself" messages to
	   * foreign windows in our heirarchy.
	   */
	  if (private->parent)
	    _gdk_windowing_window_destroy_foreign (window);

	  /* Also for historical reasons, we remove any filters
	   * on a foreign window when it or a parent is destroyed;
	   * this likely causes problems if two separate portions
	   * of code are maintaining filter lists on a foreign window.
	   */
	  window_remove_filters (window);
	}
      else
Owen Taylor's avatar
Owen Taylor committed
355
	{
Havoc Pennington's avatar
Havoc Pennington committed
356
	  private->state |= GDK_WINDOW_STATE_WITHDRAWN;
Owen Taylor's avatar
Owen Taylor committed
357 358 359
	  
	  if (private->parent)
	    {
360
	      GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
Owen Taylor's avatar
Owen Taylor committed
361 362 363 364 365 366 367
	      if (parent_private->children)
		parent_private->children = g_list_remove (parent_private->children, window);
	    }

	  _gdk_window_clear_update_area (window);
	  gdk_window_free_paint_stack (window);
	  
368 369 370
	  if (private->bg_pixmap &&
              private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
              private->bg_pixmap != GDK_NO_BG)
Owen Taylor's avatar
Owen Taylor committed
371
	    {
372
	      g_object_unref (private->bg_pixmap);
Owen Taylor's avatar
Owen Taylor committed
373 374 375
	      private->bg_pixmap = NULL;
	    }
	  
376 377 378
	  if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN)
	    g_assert (private->children == NULL);
	  else
Owen Taylor's avatar
Owen Taylor committed
379 380 381 382 383 384 385 386 387
	    {
	      children = tmp = private->children;
	      private->children = NULL;
	      
	      while (tmp)
		{
		  temp_window = tmp->data;
		  tmp = tmp->next;
		  
388
		  temp_private = (GdkWindowObject*) temp_window;
Owen Taylor's avatar
Owen Taylor committed
389
		  if (temp_private)
Sven Neumann's avatar
Sven Neumann committed
390 391
		    _gdk_window_destroy_hierarchy (temp_window,
                                                   TRUE, foreign_destroy);
Owen Taylor's avatar
Owen Taylor committed
392 393 394 395 396
		}
	      
	      g_list_free (children);
	    }
	  
397
	  _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
398
	  private->parent = NULL;
399
	  private->destroyed = TRUE;
400

401
	  window_remove_filters (window);
402 403

          gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
Owen Taylor's avatar
Owen Taylor committed
404 405 406 407 408 409 410 411
	}
      break;
    }
}

/**
 * _gdk_window_destroy:
 * @window: a #GdkWindow
Sven Neumann's avatar
Sven Neumann committed
412 413 414 415
 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
 *            external agency. The window has already been destroyed and no
 *            windowing system calls should be made. (This may never happen
 *            for some windowing systems.)
Owen Taylor's avatar
Owen Taylor committed
416
 *
Sven Neumann's avatar
Sven Neumann committed
417 418
 * Internal function to destroy a window. Like gdk_window_destroy(),
 * but does not drop the reference count created by gdk_window_new().
Owen Taylor's avatar
Owen Taylor committed
419 420 421 422 423
 **/
void
_gdk_window_destroy (GdkWindow *window,
		     gboolean   foreign_destroy)
{
424
  _gdk_window_destroy_hierarchy (window, FALSE, foreign_destroy);
Owen Taylor's avatar
Owen Taylor committed
425 426
}

Havoc Pennington's avatar
Havoc Pennington committed
427 428 429 430
/**
 * gdk_window_destroy:
 * @window: a #GdkWindow
 *
Soeren Sandmann's avatar
Soeren Sandmann committed
431 432 433 434 435 436
 * Destroys the window system resources associated with @window and decrements @window's
 * reference count. The window system resources for all children of @window are also
 * destroyed, but the children's reference counts are not decremented.
 *
 * Note that a window will not be destroyed automatically when its reference count
 * reaches zero. You must call this function yourself before that happens.
Havoc Pennington's avatar
Havoc Pennington committed
437 438
 *
 **/
Owen Taylor's avatar
Owen Taylor committed
439 440 441
void
gdk_window_destroy (GdkWindow *window)
{
442
  _gdk_window_destroy_hierarchy (window, FALSE, FALSE);
443
  g_object_unref (window);
Owen Taylor's avatar
Owen Taylor committed
444 445
}

Havoc Pennington's avatar
Havoc Pennington committed
446 447 448 449 450 451 452 453 454 455 456 457 458 459
/**
 * gdk_window_set_user_data:
 * @window: a #GdkWindow
 * @user_data: user data
 *
 * For most purposes this function is deprecated in favor of
 * g_object_set_data(). However, for historical reasons GTK+ stores
 * the #GtkWidget that owns a #GdkWindow as user data on the
 * #GdkWindow. So, custom widget implementations should use
 * this function for that. If GTK+ receives an event for a #GdkWindow,
 * and the user data for the window is non-%NULL, GTK+ will assume the
 * user data is a #GtkWidget, and forward the event to that widget.
 * 
 **/
Elliot Lee's avatar
Elliot Lee committed
460
void
461 462
gdk_window_set_user_data (GdkWindow *window,
			  gpointer   user_data)
463 464
{
  g_return_if_fail (window != NULL);
465
  
466
  ((GdkWindowObject*)window)->user_data = user_data;
467 468
}

Havoc Pennington's avatar
Havoc Pennington committed
469 470 471 472 473 474 475 476 477
/**
 * gdk_window_get_user_data:
 * @window: a #GdkWindow
 * @data: return location for user data
 *
 * Retrieves the user data for @window, which is normally the widget
 * that @window belongs to. See gdk_window_set_user_data().
 * 
 **/
Elliot Lee's avatar
Elliot Lee committed
478
void
479 480
gdk_window_get_user_data (GdkWindow *window,
			  gpointer  *data)
Elliot Lee's avatar
Elliot Lee committed
481 482
{
  g_return_if_fail (window != NULL);
483
  
484 485 486
  *data = ((GdkWindowObject*)window)->user_data;
}

Havoc Pennington's avatar
Havoc Pennington committed
487 488 489 490 491 492 493 494
/**
 * gdk_window_get_window_type:
 * @window: a #GdkWindow
 * 
 * Gets the type of the window. See #GdkWindowType.
 * 
 * Return value: type of window
 **/
495 496 497 498 499 500
GdkWindowType
gdk_window_get_window_type (GdkWindow *window)
{
  g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
  
  return GDK_WINDOW_TYPE (window);
Elliot Lee's avatar
Elliot Lee committed
501 502
}

Havoc Pennington's avatar
Havoc Pennington committed
503 504 505 506 507 508
/**
 * gdk_window_get_position:
 * @window: a #GdkWindow
 * @x: X coordinate of window
 * @y: Y coordinate of window
 *
Sven Neumann's avatar
Sven Neumann committed
509 510 511 512 513
 * Obtains the position of the window as reported in the
 * most-recently-processed #GdkEventConfigure. Contrast with
 * gdk_window_get_geometry() which queries the X server for the
 * current window position, regardless of which events have been
 * received or processed.
Havoc Pennington's avatar
Havoc Pennington committed
514 515 516 517
 *
 * The position coordinates are relative to the window's parent window.
 * 
 **/
Elliot Lee's avatar
Elliot Lee committed
518 519 520 521
void
gdk_window_get_position (GdkWindow *window,
			 gint      *x,
			 gint      *y)
522
{
523
  GdkWindowObject *obj;
524
  
525
  g_return_if_fail (GDK_IS_WINDOW (window));
526
  
527
  obj = (GdkWindowObject*) window;
528
  
529
  if (x)
530
    *x = obj->x;
531
  if (y)
532
    *y = obj->y;
Elliot Lee's avatar
Elliot Lee committed
533 534
}

Havoc Pennington's avatar
Havoc Pennington committed
535 536 537 538 539 540 541 542 543 544 545 546 547
/**
 * gdk_window_get_parent:
 * @window: a #GdkWindow
 * 
 * Obtains the parent of @window, as known to GDK. Does not query the
 * X server; thus this returns the parent as passed to gdk_window_new(),
 * not the actual parent. This should never matter unless you're using
 * Xlib calls mixed with GDK calls on the X11 platform. It may also
 * matter for toplevel windows, because the window manager may choose
 * to reparent them.
 * 
 * Return value: parent of @window
 **/
548 549
GdkWindow*
gdk_window_get_parent (GdkWindow *window)
550
{
551
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
552
  
553
  return (GdkWindow*) ((GdkWindowObject*) window)->parent;
554 555
}

Havoc Pennington's avatar
Havoc Pennington committed
556 557 558 559 560 561 562 563
/**
 * gdk_window_get_toplevel:
 * @window: a #GdkWindow
 * 
 * Gets the toplevel window that's an ancestor of @window.
 * 
 * Return value: the toplevel window containing @window
 **/
564 565
GdkWindow*
gdk_window_get_toplevel (GdkWindow *window)
Elliot Lee's avatar
Elliot Lee committed
566
{
567
  GdkWindowObject *obj;
568
  
569 570
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);

571 572 573
  obj = (GdkWindowObject *)window;
  while (GDK_WINDOW_TYPE (obj) == GDK_WINDOW_CHILD)
    obj = (GdkWindowObject *)obj->parent;
574
  
575 576 577
  return GDK_WINDOW (obj);
}

Havoc Pennington's avatar
Havoc Pennington committed
578 579 580 581 582 583 584 585 586 587 588 589 590 591
/**
 * gdk_window_get_children:
 * @window: a #GdkWindow
 * 
 * Gets the list of children of @window known to GDK.
 * This function only returns children created via GDK,
 * so for example it's useless when used with the root window;
 * it only returns windows an application created itself.
 *
 * The returned list must be freed, but the elements in the
 * list need not be.
 * 
 * Return value: list of child windows inside @window
 **/
592 593 594 595 596 597 598 599 600 601 602
GList*
gdk_window_get_children (GdkWindow *window)
{
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);

  if (GDK_WINDOW_DESTROYED (window))
    return NULL;

  return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
}

Havoc Pennington's avatar
Havoc Pennington committed
603 604 605 606 607 608 609 610 611
/**
 * gdk_window_peek_children:
 * @window: a #GdkWindow
 * 
 * Like gdk_window_get_children(), but does not copy the list of
 * children, so the list does not need to be freed.
 * 
 * Return value: a reference to the list of child windows in @window
 **/
612
GList *
Havoc Pennington's avatar
Havoc Pennington committed
613
gdk_window_peek_children (GdkWindow *window)
614 615 616 617 618 619 620
{
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);

  if (GDK_WINDOW_DESTROYED (window))
    return NULL;

  return GDK_WINDOW_OBJECT (window)->children;
Elliot Lee's avatar
Elliot Lee committed
621 622
}

Havoc Pennington's avatar
Havoc Pennington committed
623 624 625 626 627 628 629
/**
 * gdk_window_add_filter:
 * @window: a #GdkWindow
 * @function: filter callback
 * @data: data to pass to filter callback
 *
 * Adds an event filter to @window, allowing you to intercept events
Sven Neumann's avatar
Sven Neumann committed
630 631
 * before they reach GDK. This is a low-level operation and makes it
 * easy to break GDK and/or GTK+, so you have to know what you're
632 633
 * doing. Pass %NULL for @window to get all events for all windows,
 * instead of events for a specific window.
Havoc Pennington's avatar
Havoc Pennington committed
634 635
 * 
 **/
636
void          
637 638 639
gdk_window_add_filter (GdkWindow     *window,
		       GdkFilterFunc  function,
		       gpointer       data)
640
{
641
  GdkWindowObject *private;
642 643
  GList *tmp_list;
  GdkEventFilter *filter;
644
  
645
  g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
646

647 648
  private = (GdkWindowObject*) window;
  if (private && GDK_WINDOW_DESTROYED (window))
649
    return;
650 651
  
  if (private)
652 653
    tmp_list = private->filters;
  else
654
    tmp_list = _gdk_default_filters;
655
  
656 657 658 659 660 661 662
  while (tmp_list)
    {
      filter = (GdkEventFilter *)tmp_list->data;
      if ((filter->function == function) && (filter->data == data))
	return;
      tmp_list = tmp_list->next;
    }
663
  
664 665 666
  filter = g_new (GdkEventFilter, 1);
  filter->function = function;
  filter->data = data;
667 668
  
  if (private)
669 670
    private->filters = g_list_append (private->filters, filter);
  else
671
    _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
672 673
}

Havoc Pennington's avatar
Havoc Pennington committed
674 675 676 677 678 679 680 681 682
/**
 * gdk_window_remove_filter:
 * @window: a #GdkWindow
 * @function: previously-added filter function
 * @data: user data for previously-added filter function
 *
 * Remove a filter previously added with gdk_window_add_filter().
 * 
 **/
683
void
684 685 686
gdk_window_remove_filter (GdkWindow     *window,
			  GdkFilterFunc  function,
			  gpointer       data)
687
{
688
  GdkWindowObject *private;
689
  GList *tmp_list, *node;
690
  GdkEventFilter *filter;
691
  
692
  g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
693

694
  private = (GdkWindowObject*) window;
695 696
  
  if (private)
697 698
    tmp_list = private->filters;
  else
699
    tmp_list = _gdk_default_filters;
700
  
701 702 703
  while (tmp_list)
    {
      filter = (GdkEventFilter *)tmp_list->data;
704
      node = tmp_list;
705
      tmp_list = tmp_list->next;
706
      
707 708
      if ((filter->function == function) && (filter->data == data))
	{
709
	  if (private)
710
	    private->filters = g_list_remove_link (private->filters, node);
711
	  else
712
	    _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
713
	  g_list_free_1 (node);
Owen Taylor's avatar
Owen Taylor committed
714
	  g_free (filter);
715 716 717 718 719 720
	  
	  return;
	}
    }
}

Havoc Pennington's avatar
Havoc Pennington committed
721
/**
722
 * gdk_screen_get_toplevel_windows:
Matthias Clasen's avatar
Matthias Clasen committed
723
 * @screen: The #GdkScreen where the toplevels are located.
Havoc Pennington's avatar
Havoc Pennington committed
724
 * 
725
 * Obtains a list of all toplevel windows known to GDK on the screen @screen.
Havoc Pennington's avatar
Havoc Pennington committed
726 727 728 729 730 731 732
 * A toplevel window is a child of the root window (see
 * gdk_get_default_root_window()).
 *
 * The returned list should be freed with g_list_free(), but
 * its elements need not be freed.
 * 
 * Return value: list of toplevel windows, free with g_list_free()
Matthias Clasen's avatar
Matthias Clasen committed
733 734
 *
 * Since: 2.2
Havoc Pennington's avatar
Havoc Pennington committed
735
 **/
736
GList *
737
gdk_screen_get_toplevel_windows (GdkScreen *screen)
738
{
739
  GdkWindow * root_window;
740 741
  GList *new_list = NULL;
  GList *tmp_list;
742
  
743 744 745 746 747
  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
  
  root_window = gdk_screen_get_root_window (screen);

  tmp_list = ((GdkWindowObject *)root_window)->children;
748 749
  while (tmp_list)
    {
750 751
      if (GDK_WINDOW_TYPE (tmp_list->data) != GDK_WINDOW_FOREIGN)
	new_list = g_list_prepend (new_list, tmp_list->data);
752 753
      tmp_list = tmp_list->next;
    }
754
  
755 756 757
  return new_list;
}

758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773
/**
 * gdk_window_get_toplevels:
 * 
 * Obtains a list of all toplevel windows known to GDK on the default
 * screen (see gdk_window_get_toplevels_for_screen()).
 * A toplevel window is a child of the root window (see
 * gdk_get_default_root_window()).
 *
 * The returned list should be freed with g_list_free(), but
 * its elements need not be freed.
 * 
 * Return value: list of toplevel windows, free with g_list_free()
 **/
GList *
gdk_window_get_toplevels (void)
{
Owen Taylor's avatar
Owen Taylor committed
774
  return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
775 776
}

Havoc Pennington's avatar
Havoc Pennington committed
777
/**
778
 * gdk_window_is_visible:
Havoc Pennington's avatar
Havoc Pennington committed
779 780 781 782 783 784 785
 * @window: a #GdkWindow
 * 
 * Checks whether the window has been mapped (with gdk_window_show() or
 * gdk_window_show_unraised()).
 * 
 * Return value: %TRUE if the window is mapped
 **/
786 787 788
gboolean 
gdk_window_is_visible (GdkWindow *window)
{
789
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
790
  
Havoc Pennington's avatar
Havoc Pennington committed
791
  return GDK_WINDOW_IS_MAPPED (window);
792 793
}

Havoc Pennington's avatar
Havoc Pennington committed
794
/**
795
 * gdk_window_is_viewable:
Havoc Pennington's avatar
Havoc Pennington committed
796 797 798 799 800
 * @window: a #GdkWindow
 * 
 * Check if the window and all ancestors of the window are
 * mapped. (This is not necessarily "viewable" in the X sense, since
 * we only check as far as we have GDK window parents, not to the root
Sven Neumann's avatar
Sven Neumann committed
801 802
 * window.)
 *
Havoc Pennington's avatar
Havoc Pennington committed
803 804
 * Return value: %TRUE if the window is viewable
 **/
805 806 807
gboolean 
gdk_window_is_viewable (GdkWindow *window)
{
808
  GdkWindowObject *private = (GdkWindowObject *)window;
809 810
  GdkScreen *screen;
  GdkWindow *root_window;
811
  
812
  g_return_val_if_fail (window != NULL, FALSE);
813
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
814 815 816

  screen = gdk_drawable_get_screen (window);
  root_window = gdk_screen_get_root_window (screen);
817
  
818
  while (private && 
819
	 (private != (GdkWindowObject *)root_window) &&
820
	 (GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN))
821
    {
822
      if (GDK_WINDOW_DESTROYED (private) || !GDK_WINDOW_IS_MAPPED (private))
823
	return FALSE;
824
      
825
      private = (GdkWindowObject *)private->parent;
826
    }
827
  
828 829 830
  return TRUE;
}

Havoc Pennington's avatar
Havoc Pennington committed
831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849
/**
 * gdk_window_get_state:
 * @window: a #GdkWindow
 * 
 * Gets the bitwise OR of the currently active window state flags,
 * from the #GdkWindowState enumeration.
 * 
 * Return value: window state bitfield
 **/
GdkWindowState
gdk_window_get_state (GdkWindow *window)
{
  GdkWindowObject *private = (GdkWindowObject *)window;
  
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
  
  return private->state;
}

Havoc Pennington's avatar
Havoc Pennington committed
850 851 852 853 854 855 856 857 858 859
/**
 * gdk_window_begin_paint_rect:
 * @window: a #GdkWindow
 * @rectangle: rectangle you intend to draw to
 *
 * A convenience wrapper around gdk_window_begin_paint_region() which
 * creates a rectangular region for you. See
 * gdk_window_begin_paint_region() for details.
 * 
 **/
860 861 862 863 864 865 866 867 868 869 870 871 872 873
void
gdk_window_begin_paint_rect (GdkWindow    *window,
			     GdkRectangle *rectangle)
{
  GdkRegion *region;

  g_return_if_fail (window != NULL);
  g_return_if_fail (GDK_IS_WINDOW (window));

  region = gdk_region_rectangle (rectangle);
  gdk_window_begin_paint_region (window, region);
  gdk_region_destroy (region);
}

874
#ifdef GDK_WINDOWING_X11
Havoc Pennington's avatar
Havoc Pennington committed
875
#include "x11/gdkx.h"
876 877
#endif

Havoc Pennington's avatar
Havoc Pennington committed
878 879 880 881 882 883 884 885 886 887 888 889
/**
 * gdk_window_begin_paint_region:
 * @window: a #GdkWindow
 * @region: region you intend to draw to
 *
 * Indicates that you are beginning the process of redrawing @region.
 * A backing store (offscreen buffer) large enough to contain @region
 * will be created. The backing store will be initialized with the
 * background color or background pixmap for @window. Then, all
 * drawing operations performed on @window will be diverted to the
 * backing store.  When you call gdk_window_end_paint(), the backing
 * store will be copied to @window, making it visible onscreen. Only
890
 * the part of @window contained in @region will be modified; that is,
Havoc Pennington's avatar
Havoc Pennington committed
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 919 920 921 922
 * drawing operations are clipped to @region.
 *
 * The net result of all this is to remove flicker, because the user
 * sees the finished product appear all at once when you call
 * gdk_window_end_paint(). If you draw to @window directly without
 * calling gdk_window_begin_paint_region(), the user may see flicker
 * as individual drawing operations are performed in sequence.  The
 * clipping and background-initializing features of
 * gdk_window_begin_paint_region() are conveniences for the
 * programmer, so you can avoid doing that work yourself.
 *
 * When using GTK+, the widget system automatically places calls to
 * gdk_window_begin_paint_region() and gdk_window_end_paint() around
 * emissions of the expose_event signal. That is, if you're writing an
 * expose event handler, you can assume that the exposed area in
 * #GdkEventExpose has already been cleared to the window background,
 * is already set as the clip region, and already has a backing store.
 * Therefore in most cases, application code need not call
 * gdk_window_begin_paint_region(). (You can disable the automatic
 * calls around expose events on a widget-by-widget basis by calling
 * gtk_widget_set_double_buffered().)
 *
 * If you call this function multiple times before calling the
 * matching gdk_window_end_paint(), the backing stores are pushed onto
 * a stack. gdk_window_end_paint() copies the topmost backing store
 * onscreen, subtracts the topmost region from all other regions in
 * the stack, and pops the stack. All drawing operations affect only
 * the topmost backing store in the stack. One matching call to
 * gdk_window_end_paint() is required for each call to
 * gdk_window_begin_paint_region().
 * 
 **/
923 924 925 926
void	      
gdk_window_begin_paint_region (GdkWindow *window,
			       GdkRegion *region)
{
927
#ifdef USE_BACKING_STORE
928
  GdkWindowObject *private = (GdkWindowObject *)window;
929 930
  GdkRectangle clip_box;
  GdkWindowPaint *paint;
931
  GSList *list;
932 933 934 935
  
  g_return_if_fail (window != NULL);
  g_return_if_fail (GDK_IS_WINDOW (window));

936
  if (GDK_WINDOW_DESTROYED (window))
Owen Taylor's avatar
Owen Taylor committed
937
    return;
938

939
  gdk_region_get_clipbox (region, &clip_box);
940

941 942 943 944 945 946 947
  paint = g_new (GdkWindowPaint, 1);
  paint->region = gdk_region_copy (region);
  paint->x_offset = clip_box.x;
  paint->y_offset = clip_box.y;
  paint->pixmap =
    gdk_pixmap_new (window,
		    MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
948

949
  paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
Owen Taylor's avatar
Owen Taylor committed
950 951
  cairo_surface_set_device_offset (paint->surface,
				   - paint->x_offset, - paint->y_offset);
952
  
953
  for (list = private->paint_stack; list != NULL; list = list->next)
954
    {
955
      GdkWindowPaint *tmp_paint = list->data;
956

957
      gdk_region_subtract (tmp_paint->region, paint->region);
958 959 960
    }
  
  private->paint_stack = g_slist_prepend (private->paint_stack, paint);
961 962 963 964 965 966 967

  if (!gdk_region_empty (region))
    {
      gdk_window_clear_backing_rect (window,
				     clip_box.x, clip_box.y,
				     clip_box.width, clip_box.height);
    }
968
#endif /* USE_BACKING_STORE */
969 970
}

Havoc Pennington's avatar
Havoc Pennington committed
971 972 973 974 975 976 977 978 979 980 981 982 983
/**
 * gdk_window_end_paint:
 * @window: a #GdkWindow
 *
 * Indicates that the backing store created by the most recent call to
 * gdk_window_begin_paint_region() should be copied onscreen and
 * deleted, leaving the next-most-recent backing store or no backing
 * store at all as the active paint region. See
 * gdk_window_begin_paint_region() for full details. It is an error to
 * call this function without a matching
 * gdk_window_begin_paint_region() first.
 * 
 **/
984 985 986
void
gdk_window_end_paint (GdkWindow *window)
{
987
#ifdef USE_BACKING_STORE
988
  GdkWindowObject *private = (GdkWindowObject *)window;
989 990 991 992 993 994 995
  GdkWindowPaint *paint;
  GdkGC *tmp_gc;
  GdkRectangle clip_box;
  gint x_offset, y_offset;

  g_return_if_fail (window != NULL);
  g_return_if_fail (GDK_IS_WINDOW (window));
Owen Taylor's avatar
Owen Taylor committed
996

997
  if (GDK_WINDOW_DESTROYED (window))
Owen Taylor's avatar
Owen Taylor committed
998
    return;
Havoc Pennington's avatar
Havoc Pennington committed
999 1000 1001 1002 1003 1004

  if (private->paint_stack == NULL)
    {
      g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
      return