gdkwindow-x11.c 160 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 28
#include <config.h>

Elliot Lee's avatar
Elliot Lee committed
29 30 31 32
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <netinet/in.h>
33
#include <unistd.h>
34

Elliot Lee's avatar
Elliot Lee committed
35
#include "gdk.h"
Owen Taylor's avatar
Started  
Owen Taylor committed
36 37

#include "gdkwindow.h"
38
#include "gdkasync.h"
Owen Taylor's avatar
Started  
Owen Taylor committed
39
#include "gdkinputprivate.h"
40
#include "gdkdisplay-x11.h"
41
#include "gdkprivate-x11.h"
Owen Taylor's avatar
Owen Taylor committed
42
#include "gdkregion.h"
43
#include "gdkinternals.h"
44
#include "MwmUtil.h"
45
#include "gdkwindow-x11.h"
46
#include "gdkalias.h"
47

48 49 50
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
51

Elliot Lee's avatar
Elliot Lee committed
52

53 54 55 56
#ifdef HAVE_SHAPE_EXT
#include <X11/extensions/shape.h>
#endif

57
const int _gdk_event_mask_table[21] =
Elliot Lee's avatar
Elliot Lee committed
58 59 60 61 62 63 64 65
{
  ExposureMask,
  PointerMotionMask,
  PointerMotionHintMask,
  ButtonMotionMask,
  Button1MotionMask,
  Button2MotionMask,
  Button3MotionMask,
66 67
  ButtonPressMask,
  ButtonReleaseMask,
Elliot Lee's avatar
Elliot Lee committed
68 69 70 71 72 73 74
  KeyPressMask,
  KeyReleaseMask,
  EnterWindowMask,
  LeaveWindowMask,
  FocusChangeMask,
  StructureNotifyMask,
  PropertyChangeMask,
75
  VisibilityChangeMask,
Elliot Lee's avatar
Elliot Lee committed
76
  0,				/* PROXIMITY_IN */
Elliot Lee's avatar
Elliot Lee committed
77
  0,				/* PROXIMTY_OUT */
78 79
  SubstructureNotifyMask,
  ButtonPressMask      /* SCROLL; on X mouse wheel events is treated as mouse button 4/5 */
Elliot Lee's avatar
Elliot Lee committed
80
};
81
const int _gdk_nenvent_masks = sizeof (_gdk_event_mask_table) / sizeof (int);
Elliot Lee's avatar
Elliot Lee committed
82

83
/* Forward declarations */
84 85 86 87
static void     gdk_window_set_static_win_gravity (GdkWindow  *window,
						   gboolean    on);
static gboolean gdk_window_have_shape_ext         (GdkDisplay *display);
static gboolean gdk_window_icon_name_set          (GdkWindow  *window);
88
static void     gdk_window_add_colormap_windows   (GdkWindow  *window);
89 90 91
static void     set_wm_name                       (GdkDisplay  *display,
						   Window       xwindow,
						   const gchar *name);
Elliot Lee's avatar
Elliot Lee committed
92

93 94
static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable);
static void         gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
95 96 97 98 99
						      GdkColormap *cmap);
static void         gdk_window_impl_x11_get_size    (GdkDrawable *drawable,
						     gint *width,
						     gint *height);
static GdkRegion*  gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable);
100 101 102
static void gdk_window_impl_x11_init       (GdkWindowImplX11      *window);
static void gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass);
static void gdk_window_impl_x11_finalize   (GObject            *object);
103

104 105
static gpointer parent_class = NULL;

106 107
#define WINDOW_IS_TOPLEVEL(window)		   \
  (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
Alexander Larsson's avatar
Alexander Larsson committed
108
   GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
109

Matthias Clasen's avatar
Matthias Clasen committed
110 111 112 113 114 115 116 117
/* Return whether time1 is considered later than time2 as far as xserver
 * time is concerned.  Accounts for wraparound.
 */
#define XSERVER_TIME_IS_LATER(time1, time2)                        \
  ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) ||  \
    (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 ))     \
  )

118 119
GType
gdk_window_impl_x11_get_type (void)
rhlabs's avatar
rhlabs committed
120
{
121 122 123
  static GType object_type = 0;

  if (!object_type)
124
    {
125 126 127 128 129 130 131 132 133 134 135 136
      static const GTypeInfo object_info =
      {
        sizeof (GdkWindowImplX11Class),
        (GBaseInitFunc) NULL,
        (GBaseFinalizeFunc) NULL,
        (GClassInitFunc) gdk_window_impl_x11_class_init,
        NULL,           /* class_finalize */
        NULL,           /* class_data */
        sizeof (GdkWindowImplX11),
        0,              /* n_preallocs */
        (GInstanceInitFunc) gdk_window_impl_x11_init,
      };
Owen Taylor's avatar
Owen Taylor committed
137
      
138 139
      object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_X11,
                                            "GdkWindowImplX11",
140
                                            &object_info, 0);
141
    }
142 143 144 145 146 147 148 149 150
  
  return object_type;
}

GType
_gdk_window_impl_get_type (void)
{
  return gdk_window_impl_x11_get_type ();
}
151

152 153
static void
gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
154
{  
155 156
  impl->width = 1;
  impl->height = 1;
157
  impl->toplevel_window_type = -1;
rhlabs's avatar
rhlabs committed
158 159
}

160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
GdkToplevelX11 *
_gdk_x11_window_get_toplevel (GdkWindow *window)
{
  GdkWindowObject *private;
  GdkWindowImplX11 *impl;
  
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);

  if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
    return NULL;

  private = (GdkWindowObject *)window;
  impl = GDK_WINDOW_IMPL_X11 (private->impl);

  if (!impl->toplevel)
    impl->toplevel = g_new0 (GdkToplevelX11, 1);

  return impl->toplevel;
}

180 181
static void
gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
rhlabs's avatar
rhlabs committed
182
{
183 184
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
  GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
185
  
186 187 188
  parent_class = g_type_class_peek_parent (klass);

  object_class->finalize = gdk_window_impl_x11_finalize;
189

190 191 192
  drawable_class->set_colormap = gdk_window_impl_x11_set_colormap;
  drawable_class->get_colormap = gdk_window_impl_x11_get_colormap;
  drawable_class->get_size = gdk_window_impl_x11_get_size;
193 194 195 196

  /* Visible and clip regions are the same */
  drawable_class->get_clip_region = gdk_window_impl_x11_get_visible_region;
  drawable_class->get_visible_region = gdk_window_impl_x11_get_visible_region;
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
}

static void
gdk_window_impl_x11_finalize (GObject *object)
{
  GdkWindowObject *wrapper;
  GdkDrawableImplX11 *draw_impl;
  GdkWindowImplX11 *window_impl;
  
  g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (object));

  draw_impl = GDK_DRAWABLE_IMPL_X11 (object);
  window_impl = GDK_WINDOW_IMPL_X11 (object);
  
  wrapper = (GdkWindowObject*) draw_impl->wrapper;

213 214
  _gdk_xgrab_check_destroy (GDK_WINDOW (wrapper));

215
  if (!GDK_WINDOW_DESTROYED (wrapper))
216
    {
217 218 219
      GdkDisplay *display = GDK_WINDOW_DISPLAY (wrapper);
      
      _gdk_xid_table_remove (display, draw_impl->xid);
220
      if (window_impl->toplevel && window_impl->toplevel->focus_window)
221
	_gdk_xid_table_remove (display, window_impl->toplevel->focus_window);
222 223
    }

224 225 226
  if (window_impl->toplevel)
    g_free (window_impl->toplevel);

227 228
  G_OBJECT_CLASS (parent_class)->finalize (object);
}
229

Soeren Sandmann's avatar
Soeren Sandmann committed
230 231 232 233 234 235 236 237 238
static void
tmp_unset_bg (GdkWindow *window)
{
  GdkWindowImplX11 *impl;
  GdkWindowObject *obj;

  obj = (GdkWindowObject *) window;
  impl = GDK_WINDOW_IMPL_X11 (obj->impl);

239 240 241 242 243 244 245
  /* For windows without EXPOSURE_MASK, we can't do this
   * unsetting because such windows depend on the drawing
   * that the X server is going to do
   */
  if (!(obj->event_mask & GDK_EXPOSURE_MASK))
    return;
    
Soeren Sandmann's avatar
Soeren Sandmann committed
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
  impl->position_info.no_bg = TRUE;

  if (obj->bg_pixmap != GDK_NO_BG)
    XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
				GDK_DRAWABLE_XID (window), None);
}

static void
tmp_reset_bg (GdkWindow *window)
{
  GdkWindowImplX11 *impl;
  GdkWindowObject *obj;

  obj = (GdkWindowObject *) window;
  impl = GDK_WINDOW_IMPL_X11 (obj->impl);

262 263 264
  if (!(obj->event_mask & GDK_EXPOSURE_MASK))
    return;
    
Soeren Sandmann's avatar
Soeren Sandmann committed
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 294 295 296 297 298 299
  impl->position_info.no_bg = FALSE;

  if (obj->bg_pixmap == GDK_NO_BG)
    return;
  
  if (obj->bg_pixmap)
    {
      Pixmap xpixmap;

      if (obj->bg_pixmap == GDK_PARENT_RELATIVE_BG)
	xpixmap = ParentRelative;
      else 
	xpixmap = GDK_DRAWABLE_XID (obj->bg_pixmap);

      XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
				  GDK_DRAWABLE_XID (window), xpixmap);
    }
  else
    {
      XSetWindowBackground (GDK_DRAWABLE_XDISPLAY (window),
			    GDK_DRAWABLE_XID (window),
			    obj->bg_color.pixel);
    }
}

void
_gdk_x11_window_tmp_unset_bg (GdkWindow *window,
			      gboolean   recurse)
{
  GdkWindowObject *private;

  g_return_if_fail (GDK_IS_WINDOW (window));
  
  private = (GdkWindowObject *)window;

300 301 302 303 304 305
  if (private->input_only || private->destroyed ||
      (private->window_type != GDK_WINDOW_ROOT &&
       !GDK_WINDOW_IS_MAPPED (window)))
    {
      return;
    }
Soeren Sandmann's avatar
Soeren Sandmann committed
306 307

  if (private->window_type != GDK_WINDOW_ROOT &&
308
      private->window_type != GDK_WINDOW_FOREIGN)
Soeren Sandmann's avatar
Soeren Sandmann committed
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
    {
      tmp_unset_bg (window);
    }

  if (recurse)
    {
      GList *l;

      for (l = private->children; l != NULL; l = l->next)
	_gdk_x11_window_tmp_unset_bg (l->data, TRUE);
    }
}

void
_gdk_x11_window_tmp_reset_bg (GdkWindow *window,
			      gboolean   recurse)
{
  GdkWindowObject *private;

  g_return_if_fail (GDK_IS_WINDOW (window));

  private = (GdkWindowObject *)window;

332 333 334 335 336 337
  if (private->input_only || private->destroyed ||
      (private->window_type != GDK_WINDOW_ROOT &&
       !GDK_WINDOW_IS_MAPPED (window)))
    {
      return;
    }
Soeren Sandmann's avatar
Soeren Sandmann committed
338 339

  if (private->window_type != GDK_WINDOW_ROOT &&
340
      private->window_type != GDK_WINDOW_FOREIGN)
Soeren Sandmann's avatar
Soeren Sandmann committed
341 342 343 344 345 346 347 348 349 350 351 352 353
    {
      tmp_reset_bg (window);
    }

  if (recurse)
    {
      GList *l;

      for (l = private->children; l != NULL; l = l->next)
	_gdk_x11_window_tmp_reset_bg (l->data, TRUE);
    }
}

354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
static GdkColormap*
gdk_window_impl_x11_get_colormap (GdkDrawable *drawable)
{
  GdkDrawableImplX11 *drawable_impl;
  GdkWindowImplX11 *window_impl;
  
  g_return_val_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable), NULL);

  drawable_impl = GDK_DRAWABLE_IMPL_X11 (drawable);
  window_impl = GDK_WINDOW_IMPL_X11 (drawable);

  if (!((GdkWindowObject *) drawable_impl->wrapper)->input_only && 
      drawable_impl->colormap == NULL)
    {
      XWindowAttributes window_attributes;
369
      GdkVisual *visual;
370

371
      XGetWindowAttributes (GDK_SCREEN_XDISPLAY (drawable_impl->screen),
372 373
                            drawable_impl->xid,
                            &window_attributes);
374 375 376 377 378

      visual = gdk_x11_screen_lookup_visual (drawable_impl->screen,
					     window_attributes.visual->visualid);
      drawable_impl->colormap = gdk_x11_colormap_foreign_new (visual,
							      window_attributes.colormap);
379
    }
380 381 382 383 384 385 386 387 388 389 390 391
  
  return drawable_impl->colormap;
}

static void
gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
                                  GdkColormap *cmap)
{
  GdkWindowImplX11 *impl;
  GdkDrawableImplX11 *draw_impl;
  
  g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable));
392

393 394
  impl = GDK_WINDOW_IMPL_X11 (drawable);
  draw_impl = GDK_DRAWABLE_IMPL_X11 (drawable);
395

396
  if (cmap && GDK_WINDOW_DESTROYED (draw_impl->wrapper))
397 398
    return;

399 400
  /* chain up */
  GDK_DRAWABLE_CLASS (parent_class)->set_colormap (drawable, cmap);
401

402 403
  if (cmap)
    {
404
      XSetWindowColormap (GDK_SCREEN_XDISPLAY (draw_impl->screen),
405 406
                          draw_impl->xid,
                          GDK_COLORMAP_XCOLORMAP (cmap));
407

408 409 410 411
      if (((GdkWindowObject*)draw_impl->wrapper)->window_type !=
          GDK_WINDOW_TOPLEVEL)
        gdk_window_add_colormap_windows (GDK_WINDOW (draw_impl->wrapper));
    }
412 413 414 415 416 417 418 419 420 421 422 423 424 425
}


static void
gdk_window_impl_x11_get_size (GdkDrawable *drawable,
                              gint        *width,
                              gint        *height)
{
  g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable));

  if (width)
    *width = GDK_WINDOW_IMPL_X11 (drawable)->width;
  if (height)
    *height = GDK_WINDOW_IMPL_X11 (drawable)->height;
rhlabs's avatar
rhlabs committed
426 427
}

428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
static GdkRegion*
gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable)
{
  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (drawable);
  GdkRectangle result_rect;

  result_rect.x = 0;
  result_rect.y = 0;
  result_rect.width = impl->width;
  result_rect.height = impl->height;

  gdk_rectangle_intersect (&result_rect, &impl->position_info.clip_rect, &result_rect);

  return gdk_region_rectangle (&result_rect);
}

Elliot Lee's avatar
Elliot Lee committed
444
void
445
_gdk_windowing_window_init (GdkScreen * screen)
Elliot Lee's avatar
Elliot Lee committed
446
{
447 448 449
  GdkWindowObject *private;
  GdkWindowImplX11 *impl;
  GdkDrawableImplX11 *draw_impl;
450
  GdkScreenX11 *screen_x11;
451

452 453 454
  screen_x11 = GDK_SCREEN_X11 (screen);

  g_assert (screen_x11->root_window == NULL);
455

456 457
  gdk_screen_set_default_colormap (screen,
				   gdk_screen_get_system_colormap (screen));
458 459 460

  screen_x11->root_window = g_object_new (GDK_TYPE_WINDOW, NULL);
  private = (GdkWindowObject *)screen_x11->root_window;
461 462
  impl = GDK_WINDOW_IMPL_X11 (private->impl);
  draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
463
  
464 465
  draw_impl->screen = screen;
  draw_impl->xid = screen_x11->xroot_window;
466
  draw_impl->wrapper = GDK_DRAWABLE (private);
467
  draw_impl->colormap = gdk_screen_get_system_colormap (screen);
468
  g_object_ref (draw_impl->colormap);
469 470
  
  private->window_type = GDK_WINDOW_ROOT;
471
  private->depth = DefaultDepthOfScreen (screen_x11->xscreen);
472
  
473 474
  impl->width = WidthOfScreen (screen_x11->xscreen);
  impl->height = HeightOfScreen (screen_x11->xscreen);
475
  
476 477
  _gdk_window_init_position (GDK_WINDOW (private));

478 479 480
  _gdk_xid_table_insert (screen_x11->display,
			 &screen_x11->xroot_window,
			 screen_x11->root_window);
Elliot Lee's avatar
Elliot Lee committed
481 482
}

483 484 485 486
static void
set_wm_protocols (GdkWindow *window)
{
  GdkDisplay *display = gdk_drawable_get_display (window);
487 488
  Atom protocols[4];
  int n = 0;
489
  
490 491 492
  protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
  protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
  protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
493

494 495 496 497 498 499
#ifdef HAVE_XSYNC
  if (GDK_DISPLAY_X11 (display)->use_sync)
    protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
#endif
  
  XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n);
500
}
501

502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
static const gchar *
get_default_title (void)
{
  const char *title;

  title = g_get_application_name ();
  if (!title)
    title = g_get_prgname ();

  return title;
}

static void
check_leader_window_title (GdkDisplay *display)
{
  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);

519
  if (display_x11->leader_window && !display_x11->leader_window_title_set)
520 521 522 523 524 525 526 527 528
    {
      set_wm_name (display,
		   display_x11->leader_window,
		   get_default_title ());
      
      display_x11->leader_window_title_set = TRUE;
    }
}

529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546
static Window
create_focus_window (Display *xdisplay,
		     XID      parent)
{
  Window focus_window = XCreateSimpleWindow (xdisplay, parent,
					     -1, -1, 1, 1, 0,
					     0, 0);
  
  /* FIXME: probably better to actually track the requested event mask for the toplevel
   */
  XSelectInput (xdisplay, focus_window,
		KeyPressMask | KeyReleaseMask | FocusChangeMask);
  
  XMapWindow (xdisplay, focus_window);

  return focus_window;
}

547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
static void
ensure_sync_counter (GdkWindow *window)
{
#ifdef HAVE_XSYNC
  if (!GDK_WINDOW_DESTROYED (window))
    {
      GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
      GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
      GdkWindowObject *private = (GdkWindowObject *)window;
      GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);

      if (toplevel && impl->use_synchronized_configure &&
	  toplevel->update_counter == None &&
	  GDK_DISPLAY_X11 (display)->use_sync)
	{
	  Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
	  XSyncValue value;
	  Atom atom;

	  XSyncIntToValue (&value, 0);
	  
	  toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
	  
	  atom = gdk_x11_get_xatom_by_name_for_display (display,
							"_NET_WM_SYNC_REQUEST_COUNTER");
	  
	  XChangeProperty (xdisplay, GDK_WINDOW_XID (window),
			   atom, XA_CARDINAL,
			   32, PropModeReplace,
			   (guchar *)&toplevel->update_counter, 1);
	  
	  XSyncIntToValue (&toplevel->current_counter_value, 0);
	}
    }
#endif
}

584
static void
585 586
setup_toplevel_window (GdkWindow *window, 
		       GdkWindow *parent)
587 588 589 590 591 592 593 594 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 634 635 636 637
{
  GdkWindowObject *obj = (GdkWindowObject *)window;
  GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
  GdkWindowImplX11 *impl = (GdkWindowImplX11 *)obj->impl;
  Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
  XID xid = GDK_WINDOW_XID (window);
  XID xparent = GDK_WINDOW_XID (parent);
  GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (parent));
  XSizeHints size_hints;
  long pid;
    
  if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_DIALOG)
    XSetTransientForHint (xdisplay, xid, xparent);
  
  set_wm_protocols (window);
  
  if (!obj->input_only)
    {
      /* The focus window is off the visible area, and serves to receive key
       * press events so they don't get sent to child windows.
       */
      toplevel->focus_window = create_focus_window (xdisplay, xid);
      _gdk_xid_table_insert (screen_x11->display, &toplevel->focus_window, window);
    }
  
  check_leader_window_title (screen_x11->display);
  
  /* 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???
   */
  size_hints.flags = PSize;
  size_hints.width = impl->width;
  size_hints.height = impl->height;
  
  XSetWMNormalHints (xdisplay, xid, &size_hints);
  
  /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
  XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
  
  pid = getpid ();
  XChangeProperty (xdisplay, xid,
		   gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "_NET_WM_PID"),
		   XA_CARDINAL, 32,
		   PropModeReplace,
		   (guchar *)&pid, 1);
  
  XChangeProperty (xdisplay, xid, 
		   gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "WM_CLIENT_LEADER"),
		   XA_WINDOW, 32, PropModeReplace,
		   (guchar *) &GDK_DISPLAY_X11 (screen_x11->display)->leader_window, 1);
638

639
  if (!obj->focus_on_map)
640
    gdk_x11_window_set_user_time (window, 0);
641
  else if (GDK_DISPLAY_X11 (screen_x11->display)->user_time != 0)
642
    gdk_x11_window_set_user_time (window, GDK_DISPLAY_X11 (screen_x11->display)->user_time);
643 644

  ensure_sync_counter (window);
645 646
}

Havoc Pennington's avatar
Havoc Pennington committed
647 648
/**
 * gdk_window_new:
649 650
 * @parent: a #GdkWindow, or %NULL to create the window as a child of
 *   the default root window for the default display.
Havoc Pennington's avatar
Havoc Pennington committed
651 652 653
 * @attributes: attributes of the new window
 * @attributes_mask: mask indicating which fields in @attributes are valid
 * 
654
 * Creates a new #GdkWindow using the attributes from
Matthias Clasen's avatar
Matthias Clasen committed
655
 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
656 657
 * more details.  Note: to use this on displays other than the default
 * display, @parent must be specified.
Havoc Pennington's avatar
Havoc Pennington committed
658 659 660
 * 
 * Return value: the new #GdkWindow
 **/
Elliot Lee's avatar
Elliot Lee committed
661 662 663 664 665 666
GdkWindow*
gdk_window_new (GdkWindow     *parent,
		GdkWindowAttr *attributes,
		gint           attributes_mask)
{
  GdkWindow *window;
667 668 669
  GdkWindowObject *private;
  GdkWindowImplX11 *impl;
  GdkDrawableImplX11 *draw_impl;
670 671
  GdkScreenX11 *screen_x11;
  GdkScreen *screen;
672
  
Elliot Lee's avatar
Elliot Lee committed
673 674 675
  GdkVisual *visual;
  Window xparent;
  Visual *xvisual;
676 677
  Display *xdisplay;
  Window xid;
678

Elliot Lee's avatar
Elliot Lee committed
679 680 681 682
  XSetWindowAttributes xattributes;
  long xattributes_mask;
  XClassHint *class_hint;
  int x, y, depth;
683
  
Elliot Lee's avatar
Elliot Lee committed
684
  unsigned int class;
685
  const char *title;
Elliot Lee's avatar
Elliot Lee committed
686
  int i;
687
  
Elliot Lee's avatar
Elliot Lee committed
688
  g_return_val_if_fail (attributes != NULL, NULL);
689
  
Elliot Lee's avatar
Elliot Lee committed
690
  if (!parent)
691 692 693 694
    {
      GDK_NOTE (MULTIHEAD,
		g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
      
Owen Taylor's avatar
Owen Taylor committed
695
      screen = gdk_screen_get_default ();
696 697 698 699 700 701
      parent = gdk_screen_get_root_window (screen);
    }
  else
    screen = gdk_drawable_get_screen (parent);

  screen_x11 = GDK_SCREEN_X11 (screen);
702 703

  g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
704
  
705
  if (GDK_WINDOW_DESTROYED (parent))
706
    return NULL;
707
  
708
  xparent = GDK_WINDOW_XID (parent);
709
  
710
  window = g_object_new (GDK_TYPE_WINDOW, NULL);
711 712 713 714
  private = (GdkWindowObject *)window;
  impl = GDK_WINDOW_IMPL_X11 (private->impl);
  draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
  draw_impl->wrapper = GDK_DRAWABLE (window);
715 716 717
  
  draw_impl->screen = screen;
  xdisplay = screen_x11->xdisplay;
718 719 720 721 722

  /* Windows with a foreign parent are treated as if they are children
   * of the root window, except for actual creation.
   */
  if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
723
    parent = gdk_screen_get_root_window (screen);
724
  
725
  private->parent = (GdkWindowObject *)parent;
726

727
  private->accept_focus = TRUE;
728
  private->focus_on_map = TRUE;
729

Elliot Lee's avatar
Elliot Lee committed
730
  xattributes_mask = 0;
731
  
Elliot Lee's avatar
Elliot Lee committed
732 733 734 735
  if (attributes_mask & GDK_WA_X)
    x = attributes->x;
  else
    x = 0;
736
  
Elliot Lee's avatar
Elliot Lee committed
737 738 739 740
  if (attributes_mask & GDK_WA_Y)
    y = attributes->y;
  else
    y = 0;
741
  
Elliot Lee's avatar
Elliot Lee committed
742 743
  private->x = x;
  private->y = y;
744 745
  impl->width = (attributes->width > 1) ? (attributes->width) : (1);
  impl->height = (attributes->height > 1) ? (attributes->height) : (1);
746 747 748 749 750 751 752

  if (attributes->wclass == GDK_INPUT_ONLY)
    {
      /* Backwards compatiblity - we've always ignored
       * attributes->window_type for input-only windows
       * before
       */
753
      if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
754 755 756 757 758 759
	private->window_type = GDK_WINDOW_TEMP;
      else
	private->window_type = GDK_WINDOW_CHILD;
    }
  else
    private->window_type = attributes->window_type;
760

761 762
  _gdk_window_init_position (GDK_WINDOW (private));
  if (impl->position_info.big)
763
    private->guffaw_gravity = TRUE;
764
  
Elliot Lee's avatar
Elliot Lee committed
765 766 767
  if (attributes_mask & GDK_WA_VISUAL)
    visual = attributes->visual;
  else
768
    visual = gdk_screen_get_system_visual (screen);
Elliot Lee's avatar
Elliot Lee committed
769
  xvisual = ((GdkVisualPrivate*) visual)->xvisual;
770
  
771
  xattributes.event_mask = StructureNotifyMask | PropertyChangeMask;
772
  for (i = 0; i < _gdk_nenvent_masks; i++)
Elliot Lee's avatar
Elliot Lee committed
773 774
    {
      if (attributes->event_mask & (1 << (i + 1)))
775
	xattributes.event_mask |= _gdk_event_mask_table[i];
Elliot Lee's avatar
Elliot Lee committed
776
    }
777
  private->event_mask = attributes->event_mask;
778
  
Elliot Lee's avatar
Elliot Lee committed
779 780
  if (xattributes.event_mask)
    xattributes_mask |= CWEventMask;
781
  
782 783 784
  if (attributes_mask & GDK_WA_NOREDIR)
    {
      xattributes.override_redirect =
785
	(attributes->override_redirect == FALSE)?False:True;
786 787 788
      xattributes_mask |= CWOverrideRedirect;
    } 
  else
789
    xattributes.override_redirect = False;
790

791 792
  impl->override_redirect = xattributes.override_redirect;
  
793
  if (private->parent && private->parent->guffaw_gravity)
794 795 796 797
    {
      xattributes.win_gravity = StaticGravity;
      xattributes_mask |= CWWinGravity;
    }
798
  
799 800 801 802 803 804
  /* Sanity checks */
  switch (private->window_type)
    {
    case GDK_WINDOW_TOPLEVEL:
    case GDK_WINDOW_DIALOG:
    case GDK_WINDOW_TEMP:
805
      if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
806 807 808
	{
	  g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
		     "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
809
	  xparent = GDK_SCREEN_XROOTWIN (screen);
810 811 812 813 814 815 816 817
	}
    case GDK_WINDOW_CHILD:
      break;
    default:
      g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
      return NULL;
    }
	  
Elliot Lee's avatar
Elliot Lee committed
818 819 820 821
  if (attributes->wclass == GDK_INPUT_OUTPUT)
    {
      class = InputOutput;
      depth = visual->depth;
822 823

      private->input_only = FALSE;
824
      private->depth = depth;
825
      
Elliot Lee's avatar
Elliot Lee committed
826
      if (attributes_mask & GDK_WA_COLORMAP)
827 828
        {
          draw_impl->colormap = attributes->colormap;
829
          g_object_ref (attributes->colormap);
830
        }
Elliot Lee's avatar
Elliot Lee committed
831
      else
832
	{
833
	  if ((((GdkVisualPrivate *)gdk_screen_get_system_visual (screen))->xvisual) ==  xvisual)
834
            {
835
	      draw_impl->colormap = gdk_screen_get_system_colormap (screen);
836
              g_object_ref (draw_impl->colormap);
837
            }
838
	  else
839
            {
840
              draw_impl->colormap = gdk_colormap_new (visual, FALSE);
841
            }
842
	}
843
      
844
      private->bg_color.pixel = BlackPixel (xdisplay, screen_x11->screen_num);
845 846 847 848
      xattributes.background_pixel = private->bg_color.pixel;

      private->bg_pixmap = NULL;
      
849
      xattributes.border_pixel = BlackPixel (xdisplay, screen_x11->screen_num);
Elliot Lee's avatar
Elliot Lee committed
850
      xattributes_mask |= CWBorderPixel | CWBackPixel;
851 852 853 854 855

      if (private->guffaw_gravity)
	xattributes.bit_gravity = StaticGravity;
      else
	xattributes.bit_gravity = NorthWestGravity;
856
      
857
      xattributes_mask |= CWBitGravity;
858 859 860 861 862

      xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap);
      xattributes_mask |= CWColormap;

      if (private->window_type == GDK_WINDOW_TEMP)
Elliot Lee's avatar
Elliot Lee committed
863 864 865 866 867
	{
	  xattributes.save_under = True;
	  xattributes.override_redirect = True;
	  xattributes.cursor = None;
	  xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
868 869

	  impl->override_redirect = TRUE;
Elliot Lee's avatar
Elliot Lee committed
870 871 872 873
	}
    }
  else
    {
874
      depth = 0;
875
      private->depth = 0;
Elliot Lee's avatar
Elliot Lee committed
876
      class = InputOnly;
877
      private->input_only = TRUE;
878
      draw_impl->colormap = gdk_screen_get_system_colormap (screen);
879
      g_object_ref (draw_impl->colormap);
Elliot Lee's avatar
Elliot Lee committed
880
    }
881

882 883 884 885 886
  xid = draw_impl->xid = XCreateWindow (xdisplay, xparent,
					impl->position_info.x, impl->position_info.y,
					impl->position_info.width, impl->position_info.height,
					0, depth, class, xvisual,
					xattributes_mask, &xattributes);
887

888
  g_object_ref (window);
889
  _gdk_xid_table_insert (screen_x11->display, &draw_impl->xid, window);
890
  
891 892 893
  gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
				  (attributes->cursor) :
				  NULL));
894
  
895 896
  if (private->parent)
    private->parent->children = g_list_prepend (private->parent->children, window);
897
  
898
  switch (GDK_WINDOW_TYPE (private))
Elliot Lee's avatar
Elliot Lee committed
899 900 901 902
    {
    case GDK_WINDOW_DIALOG:
    case GDK_WINDOW_TOPLEVEL:
    case GDK_WINDOW_TEMP:
903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919
      if (attributes_mask & GDK_WA_TITLE)
	title = attributes->title;
      else
	title = get_default_title ();
      
      gdk_window_set_title (window, title);
      
      if (attributes_mask & GDK_WA_WMCLASS)
	{
	  class_hint = XAllocClassHint ();
	  class_hint->res_name = attributes->wmclass_name;
	  class_hint->res_class = attributes->wmclass_class;
	  XSetClassHint (xdisplay, xid, class_hint);
	  XFree (class_hint);
	}
  
      setup_toplevel_window (window, parent);
Elliot Lee's avatar
Elliot Lee committed
920
      break;
921

Elliot Lee's avatar
Elliot Lee committed
922 923
    case GDK_WINDOW_CHILD:
      if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
924
	  (draw_impl->colormap != gdk_screen_get_system_colormap (screen)) &&
925
	  (draw_impl->colormap != gdk_drawable_get_colormap (gdk_window_get_toplevel (window))))
Elliot Lee's avatar
Elliot Lee committed
926
	{
927
	  GDK_NOTE (MISC, g_message ("adding colormap window\n"));
Elliot Lee's avatar
Elliot Lee committed
928 929
	  gdk_window_add_colormap_windows (window);
	}
930
      break;
931
      
Elliot Lee's avatar
Elliot Lee committed
932
    default:
933
      break;
934 935
    }

Elliot Lee's avatar
Elliot Lee committed
936 937 938
  return window;
}

939 940 941 942 943 944 945 946 947 948 949 950 951 952 953
static GdkEventMask
x_event_mask_to_gdk_event_mask (long mask)
{
  GdkEventMask event_mask = 0;
  int i;

  for (i = 0; i < _gdk_nenvent_masks; i++)
    {
      if (mask & _gdk_event_mask_table[i])
	event_mask |= 1 << (i + 1);
    }

  return event_mask;
}

Havoc Pennington's avatar
Havoc Pennington committed
954
/**
955 956
 * gdk_window_foreign_new_for_display:
 * @display: the #GdkDisplay where the window handle comes from.
957
 * @anid: a native window handle.
Havoc Pennington's avatar
Havoc Pennington committed
958
 * 
959
 * Wraps a native window in a #GdkWindow.
960 961 962
 * This may fail if the window has been destroyed. If the window
 * was already known to GDK, a new reference to the existing 
 * #GdkWindow is returned.
963 964 965
 *
 * For example in the X backend, a native window handle is an Xlib
 * <type>XID</type>.
Havoc Pennington's avatar
Havoc Pennington committed
966
 * 
967 968 969
 * Return value: a #GdkWindow wrapper for the native window or 
 *   %NULL if the window has been destroyed. The wrapper will be
 *   newly created, if one doesn't exist already.
Matthias Clasen's avatar
Matthias Clasen committed
970 971
 *
 * Since: 2.2
Havoc Pennington's avatar
Havoc Pennington committed
972
 **/
Elliot Lee's avatar
Elliot Lee committed
973
GdkWindow *
974 975
gdk_window_foreign_new_for_display (GdkDisplay     *display,
				    GdkNativeWindow anid)
Elliot Lee's avatar
Elliot Lee committed
976 977
{
  GdkWindow *window;
978 979 980
  GdkWindowObject *private;
  GdkWindowImplX11 *impl;
  GdkDrawableImplX11 *draw_impl;
981
  GdkDisplayX11 *display_x11;
Elliot Lee's avatar
Elliot Lee committed
982
  XWindowAttributes attrs;
983
  Window root, parent;
984
  Window *children = NULL;
985
  guint nchildren;
986 987
  gboolean result;

988 989 990
  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);

  display_x11 = GDK_DISPLAY_X11 (display);
991 992 993 994

  if ((window = gdk_xid_table_lookup_for_display (display, anid)) != NULL)
    return g_object_ref (window);

995
  gdk_error_trap_push ();
996
  result = XGetWindowAttributes (display_x11->xdisplay, anid, &attrs);
997 998 999 1000 1001 1002
  if (gdk_error_trap_pop () || !result)
    return NULL;

  /* FIXME: This is pretty expensive. Maybe the caller should supply
   *        the parent */
  gdk_error_trap_push ();
1003
  result = XQueryTree (display_x11->xdisplay, anid, &root, &parent, &children, &nchildren);
1004
  if (gdk_error_trap_pop () || !result)
1005
    return NULL;
1006

1007 1008
  if (children)
    XFree (children);
1009
  
1010
  window = g_object_new (GDK_TYPE_WINDOW, NULL);
1011 1012 1013 1014
  private = (GdkWindowObject *)window;
  impl = GDK_WINDOW_IMPL_X11 (private->impl);
  draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
  draw_impl->wrapper = GDK_DRAWABLE (window);
1015