gdkwindow-x11.c 173 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
static void     gdk_window_set_static_win_gravity (GdkWindow  *window,
						   gboolean    on);
static gboolean gdk_window_icon_name_set          (GdkWindow  *window);
87
static void     gdk_window_add_colormap_windows   (GdkWindow  *window);
88 89 90
static void     set_wm_name                       (GdkDisplay  *display,
						   Window       xwindow,
						   const gchar *name);
91
static void     move_to_current_desktop           (GdkWindow *window);
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
static void gdk_window_impl_x11_finalize   (GObject            *object);
101

102 103
#define WINDOW_IS_TOPLEVEL(window)		   \
  (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
Alexander Larsson's avatar
Alexander Larsson committed
104
   GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
105

Matthias Clasen's avatar
Matthias Clasen committed
106 107 108 109 110 111 112 113
/* 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 ))     \
  )

Matthias Clasen's avatar
Matthias Clasen committed
114
G_DEFINE_TYPE (GdkWindowImplX11, gdk_window_impl_x11, GDK_TYPE_DRAWABLE_IMPL_X11)
115 116 117 118 119 120

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

122 123
static void
gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
124
{  
125 126
  impl->width = 1;
  impl->height = 1;
127
  impl->toplevel_window_type = -1;
rhlabs's avatar
rhlabs committed
128 129
}

130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
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;
}

150 151
static void
gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
rhlabs's avatar
rhlabs committed
152
{
153 154
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
  GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
155
  
156
  object_class->finalize = gdk_window_impl_x11_finalize;
157

158 159 160
  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;
161 162 163 164

  /* 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;
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
}

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;

181 182
  _gdk_xgrab_check_destroy (GDK_WINDOW (wrapper));

183
  if (!GDK_WINDOW_DESTROYED (wrapper))
184
    {
185 186 187
      GdkDisplay *display = GDK_WINDOW_DISPLAY (wrapper);
      
      _gdk_xid_table_remove (display, draw_impl->xid);
188
      if (window_impl->toplevel && window_impl->toplevel->focus_window)
189
	_gdk_xid_table_remove (display, window_impl->toplevel->focus_window);
190 191
    }

192 193 194
  if (window_impl->toplevel)
    g_free (window_impl->toplevel);

195 196 197
  if (window_impl->cursor)
    gdk_cursor_unref (window_impl->cursor);

Matthias Clasen's avatar
Matthias Clasen committed
198
  G_OBJECT_CLASS (gdk_window_impl_x11_parent_class)->finalize (object);
199
}
200

Soeren Sandmann's avatar
Soeren Sandmann committed
201 202 203 204 205 206 207 208 209
static void
tmp_unset_bg (GdkWindow *window)
{
  GdkWindowImplX11 *impl;
  GdkWindowObject *obj;

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

210 211 212 213 214 215 216
  /* 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
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
  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);

233 234 235
  if (!(obj->event_mask & GDK_EXPOSURE_MASK))
    return;
    
Soeren Sandmann's avatar
Soeren Sandmann committed
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
  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);
    }
}

261 262 263 264 265 266 267
/* Unsetting and resetting window backgrounds.
 *
 * In many cases it is possible to avoid flicker by unsetting the
 * background of windows. For example if the background of the
 * parent window is unset when a window is unmapped, a brief flicker
 * of background painting is avoided.
 */
Soeren Sandmann's avatar
Soeren Sandmann committed
268 269 270 271 272 273 274 275 276 277
void
_gdk_x11_window_tmp_unset_bg (GdkWindow *window,
			      gboolean   recurse)
{
  GdkWindowObject *private;

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

278 279 280 281 282 283
  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
284 285

  if (private->window_type != GDK_WINDOW_ROOT &&
286
      private->window_type != GDK_WINDOW_FOREIGN)
Soeren Sandmann's avatar
Soeren Sandmann committed
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
    {
      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;

310 311 312 313 314 315
  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
316 317

  if (private->window_type != GDK_WINDOW_ROOT &&
318
      private->window_type != GDK_WINDOW_FOREIGN)
Soeren Sandmann's avatar
Soeren Sandmann committed
319 320 321 322 323 324 325 326 327 328 329 330 331
    {
      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);
    }
}

332 333 334 335 336 337 338 339 340 341 342 343 344
static GdkColormap*
gdk_window_impl_x11_get_colormap (GdkDrawable *drawable)
{
  GdkDrawableImplX11 *drawable_impl;
  
  g_return_val_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable), NULL);

  drawable_impl = GDK_DRAWABLE_IMPL_X11 (drawable);

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

347
      XGetWindowAttributes (GDK_SCREEN_XDISPLAY (drawable_impl->screen),
348 349
                            drawable_impl->xid,
                            &window_attributes);
350 351 352 353 354

      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);
355
    }
356 357 358 359 360 361 362 363 364 365 366
  
  return drawable_impl->colormap;
}

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

368
  draw_impl = GDK_DRAWABLE_IMPL_X11 (drawable);
369

370
  if (cmap && GDK_WINDOW_DESTROYED (draw_impl->wrapper))
371 372
    return;

373
  /* chain up */
Matthias Clasen's avatar
Matthias Clasen committed
374
  GDK_DRAWABLE_CLASS (gdk_window_impl_x11_parent_class)->set_colormap (drawable, cmap);
375

376 377
  if (cmap)
    {
378
      XSetWindowColormap (GDK_SCREEN_XDISPLAY (draw_impl->screen),
379 380
                          draw_impl->xid,
                          GDK_COLORMAP_XCOLORMAP (cmap));
381

382 383 384 385
      if (((GdkWindowObject*)draw_impl->wrapper)->window_type !=
          GDK_WINDOW_TOPLEVEL)
        gdk_window_add_colormap_windows (GDK_WINDOW (draw_impl->wrapper));
    }
386 387 388 389 390 391 392 393 394 395 396 397 398 399
}


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
400 401
}

402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
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
418
void
419
_gdk_windowing_window_init (GdkScreen * screen)
Elliot Lee's avatar
Elliot Lee committed
420
{
421 422 423
  GdkWindowObject *private;
  GdkWindowImplX11 *impl;
  GdkDrawableImplX11 *draw_impl;
424
  GdkScreenX11 *screen_x11;
425

426 427 428
  screen_x11 = GDK_SCREEN_X11 (screen);

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

430 431
  gdk_screen_set_default_colormap (screen,
				   gdk_screen_get_system_colormap (screen));
432 433 434

  screen_x11->root_window = g_object_new (GDK_TYPE_WINDOW, NULL);
  private = (GdkWindowObject *)screen_x11->root_window;
435 436
  impl = GDK_WINDOW_IMPL_X11 (private->impl);
  draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
437
  
438 439
  draw_impl->screen = screen;
  draw_impl->xid = screen_x11->xroot_window;
440
  draw_impl->wrapper = GDK_DRAWABLE (private);
441
  draw_impl->colormap = gdk_screen_get_system_colormap (screen);
442
  g_object_ref (draw_impl->colormap);
443 444
  
  private->window_type = GDK_WINDOW_ROOT;
445
  private->depth = DefaultDepthOfScreen (screen_x11->xscreen);
446
  
447 448
  impl->width = WidthOfScreen (screen_x11->xscreen);
  impl->height = HeightOfScreen (screen_x11->xscreen);
449
  
450 451
  _gdk_window_init_position (GDK_WINDOW (private));

452 453 454
  _gdk_xid_table_insert (screen_x11->display,
			 &screen_x11->xroot_window,
			 screen_x11->root_window);
Elliot Lee's avatar
Elliot Lee committed
455 456
}

457 458 459 460
static void
set_wm_protocols (GdkWindow *window)
{
  GdkDisplay *display = gdk_drawable_get_display (window);
461 462
  Atom protocols[4];
  int n = 0;
463
  
464 465 466
  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");
467

468 469 470 471 472 473
#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);
474
}
475

476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492
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);

493
  if (display_x11->leader_window && !display_x11->leader_window_title_set)
494 495 496 497 498 499 500 501 502
    {
      set_wm_name (display,
		   display_x11->leader_window,
		   get_default_title ());
      
      display_x11->leader_window_title_set = TRUE;
    }
}

503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
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;
}

521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
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
}

558
static void
559 560
setup_toplevel_window (GdkWindow *window, 
		       GdkWindow *parent)
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 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
{
  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);
612

613
  if (!obj->focus_on_map)
614
    gdk_x11_window_set_user_time (window, 0);
615
  else if (GDK_DISPLAY_X11 (screen_x11->display)->user_time != 0)
616
    gdk_x11_window_set_user_time (window, GDK_DISPLAY_X11 (screen_x11->display)->user_time);
617 618

  ensure_sync_counter (window);
619 620
}

Havoc Pennington's avatar
Havoc Pennington committed
621 622
/**
 * gdk_window_new:
623 624
 * @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
625 626 627
 * @attributes: attributes of the new window
 * @attributes_mask: mask indicating which fields in @attributes are valid
 * 
628
 * Creates a new #GdkWindow using the attributes from
Matthias Clasen's avatar
Matthias Clasen committed
629
 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
630 631
 * more details.  Note: to use this on displays other than the default
 * display, @parent must be specified.
Havoc Pennington's avatar
Havoc Pennington committed
632 633 634
 * 
 * Return value: the new #GdkWindow
 **/
Elliot Lee's avatar
Elliot Lee committed
635 636 637 638 639 640
GdkWindow*
gdk_window_new (GdkWindow     *parent,
		GdkWindowAttr *attributes,
		gint           attributes_mask)
{
  GdkWindow *window;
641 642 643
  GdkWindowObject *private;
  GdkWindowImplX11 *impl;
  GdkDrawableImplX11 *draw_impl;
644 645
  GdkScreenX11 *screen_x11;
  GdkScreen *screen;
646
  
Elliot Lee's avatar
Elliot Lee committed
647 648 649
  GdkVisual *visual;
  Window xparent;
  Visual *xvisual;
650 651
  Display *xdisplay;
  Window xid;
652

Elliot Lee's avatar
Elliot Lee committed
653 654 655 656
  XSetWindowAttributes xattributes;
  long xattributes_mask;
  XClassHint *class_hint;
  int x, y, depth;
657
  
Elliot Lee's avatar
Elliot Lee committed
658
  unsigned int class;
659
  const char *title;
Elliot Lee's avatar
Elliot Lee committed
660
  int i;
661
  
Elliot Lee's avatar
Elliot Lee committed
662
  g_return_val_if_fail (attributes != NULL, NULL);
663
  
Elliot Lee's avatar
Elliot Lee committed
664
  if (!parent)
665 666 667 668
    {
      GDK_NOTE (MULTIHEAD,
		g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
      
Owen Taylor's avatar
Owen Taylor committed
669
      screen = gdk_screen_get_default ();
670 671 672 673 674 675
      parent = gdk_screen_get_root_window (screen);
    }
  else
    screen = gdk_drawable_get_screen (parent);

  screen_x11 = GDK_SCREEN_X11 (screen);
676 677

  g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
678
  
679
  if (GDK_WINDOW_DESTROYED (parent))
680
    return NULL;
681
  
682
  xparent = GDK_WINDOW_XID (parent);
683
  
684
  window = g_object_new (GDK_TYPE_WINDOW, NULL);
685 686 687 688
  private = (GdkWindowObject *)window;
  impl = GDK_WINDOW_IMPL_X11 (private->impl);
  draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
  draw_impl->wrapper = GDK_DRAWABLE (window);
689 690 691
  
  draw_impl->screen = screen;
  xdisplay = screen_x11->xdisplay;
692 693 694 695 696

  /* 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)
697
    parent = gdk_screen_get_root_window (screen);
698
  
699
  private->parent = (GdkWindowObject *)parent;
700

701
  private->accept_focus = TRUE;
702
  private->focus_on_map = TRUE;
703

Elliot Lee's avatar
Elliot Lee committed
704
  xattributes_mask = 0;
705
  
Elliot Lee's avatar
Elliot Lee committed
706 707 708 709
  if (attributes_mask & GDK_WA_X)
    x = attributes->x;
  else
    x = 0;
710
  
Elliot Lee's avatar
Elliot Lee committed
711 712 713 714
  if (attributes_mask & GDK_WA_Y)
    y = attributes->y;
  else
    y = 0;
715
  
Elliot Lee's avatar
Elliot Lee committed
716 717
  private->x = x;
  private->y = y;
718 719
  impl->width = (attributes->width > 1) ? (attributes->width) : (1);
  impl->height = (attributes->height > 1) ? (attributes->height) : (1);
720 721 722 723 724 725 726

  if (attributes->wclass == GDK_INPUT_ONLY)
    {
      /* Backwards compatiblity - we've always ignored
       * attributes->window_type for input-only windows
       * before
       */
727
      if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
728 729 730 731 732 733
	private->window_type = GDK_WINDOW_TEMP;
      else
	private->window_type = GDK_WINDOW_CHILD;
    }
  else
    private->window_type = attributes->window_type;
734

735 736 737 738 739 740 741 742 743 744 745
  /* Work around a bug where Xorg refuses to map toplevel InputOnly windows 
   * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
   */
  if (attributes->wclass == GDK_INPUT_ONLY &&
      GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT &&
      !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
    {
      g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
      attributes->wclass = GDK_INPUT_OUTPUT;
    }

746 747
  _gdk_window_init_position (GDK_WINDOW (private));
  if (impl->position_info.big)
748
    private->guffaw_gravity = TRUE;
749
  
Elliot Lee's avatar
Elliot Lee committed
750 751 752
  if (attributes_mask & GDK_WA_VISUAL)
    visual = attributes->visual;
  else
753
    visual = gdk_screen_get_system_visual (screen);
Elliot Lee's avatar
Elliot Lee committed
754
  xvisual = ((GdkVisualPrivate*) visual)->xvisual;
755
  
756
  xattributes.event_mask = StructureNotifyMask | PropertyChangeMask;
757
  for (i = 0; i < _gdk_nenvent_masks; i++)
Elliot Lee's avatar
Elliot Lee committed
758 759
    {
      if (attributes->event_mask & (1 << (i + 1)))
760
	xattributes.event_mask |= _gdk_event_mask_table[i];
Elliot Lee's avatar
Elliot Lee committed
761
    }
762
  private->event_mask = attributes->event_mask;
763
  
Elliot Lee's avatar
Elliot Lee committed
764 765
  if (xattributes.event_mask)
    xattributes_mask |= CWEventMask;
766
  
767 768 769
  if (attributes_mask & GDK_WA_NOREDIR)
    {
      xattributes.override_redirect =
770
	(attributes->override_redirect == FALSE)?False:True;
771 772 773
      xattributes_mask |= CWOverrideRedirect;
    } 
  else
774
    xattributes.override_redirect = False;
775

776 777
  impl->override_redirect = xattributes.override_redirect;
  
778
  if (private->parent && private->parent->guffaw_gravity)
779 780 781 782
    {
      xattributes.win_gravity = StaticGravity;
      xattributes_mask |= CWWinGravity;
    }
783
  
784 785 786 787 788 789
  /* Sanity checks */
  switch (private->window_type)
    {
    case GDK_WINDOW_TOPLEVEL:
    case GDK_WINDOW_DIALOG:
    case GDK_WINDOW_TEMP:
790
      if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
791 792 793
	{
	  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");
794
	  xparent = GDK_SCREEN_XROOTWIN (screen);
795 796 797 798 799 800 801 802
	}
    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
803 804 805 806
  if (attributes->wclass == GDK_INPUT_OUTPUT)
    {
      class = InputOutput;
      depth = visual->depth;
807 808

      private->input_only = FALSE;
809
      private->depth = depth;
810
      
Elliot Lee's avatar
Elliot Lee committed
811
      if (attributes_mask & GDK_WA_COLORMAP)
812 813
        {
          draw_impl->colormap = attributes->colormap;
814
          g_object_ref (attributes->colormap);
815
        }
Elliot Lee's avatar
Elliot Lee committed
816
      else
817
	{
818
	  if ((((GdkVisualPrivate *)gdk_screen_get_system_visual (screen))->xvisual) ==  xvisual)
819
            {
820
	      draw_impl->colormap = gdk_screen_get_system_colormap (screen);
821
              g_object_ref (draw_impl->colormap);
822
            }
823
	  else
824
            {
825
              draw_impl->colormap = gdk_colormap_new (visual, FALSE);
826
            }
827
	}
828
      
829
      private->bg_color.pixel = BlackPixel (xdisplay, screen_x11->screen_num);
830
      private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
831 832 833 834
      xattributes.background_pixel = private->bg_color.pixel;

      private->bg_pixmap = NULL;
      
835
      xattributes.border_pixel = BlackPixel (xdisplay, screen_x11->screen_num);
Elliot Lee's avatar
Elliot Lee committed
836
      xattributes_mask |= CWBorderPixel | CWBackPixel;
837 838 839 840 841

      if (private->guffaw_gravity)
	xattributes.bit_gravity = StaticGravity;
      else
	xattributes.bit_gravity = NorthWestGravity;
842
      
843
      xattributes_mask |= CWBitGravity;
844 845 846 847 848

      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
849 850 851 852 853
	{
	  xattributes.save_under = True;
	  xattributes.override_redirect = True;
	  xattributes.cursor = None;
	  xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
854 855

	  impl->override_redirect = TRUE;
Elliot Lee's avatar
Elliot Lee committed
856 857 858 859
	}
    }
  else
    {
860
      depth = 0;
861
      private->depth = 0;
Elliot Lee's avatar
Elliot Lee committed
862
      class = InputOnly;
863
      private->input_only = TRUE;
864
      draw_impl->colormap = gdk_screen_get_system_colormap (screen);
865
      g_object_ref (draw_impl->colormap);
Elliot Lee's avatar
Elliot Lee committed
866
    }
867

868 869 870 871 872
  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);
873

874
  g_object_ref (window);
875
  _gdk_xid_table_insert (screen_x11->display, &draw_impl->xid, window);
876
  
877 878 879
  gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
				  (attributes->cursor) :
				  NULL));
880
  
881 882
  if (private->parent)
    private->parent->children = g_list_prepend (private->parent->children, window);
883
  
884
  switch (GDK_WINDOW_TYPE (private))
Elliot Lee's avatar
Elliot Lee committed
885 886 887 888
    {
    case GDK_WINDOW_DIALOG:
    case GDK_WINDOW_TOPLEVEL:
    case GDK_WINDOW_TEMP:
889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905
      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
906
      break;
907

Elliot Lee's avatar
Elliot Lee committed
908 909
    case GDK_WINDOW_CHILD:
      if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
910
	  (draw_impl->colormap != gdk_screen_get_system_colormap (screen)) &&
911
	  (draw_impl->colormap != gdk_drawable_get_colormap (gdk_window_get_toplevel (window))))
Elliot Lee's avatar
Elliot Lee committed
912
	{
913
	  GDK_NOTE (MISC, g_message ("adding colormap window\n"));
Elliot Lee's avatar
Elliot Lee committed
914 915
	  gdk_window_add_colormap_windows (window);
	}
916
      break;
917
      
Elliot Lee's avatar
Elliot Lee committed
918
    default:
919
      break;
920 921
    }

Elliot Lee's avatar
Elliot Lee committed
922 923 924
  return window;
}

925 926 927 928 929 930 931 932 933 934 935 936 937 938 939
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
940
/**
941 942
 * gdk_window_foreign_new_for_display:
 * @display: the #GdkDisplay where the window handle comes from.
943
 * @anid: a native window handle.
Havoc Pennington's avatar
Havoc Pennington committed
944
 * 
945
 * Wraps a native window in a #GdkWindow.
946 947 948
 * 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.
949 950 951
 *
 * For example in the X backend, a native window handle is an Xlib
 * <type>XID</type>.
Havoc Pennington's avatar
Havoc Pennington committed
952
 * 
953 954 955
 * 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
956 957
 *
 * Since: 2.2
Havoc Pennington's avatar
Havoc Pennington committed
958
 **/
Elliot Lee's avatar
Elliot Lee committed
959
GdkWindow *
960 961
gdk_window_foreign_new_for_display (GdkDisplay     *display,
				    GdkNativeWindow anid)
Elliot Lee's avatar
Elliot Lee committed
962 963
{
  GdkWindow *window;
964 965 966
  GdkWindowObject *private;
  GdkWindowImplX11 *impl;
  GdkDrawableImplX11 *draw_impl;
967
  GdkDisplayX11 *display_x11;
Elliot Lee's avatar
Elliot Lee committed
968
  XWindowAttributes attrs;
969
  Window root, parent;
970
  Window *children = NULL;
971
  guint nchildren;
972 973
  gboolean result;

974 975 976
  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);

  display_x11 = GDK_DISPLAY_X11 (display);
977 978 979 980

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

981
  gdk_error_trap_push ();
982
  result = XGetWindowAttributes (display_x11->xdisplay, anid, &attrs);
983 984 985 986 987 988
  if (gdk_error_trap_pop () || !result)
    return NULL;

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

993 994
  if (children)
    XFree (children);
995
  
996
  window = g_object_new (GDK_TYPE_WINDOW, NULL);
997 998 999 1000
  private = (GdkWindowObject *)window;
  impl = GDK_WINDOW_IMPL_X11 (private->impl);
  draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
  draw_impl->wrapper = GDK_DRAWABLE (window);
1001 1002 1003
  draw_impl->screen = _gdk_x11_display_screen_for_xrootwin (display, root);
  
  private->parent = gdk_xid_table_lookup_for_display (display, parent);
1004
  
1005
  if (!private->parent || GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_FOREIGN)
<