gdkwindow-x11.c 166 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
      object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_X11,
139
                                            g_intern_static_string ("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
229
  if (window_impl->cursor)
    gdk_cursor_unref (window_impl->cursor);

230
231
  G_OBJECT_CLASS (parent_class)->finalize (object);
}
232

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

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

242
243
244
245
246
247
248
  /* 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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
  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);

265
266
267
  if (!(obj->event_mask & GDK_EXPOSURE_MASK))
    return;
    
Soeren Sandmann's avatar
Soeren Sandmann committed
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
300
301
302
  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;

303
304
305
306
307
308
  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
309
310

  if (private->window_type != GDK_WINDOW_ROOT &&
311
      private->window_type != GDK_WINDOW_FOREIGN)
Soeren Sandmann's avatar
Soeren Sandmann committed
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
    {
      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;

335
336
337
338
339
340
  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
341
342

  if (private->window_type != GDK_WINDOW_ROOT &&
343
      private->window_type != GDK_WINDOW_FOREIGN)
Soeren Sandmann's avatar
Soeren Sandmann committed
344
345
346
347
348
349
350
351
352
353
354
355
356
    {
      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);
    }
}

357
358
359
360
361
362
363
364
365
366
367
368
369
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;
370
      GdkVisual *visual;
371

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

      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);
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)
{
  GdkDrawableImplX11 *draw_impl;
  
  g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable));
392

393
  draw_impl = GDK_DRAWABLE_IMPL_X11 (drawable);
394

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

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

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

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


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
425
426
}

427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
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
443
void
444
_gdk_windowing_window_init (GdkScreen * screen)
Elliot Lee's avatar
Elliot Lee committed
445
{
446
447
448
  GdkWindowObject *private;
  GdkWindowImplX11 *impl;
  GdkDrawableImplX11 *draw_impl;
449
  GdkScreenX11 *screen_x11;
450

451
452
453
  screen_x11 = GDK_SCREEN_X11 (screen);

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

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

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

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

482
483
484
485
static void
set_wm_protocols (GdkWindow *window)
{
  GdkDisplay *display = gdk_drawable_get_display (window);
486
487
  Atom protocols[4];
  int n = 0;
488
  
489
490
491
  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");
492

493
494
495
496
497
498
#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);
499
}
500

501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
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);

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

528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
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;
}

546
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
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
}

583
static void
584
585
setup_toplevel_window (GdkWindow *window, 
		       GdkWindow *parent)
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
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
{
  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);
637

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

  ensure_sync_counter (window);
644
645
}

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

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

  screen_x11 = GDK_SCREEN_X11 (screen);
701
702

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

  /* 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)
722
    parent = gdk_screen_get_root_window (screen);
723
  
724
  private->parent = (GdkWindowObject *)parent;
725

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

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

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

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

790
791
  impl->override_redirect = xattributes.override_redirect;
  
792
  if (private->parent && private->parent->guffaw_gravity)
793
794
795
796
    {
      xattributes.win_gravity = StaticGravity;
      xattributes_mask |= CWWinGravity;
    }
797
  
798
799
800
801
802
803
  /* Sanity checks */
  switch (private->window_type)
    {
    case GDK_WINDOW_TOPLEVEL:
    case GDK_WINDOW_DIALOG:
    case GDK_WINDOW_TEMP:
804
      if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
805
806
807
	{
	  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");
808
	  xparent = GDK_SCREEN_XROOTWIN (screen);
809
810
811
812
813
814
815
816
	}
    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
817
818
819
820
  if (attributes->wclass == GDK_INPUT_OUTPUT)
    {
      class = InputOutput;
      depth = visual->depth;
821
822

      private->input_only = FALSE;
823
      private->depth = depth;
824
      
Elliot Lee's avatar
Elliot Lee committed
825
      if (attributes_mask & GDK_WA_COLORMAP)
826
827
        {
          draw_impl->colormap = attributes->colormap;
828
          g_object_ref (attributes->colormap);
829
        }
Elliot Lee's avatar
Elliot Lee committed
830
      else
831
	{
832
	  if ((((GdkVisualPrivate *)gdk_screen_get_system_visual (screen))->xvisual) ==  xvisual)
833
            {
834
	      draw_impl->colormap = gdk_screen_get_system_colormap (screen);
835
              g_object_ref (draw_impl->colormap);
836
            }
837
	  else
838
            {
839
              draw_impl->colormap = gdk_colormap_new (visual, FALSE);
840
            }
841
	}
842
      
843
      private->bg_color.pixel = BlackPixel (xdisplay, screen_x11->screen_num);
844
      private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
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
  if (gdk_error_trap_pop () || !result)
    return NULL;

  /* FIXME: This is pretty expensive. Maybe the caller should supply