gdkwindow.c 49.7 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/* 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
 * modify it under the terms of the GNU Library General Public
 * 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library 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

Elliot Lee's avatar
Elliot Lee committed
20 21 22 23 24
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <netinet/in.h>
#include "gdk.h"
25
#include "../config.h"
Elliot Lee's avatar
Elliot Lee committed
26 27
#include "gdkinput.h"
#include "gdkprivate.h"
28
#include "MwmUtil.h"
Elliot Lee's avatar
Elliot Lee committed
29
#include <stdlib.h>
30
#include <stdio.h>
Elliot Lee's avatar
Elliot Lee committed
31

32 33 34 35
#ifdef HAVE_SHAPE_EXT
#include <X11/extensions/shape.h>
#endif

36 37
int nevent_masks = 20;
int event_mask_table[20] =
Elliot Lee's avatar
Elliot Lee committed
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
{
  ExposureMask,
  PointerMotionMask,
  PointerMotionHintMask,
  ButtonMotionMask,
  Button1MotionMask,
  Button2MotionMask,
  Button3MotionMask,
  ButtonPressMask | OwnerGrabButtonMask,
  ButtonReleaseMask | OwnerGrabButtonMask,
  KeyPressMask,
  KeyReleaseMask,
  EnterWindowMask,
  LeaveWindowMask,
  FocusChangeMask,
  StructureNotifyMask,
  PropertyChangeMask,
55
  VisibilityChangeMask,
Elliot Lee's avatar
Elliot Lee committed
56
  0,				/* PROXIMITY_IN */
57 58
  0,				/* PROXIMTY_OUT */
  SubstructureNotifyMask
Elliot Lee's avatar
Elliot Lee committed
59 60 61
};


rhlabs's avatar
rhlabs committed
62 63
/* internal function created for and used by gdk_window_xid_at_coords */
Window
64 65 66 67 68 69 70
gdk_window_xid_at (Window   base,
		   gint     bx,
		   gint     by,
		   gint     x,
		   gint     y, 
		   GList   *excludes,
		   gboolean excl_child)
rhlabs's avatar
rhlabs committed
71 72 73 74
{
   GdkWindow *window;
   GdkWindowPrivate *private;
   Display *disp;
75 76
   Window *list = NULL;
   Window child = 0, parent_win = 0, root_win = 0;
77
   int i;
78
   unsigned int ww, wh, wb, wd, num;
79
   int wx, wy;
80
   
81 82 83 84
   window = (GdkWindow*) &gdk_root_parent;
   private = (GdkWindowPrivate*) window;
   disp = private->xdisplay;
   if (!XGetGeometry (disp, base, &root_win, &wx, &wy, &ww, &wh, &wb, &wd))
rhlabs's avatar
rhlabs committed
85
     return 0;
86 87 88 89 90 91 92
   wx += bx;
   wy += by;

   if (!((x >= wx) &&
	 (y >= wy) &&
	 (x < (int) (wx + ww)) &&
	 (y < (int) (wy + wh))))
rhlabs's avatar
rhlabs committed
93
     return 0;
94 95

   if (!XQueryTree (disp, base, &root_win, &parent_win, &list, &num))
rhlabs's avatar
rhlabs committed
96
     return base;
97

rhlabs's avatar
rhlabs committed
98 99
   if (list)
     {
100
	for (i = num - 1; ; i--)
rhlabs's avatar
rhlabs committed
101
	  {
102
	     if ((!excl_child) || (!g_list_find (excludes, (gpointer *) list[i])))
rhlabs's avatar
rhlabs committed
103
	       {
104
		 if ((child = gdk_window_xid_at (list[i], wx, wy, x, y, excludes, excl_child)) != 0)
105
		   {
106
		     XFree (list);
107 108
		     return child;
		   }
rhlabs's avatar
rhlabs committed
109
	       }
110 111
	     if (!i)
	       break;
rhlabs's avatar
rhlabs committed
112
	  }
113
	XFree (list);
rhlabs's avatar
rhlabs committed
114
     }
rhlabs's avatar
rhlabs committed
115
   return base;
rhlabs's avatar
rhlabs committed
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
}

/* 
 * The following fucntion by The Rasterman <raster@redhat.com>
 * This function returns the X Window ID in which the x y location is in 
 * (x and y being relative to the root window), excluding any windows listed
 * in the GList excludes (this is a list of X Window ID's - gpointer being
 * the Window ID).
 * 
 * This is primarily designed for internal gdk use - for DND for example
 * when using a shaped icon window as the drag object - you exclude the
 * X Window ID of the "icon" (perhaps more if excludes may be needed) and
 * You can get back an X Window ID as to what X Window ID is infact under
 * those X,Y co-ordinates.
 */
Window
132 133 134 135
gdk_window_xid_at_coords (gint     x,
			  gint     y,
			  GList   *excludes,
			  gboolean excl_child)
rhlabs's avatar
rhlabs committed
136 137 138 139
{
   GdkWindow *window;
   GdkWindowPrivate *private;
   Display *disp;
140 141
   Window *list = NULL;
   Window root, child = 0, parent_win = 0, root_win = 0;
142 143
   unsigned int num;
   int i;
rhlabs's avatar
rhlabs committed
144
   
145 146 147 148 149 150 151 152 153 154 155 156
   window = (GdkWindow*) &gdk_root_parent;
   private = (GdkWindowPrivate*) window;
   disp = private->xdisplay;
   root = private->xwindow;
   num = g_list_length (excludes);

   XGrabServer (disp);
   if (!XQueryTree (disp, root, &root_win, &parent_win, &list, &num))
     {
       XUngrabServer(disp);
       return root;
     }
rhlabs's avatar
rhlabs committed
157 158
   if (list)
     {
159 160 161 162 163 164 165 166 167 168
       i = num - 1;
       do
	 {
	   XWindowAttributes xwa;

	   XGetWindowAttributes (disp, list [i], &xwa);

	   if (xwa.map_state != IsViewable)
	     continue;

169
	   if (excl_child && g_list_find (excludes, (gpointer *) list[i]))
170 171 172 173 174 175 176
	     continue;
	   
	   if ((child = gdk_window_xid_at (list[i], 0, 0, x, y, excludes, excl_child)) == 0)
	     continue;

	   if (excludes)
	     {
177
	       if (!g_list_find (excludes, (gpointer *) child))
178
		 {
179 180
		   XFree (list);
		   XUngrabServer (disp);
181 182 183 184 185
		   return child;
		 }
	     }
	   else
	     {
186 187
	       XFree (list);
	       XUngrabServer (disp);
188 189 190
	       return child;
	     }
	 } while (--i > 0);
191
	XFree (list);
rhlabs's avatar
rhlabs committed
192
     }
193
   XUngrabServer (disp);
rhlabs's avatar
rhlabs committed
194 195 196
   return root;
}

Elliot Lee's avatar
Elliot Lee committed
197
void
198
gdk_window_init (void)
Elliot Lee's avatar
Elliot Lee committed
199 200 201 202 203 204 205 206 207 208 209 210 211
{
  XWindowAttributes xattributes;
  unsigned int width;
  unsigned int height;
  unsigned int border_width;
  unsigned int depth;
  int x, y;

  XGetGeometry (gdk_display, gdk_root_window, &gdk_root_window,
		&x, &y, &width, &height, &border_width, &depth);
  XGetWindowAttributes (gdk_display, gdk_root_window, &xattributes);

  gdk_root_parent.xwindow = gdk_root_window;
212
  gdk_root_parent.xdisplay = gdk_display;
Elliot Lee's avatar
Elliot Lee committed
213 214
  gdk_root_parent.window_type = GDK_WINDOW_ROOT;
  gdk_root_parent.window.user_data = NULL;
215 216
  gdk_root_parent.width = width;
  gdk_root_parent.height = height;
217
  gdk_root_parent.children = NULL;
218
  gdk_root_parent.colormap = NULL;
Elliot Lee's avatar
Elliot Lee committed
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
}

GdkWindow*
gdk_window_new (GdkWindow     *parent,
		GdkWindowAttr *attributes,
		gint           attributes_mask)
{
  GdkWindow *window;
  GdkWindowPrivate *private;
  GdkWindowPrivate *parent_private;
  GdkVisual *visual;
  Display *parent_display;
  Window xparent;
  Visual *xvisual;
  XSetWindowAttributes xattributes;
  long xattributes_mask;
  XSizeHints size_hints;
  XWMHints wm_hints;
  XClassHint *class_hint;
  int x, y, depth;
  unsigned int class;
  char *title;
  int i;

  g_return_val_if_fail (attributes != NULL, NULL);

  if (!parent)
    parent = (GdkWindow*) &gdk_root_parent;

  parent_private = (GdkWindowPrivate*) parent;
249 250 251
  if (parent_private->destroyed)
    return NULL;

Elliot Lee's avatar
Elliot Lee committed
252 253 254 255 256 257 258
  xparent = parent_private->xwindow;
  parent_display = parent_private->xdisplay;

  private = g_new (GdkWindowPrivate, 1);
  window = (GdkWindow*) private;

  private->parent = parent;
259

260
  if (parent_private)
261 262
    parent_private->children = g_list_prepend (parent_private->children, window);

Elliot Lee's avatar
Elliot Lee committed
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
  private->xdisplay = parent_display;
  private->destroyed = FALSE;
  private->resize_count = 0;
  private->ref_count = 1;
  xattributes_mask = 0;

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

  if (attributes_mask & GDK_WA_Y)
    y = attributes->y;
  else
    y = 0;

  private->x = x;
  private->y = y;
  private->width = (attributes->width > 1) ? (attributes->width) : (1);
  private->height = (attributes->height > 1) ? (attributes->height) : (1);
  private->window_type = attributes->window_type;
  private->extension_events = FALSE;
  private->dnd_drag_data_type = None;
  private->dnd_drag_data_typesavail =
    private->dnd_drop_data_typesavail = NULL;
  private->dnd_drop_enabled = private->dnd_drag_enabled =
    private->dnd_drag_accepted = private->dnd_drag_datashow =
    private->dnd_drop_data_numtypesavail =
    private->dnd_drag_data_numtypesavail = 0;
  private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;

294
  private->filters = NULL;
295
  private->children = NULL;
296

Elliot Lee's avatar
Elliot Lee committed
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
  window->user_data = NULL;

  if (attributes_mask & GDK_WA_VISUAL)
    visual = attributes->visual;
  else
    visual = gdk_visual_get_system ();
  xvisual = ((GdkVisualPrivate*) visual)->xvisual;

  xattributes.event_mask = StructureNotifyMask;
  for (i = 0; i < nevent_masks; i++)
    {
      if (attributes->event_mask & (1 << (i + 1)))
	xattributes.event_mask |= event_mask_table[i];
    }

  if (xattributes.event_mask)
    xattributes_mask |= CWEventMask;

315 316 317 318 319 320 321
  if(attributes_mask & GDK_WA_NOREDIR) {
	xattributes.override_redirect =
		(attributes->override_redirect == FALSE)?False:True;
	xattributes_mask |= CWOverrideRedirect;
  } else
    xattributes.override_redirect = False;

Elliot Lee's avatar
Elliot Lee committed
322 323 324 325 326 327
  if (attributes->wclass == GDK_INPUT_OUTPUT)
    {
      class = InputOutput;
      depth = visual->depth;

      if (attributes_mask & GDK_WA_COLORMAP)
328
	private->colormap = attributes->colormap;
Elliot Lee's avatar
Elliot Lee committed
329
      else
330
	private->colormap = gdk_colormap_get_system ();
Elliot Lee's avatar
Elliot Lee committed
331 332 333 334 335 336 337 338

      xattributes.background_pixel = BlackPixel (gdk_display, gdk_screen);
      xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen);
      xattributes_mask |= CWBorderPixel | CWBackPixel;

      switch (private->window_type)
	{
	case GDK_WINDOW_TOPLEVEL:
339
	  xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
Elliot Lee's avatar
Elliot Lee committed
340 341 342 343 344 345
	  xattributes_mask |= CWColormap;

	  xparent = gdk_root_window;
	  break;

	case GDK_WINDOW_CHILD:
346
	  xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
Elliot Lee's avatar
Elliot Lee committed
347 348 349 350
	  xattributes_mask |= CWColormap;
	  break;

	case GDK_WINDOW_DIALOG:
351
	  xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
Elliot Lee's avatar
Elliot Lee committed
352 353 354 355 356 357
	  xattributes_mask |= CWColormap;

	  xparent = gdk_root_window;
	  break;

	case GDK_WINDOW_TEMP:
358
	  xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
Elliot Lee's avatar
Elliot Lee committed
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
	  xattributes_mask |= CWColormap;

	  xparent = gdk_root_window;

	  xattributes.save_under = True;
	  xattributes.override_redirect = True;
	  xattributes.cursor = None;
	  xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
	  break;
	case GDK_WINDOW_ROOT:
	  g_error ("cannot make windows of type GDK_WINDOW_ROOT");
	  break;
	case GDK_WINDOW_PIXMAP:
	  g_error ("cannot make windows of type GDK_WINDOW_PIXMAP (use gdk_pixmap_new)");
	  break;
	}
    }
  else
    {
378
      depth = 0;
Elliot Lee's avatar
Elliot Lee committed
379
      class = InputOnly;
380
      private->colormap = NULL;
Elliot Lee's avatar
Elliot Lee committed
381 382 383 384 385 386
    }

  private->xwindow = XCreateWindow (private->xdisplay, xparent,
				    x, y, private->width, private->height,
				    0, depth, class, xvisual,
				    xattributes_mask, &xattributes);
387
  gdk_window_ref (window);
Elliot Lee's avatar
Elliot Lee committed
388 389
  gdk_xid_table_insert (&private->xwindow, window);

390 391 392
  if (private->colormap)
    gdk_colormap_ref (private->colormap);

393 394 395 396
  gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
				  (attributes->cursor) :
				  NULL));

Elliot Lee's avatar
Elliot Lee committed
397 398 399 400 401 402 403 404 405 406
  switch (private->window_type)
    {
    case GDK_WINDOW_DIALOG:
      XSetTransientForHint (private->xdisplay, private->xwindow, xparent);
    case GDK_WINDOW_TOPLEVEL:
    case GDK_WINDOW_TEMP:
      XSetWMProtocols (private->xdisplay, private->xwindow, gdk_wm_window_protocols, 2);
      break;
    case GDK_WINDOW_CHILD:
      if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
407 408
	  (private->colormap != gdk_colormap_get_system ()) &&
	  (private->colormap != gdk_window_get_colormap (gdk_window_get_toplevel (window))))
Elliot Lee's avatar
Elliot Lee committed
409
	{
410
	  GDK_NOTE (MISC, g_message ("adding colormap window\n"));
Elliot Lee's avatar
Elliot Lee committed
411 412
	  gdk_window_add_colormap_windows (window);
	}
413 414

      return window;
Elliot Lee's avatar
Elliot Lee committed
415
    default:
416 417

      return window;
Elliot Lee's avatar
Elliot Lee committed
418 419
    }

420
  size_hints.flags = PSize;
Elliot Lee's avatar
Elliot Lee committed
421 422 423 424 425 426 427 428
  size_hints.width = private->width;
  size_hints.height = private->height;

  wm_hints.flags = InputHint | StateHint | WindowGroupHint;
  wm_hints.window_group = gdk_leader_window;
  wm_hints.input = True;
  wm_hints.initial_state = NormalState;

429 430 431 432
  /* FIXME: Is there any point in doing this? Do any WM's pay
   * attention to PSize, and even if they do, is this the
   * correct value???
   */
Elliot Lee's avatar
Elliot Lee committed
433
  XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
434

Elliot Lee's avatar
Elliot Lee committed
435 436 437 438 439
  XSetWMHints (private->xdisplay, private->xwindow, &wm_hints);

  if (attributes_mask & GDK_WA_TITLE)
    title = attributes->title;
  else
440
    title = g_get_prgname ();
Elliot Lee's avatar
Elliot Lee committed
441

442 443 444 445
  XmbSetWMProperties (private->xdisplay, private->xwindow,
                      title, title,
                      NULL, 0,
                      NULL, NULL, NULL);
Elliot Lee's avatar
Elliot Lee committed
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464

  if (attributes_mask & GDK_WA_WMCLASS)
    {
      class_hint = XAllocClassHint ();
      class_hint->res_name = attributes->wmclass_name;
      class_hint->res_class = attributes->wmclass_class;
      XSetClassHint (private->xdisplay, private->xwindow, class_hint);
      XFree (class_hint);
    }


  return window;
}

GdkWindow *
gdk_window_foreign_new (guint32 anid)
{
  GdkWindow *window;
  GdkWindowPrivate *private;
465
  GdkWindowPrivate *parent_private;
Elliot Lee's avatar
Elliot Lee committed
466
  XWindowAttributes attrs;
467
  Window root, parent;
468
  Window *children = NULL;
469
  guint nchildren;
Elliot Lee's avatar
Elliot Lee committed
470

471 472 473 474 475
  if(!XGetWindowAttributes (gdk_display, anid, &attrs)) {
    g_warning("XGetWindowAttributes failed on window ID %d\n", anid);
    return NULL;
  }

Elliot Lee's avatar
Elliot Lee committed
476 477 478
  private = g_new (GdkWindowPrivate, 1);
  window = (GdkWindow*) private;

479 480 481
  /* FIXME: This is pretty expensive. Maybe the caller should supply
   *        the parent */
  XQueryTree (gdk_display, anid, &root, &parent, &children, &nchildren);
482

483 484
  if (children)
    XFree (children);
485 486
  private->parent = gdk_xid_table_lookup (parent);

487 488 489 490 491
  parent_private = (GdkWindowPrivate *)private->parent;
  
  if (parent_private)
    parent_private->children = g_list_prepend (parent_private->children, window);

Elliot Lee's avatar
Elliot Lee committed
492 493 494 495 496 497 498 499
  private->xwindow = anid;
  private->xdisplay = gdk_display;
  private->x = attrs.x;
  private->y = attrs.y;
  private->width = attrs.width;
  private->height = attrs.height;
  private->resize_count = 0;
  private->ref_count = 1;
500
  private->window_type = GDK_WINDOW_FOREIGN;
Elliot Lee's avatar
Elliot Lee committed
501 502
  private->destroyed = FALSE;
  private->extension_events = 0;
503

504
  private->colormap = NULL;
505 506 507 508 509 510 511 512 513 514

  private->dnd_drag_data_type = None;
  private->dnd_drag_data_typesavail =
    private->dnd_drop_data_typesavail = NULL;
  private->dnd_drop_enabled = private->dnd_drag_enabled =
    private->dnd_drag_accepted = private->dnd_drag_datashow =
    private->dnd_drop_data_numtypesavail =
    private->dnd_drag_data_numtypesavail = 0;
  private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;

515
  private->filters = NULL;
516
  private->children = NULL;
Elliot Lee's avatar
Elliot Lee committed
517 518 519

  window->user_data = NULL;

520
  gdk_window_ref (window);
Elliot Lee's avatar
Elliot Lee committed
521 522 523 524 525
  gdk_xid_table_insert (&private->xwindow, window);

  return window;
}

526 527 528 529 530 531 532
/* Call this function when you want a window and all its children to
   disappear.  When xdestroy is true, a request to destroy the XWindow
   is sent out.  When it is false, it is assumed that the XWindow has
   been or will be destroyed by destroying some ancestor of this
   window.  */

static void
533 534
gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy,
			     gboolean our_destroy)
Elliot Lee's avatar
Elliot Lee committed
535 536 537 538 539 540 541 542 543 544
{
  GdkWindowPrivate *private;
  GdkWindowPrivate *temp_private;
  GdkWindow *temp_window;
  GList *children;
  GList *tmp;

  g_return_if_fail (window != NULL);

  private = (GdkWindowPrivate*) window;
545

Elliot Lee's avatar
Elliot Lee committed
546 547 548 549 550 551
  switch (private->window_type)
    {
    case GDK_WINDOW_TOPLEVEL:
    case GDK_WINDOW_CHILD:
    case GDK_WINDOW_DIALOG:
    case GDK_WINDOW_TEMP:
552
    case GDK_WINDOW_FOREIGN:
553
      if (!private->destroyed)
Elliot Lee's avatar
Elliot Lee committed
554
	{
555 556 557 558 559 560 561
	  if (private->parent)
	    {
	      GdkWindowPrivate *parent_private = (GdkWindowPrivate *)private->parent;
	      if (parent_private->children)
		parent_private->children = g_list_remove (parent_private->children, window);
	    }

562
	  if (private->window_type != GDK_WINDOW_FOREIGN)
Elliot Lee's avatar
Elliot Lee committed
563
	    {
564 565
	      children = tmp = private->children;
	      private->children = NULL;
566 567 568 569 570 571 572 573 574 575 576

	      while (tmp)
		{
		  temp_window = tmp->data;
		  tmp = tmp->next;
		  
		  temp_private = (GdkWindowPrivate*) temp_window;
		  if (temp_private)
		    gdk_window_internal_destroy (temp_window, FALSE,
						 our_destroy);
		}
577

578
	      g_list_free (children);
Elliot Lee's avatar
Elliot Lee committed
579 580
	    }

581 582 583
	  if (private->extension_events != 0)
	    gdk_input_window_destroy (window);

584 585 586 587 588 589 590 591 592 593 594
	  if(private->dnd_drag_data_numtypesavail > 0) 
	    {
	      g_free (private->dnd_drag_data_typesavail);
	      private->dnd_drag_data_typesavail = NULL;
	    }
	  if(private->dnd_drop_data_numtypesavail > 0) 
	    {
	      g_free (private->dnd_drop_data_typesavail);
	      private->dnd_drop_data_typesavail = NULL;
	    }

595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
	  if (private->filters)
	    {
	      tmp = private->filters;

	      while (tmp)
		{
		  g_free (tmp->data);
		  tmp = tmp->next;
		}

	      g_list_free (private->filters);
	      private->filters = NULL;
	    }
	  
	  if (private->window_type == GDK_WINDOW_FOREIGN)
	    {
	      if (our_destroy && (private->parent != NULL))
		{
		  /* It's somebody elses window, but in our heirarchy,
		   * so reparent it to the root window, and then send
		   * it a delete event, as if we were a WM
		   */
		  XClientMessageEvent xevent;
		  
		  gdk_window_hide (window);
		  gdk_window_reparent (window, NULL, 0, 0);
		  
		  xevent.type = ClientMessage;
		  xevent.window = private->xwindow;
		  xevent.message_type = gdk_wm_protocols;
		  xevent.format = 32;
		  xevent.data.l[0] = gdk_wm_delete_window;
		  xevent.data.l[1] = CurrentTime;
		  
		  XSendEvent (private->xdisplay, private->xwindow,
			      False, 0, (XEvent *)&xevent);
		}
	    }
	  else if (xdestroy)
Elliot Lee's avatar
Elliot Lee committed
634
	    XDestroyWindow (private->xdisplay, private->xwindow);
635

636 637 638
	  if (private->colormap)
	    gdk_colormap_unref (private->colormap);

Elliot Lee's avatar
Elliot Lee committed
639 640 641 642 643 644 645 646 647
	  private->destroyed = TRUE;
	}
      break;

    case GDK_WINDOW_ROOT:
      g_error ("attempted to destroy root window");
      break;

    case GDK_WINDOW_PIXMAP:
648
      g_error ("called gdk_window_destroy on a pixmap (use gdk_pixmap_unref)");
Elliot Lee's avatar
Elliot Lee committed
649 650 651 652
      break;
    }
}

653 654 655
/* Like internal_destroy, but also destroys the reference created by
   gdk_window_new. */

Elliot Lee's avatar
Elliot Lee committed
656
void
657 658
gdk_window_destroy (GdkWindow *window)
{
659
  gdk_window_internal_destroy (window, TRUE, TRUE);
660 661 662 663 664 665 666
  gdk_window_unref (window);
}

/* This function is called when the XWindow is really gone.  */

void
gdk_window_destroy_notify (GdkWindow *window)
Elliot Lee's avatar
Elliot Lee committed
667 668 669 670 671 672 673
{
  GdkWindowPrivate *private;

  g_return_if_fail (window != NULL);

  private = (GdkWindowPrivate*) window;

674 675 676 677 678
  if (!private->destroyed)
    {
      if (private->window_type == GDK_WINDOW_FOREIGN)
	gdk_window_internal_destroy (window, FALSE, FALSE);
      else
679
	g_warning ("GdkWindow %#lx unexpectedly destroyed", private->xwindow);
680 681
    }
  
682 683
  gdk_xid_table_remove (private->xwindow);
  gdk_window_unref (window);
Elliot Lee's avatar
Elliot Lee committed
684 685 686 687 688 689
}

GdkWindow*
gdk_window_ref (GdkWindow *window)
{
  GdkWindowPrivate *private = (GdkWindowPrivate *)window;
Tim Janik's avatar
Tim Janik committed
690
  g_return_val_if_fail (window != NULL, NULL);
Elliot Lee's avatar
Elliot Lee committed
691 692 693 694 695 696 697 698 699 700 701 702 703

  private->ref_count += 1;
  return window;
}

void
gdk_window_unref (GdkWindow *window)
{
  GdkWindowPrivate *private = (GdkWindowPrivate *)window;
  g_return_if_fail (window != NULL);

  private->ref_count -= 1;
  if (private->ref_count == 0)
704 705 706
    {
      if (!private->destroyed)
	g_warning ("losing last reference to undestroyed window\n");
707
      g_dataset_destroy (window);
708 709
      g_free (window);
    }
710

Elliot Lee's avatar
Elliot Lee committed
711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739
}

void
gdk_window_show (GdkWindow *window)
{
  GdkWindowPrivate *private;

  g_return_if_fail (window != NULL);

  private = (GdkWindowPrivate*) window;
  if (!private->destroyed)
    {
      XRaiseWindow (private->xdisplay, private->xwindow);
      XMapWindow (private->xdisplay, private->xwindow);
    }
}

void
gdk_window_hide (GdkWindow *window)
{
  GdkWindowPrivate *private;

  g_return_if_fail (window != NULL);

  private = (GdkWindowPrivate*) window;
  if (!private->destroyed)
    XUnmapWindow (private->xdisplay, private->xwindow);
}

740 741 742 743 744 745 746 747 748 749 750 751
void
gdk_window_withdraw (GdkWindow *window)
{
  GdkWindowPrivate *private;

  g_return_if_fail (window != NULL);

  private = (GdkWindowPrivate*) window;
  if (!private->destroyed)
    XWithdrawWindow (private->xdisplay, private->xwindow, 0);
}

Elliot Lee's avatar
Elliot Lee committed
752 753 754 755 756 757 758 759 760 761
void
gdk_window_move (GdkWindow *window,
		 gint       x,
		 gint       y)
{
  GdkWindowPrivate *private;

  g_return_if_fail (window != NULL);

  private = (GdkWindowPrivate*) window;
762
  if (!private->destroyed)
Elliot Lee's avatar
Elliot Lee committed
763
    {
764 765 766 767 768 769 770
      XMoveWindow (private->xdisplay, private->xwindow, x, y);
      
      if (private->window_type == GDK_WINDOW_CHILD)
	{
	  private->x = x;
	  private->y = y;
	}
Elliot Lee's avatar
Elliot Lee committed
771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822
    }
}

void
gdk_window_resize (GdkWindow *window,
		   gint       width,
		   gint       height)
{
  GdkWindowPrivate *private;

  g_return_if_fail (window != NULL);

  if (width < 1)
    width = 1;
  if (height < 1)
    height = 1;

  private = (GdkWindowPrivate*) window;

  if (!private->destroyed &&
      ((private->resize_count > 0) ||
       (private->width != (guint16) width) ||
       (private->height != (guint16) height)))
    {
      XResizeWindow (private->xdisplay, private->xwindow, width, height);
      private->resize_count += 1;

      if (private->window_type == GDK_WINDOW_CHILD)
	{
	  private->width = width;
	  private->height = height;
	}
    }
}

void
gdk_window_move_resize (GdkWindow *window,
			gint       x,
			gint       y,
			gint       width,
			gint       height)
{
  GdkWindowPrivate *private;

  g_return_if_fail (window != NULL);

  if (width < 1)
    width = 1;
  if (height < 1)
    height = 1;

  private = (GdkWindowPrivate*) window;
823
  if (!private->destroyed)
Elliot Lee's avatar
Elliot Lee committed
824
    {
825 826 827 828 829 830 831 832 833
      XMoveResizeWindow (private->xdisplay, private->xwindow, x, y, width, height);
      
      if (private->window_type == GDK_WINDOW_CHILD)
	{
	  private->x = x;
	  private->y = y;
	  private->width = width;
	  private->height = height;
	}
Elliot Lee's avatar
Elliot Lee committed
834 835 836 837 838 839 840 841 842 843 844
    }
}

void
gdk_window_reparent (GdkWindow *window,
		     GdkWindow *new_parent,
		     gint       x,
		     gint       y)
{
  GdkWindowPrivate *window_private;
  GdkWindowPrivate *parent_private;
845
  GdkWindowPrivate *old_parent_private;
Elliot Lee's avatar
Elliot Lee committed
846 847 848 849 850 851 852

  g_return_if_fail (window != NULL);

  if (!new_parent)
    new_parent = (GdkWindow*) &gdk_root_parent;

  window_private = (GdkWindowPrivate*) window;
853
  old_parent_private = (GdkWindowPrivate*)window_private->parent;
Elliot Lee's avatar
Elliot Lee committed
854 855
  parent_private = (GdkWindowPrivate*) new_parent;

856 857 858 859 860
  if (!window_private->destroyed && !parent_private->destroyed)
    XReparentWindow (window_private->xdisplay,
		     window_private->xwindow,
		     parent_private->xwindow,
		     x, y);
861

862 863
  window_private->parent = new_parent;

864 865
  if (old_parent_private)
    old_parent_private->children = g_list_remove (old_parent_private->children, window);
866 867
  parent_private->children = g_list_prepend (parent_private->children, window);
  
Elliot Lee's avatar
Elliot Lee committed
868 869 870 871 872 873 874 875 876 877 878
}

void
gdk_window_clear (GdkWindow *window)
{
  GdkWindowPrivate *private;

  g_return_if_fail (window != NULL);

  private = (GdkWindowPrivate*) window;

879 880
  if (!private->destroyed)
    XClearWindow (private->xdisplay, private->xwindow);
Elliot Lee's avatar
Elliot Lee committed
881 882 883 884 885 886 887 888 889 890
}

void
gdk_window_clear_area (GdkWindow *window,
		       gint       x,
		       gint       y,
		       gint       width,
		       gint       height)
{
  GdkWindowPrivate *private;
891
  
Elliot Lee's avatar
Elliot Lee committed
892
  g_return_if_fail (window != NULL);
893
  
Elliot Lee's avatar
Elliot Lee committed
894
  private = (GdkWindowPrivate*) window;
895
  
Elliot Lee's avatar
Elliot Lee committed
896 897 898 899 900 901 902 903 904 905 906 907 908
  if (!private->destroyed)
    XClearArea (private->xdisplay, private->xwindow,
		x, y, width, height, False);
}

void
gdk_window_clear_area_e (GdkWindow *window,
		         gint       x,
		         gint       y,
		         gint       width,
		         gint       height)
{
  GdkWindowPrivate *private;
909
  
Elliot Lee's avatar
Elliot Lee committed
910
  g_return_if_fail (window != NULL);
911
  
Elliot Lee's avatar
Elliot Lee committed
912
  private = (GdkWindowPrivate*) window;
913
  
Elliot Lee's avatar
Elliot Lee committed
914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
  if (!private->destroyed)
    XClearArea (private->xdisplay, private->xwindow,
		x, y, width, height, True);
}

void
gdk_window_copy_area (GdkWindow    *window,
		      GdkGC        *gc,
		      gint          x,
		      gint          y,
		      GdkWindow    *source_window,
		      gint          source_x,
		      gint          source_y,
		      gint          width,
		      gint          height)
{
  GdkWindowPrivate *src_private;
  GdkWindowPrivate *dest_private;
  GdkGCPrivate *gc_private;
933 934
  
  g_return_if_fail (window != NULL);
Elliot Lee's avatar
Elliot Lee committed
935 936 937 938
  g_return_if_fail (gc != NULL);
  
  if (source_window == NULL)
    source_window = window;
939
  
Elliot Lee's avatar
Elliot Lee committed
940 941 942 943 944
  src_private = (GdkWindowPrivate*) source_window;
  dest_private = (GdkWindowPrivate*) window;
  gc_private = (GdkGCPrivate*) gc;
  
  if (!src_private->destroyed && !dest_private->destroyed)
945 946 947 948 949 950 951
    {
      XCopyArea (dest_private->xdisplay, src_private->xwindow, dest_private->xwindow,
		 gc_private->xgc,
		 source_x, source_y,
		 width, height,
		 x, y);
    }
Elliot Lee's avatar
Elliot Lee committed
952 953 954 955 956 957
}

void
gdk_window_raise (GdkWindow *window)
{
  GdkWindowPrivate *private;
958
  
Elliot Lee's avatar
Elliot Lee committed
959
  g_return_if_fail (window != NULL);
960
  
Elliot Lee's avatar
Elliot Lee committed
961
  private = (GdkWindowPrivate*) window;
962
  
Elliot Lee's avatar
Elliot Lee committed
963 964 965 966 967 968 969 970
  if (!private->destroyed)
    XRaiseWindow (private->xdisplay, private->xwindow);
}

void
gdk_window_lower (GdkWindow *window)
{
  GdkWindowPrivate *private;
971
  
Elliot Lee's avatar
Elliot Lee committed
972
  g_return_if_fail (window != NULL);
973
  
Elliot Lee's avatar
Elliot Lee committed
974
  private = (GdkWindowPrivate*) window;
975
  
Elliot Lee's avatar
Elliot Lee committed
976 977 978 979 980 981 982 983 984
  if (!private->destroyed)
    XLowerWindow (private->xdisplay, private->xwindow);
}

void
gdk_window_set_user_data (GdkWindow *window,
			  gpointer   user_data)
{
  g_return_if_fail (window != NULL);
985
  
Elliot Lee's avatar
Elliot Lee committed
986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
  window->user_data = user_data;
}

void
gdk_window_set_hints (GdkWindow *window,
		      gint       x,
		      gint       y,
		      gint       min_width,
		      gint       min_height,
		      gint       max_width,
		      gint       max_height,
		      gint       flags)
{
  GdkWindowPrivate *private;
  XSizeHints size_hints;
1001
  
Elliot Lee's avatar
Elliot Lee committed
1002
  g_return_if_fail (window != NULL);
1003
  
Elliot Lee's avatar
Elliot Lee committed
1004
  private = (GdkWindowPrivate*) window;
1005 1006
  if (private->destroyed)
    return;
1007
  
Elliot Lee's avatar
Elliot Lee committed
1008
  size_hints.flags = 0;
1009
  
Elliot Lee's avatar
Elliot Lee committed
1010 1011 1012 1013 1014 1015
  if (flags & GDK_HINT_POS)
    {
      size_hints.flags |= PPosition;
      size_hints.x = x;
      size_hints.y = y;
    }
1016
  
Elliot Lee's avatar
Elliot Lee committed
1017 1018 1019 1020 1021 1022
  if (flags & GDK_HINT_MIN_SIZE)
    {
      size_hints.flags |= PMinSize;
      size_hints.min_width = min_width;
      size_hints.min_height = min_height;
    }
1023
  
Elliot Lee's avatar
Elliot Lee committed
1024 1025 1026 1027 1028 1029
  if (flags & GDK_HINT_MAX_SIZE)
    {
      size_hints.flags |= PMaxSize;
      size_hints.max_width = max_width;
      size_hints.max_height = max_height;
    }
1030
  
Elliot Lee's avatar
Elliot Lee committed
1031 1032 1033 1034 1035 1036 1037 1038 1039
  if (flags)
    XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
}

void
gdk_window_set_title (GdkWindow   *window,
		      const gchar *title)
{
  GdkWindowPrivate *private;
1040
  
Elliot Lee's avatar
Elliot Lee committed
1041
  g_return_if_fail (window != NULL);
1042
  
Elliot Lee's avatar
Elliot Lee committed
1043
  private = (GdkWindowPrivate*) window;
1044 1045 1046
  if (!private->destroyed)
    XmbSetWMProperties (private->xdisplay, private->xwindow,
			title, title, NULL, 0, NULL, NULL, NULL);
Elliot Lee's avatar
Elliot Lee committed
1047 1048 1049 1050 1051 1052 1053
}

void
gdk_window_set_background (GdkWindow *window,
			   GdkColor  *color)
{
  GdkWindowPrivate *private;
1054
  
Elliot Lee's avatar
Elliot Lee committed
1055
  g_return_if_fail (window != NULL);
1056
  
Elliot Lee's avatar
Elliot Lee committed
1057
  private = (GdkWindowPrivate*) window;
1058 1059
  if (!private->destroyed)
    XSetWindowBackground (private->xdisplay, private->xwindow, color->pixel);
Elliot Lee's avatar
Elliot Lee committed
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069
}

void
gdk_window_set_back_pixmap (GdkWindow *window,
			    GdkPixmap *pixmap,
			    gint       parent_relative)
{
  GdkWindowPrivate *window_private;
  GdkPixmapPrivate *pixmap_private;
  Pixmap xpixmap;
1070
  
Elliot Lee's avatar
Elliot Lee committed
1071
  g_return_if_fail (window != NULL);
1072
  
Elliot Lee's avatar
Elliot Lee committed
1073 1074
  window_private = (GdkWindowPrivate*) window;
  pixmap_private = (GdkPixmapPrivate*) pixmap;
1075
  
Elliot Lee's avatar
Elliot Lee committed
1076 1077 1078 1079
  if (pixmap)
    xpixmap = pixmap_private->xwindow;
  else
    xpixmap = None;
1080
  
Elliot Lee's avatar
Elliot Lee committed
1081 1082
  if (parent_relative)
    xpixmap = ParentRelative;
1083
  
1084 1085
  if (!window_private->destroyed)
    XSetWindowBackgroundPixmap (window_private->xdisplay, window_private->xwindow, xpixmap);
Elliot Lee's avatar
Elliot Lee committed
1086 1087 1088 1089 1090 1091 1092 1093 1094
}

void
gdk_window_set_cursor (GdkWindow *window,
		       GdkCursor *cursor)
{
  GdkWindowPrivate *window_private;
  GdkCursorPrivate *cursor_private;
  Cursor xcursor;
1095
  
Elliot Lee's avatar
Elliot Lee committed
1096
  g_return_if_fail (window != NULL);
1097
  
Elliot Lee's avatar
Elliot Lee committed
1098 1099
  window_private = (GdkWindowPrivate*) window;
  cursor_private = (GdkCursorPrivate*) cursor;
1100
  
Elliot Lee's avatar
Elliot Lee committed
1101 1102 1103 1104
  if (!cursor)
    xcursor = None;
  else
    xcursor = cursor_private->xcursor;
1105
  
1106 1107
  if (!window_private->destroyed)
    XDefineCursor (window_private->xdisplay, window_private->xwindow, xcursor);
Elliot Lee's avatar
Elliot Lee committed
1108 1109 1110 1111 1112 1113 1114 1115
}

void
gdk_window_set_colormap (GdkWindow   *window,
			 GdkColormap *colormap)
{
  GdkWindowPrivate *window_private;
  GdkColormapPrivate *colormap_private;
1116
  
Elliot Lee's avatar
Elliot Lee committed
1117 1118
  g_return_if_fail (window != NULL);
  g_return_if_fail (colormap != NULL);
1119
  
Elliot Lee's avatar
Elliot Lee committed
1120 1121
  window_private = (GdkWindowPrivate*) window;
  colormap_private = (GdkColormapPrivate*) colormap;
1122
  
1123 1124 1125 1126 1127
  if (!window_private->destroyed)
    {
      XSetWindowColormap (window_private->xdisplay,
			  window_private->xwindow,
			  colormap_private->xcolormap);
1128 1129 1130 1131 1132

      if (window_private->colormap)
	gdk_colormap_unref (window_private->colormap);
      window_private->colormap = colormap;
      gdk_colormap_ref (window_private->colormap);
1133 1134 1135 1136
      
      if (window_private->window_type != GDK_WINDOW_TOPLEVEL)
	gdk_window_add_colormap_windows (window);
    }
Elliot Lee's avatar
Elliot Lee committed
1137 1138 1139 1140 1141 1142 1143
}

void
gdk_window_get_user_data (GdkWindow *window,
			  gpointer  *data)
{
  g_return_if_fail (window != NULL);
1144
  
Elliot Lee's avatar
Elliot Lee committed
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163
  *data = window->user_data;
}

void
gdk_window_get_geometry (GdkWindow *window,
			 gint      *x,
			 gint      *y,
			 gint      *width,
			 gint      *height,
			 gint      *depth)
{
  GdkWindowPrivate *window_private;
  Window root;
  gint tx;
  gint ty;
  guint twidth;
  guint theight;
  guint tborder_width;
  guint tdepth;
1164
  
Elliot Lee's avatar
Elliot Lee committed
1165 1166
  if (!window)
    window = (GdkWindow*) &gdk_root_parent;
1167
  
Elliot Lee's avatar
Elliot Lee committed
1168
  window_private = (GdkWindowPrivate*) window;
1169
  
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185
  if (!window_private->destroyed)
    {
      XGetGeometry (window_private->xdisplay, window_private->xwindow,
		    &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
      
      if (x)
	*x = tx;
      if (y)
	*y = ty;
      if (width)
	*width = twidth;
      if (height)
	*height = theight;
      if (depth)
	*depth = tdepth;
    }
Elliot Lee's avatar
Elliot Lee committed
1186 1187 1188 1189 1190 1191 1192 1193
}

void
gdk_window_get_position (GdkWindow *window,
			 gint      *x,
			 gint      *y)
{
  GdkWindowPrivate *window_private;
1194
  
Elliot Lee's avatar
Elliot Lee committed
1195
  g_return_if_fail (window != NULL);
1196
  
Elliot Lee's avatar
Elliot Lee committed
1197
  window_private = (GdkWindowPrivate*) window;
1198
  
Elliot Lee's avatar
Elliot Lee committed
1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210
  if (x)
    *x = window_private->x;
  if (y)
    *y = window_private->y;
}

void
gdk_window_get_size (GdkWindow *window,
		     gint       *width,
		     gint       *height)
{
  GdkWindowPrivate *window_private;
1211
  
Elliot Lee's avatar
Elliot Lee committed
1212
  g_return_if_fail (window != NULL);
1213
  
Elliot Lee's avatar
Elliot Lee committed
1214
  window_private = (GdkWindowPrivate*) window;
1215
  
Elliot Lee's avatar
Elliot Lee committed
1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226
  if (width)
    *width = window_private->width;
  if (height)
    *height = window_private->height;
}

GdkVisual*
gdk_window_get_visual (GdkWindow *window)
{
  GdkWindowPrivate *window_private;
  XWindowAttributes window_attributes;
1227
   
Elliot Lee's avatar
Elliot Lee committed
1228
  g_return_val_if_fail (window != NULL, NULL);
1229

Elliot Lee's avatar
Elliot Lee committed
1230
  window_private = (GdkWindowPrivate*) window;
1231 1232 1233
  /* Huh? ->parent is never set for a pixmap. We should just return
   * null immeditately
   */
Elliot Lee's avatar
Elliot Lee committed
1234 1235
  while (window_private && (window_private->window_type == GDK_WINDOW_PIXMAP))
    window_private = (GdkWindowPrivate*) window_private->parent;
1236
  
1237
  if (window_private && !window_private->destroyed)
Elliot Lee's avatar
Elliot Lee committed
1238
    {
1239
       if (window_private->colormap == NULL)
1240 1241 1242 1243 1244 1245 1246 1247
	 {
	    XGetWindowAttributes (window_private->xdisplay,
				  window_private->xwindow,
				  &window_attributes);
	    return gdk_visual_lookup (window_attributes.visual);
	 }
       else
	 return ((GdkColormapPrivate *)window_private->colormap)->visual;
Elliot Lee's avatar
Elliot Lee committed
1248
    }
1249
  
Elliot Lee's avatar
Elliot Lee committed
1250 1251 1252 1253 1254 1255 1256
  return NULL;
}

GdkColormap*
gdk_window_get_colormap (GdkWindow *window)
{
  GdkWindowPrivate *window_private;
1257
  XWindowAttributes window_attributes;
1258
  
Elliot Lee's avatar
Elliot Lee committed
1259 1260
  g_return_val_if_fail (window != NULL, NULL);
  window_private = (GdkWindowPrivate*) window;
1261 1262

  g_return_val_if_fail (window_private->window_type != GDK_WINDOW_PIXMAP, NULL);
1263 1264
  if (!window_private->destroyed)
    {
1265
      if (window_private->colormap == NULL)
1266 1267 1268 1269 1270 1271 1272 1273
	{
	  XGetWindowAttributes (window_private->xdisplay,
				window_private->xwindow,
				&window_attributes);
	  return gdk_colormap_lookup (window_attributes.colormap);
	 }
       else
	 return window_private->colormap;
1274
    }
1275
  
1276
  return NULL;
Elliot Lee's avatar
Elliot Lee committed
1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297
}

GdkWindowType
gdk_window_get_type (GdkWindow *window)
{
  GdkWindowPrivate *window_private;

  g_return_val_if_fail (window != NULL, (GdkWindowType) -1);

  window_private = (GdkWindowPrivate*) window;
  return window_private->window_type;
}

gint
gdk_window_get_origin (GdkWindow *window,
		       gint      *x,
		       gint      *y)
{
  GdkWindowPrivate *private;
  gint return_val;
  Window child;
1298 1299
  gint tx = 0;
  gint ty = 0;
Elliot Lee's avatar
Elliot Lee committed
1300 1301 1302 1303 1304

  g_return_val_if_fail (window != NULL, 0);

  private = (GdkWindowPrivate*) window;

1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316
  if (!private->destroyed)
    {
      return_val = XTranslateCoordinates (private->xdisplay,
					  private->xwindow,
					  gdk_root_window,
					  0, 0, &tx, &ty,
					  &child);
      
    }
  else
    return_val = 0;
  
1317 1318 1319 1320 1321
  if (x)
    *x = tx;
  if (y)
    *y = ty;
  
Elliot Lee's avatar
Elliot Lee committed
1322 1323 1324
  return return_val;
}

1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380
void
gdk_window_get_root_origin (GdkWindow *window,
			    gint      *x,
			    gint      *y)
{
  GdkWindowPrivate *private;
  Window xwindow;
  Window xparent;
  Window root;
  Window *children;
  unsigned int nchildren;

  g_return_if_fail (window != NULL);

  private = (GdkWindowPrivate*) window;
  if (x)
    *x = 0;
  if (y)
    *y = 0;
  if (private->destroyed)
    return;
      
  while (private->parent && ((GdkWindowPrivate*) private->parent)->parent)
    private = (GdkWindowPrivate*) private->parent;
  if (private->destroyed)
    return;

  xparent = private->xwindow;
  do
    {
      xwindow = xparent;
      if (!XQueryTree (private->xdisplay, xwindow,
		       &root, &xparent,
		       &children, &nchildren))
	return;

      if (children)
	XFree (children);
    }
  while (xparent != root);

  if (xparent == root)
    {
      unsigned int ww, wh, wb, wd;
      int wx, wy;

      if (XGetGeometry (private->xdisplay, xwindow, &root, &wx, &wy, &ww, &wh, &wb, &wd))
	{
	  if (x)
	    *x = wx;
	  if (y)
	    *y = wy;
	}
    }
}

Elliot Lee's avatar
Elliot Lee committed
1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391
GdkWindow*
gdk_window_get_pointer (GdkWindow       *window,
			gint            *x,
			gint            *y,
			GdkModifierType *mask)
{
  GdkWindowPrivate *private;
  GdkWindow *return_val;
  Window root;
  Window child;
  int rootx, rooty;
1392 1393 1394
  int winx = 0;
  int winy = 0;
  unsigned int xmask = 0;
Elliot Lee's avatar
Elliot Lee committed
1395 1396 1397 1398 1399 1400 1401

  if (!window)
    window = (GdkWindow*) &gdk_root_parent;

  private = (GdkWindowPrivate*) window;

  return_val = NULL;
1402 1403
  if (!private->destroyed &&
      XQueryPointer (private->xdisplay, private->xwindow, &root, &child,
Elliot Lee's avatar
Elliot Lee committed
1404 1405 1406 1407 1408
		     &rootx, &rooty, &winx, &winy, &xmask))
    {
      if (child)
	return_val = gdk_window_lookup (child);
    }
1409
  
1410 1411 1412 1413 1414 1415 1416
  if (x)
    *x = winx;
  if (y)
    *y = winy;
  if (mask)
    *mask = xmask;
  
Elliot Lee's avatar
Elliot Lee committed
1417 1418 1419
  return return_val;
}

1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459
GdkWindow*
gdk_window_at_pointer (gint *win_x,
		       gint *win_y)
{
  GdkWindowPrivate *private;
  GdkWindow *window;
  Window root;
  Window xwindow;
  Window xwindow_last = 0;
  int rootx = -1, rooty = -1;
  int winx, winy;
  unsigned int xmask;

  private = &gdk_root_parent;

  xwindow = private->xwindow;

  XGrabServer (private->xdisplay);
  while (xwindow)
    {
      xwindow_last = xwindow;
      XQueryPointer (private->xdisplay,
		     xwindow,
		     &root, &xwindow,
		     &rootx, &rooty,
		     &winx, &winy,
		     &xmask);
    }
  XUngrabServer (private->xdisplay);
  
  window = gdk_window_lookup (xwindow_last);

  if (win_x)
    *win_x = window ? winx : -1;
  if (win_y)
    *win_y = window ? winy : -1;

  return window;
}

Elliot Lee's avatar
Elliot Lee committed
1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500
GdkWindow*
gdk_window_get_parent (GdkWindow *window)
{
  g_return_val_if_fail (window != NULL, NULL);

  return ((GdkWindowPrivate*) window)->parent;
}

GdkWindow*
gdk_window_get_toplevel (GdkWindow *window)
{
  GdkWindowPrivate *private;

  g_return_val_if_fail (window != NULL, NULL);

  private = (GdkWindowPrivate*) window;

  while (private->window_type == GDK_WINDOW_CHILD)
    {
      window = ((GdkWindowPrivate*) window)->parent;
      private = (GdkWindowPrivate*) window;
    }

  return window;
}

GList*
gdk_window_get_children (GdkWindow *window)
{
  GdkWindowPrivate *private;
  GdkWindow *child;
  GList *children;
  Window root;
  Window parent;
  Window *xchildren;
  unsigned int nchildren;
  unsigned int i;

  g_return_val_if_fail (window != NULL, NULL);

  private = (GdkWindowPrivate*) window;
1501 1502
  if (private->destroyed)
    return NULL;
Elliot Lee's avatar
Elliot Lee committed
1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517

  XQueryTree (private->xdisplay, private->xwindow,
	      &root, &parent, &xchildren, &nchildren);

  children = NULL;

  if (nchildren > 0)
    {
      for (i = 0; i < nchildren; i++)
	{
	  child = gdk_window_lookup (xchildren[i]);
          if (child)
            children = g_list_prepend (children, child);
	}

1518 1519
      if (xchildren)
	XFree (xchildren);
Elliot Lee's avatar
Elliot Lee committed
1520 1521 1522 1523 1524 1525 1526 1527
    }

  return children;
}

GdkEventMask  
gdk_window_get_events      (GdkWindow       *window)
{
1528
  GdkWindowPrivate *private;
Elliot Lee's avatar
Elliot Lee committed
1529 1530 1531 1532
  XWindowAttributes attrs;
  GdkEventMask event_mask;
  int i;

1533 1534 1535 1536 1537 1538 1539
  g_return_val_if_fail (window != NULL, 0);

  private = (GdkWindowPrivate*) window;
  if (private->destroyed)
    return 0;

  XGetWindowAttributes (gdk_display, private->xwindow, 
Elliot Lee's avatar
Elliot Lee committed
1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555
			&attrs);

  event_mask = 0;
  for (i = 0; i < nevent_masks; i++)
    {
      if (attrs.your_event_mask & event_mask_table[i])
	event_mask |= 1 << (i + 1);
    }

  return event_mask;
}

void          
gdk_window_set_events      (GdkWindow       *window,
			    GdkEventMask     event_mask)
{
1556
  GdkWindowPrivate *private;
Elliot Lee's avatar
Elliot Lee committed
1557 1558 1559
  long xevent_mask;
  int i;

1560 1561 1562 1563 1564 1565
  g_return_if_fail (window != NULL);

  private = (GdkWindowPrivate*) window;
  if (private->destroyed)
    return;

Elliot Lee's avatar
Elliot Lee committed
1566 1567 1568 1569 1570 1571 1572
  xevent_mask = StructureNotifyMask;
  for (i = 0; i < nevent_masks; i++)
    {
      if (event_mask & (1 << (i + 1)))
	xevent_mask |= event_mask_table[i];
    }
  
1573
  XSelectInput (gdk_display, private->xwindow, 
Elliot Lee's avatar
Elliot Lee committed
1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591
		xevent_mask);
}

void
gdk_window_add_colormap_windows (GdkWindow *window)
{
  GdkWindow *toplevel;
  GdkWindowPrivate *toplevel_private;
  GdkWindowPrivate *window_private;
  Window *old_windows;
  Window *new_windows;
  int i, count;

  g_return_if_fail (window != NULL);

  toplevel = gdk_window_get_toplevel (window);
  toplevel_private = (GdkWindowPrivate*) toplevel;
  window_private = (GdkWindowPrivate*) window;
1592 1593
  if (window_private->destroyed)
    return;
Elliot Lee's avatar
Elliot Lee committed
1594

1595
  old_windows = NULL;
Elliot Lee's avatar
Elliot Lee committed
1596 1597 1598 1599 1600 1601 1602 1603 1604
  if (!XGetWMColormapWindows (toplevel_private->xdisplay,
			      toplevel_private->xwindow,
			      &old_windows, &count))
    {
      count = 0;
    }

  for (i = 0; i < count; i++)
    if (old_windows[i] == window_private->xwindow)
1605 1606 1607 1608
      {
	XFree (old_windows);
	return;
      }
Elliot Lee's avatar
Elliot Lee committed
1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626

  new_windows = g_new (Window, count + 1);

  for (i = 0; i < count; i++)
    new_windows[i] = old_windows[i];
  new_windows[count] = window_private->xwindow;

  XSetWMColormapWindows (toplevel_private->xdisplay,
			 toplevel_private->xwindow,
			 new_windows, count + 1);

  g_free (new_windows);
  if (old_windows)
    XFree (old_windows);
}

/*
 * This needs the X11 shape extension.
1627
 * If not available, shaped windows will look
Elliot Lee's avatar
Elliot Lee committed
1628 1629 1630 1631 1632 1633 1634
 * ugly, but programs still work.    Stefan Wille
 */
void
gdk_window_shape_combine_mask (GdkWindow *window,
			       GdkBitmap *mask,
			       gint x, gint y)
{
1635 1636 1637 1638
  enum { UNKNOWN, NO, YES };

  static gint have_shape = UNKNOWN;

Elliot Lee's avatar
Elliot Lee committed
1639
  GdkWindowPrivate *window_private;
1640
  Pixmap pixmap;
Elliot Lee's avatar
Elliot Lee committed
1641 1642 1643

  g_return_if_fail (window != NULL);

1644 1645
#ifdef HAVE_SHAPE_EXT
  if (have_shape == UNKNOWN)
1646
    {
1647 1648 1649 1650 1651
      int ignore;
      if (XQueryExtension(gdk_display, "SHAPE", &ignore, &ignore, &ignore))
	have_shape = YES;
      else
	have_shape = NO;
1652
    }
1653 1654
  
  if (have_shape == YES)
1655
    {
1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679
      window_private = (GdkWindowPrivate*) window;
      if (window_private->destroyed)
	return;
      
      if (mask)
	{
	  GdkWindowPrivate *pixmap_private;
	  
	  pixmap_private = (GdkWindowPrivate*) mask;
	  pixmap = (Pixmap) pixmap_private->xwindow;
	}
      else
	{
	  x = 0;
	  y = 0;
	  pixmap = None;
	}
      
      XShapeCombineMask  (window_private->xdisplay,
			  window_private->xwindow,
			  ShapeBounding,
			  x, y,
			  pixmap,
			  ShapeSet);
1680
    }
1681
#endif /* HAVE_SHAPE_EXT */
Elliot Lee's avatar
Elliot Lee committed
1682 1683 1684 1685 1686 1687 1688 1689 1690 1691
}

void
gdk_dnd_drag_addwindow (GdkWindow *window)
{
  GdkWindowPrivate *window_private;
  
  g_return_if_fail (window != NULL);
  
  window_private = (GdkWindowPrivate *) window;
1692 1693
  if (window_private->destroyed)
    return;
Elliot Lee's avatar
Elliot Lee committed
1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718
  
  if (window_private->dnd_drag_enabled == 1 && gdk_dnd.drag_really == 0)
    {
      gdk_dnd.drag_numwindows++;
      gdk_dnd.drag_startwindows = g_realloc (gdk_dnd.drag_startwindows,
					     gdk_dnd.drag_numwindows
					     * sizeof(GdkWindow *));
      gdk_dnd.drag_startwindows[gdk_dnd.drag_numwindows - 1] = window;
      window_private->dnd_drag_accepted = 0;
    } 
  else
    g_warning ("dnd_really is 1 or drag is not enabled! can't addwindow\n");
}

void
gdk_window_dnd_drag_set (GdkWindow   *window,
			 guint8       drag_enable,
			 gchar      **typelist,
			 guint        numtypes)
{
  GdkWindowPrivate *window_private;
  int i, wasset = 0;
  
  g_return_if_fail (window != NULL);
  window_private = (GdkWindowPrivate *) window;
1719 1720
  if (window_private->destroyed)
    return;
Elliot Lee's avatar
Elliot Lee committed
1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759
  
  window_private->dnd_drag_enabled = drag_enable ? 1 : 0;
  
  if (drag_enable)
    {
      g_return_if_fail(typelist != NULL);
      
      if (window_private->dnd_drag_data_numtypesavail > 3)
	wasset = 1;
      window_private->dnd_drag_data_numtypesavail = numtypes;
      
      window_private->dnd_drag_data_typesavail =
	g_realloc (window_private->dnd_drag_data_typesavail,
		   (numtypes + 1) * sizeof (GdkAtom));
      
      for (i = 0; i < numtypes; i++)
	{
	  /* Allow blanket use of ALL to get anything... */
	  if (strcmp (typelist[i], "ALL"))
	    window_private->dnd_drag_data_typesavail[i] =
	      gdk_atom_intern (typelist[i], FALSE);
	  else
	    window_private->dnd_drag_data_typesavail[i] = None;
	}
      
      /* 
       * set our extended type list if we need to 
       */
      if (numtypes > 3)
	gdk_property_change(window, gdk_dnd.gdk_XdeTypelist,
			    XA_PRIMARY, 32, GDK_PROP_MODE_REPLACE,
			    (guchar *)(window_private->dnd_drag_data_typesavail
			     + (sizeof(GdkAtom) * 3)),
			    (numtypes - 3) * sizeof(GdkAtom));
      else if (wasset)
	gdk_property_delete (window, gdk_dnd.gdk_XdeTypelist);
    }
  else
    {
Elliot Lee's avatar
Elliot Lee committed
1760
      g_free (window_private->dnd_drag_data_typesavail);
Elliot Lee's avatar
Elliot Lee committed
1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777
      window_private->dnd_drag_data_typesavail = NULL;
      window_private->dnd_drag_data_numtypesavail = 0;
    }
}

void
gdk_window_dnd_drop_set (GdkWindow   *window,
			 guint8       drop_enable,
			 gchar      **typelist,
			 guint        numtypes,
			 guint8       destructive_op)
{
  GdkWindowPrivate *window_private;
  int i;
  
  g_return_if_fail (window != NULL);
  window_private = (GdkWindowPrivate *) window;
1778 1779
  if (window_private->destroyed)
    return;
Elliot Lee's avatar
Elliot Lee committed
1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814