~canonical-dx-team/ubuntu/maverick/gtk+2.0/menuproxy

« back to all changes in this revision

Viewing changes to gdk/x11/gdkwindow-x11.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-05-04 12:24:25 UTC
  • mfrom: (1.1.21 upstream)
  • Revision ID: james.westby@ubuntu.com-20070504122425-0m8midgzrp40y8w2
Tags: 2.10.12-1ubuntu1
* Sync with Debian
* New upstream version:
  Fixed bugs:
  - 379414 file chooser warnings when changing path in the entry
  - 418585 GtkFileChooserDefault sizing code is not DPI independent
  - 419568 Crash in search if start with special letter
  - 435062 build dies with icon cache validation
  - 379399 Segfault to call gtk_print_operation_run twice.
  - 387889 cups backend has problems when there are too many printers
  - 418531 invalid read to gtkicontheme.c gtk_icon_theme_lookup_icon...
  - 423916 crash in color scheme code
  - 424042 Segmentation fault while quickly pressing Alt+arrows
  - 415260 Protect against negative indices when setting values in G...
  - 419171 XGetVisualInfo() may not set nxvisuals
  - 128852 Gdk cursors don't look good on win32
  - 344657 Ctrl-H doesn't toggle "Show Hidden Files" setting
  - 345345 PrintOperation::paginate is not emitted for class handler
  - 347567 GtkPrintOperation::end-print is not emitted if it's cance...
  - 369112 gtk_ui_manager_add_ui should accept unnamed separator
  - 392015 Selected menu item invisible on Windows Vista
  - 399253 MS-Windows Theme Bottom Tab placement rendering glitches
  - 399425 gtk_input_dialog_fill_axes() adds child to gtkscrolledwin...
  - 403251 [patch] little memory leak in GtkPrintJob
  - 403267 [patch] memory leak in GtkPageSetupUnixDialog
  - 403470 MS-Windows Theme tab placement other than on top leaks a ...
  - 404506 Windows system fonts that have multi-byte font names cann...
  - 405089 Incorrect window placement for GtkEventBox private window
  - 405515 Minor leak in gtkfilesystemmodel.c
  - 405539 gdk_pixbuf_save() for PNG saver can return FALSE without ...
  - 415681 gdk_window_clear_area includes an extra line and column o...
  - 418219 GtkRecentChooser should apply filter before sorting and c...
  - 418403 Scroll to printer after selecting it from settings
  - 421985 _gtk_print_operation_platform_backend_launch_preview
  - 421990 gtk_print_job_get_surface
  - 421993 gtk_print_operation_init
  - 423064 Conditional jump or move depends on uninitialised value(s...
  - 423722 Fix printing header in gtk-demo
  - 424168 gtk_print_operation_run on async preview
  - 425655 Don't install gtk+-unix-print-2.0.pc on non-UNIX platforms
  - 425786 GDK segfaults if XineramaQueryScreens fails
  - 428665 Lpr Backend gets stuck in infinite loop during gtk_enumer...
  - 429902 GtkPrintOperation leaks cairo contextes
  - 431997 First delay of GdkPixbufAnimationIter is wrong
  - 433242 Inconsistent scroll arrow position calculations
  - 433972 Placing gtk.Expander inside a gtk.TextView() changes gtk....
  - 434261 _gtk_toolbar_elide_underscores incorrectly handles some s...
  - 383354 ctrl-L should make 'Location' entry disappear
  - 418673 gtk_recent_manager_add_item
  - 429732 gtk_accel_group_finalize accesses invalid memory
  - 435028 WM_CLIENT_LEADER is wrong on the leader_window
  - 431067 Background of the header window is not updated
  - 338843 add recent files support inside the ui manager
  - 148535 add drop shadow to menus, tooltips, etc. under Windows XP
* debian/control.in:
  - Conflicts on ubuntulooks (<= 0.9.11-1)
* debian/patches/15_default-fallback-icon-theme.patch:
  - patch from Debian, fallback on gnome icon theme

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GDK - The GIMP Drawing Kit
 
2
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Lesser General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2 of the License, or (at your option) any later version.
 
8
 *
 
9
 * This library is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * Lesser General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Lesser General Public
 
15
 * License along with this library; if not, write to the
 
16
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
17
 * Boston, MA 02111-1307, USA.
 
18
 */
 
19
 
 
20
/*
 
21
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
 
22
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 
23
 * files for a list of changes.  These files are distributed with
 
24
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 
25
 */
 
26
 
 
27
#include <config.h>
 
28
 
 
29
#include <X11/Xlib.h>
 
30
#include <X11/Xutil.h>
 
31
#include <X11/Xatom.h>
 
32
#include <netinet/in.h>
 
33
#include <unistd.h>
 
34
 
 
35
#include "gdk.h"
 
36
 
 
37
#include "gdkwindow.h"
 
38
#include "gdkasync.h"
 
39
#include "gdkinputprivate.h"
 
40
#include "gdkdisplay-x11.h"
 
41
#include "gdkprivate-x11.h"
 
42
#include "gdkregion.h"
 
43
#include "gdkinternals.h"
 
44
#include "MwmUtil.h"
 
45
#include "gdkwindow-x11.h"
 
46
#include "gdkalias.h"
 
47
 
 
48
#include <stdlib.h>
 
49
#include <stdio.h>
 
50
#include <string.h>
 
51
 
 
52
 
 
53
#ifdef HAVE_SHAPE_EXT
 
54
#include <X11/extensions/shape.h>
 
55
#endif
 
56
 
 
57
const int _gdk_event_mask_table[21] =
 
58
{
 
59
  ExposureMask,
 
60
  PointerMotionMask,
 
61
  PointerMotionHintMask,
 
62
  ButtonMotionMask,
 
63
  Button1MotionMask,
 
64
  Button2MotionMask,
 
65
  Button3MotionMask,
 
66
  ButtonPressMask,
 
67
  ButtonReleaseMask,
 
68
  KeyPressMask,
 
69
  KeyReleaseMask,
 
70
  EnterWindowMask,
 
71
  LeaveWindowMask,
 
72
  FocusChangeMask,
 
73
  StructureNotifyMask,
 
74
  PropertyChangeMask,
 
75
  VisibilityChangeMask,
 
76
  0,                            /* PROXIMITY_IN */
 
77
  0,                            /* PROXIMTY_OUT */
 
78
  SubstructureNotifyMask,
 
79
  ButtonPressMask      /* SCROLL; on X mouse wheel events is treated as mouse button 4/5 */
 
80
};
 
81
const int _gdk_nenvent_masks = sizeof (_gdk_event_mask_table) / sizeof (int);
 
82
 
 
83
/* Forward declarations */
 
84
static void     gdk_window_set_static_win_gravity (GdkWindow  *window,
 
85
                                                   gboolean    on);
 
86
static gboolean gdk_window_icon_name_set          (GdkWindow  *window);
 
87
static void     gdk_window_add_colormap_windows   (GdkWindow  *window);
 
88
static void     set_wm_name                       (GdkDisplay  *display,
 
89
                                                   Window       xwindow,
 
90
                                                   const gchar *name);
 
91
static void     move_to_current_desktop           (GdkWindow *window);
 
92
 
 
93
static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable);
 
94
static void         gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
 
95
                                                      GdkColormap *cmap);
 
96
static void         gdk_window_impl_x11_get_size    (GdkDrawable *drawable,
 
97
                                                     gint *width,
 
98
                                                     gint *height);
 
99
static GdkRegion*  gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable);
 
100
static void gdk_window_impl_x11_finalize   (GObject            *object);
 
101
 
 
102
#define WINDOW_IS_TOPLEVEL(window)                 \
 
103
  (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
 
104
   GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
 
105
 
 
106
/* Return whether time1 is considered later than time2 as far as xserver
 
107
 * time is concerned.  Accounts for wraparound.
 
108
 */
 
109
#define XSERVER_TIME_IS_LATER(time1, time2)                        \
 
110
  ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) ||  \
 
111
    (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 ))     \
 
112
  )
 
113
 
 
114
G_DEFINE_TYPE (GdkWindowImplX11, gdk_window_impl_x11, GDK_TYPE_DRAWABLE_IMPL_X11)
 
115
 
 
116
GType
 
117
_gdk_window_impl_get_type (void)
 
118
{
 
119
  return gdk_window_impl_x11_get_type ();
 
120
}
 
121
 
 
122
static void
 
123
gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
 
124
{  
 
125
  impl->width = 1;
 
126
  impl->height = 1;
 
127
  impl->toplevel_window_type = -1;
 
128
}
 
129
 
 
130
GdkToplevelX11 *
 
131
_gdk_x11_window_get_toplevel (GdkWindow *window)
 
132
{
 
133
  GdkWindowObject *private;
 
134
  GdkWindowImplX11 *impl;
 
135
  
 
136
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
137
 
 
138
  if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
 
139
    return NULL;
 
140
 
 
141
  private = (GdkWindowObject *)window;
 
142
  impl = GDK_WINDOW_IMPL_X11 (private->impl);
 
143
 
 
144
  if (!impl->toplevel)
 
145
    impl->toplevel = g_new0 (GdkToplevelX11, 1);
 
146
 
 
147
  return impl->toplevel;
 
148
}
 
149
 
 
150
static void
 
151
gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
 
152
{
 
153
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
154
  GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
 
155
  
 
156
  object_class->finalize = gdk_window_impl_x11_finalize;
 
157
 
 
158
  drawable_class->set_colormap = gdk_window_impl_x11_set_colormap;
 
159
  drawable_class->get_colormap = gdk_window_impl_x11_get_colormap;
 
160
  drawable_class->get_size = gdk_window_impl_x11_get_size;
 
161
 
 
162
  /* Visible and clip regions are the same */
 
163
  drawable_class->get_clip_region = gdk_window_impl_x11_get_visible_region;
 
164
  drawable_class->get_visible_region = gdk_window_impl_x11_get_visible_region;
 
165
}
 
166
 
 
167
static void
 
168
gdk_window_impl_x11_finalize (GObject *object)
 
169
{
 
170
  GdkWindowObject *wrapper;
 
171
  GdkDrawableImplX11 *draw_impl;
 
172
  GdkWindowImplX11 *window_impl;
 
173
  
 
174
  g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (object));
 
175
 
 
176
  draw_impl = GDK_DRAWABLE_IMPL_X11 (object);
 
177
  window_impl = GDK_WINDOW_IMPL_X11 (object);
 
178
  
 
179
  wrapper = (GdkWindowObject*) draw_impl->wrapper;
 
180
 
 
181
  _gdk_xgrab_check_destroy (GDK_WINDOW (wrapper));
 
182
 
 
183
  if (!GDK_WINDOW_DESTROYED (wrapper))
 
184
    {
 
185
      GdkDisplay *display = GDK_WINDOW_DISPLAY (wrapper);
 
186
      
 
187
      _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
  if (window_impl->toplevel)
 
193
    g_free (window_impl->toplevel);
 
194
 
 
195
  if (window_impl->cursor)
 
196
    gdk_cursor_unref (window_impl->cursor);
 
197
 
 
198
  G_OBJECT_CLASS (gdk_window_impl_x11_parent_class)->finalize (object);
 
199
}
 
200
 
 
201
static void
 
202
tmp_unset_bg (GdkWindow *window)
 
203
{
 
204
  GdkWindowImplX11 *impl;
 
205
  GdkWindowObject *obj;
 
206
 
 
207
  obj = (GdkWindowObject *) window;
 
208
  impl = GDK_WINDOW_IMPL_X11 (obj->impl);
 
209
 
 
210
  /* For windows without EXPOSURE_MASK, we can't do this
 
211
   * unsetting because such windows depend on the drawing
 
212
   * that the X server is going to do
 
213
   */
 
214
  if (!(obj->event_mask & GDK_EXPOSURE_MASK))
 
215
    return;
 
216
    
 
217
  impl->position_info.no_bg = TRUE;
 
218
 
 
219
  if (obj->bg_pixmap != GDK_NO_BG)
 
220
    XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
 
221
                                GDK_DRAWABLE_XID (window), None);
 
222
}
 
223
 
 
224
static void
 
225
tmp_reset_bg (GdkWindow *window)
 
226
{
 
227
  GdkWindowImplX11 *impl;
 
228
  GdkWindowObject *obj;
 
229
 
 
230
  obj = (GdkWindowObject *) window;
 
231
  impl = GDK_WINDOW_IMPL_X11 (obj->impl);
 
232
 
 
233
  if (!(obj->event_mask & GDK_EXPOSURE_MASK))
 
234
    return;
 
235
    
 
236
  impl->position_info.no_bg = FALSE;
 
237
 
 
238
  if (obj->bg_pixmap == GDK_NO_BG)
 
239
    return;
 
240
  
 
241
  if (obj->bg_pixmap)
 
242
    {
 
243
      Pixmap xpixmap;
 
244
 
 
245
      if (obj->bg_pixmap == GDK_PARENT_RELATIVE_BG)
 
246
        xpixmap = ParentRelative;
 
247
      else 
 
248
        xpixmap = GDK_DRAWABLE_XID (obj->bg_pixmap);
 
249
 
 
250
      XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
 
251
                                  GDK_DRAWABLE_XID (window), xpixmap);
 
252
    }
 
253
  else
 
254
    {
 
255
      XSetWindowBackground (GDK_DRAWABLE_XDISPLAY (window),
 
256
                            GDK_DRAWABLE_XID (window),
 
257
                            obj->bg_color.pixel);
 
258
    }
 
259
}
 
260
 
 
261
/* Unsetting and resetting window backgrounds.
 
262
 *
 
263
 * In many cases it is possible to avoid flicker by unsetting the
 
264
 * background of windows. For example if the background of the
 
265
 * parent window is unset when a window is unmapped, a brief flicker
 
266
 * of background painting is avoided.
 
267
 */
 
268
void
 
269
_gdk_x11_window_tmp_unset_bg (GdkWindow *window,
 
270
                              gboolean   recurse)
 
271
{
 
272
  GdkWindowObject *private;
 
273
 
 
274
  g_return_if_fail (GDK_IS_WINDOW (window));
 
275
  
 
276
  private = (GdkWindowObject *)window;
 
277
 
 
278
  if (private->input_only || private->destroyed ||
 
279
      (private->window_type != GDK_WINDOW_ROOT &&
 
280
       !GDK_WINDOW_IS_MAPPED (window)))
 
281
    {
 
282
      return;
 
283
    }
 
284
 
 
285
  if (private->window_type != GDK_WINDOW_ROOT &&
 
286
      private->window_type != GDK_WINDOW_FOREIGN)
 
287
    {
 
288
      tmp_unset_bg (window);
 
289
    }
 
290
 
 
291
  if (recurse)
 
292
    {
 
293
      GList *l;
 
294
 
 
295
      for (l = private->children; l != NULL; l = l->next)
 
296
        _gdk_x11_window_tmp_unset_bg (l->data, TRUE);
 
297
    }
 
298
}
 
299
 
 
300
void
 
301
_gdk_x11_window_tmp_reset_bg (GdkWindow *window,
 
302
                              gboolean   recurse)
 
303
{
 
304
  GdkWindowObject *private;
 
305
 
 
306
  g_return_if_fail (GDK_IS_WINDOW (window));
 
307
 
 
308
  private = (GdkWindowObject *)window;
 
309
 
 
310
  if (private->input_only || private->destroyed ||
 
311
      (private->window_type != GDK_WINDOW_ROOT &&
 
312
       !GDK_WINDOW_IS_MAPPED (window)))
 
313
    {
 
314
      return;
 
315
    }
 
316
 
 
317
  if (private->window_type != GDK_WINDOW_ROOT &&
 
318
      private->window_type != GDK_WINDOW_FOREIGN)
 
319
    {
 
320
      tmp_reset_bg (window);
 
321
    }
 
322
 
 
323
  if (recurse)
 
324
    {
 
325
      GList *l;
 
326
 
 
327
      for (l = private->children; l != NULL; l = l->next)
 
328
        _gdk_x11_window_tmp_reset_bg (l->data, TRUE);
 
329
    }
 
330
}
 
331
 
 
332
static GdkColormap*
 
333
gdk_window_impl_x11_get_colormap (GdkDrawable *drawable)
 
334
{
 
335
  GdkDrawableImplX11 *drawable_impl;
 
336
  
 
337
  g_return_val_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable), NULL);
 
338
 
 
339
  drawable_impl = GDK_DRAWABLE_IMPL_X11 (drawable);
 
340
 
 
341
  if (!((GdkWindowObject *) drawable_impl->wrapper)->input_only && 
 
342
      drawable_impl->colormap == NULL)
 
343
    {
 
344
      XWindowAttributes window_attributes;
 
345
      GdkVisual *visual;
 
346
 
 
347
      XGetWindowAttributes (GDK_SCREEN_XDISPLAY (drawable_impl->screen),
 
348
                            drawable_impl->xid,
 
349
                            &window_attributes);
 
350
 
 
351
      visual = gdk_x11_screen_lookup_visual (drawable_impl->screen,
 
352
                                             window_attributes.visual->visualid);
 
353
      drawable_impl->colormap = gdk_x11_colormap_foreign_new (visual,
 
354
                                                              window_attributes.colormap);
 
355
    }
 
356
  
 
357
  return drawable_impl->colormap;
 
358
}
 
359
 
 
360
static void
 
361
gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
 
362
                                  GdkColormap *cmap)
 
363
{
 
364
  GdkDrawableImplX11 *draw_impl;
 
365
  
 
366
  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
    return;
 
372
 
 
373
  /* chain up */
 
374
  GDK_DRAWABLE_CLASS (gdk_window_impl_x11_parent_class)->set_colormap (drawable, cmap);
 
375
 
 
376
  if (cmap)
 
377
    {
 
378
      XSetWindowColormap (GDK_SCREEN_XDISPLAY (draw_impl->screen),
 
379
                          draw_impl->xid,
 
380
                          GDK_COLORMAP_XCOLORMAP (cmap));
 
381
 
 
382
      if (((GdkWindowObject*)draw_impl->wrapper)->window_type !=
 
383
          GDK_WINDOW_TOPLEVEL)
 
384
        gdk_window_add_colormap_windows (GDK_WINDOW (draw_impl->wrapper));
 
385
    }
 
386
}
 
387
 
 
388
 
 
389
static void
 
390
gdk_window_impl_x11_get_size (GdkDrawable *drawable,
 
391
                              gint        *width,
 
392
                              gint        *height)
 
393
{
 
394
  g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable));
 
395
 
 
396
  if (width)
 
397
    *width = GDK_WINDOW_IMPL_X11 (drawable)->width;
 
398
  if (height)
 
399
    *height = GDK_WINDOW_IMPL_X11 (drawable)->height;
 
400
}
 
401
 
 
402
static GdkRegion*
 
403
gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable)
 
404
{
 
405
  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (drawable);
 
406
  GdkRectangle result_rect;
 
407
 
 
408
  result_rect.x = 0;
 
409
  result_rect.y = 0;
 
410
  result_rect.width = impl->width;
 
411
  result_rect.height = impl->height;
 
412
 
 
413
  gdk_rectangle_intersect (&result_rect, &impl->position_info.clip_rect, &result_rect);
 
414
 
 
415
  return gdk_region_rectangle (&result_rect);
 
416
}
 
417
 
 
418
void
 
419
_gdk_windowing_window_init (GdkScreen * screen)
 
420
{
 
421
  GdkWindowObject *private;
 
422
  GdkWindowImplX11 *impl;
 
423
  GdkDrawableImplX11 *draw_impl;
 
424
  GdkScreenX11 *screen_x11;
 
425
 
 
426
  screen_x11 = GDK_SCREEN_X11 (screen);
 
427
 
 
428
  g_assert (screen_x11->root_window == NULL);
 
429
 
 
430
  gdk_screen_set_default_colormap (screen,
 
431
                                   gdk_screen_get_system_colormap (screen));
 
432
 
 
433
  screen_x11->root_window = g_object_new (GDK_TYPE_WINDOW, NULL);
 
434
  private = (GdkWindowObject *)screen_x11->root_window;
 
435
  impl = GDK_WINDOW_IMPL_X11 (private->impl);
 
436
  draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
 
437
  
 
438
  draw_impl->screen = screen;
 
439
  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
  impl->width = WidthOfScreen (screen_x11->xscreen);
 
448
  impl->height = HeightOfScreen (screen_x11->xscreen);
 
449
  
 
450
  _gdk_window_init_position (GDK_WINDOW (private));
 
451
 
 
452
  _gdk_xid_table_insert (screen_x11->display,
 
453
                         &screen_x11->xroot_window,
 
454
                         screen_x11->root_window);
 
455
}
 
456
 
 
457
static void
 
458
set_wm_protocols (GdkWindow *window)
 
459
{
 
460
  GdkDisplay *display = gdk_drawable_get_display (window);
 
461
  Atom protocols[4];
 
462
  int n = 0;
 
463
  
 
464
  protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
 
465
  protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
 
466
  protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
 
467
 
 
468
#ifdef HAVE_XSYNC
 
469
  if (GDK_DISPLAY_X11 (display)->use_sync)
 
470
    protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
 
471
#endif
 
472
  
 
473
  XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n);
 
474
}
 
475
 
 
476
static const gchar *
 
477
get_default_title (void)
 
478
{
 
479
  const char *title;
 
480
 
 
481
  title = g_get_application_name ();
 
482
  if (!title)
 
483
    title = g_get_prgname ();
 
484
 
 
485
  return title;
 
486
}
 
487
 
 
488
static void
 
489
check_leader_window_title (GdkDisplay *display)
 
490
{
 
491
  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
 
492
 
 
493
  if (display_x11->leader_window && !display_x11->leader_window_title_set)
 
494
    {
 
495
      set_wm_name (display,
 
496
                   display_x11->leader_window,
 
497
                   get_default_title ());
 
498
      
 
499
      display_x11->leader_window_title_set = TRUE;
 
500
    }
 
501
}
 
502
 
 
503
static Window
 
504
create_focus_window (Display *xdisplay,
 
505
                     XID      parent)
 
506
{
 
507
  Window focus_window = XCreateSimpleWindow (xdisplay, parent,
 
508
                                             -1, -1, 1, 1, 0,
 
509
                                             0, 0);
 
510
  
 
511
  /* FIXME: probably better to actually track the requested event mask for the toplevel
 
512
   */
 
513
  XSelectInput (xdisplay, focus_window,
 
514
                KeyPressMask | KeyReleaseMask | FocusChangeMask);
 
515
  
 
516
  XMapWindow (xdisplay, focus_window);
 
517
 
 
518
  return focus_window;
 
519
}
 
520
 
 
521
static void
 
522
ensure_sync_counter (GdkWindow *window)
 
523
{
 
524
#ifdef HAVE_XSYNC
 
525
  if (!GDK_WINDOW_DESTROYED (window))
 
526
    {
 
527
      GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
 
528
      GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
 
529
      GdkWindowObject *private = (GdkWindowObject *)window;
 
530
      GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
 
531
 
 
532
      if (toplevel && impl->use_synchronized_configure &&
 
533
          toplevel->update_counter == None &&
 
534
          GDK_DISPLAY_X11 (display)->use_sync)
 
535
        {
 
536
          Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
 
537
          XSyncValue value;
 
538
          Atom atom;
 
539
 
 
540
          XSyncIntToValue (&value, 0);
 
541
          
 
542
          toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
 
543
          
 
544
          atom = gdk_x11_get_xatom_by_name_for_display (display,
 
545
                                                        "_NET_WM_SYNC_REQUEST_COUNTER");
 
546
          
 
547
          XChangeProperty (xdisplay, GDK_WINDOW_XID (window),
 
548
                           atom, XA_CARDINAL,
 
549
                           32, PropModeReplace,
 
550
                           (guchar *)&toplevel->update_counter, 1);
 
551
          
 
552
          XSyncIntToValue (&toplevel->current_counter_value, 0);
 
553
        }
 
554
    }
 
555
#endif
 
556
}
 
557
 
 
558
static void
 
559
setup_toplevel_window (GdkWindow *window, 
 
560
                       GdkWindow *parent)
 
561
{
 
562
  GdkWindowObject *obj = (GdkWindowObject *)window;
 
563
  GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
 
564
  GdkWindowImplX11 *impl = (GdkWindowImplX11 *)obj->impl;
 
565
  Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
 
566
  XID xid = GDK_WINDOW_XID (window);
 
567
  XID xparent = GDK_WINDOW_XID (parent);
 
568
  GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (parent));
 
569
  XSizeHints size_hints;
 
570
  long pid;
 
571
  Window leader_window;
 
572
    
 
573
  if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_DIALOG)
 
574
    XSetTransientForHint (xdisplay, xid, xparent);
 
575
  
 
576
  set_wm_protocols (window);
 
577
  
 
578
  if (!obj->input_only)
 
579
    {
 
580
      /* The focus window is off the visible area, and serves to receive key
 
581
       * press events so they don't get sent to child windows.
 
582
       */
 
583
      toplevel->focus_window = create_focus_window (xdisplay, xid);
 
584
      _gdk_xid_table_insert (screen_x11->display, &toplevel->focus_window, window);
 
585
    }
 
586
  
 
587
  check_leader_window_title (screen_x11->display);
 
588
  
 
589
  /* FIXME: Is there any point in doing this? Do any WM's pay
 
590
   * attention to PSize, and even if they do, is this the
 
591
   * correct value???
 
592
   */
 
593
  size_hints.flags = PSize;
 
594
  size_hints.width = impl->width;
 
595
  size_hints.height = impl->height;
 
596
  
 
597
  XSetWMNormalHints (xdisplay, xid, &size_hints);
 
598
  
 
599
  /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
 
600
  XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
 
601
  
 
602
  pid = getpid ();
 
603
  XChangeProperty (xdisplay, xid,
 
604
                   gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "_NET_WM_PID"),
 
605
                   XA_CARDINAL, 32,
 
606
                   PropModeReplace,
 
607
                   (guchar *)&pid, 1);
 
608
 
 
609
  leader_window = GDK_DISPLAY_X11 (screen_x11->display)->leader_window;
 
610
  if (!leader_window)
 
611
    leader_window = xid;
 
612
  XChangeProperty (xdisplay, xid, 
 
613
                   gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "WM_CLIENT_LEADER"),
 
614
                   XA_WINDOW, 32, PropModeReplace,
 
615
                   (guchar *) &leader_window, 1);
 
616
 
 
617
  if (!obj->focus_on_map)
 
618
    gdk_x11_window_set_user_time (window, 0);
 
619
  else if (GDK_DISPLAY_X11 (screen_x11->display)->user_time != 0)
 
620
    gdk_x11_window_set_user_time (window, GDK_DISPLAY_X11 (screen_x11->display)->user_time);
 
621
 
 
622
  ensure_sync_counter (window);
 
623
}
 
624
 
 
625
/**
 
626
 * gdk_window_new:
 
627
 * @parent: a #GdkWindow, or %NULL to create the window as a child of
 
628
 *   the default root window for the default display.
 
629
 * @attributes: attributes of the new window
 
630
 * @attributes_mask: mask indicating which fields in @attributes are valid
 
631
 * 
 
632
 * Creates a new #GdkWindow using the attributes from
 
633
 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
 
634
 * more details.  Note: to use this on displays other than the default
 
635
 * display, @parent must be specified.
 
636
 * 
 
637
 * Return value: the new #GdkWindow
 
638
 **/
 
639
GdkWindow*
 
640
gdk_window_new (GdkWindow     *parent,
 
641
                GdkWindowAttr *attributes,
 
642
                gint           attributes_mask)
 
643
{
 
644
  GdkWindow *window;
 
645
  GdkWindowObject *private;
 
646
  GdkWindowImplX11 *impl;
 
647
  GdkDrawableImplX11 *draw_impl;
 
648
  GdkScreenX11 *screen_x11;
 
649
  GdkScreen *screen;
 
650
  
 
651
  GdkVisual *visual;
 
652
  Window xparent;
 
653
  Visual *xvisual;
 
654
  Display *xdisplay;
 
655
  Window xid;
 
656
 
 
657
  XSetWindowAttributes xattributes;
 
658
  long xattributes_mask;
 
659
  XClassHint *class_hint;
 
660
  int x, y, depth;
 
661
  
 
662
  unsigned int class;
 
663
  const char *title;
 
664
  int i;
 
665
  
 
666
  g_return_val_if_fail (attributes != NULL, NULL);
 
667
  
 
668
  if (!parent)
 
669
    {
 
670
      GDK_NOTE (MULTIHEAD,
 
671
                g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
 
672
      
 
673
      screen = gdk_screen_get_default ();
 
674
      parent = gdk_screen_get_root_window (screen);
 
675
    }
 
676
  else
 
677
    screen = gdk_drawable_get_screen (parent);
 
678
 
 
679
  screen_x11 = GDK_SCREEN_X11 (screen);
 
680
 
 
681
  g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
 
682
  
 
683
  if (GDK_WINDOW_DESTROYED (parent))
 
684
    return NULL;
 
685
  
 
686
  xparent = GDK_WINDOW_XID (parent);
 
687
  
 
688
  window = g_object_new (GDK_TYPE_WINDOW, NULL);
 
689
  private = (GdkWindowObject *)window;
 
690
  impl = GDK_WINDOW_IMPL_X11 (private->impl);
 
691
  draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
 
692
  draw_impl->wrapper = GDK_DRAWABLE (window);
 
693
  
 
694
  draw_impl->screen = screen;
 
695
  xdisplay = screen_x11->xdisplay;
 
696
 
 
697
  /* Windows with a foreign parent are treated as if they are children
 
698
   * of the root window, except for actual creation.
 
699
   */
 
700
  if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
 
701
    parent = gdk_screen_get_root_window (screen);
 
702
  
 
703
  private->parent = (GdkWindowObject *)parent;
 
704
 
 
705
  private->accept_focus = TRUE;
 
706
  private->focus_on_map = TRUE;
 
707
 
 
708
  xattributes_mask = 0;
 
709
  
 
710
  if (attributes_mask & GDK_WA_X)
 
711
    x = attributes->x;
 
712
  else
 
713
    x = 0;
 
714
  
 
715
  if (attributes_mask & GDK_WA_Y)
 
716
    y = attributes->y;
 
717
  else
 
718
    y = 0;
 
719
  
 
720
  private->x = x;
 
721
  private->y = y;
 
722
  impl->width = (attributes->width > 1) ? (attributes->width) : (1);
 
723
  impl->height = (attributes->height > 1) ? (attributes->height) : (1);
 
724
 
 
725
  if (attributes->wclass == GDK_INPUT_ONLY)
 
726
    {
 
727
      /* Backwards compatiblity - we've always ignored
 
728
       * attributes->window_type for input-only windows
 
729
       * before
 
730
       */
 
731
      if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
 
732
        private->window_type = GDK_WINDOW_TEMP;
 
733
      else
 
734
        private->window_type = GDK_WINDOW_CHILD;
 
735
    }
 
736
  else
 
737
    private->window_type = attributes->window_type;
 
738
 
 
739
  /* Work around a bug where Xorg refuses to map toplevel InputOnly windows 
 
740
   * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
 
741
   */
 
742
  if (attributes->wclass == GDK_INPUT_ONLY &&
 
743
      GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT &&
 
744
      !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
 
745
    {
 
746
      g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
 
747
      attributes->wclass = GDK_INPUT_OUTPUT;
 
748
    }
 
749
 
 
750
  _gdk_window_init_position (GDK_WINDOW (private));
 
751
  if (impl->position_info.big)
 
752
    private->guffaw_gravity = TRUE;
 
753
  
 
754
  if (attributes_mask & GDK_WA_VISUAL)
 
755
    visual = attributes->visual;
 
756
  else
 
757
    visual = gdk_screen_get_system_visual (screen);
 
758
  xvisual = ((GdkVisualPrivate*) visual)->xvisual;
 
759
  
 
760
  xattributes.event_mask = StructureNotifyMask | PropertyChangeMask;
 
761
  for (i = 0; i < _gdk_nenvent_masks; i++)
 
762
    {
 
763
      if (attributes->event_mask & (1 << (i + 1)))
 
764
        xattributes.event_mask |= _gdk_event_mask_table[i];
 
765
    }
 
766
  private->event_mask = attributes->event_mask;
 
767
  
 
768
  if (xattributes.event_mask)
 
769
    xattributes_mask |= CWEventMask;
 
770
  
 
771
  if (attributes_mask & GDK_WA_NOREDIR)
 
772
    {
 
773
      xattributes.override_redirect =
 
774
        (attributes->override_redirect == FALSE)?False:True;
 
775
      xattributes_mask |= CWOverrideRedirect;
 
776
    } 
 
777
  else
 
778
    xattributes.override_redirect = False;
 
779
 
 
780
  impl->override_redirect = xattributes.override_redirect;
 
781
  
 
782
  if (private->parent && private->parent->guffaw_gravity)
 
783
    {
 
784
      xattributes.win_gravity = StaticGravity;
 
785
      xattributes_mask |= CWWinGravity;
 
786
    }
 
787
  
 
788
  /* Sanity checks */
 
789
  switch (private->window_type)
 
790
    {
 
791
    case GDK_WINDOW_TOPLEVEL:
 
792
    case GDK_WINDOW_DIALOG:
 
793
    case GDK_WINDOW_TEMP:
 
794
      if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
 
795
        {
 
796
          g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
 
797
                     "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
 
798
          xparent = GDK_SCREEN_XROOTWIN (screen);
 
799
        }
 
800
    case GDK_WINDOW_CHILD:
 
801
      break;
 
802
    default:
 
803
      g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
 
804
      return NULL;
 
805
    }
 
806
          
 
807
  if (attributes->wclass == GDK_INPUT_OUTPUT)
 
808
    {
 
809
      class = InputOutput;
 
810
      depth = visual->depth;
 
811
 
 
812
      private->input_only = FALSE;
 
813
      private->depth = depth;
 
814
      
 
815
      if (attributes_mask & GDK_WA_COLORMAP)
 
816
        {
 
817
          draw_impl->colormap = attributes->colormap;
 
818
          g_object_ref (attributes->colormap);
 
819
        }
 
820
      else
 
821
        {
 
822
          if ((((GdkVisualPrivate *)gdk_screen_get_system_visual (screen))->xvisual) ==  xvisual)
 
823
            {
 
824
              draw_impl->colormap = gdk_screen_get_system_colormap (screen);
 
825
              g_object_ref (draw_impl->colormap);
 
826
            }
 
827
          else
 
828
            {
 
829
              draw_impl->colormap = gdk_colormap_new (visual, FALSE);
 
830
            }
 
831
        }
 
832
      
 
833
      private->bg_color.pixel = BlackPixel (xdisplay, screen_x11->screen_num);
 
834
      private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
 
835
      xattributes.background_pixel = private->bg_color.pixel;
 
836
 
 
837
      private->bg_pixmap = NULL;
 
838
      
 
839
      xattributes.border_pixel = BlackPixel (xdisplay, screen_x11->screen_num);
 
840
      xattributes_mask |= CWBorderPixel | CWBackPixel;
 
841
 
 
842
      if (private->guffaw_gravity)
 
843
        xattributes.bit_gravity = StaticGravity;
 
844
      else
 
845
        xattributes.bit_gravity = NorthWestGravity;
 
846
      
 
847
      xattributes_mask |= CWBitGravity;
 
848
 
 
849
      xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap);
 
850
      xattributes_mask |= CWColormap;
 
851
 
 
852
      if (private->window_type == GDK_WINDOW_TEMP)
 
853
        {
 
854
          xattributes.save_under = True;
 
855
          xattributes.override_redirect = True;
 
856
          xattributes.cursor = None;
 
857
          xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
 
858
 
 
859
          impl->override_redirect = TRUE;
 
860
        }
 
861
    }
 
862
  else
 
863
    {
 
864
      depth = 0;
 
865
      private->depth = 0;
 
866
      class = InputOnly;
 
867
      private->input_only = TRUE;
 
868
      draw_impl->colormap = gdk_screen_get_system_colormap (screen);
 
869
      g_object_ref (draw_impl->colormap);
 
870
    }
 
871
 
 
872
  xid = draw_impl->xid = XCreateWindow (xdisplay, xparent,
 
873
                                        impl->position_info.x, impl->position_info.y,
 
874
                                        impl->position_info.width, impl->position_info.height,
 
875
                                        0, depth, class, xvisual,
 
876
                                        xattributes_mask, &xattributes);
 
877
 
 
878
  g_object_ref (window);
 
879
  _gdk_xid_table_insert (screen_x11->display, &draw_impl->xid, window);
 
880
  
 
881
  gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
 
882
                                  (attributes->cursor) :
 
883
                                  NULL));
 
884
  
 
885
  if (private->parent)
 
886
    private->parent->children = g_list_prepend (private->parent->children, window);
 
887
  
 
888
  switch (GDK_WINDOW_TYPE (private))
 
889
    {
 
890
    case GDK_WINDOW_DIALOG:
 
891
    case GDK_WINDOW_TOPLEVEL:
 
892
    case GDK_WINDOW_TEMP:
 
893
      if (attributes_mask & GDK_WA_TITLE)
 
894
        title = attributes->title;
 
895
      else
 
896
        title = get_default_title ();
 
897
      
 
898
      gdk_window_set_title (window, title);
 
899
      
 
900
      if (attributes_mask & GDK_WA_WMCLASS)
 
901
        {
 
902
          class_hint = XAllocClassHint ();
 
903
          class_hint->res_name = attributes->wmclass_name;
 
904
          class_hint->res_class = attributes->wmclass_class;
 
905
          XSetClassHint (xdisplay, xid, class_hint);
 
906
          XFree (class_hint);
 
907
        }
 
908
  
 
909
      setup_toplevel_window (window, parent);
 
910
      break;
 
911
 
 
912
    case GDK_WINDOW_CHILD:
 
913
      if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
 
914
          (draw_impl->colormap != gdk_screen_get_system_colormap (screen)) &&
 
915
          (draw_impl->colormap != gdk_drawable_get_colormap (gdk_window_get_toplevel (window))))
 
916
        {
 
917
          GDK_NOTE (MISC, g_message ("adding colormap window\n"));
 
918
          gdk_window_add_colormap_windows (window);
 
919
        }
 
920
      break;
 
921
      
 
922
    default:
 
923
      break;
 
924
    }
 
925
 
 
926
  if (attributes_mask & GDK_WA_TYPE_HINT)
 
927
    gdk_window_set_type_hint (window, attributes->type_hint);
 
928
 
 
929
  return window;
 
930
}
 
931
 
 
932
static GdkEventMask
 
933
x_event_mask_to_gdk_event_mask (long mask)
 
934
{
 
935
  GdkEventMask event_mask = 0;
 
936
  int i;
 
937
 
 
938
  for (i = 0; i < _gdk_nenvent_masks; i++)
 
939
    {
 
940
      if (mask & _gdk_event_mask_table[i])
 
941
        event_mask |= 1 << (i + 1);
 
942
    }
 
943
 
 
944
  return event_mask;
 
945
}
 
946
 
 
947
/**
 
948
 * gdk_window_foreign_new_for_display:
 
949
 * @display: the #GdkDisplay where the window handle comes from.
 
950
 * @anid: a native window handle.
 
951
 * 
 
952
 * Wraps a native window in a #GdkWindow.
 
953
 * This may fail if the window has been destroyed. If the window
 
954
 * was already known to GDK, a new reference to the existing 
 
955
 * #GdkWindow is returned.
 
956
 *
 
957
 * For example in the X backend, a native window handle is an Xlib
 
958
 * <type>XID</type>.
 
959
 * 
 
960
 * Return value: a #GdkWindow wrapper for the native window or 
 
961
 *   %NULL if the window has been destroyed. The wrapper will be
 
962
 *   newly created, if one doesn't exist already.
 
963
 *
 
964
 * Since: 2.2
 
965
 **/
 
966
GdkWindow *
 
967
gdk_window_foreign_new_for_display (GdkDisplay     *display,
 
968
                                    GdkNativeWindow anid)
 
969
{
 
970
  GdkWindow *window;
 
971
  GdkWindowObject *private;
 
972
  GdkWindowImplX11 *impl;
 
973
  GdkDrawableImplX11 *draw_impl;
 
974
  GdkDisplayX11 *display_x11;
 
975
  XWindowAttributes attrs;
 
976
  Window root, parent;
 
977
  Window *children = NULL;
 
978
  guint nchildren;
 
979
  gboolean result;
 
980
 
 
981
  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
 
982
 
 
983
  display_x11 = GDK_DISPLAY_X11 (display);
 
984
 
 
985
  if ((window = gdk_xid_table_lookup_for_display (display, anid)) != NULL)
 
986
    return g_object_ref (window);
 
987
 
 
988
  gdk_error_trap_push ();
 
989
  result = XGetWindowAttributes (display_x11->xdisplay, anid, &attrs);
 
990
  if (gdk_error_trap_pop () || !result)
 
991
    return NULL;
 
992
 
 
993
  /* FIXME: This is pretty expensive. Maybe the caller should supply
 
994
   *        the parent */
 
995
  gdk_error_trap_push ();
 
996
  result = XQueryTree (display_x11->xdisplay, anid, &root, &parent, &children, &nchildren);
 
997
  if (gdk_error_trap_pop () || !result)
 
998
    return NULL;
 
999
 
 
1000
  if (children)
 
1001
    XFree (children);
 
1002
  
 
1003
  window = g_object_new (GDK_TYPE_WINDOW, NULL);
 
1004
  private = (GdkWindowObject *)window;
 
1005
  impl = GDK_WINDOW_IMPL_X11 (private->impl);
 
1006
  draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
 
1007
  draw_impl->wrapper = GDK_DRAWABLE (window);
 
1008
  draw_impl->screen = _gdk_x11_display_screen_for_xrootwin (display, root);
 
1009
  
 
1010
  private->parent = gdk_xid_table_lookup_for_display (display, parent);
 
1011
  
 
1012
  if (!private->parent || GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_FOREIGN)
 
1013
    private->parent = (GdkWindowObject *) gdk_screen_get_root_window (draw_impl->screen);
 
1014
  
 
1015
  private->parent->children = g_list_prepend (private->parent->children, window);
 
1016
 
 
1017
  draw_impl->xid = anid;
 
1018
 
 
1019
  private->x = attrs.x;
 
1020
  private->y = attrs.y;
 
1021
  impl->width = attrs.width;
 
1022
  impl->height = attrs.height;
 
1023
  private->window_type = GDK_WINDOW_FOREIGN;
 
1024
  private->destroyed = FALSE;
 
1025
 
 
1026
  private->event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
 
1027
 
 
1028
  if (attrs.map_state == IsUnmapped)
 
1029
    private->state = GDK_WINDOW_STATE_WITHDRAWN;
 
1030
  else
 
1031
    private->state = 0;
 
1032
 
 
1033
  private->depth = attrs.depth;
 
1034
  
 
1035
  _gdk_window_init_position (GDK_WINDOW (private));
 
1036
 
 
1037
  g_object_ref (window);
 
1038
  _gdk_xid_table_insert (display, &GDK_WINDOW_XID (window), window);
 
1039
  return window;
 
1040
}
 
1041
 
 
1042
/**
 
1043
 * gdk_window_lookup_for_display:
 
1044
 * @display: the #GdkDisplay corresponding to the window handle
 
1045
 * @anid: a native window handle.
 
1046
 *
 
1047
 * Looks up the #GdkWindow that wraps the given native window handle.
 
1048
 *
 
1049
 * For example in the X backend, a native window handle is an Xlib
 
1050
 * <type>XID</type>.
 
1051
 *
 
1052
 * Return value: the #GdkWindow wrapper for the native window, 
 
1053
 *    or %NULL if there is none.
 
1054
 *
 
1055
 * Since: 2.2
 
1056
 **/
 
1057
GdkWindow *
 
1058
gdk_window_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid)
 
1059
{
 
1060
  return (GdkWindow*) gdk_xid_table_lookup_for_display (display, anid);
 
1061
}
 
1062
 
 
1063
/**
 
1064
 * gdk_window_lookup:
 
1065
 * @anid: a native window handle.
 
1066
 *
 
1067
 * Looks up the #GdkWindow that wraps the given native window handle. 
 
1068
 *
 
1069
 * For example in the X backend, a native window handle is an Xlib
 
1070
 * <type>XID</type>.
 
1071
 *
 
1072
 * Return value: the #GdkWindow wrapper for the native window, 
 
1073
 *    or %NULL if there is none.
 
1074
 **/
 
1075
GdkWindow *
 
1076
gdk_window_lookup (GdkNativeWindow anid)
 
1077
{
 
1078
  return (GdkWindow*) gdk_xid_table_lookup (anid);
 
1079
}
 
1080
 
 
1081
static void
 
1082
gdk_toplevel_x11_free_contents (GdkDisplay *display,
 
1083
                                GdkToplevelX11 *toplevel)
 
1084
{
 
1085
  if (toplevel->icon_window)
 
1086
    {
 
1087
      g_object_unref (toplevel->icon_window);
 
1088
      toplevel->icon_window = NULL;
 
1089
    }
 
1090
  if (toplevel->icon_pixmap)
 
1091
    {
 
1092
      g_object_unref (toplevel->icon_pixmap);
 
1093
      toplevel->icon_pixmap = NULL;
 
1094
    }
 
1095
  if (toplevel->icon_mask)
 
1096
    {
 
1097
      g_object_unref (toplevel->icon_mask);
 
1098
      toplevel->icon_mask = NULL;
 
1099
    }
 
1100
  if (toplevel->group_leader)
 
1101
    {
 
1102
      g_object_unref (toplevel->group_leader);
 
1103
      toplevel->group_leader = NULL;
 
1104
    }
 
1105
#ifdef HAVE_XSYNC
 
1106
  if (toplevel->update_counter != None)
 
1107
    {
 
1108
      XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display), 
 
1109
                           toplevel->update_counter);
 
1110
      toplevel->update_counter = None;
 
1111
 
 
1112
      XSyncIntToValue (&toplevel->current_counter_value, 0);
 
1113
    }
 
1114
#endif
 
1115
}
 
1116
 
 
1117
void
 
1118
_gdk_windowing_window_destroy (GdkWindow *window,
 
1119
                               gboolean   recursing,
 
1120
                               gboolean   foreign_destroy)
 
1121
{
 
1122
  GdkWindowObject *private = (GdkWindowObject *)window;
 
1123
  GdkToplevelX11 *toplevel;
 
1124
  
 
1125
  g_return_if_fail (GDK_IS_WINDOW (window));
 
1126
 
 
1127
  _gdk_selection_window_destroyed (window);
 
1128
  
 
1129
  if (private->extension_events != 0)
 
1130
    _gdk_input_window_destroy (window);
 
1131
 
 
1132
  toplevel = _gdk_x11_window_get_toplevel (window);
 
1133
  if (toplevel)
 
1134
    gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
 
1135
 
 
1136
  _gdk_x11_drawable_finish (private->impl);
 
1137
 
 
1138
  if (!recursing && !foreign_destroy)
 
1139
    {
 
1140
      XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
 
1141
    }
 
1142
}
 
1143
 
 
1144
void
 
1145
_gdk_windowing_window_destroy_foreign (GdkWindow *window)
 
1146
{
 
1147
  /* It's somebody else's window, but in our heirarchy,
 
1148
   * so reparent it to the root window, and then send
 
1149
   * it a delete event, as if we were a WM
 
1150
   */
 
1151
  XClientMessageEvent xclient;
 
1152
  
 
1153
  gdk_error_trap_push ();
 
1154
  gdk_window_hide (window);
 
1155
  gdk_window_reparent (window, NULL, 0, 0);
 
1156
  
 
1157
  memset (&xclient, 0, sizeof (xclient));
 
1158
  xclient.type = ClientMessage;
 
1159
  xclient.window = GDK_WINDOW_XID (window);
 
1160
  xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
 
1161
                                                               "WM_PROTOCOLS");
 
1162
  xclient.format = 32;
 
1163
  xclient.data.l[0] = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
 
1164
                                                            "WM_DELETE_WINDOW");
 
1165
  xclient.data.l[1] = CurrentTime;
 
1166
  xclient.data.l[2] = 0;
 
1167
  xclient.data.l[3] = 0;
 
1168
  xclient.data.l[4] = 0;
 
1169
  
 
1170
  XSendEvent (GDK_WINDOW_XDISPLAY (window),
 
1171
              GDK_WINDOW_XID (window),
 
1172
              False, 0, (XEvent *)&xclient);
 
1173
  gdk_display_sync (GDK_WINDOW_DISPLAY (window));
 
1174
  gdk_error_trap_pop ();
 
1175
}
 
1176
 
 
1177
static GdkWindow *
 
1178
get_root (GdkWindow *window)
 
1179
{
 
1180
  GdkScreen *screen = gdk_drawable_get_screen (window);
 
1181
 
 
1182
  return gdk_screen_get_root_window (screen);
 
1183
}
 
1184
 
 
1185
/* This function is called when the XWindow is really gone.
 
1186
 */
 
1187
void
 
1188
gdk_window_destroy_notify (GdkWindow *window)
 
1189
{
 
1190
  GdkWindowImplX11 *window_impl;
 
1191
 
 
1192
  g_return_if_fail (GDK_IS_WINDOW (window));
 
1193
  
 
1194
  window_impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
 
1195
 
 
1196
  if (!GDK_WINDOW_DESTROYED (window))
 
1197
    {
 
1198
      if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
 
1199
        g_warning ("GdkWindow %#lx unexpectedly destroyed", GDK_WINDOW_XID (window));
 
1200
 
 
1201
      _gdk_window_destroy (window, TRUE);
 
1202
    }
 
1203
  
 
1204
  _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), GDK_WINDOW_XID (window));
 
1205
  if (window_impl->toplevel && window_impl->toplevel->focus_window)
 
1206
    _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), window_impl->toplevel->focus_window);
 
1207
 
 
1208
  _gdk_xgrab_check_destroy (window);
 
1209
  
 
1210
  g_object_unref (window);
 
1211
}
 
1212
 
 
1213
static void
 
1214
update_wm_hints (GdkWindow *window,
 
1215
                 gboolean   force)
 
1216
{
 
1217
  GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
 
1218
  GdkWindowObject *private = (GdkWindowObject *)window;
 
1219
  GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
 
1220
  XWMHints wm_hints;
 
1221
 
 
1222
  if (!force &&
 
1223
      !toplevel->is_leader &&
 
1224
      private->state & GDK_WINDOW_STATE_WITHDRAWN)
 
1225
    return;
 
1226
 
 
1227
  wm_hints.flags = StateHint | InputHint;
 
1228
  wm_hints.input = private->accept_focus ? True : False;
 
1229
  wm_hints.initial_state = NormalState;
 
1230
  
 
1231
  if (private->state & GDK_WINDOW_STATE_ICONIFIED)
 
1232
    {
 
1233
      wm_hints.flags |= StateHint;
 
1234
      wm_hints.initial_state = IconicState;
 
1235
    }
 
1236
 
 
1237
  if (toplevel->icon_window && !GDK_WINDOW_DESTROYED (toplevel->icon_window))
 
1238
    {
 
1239
      wm_hints.flags |= IconWindowHint;
 
1240
      wm_hints.icon_window = GDK_WINDOW_XID (toplevel->icon_window);
 
1241
    }
 
1242
 
 
1243
  if (toplevel->icon_pixmap)
 
1244
    {
 
1245
      wm_hints.flags |= IconPixmapHint;
 
1246
      wm_hints.icon_pixmap = GDK_PIXMAP_XID (toplevel->icon_pixmap);
 
1247
    }
 
1248
 
 
1249
  if (toplevel->icon_mask)
 
1250
    {
 
1251
      wm_hints.flags |= IconMaskHint;
 
1252
      wm_hints.icon_mask = GDK_PIXMAP_XID (toplevel->icon_mask);
 
1253
    }
 
1254
  
 
1255
  wm_hints.flags |= WindowGroupHint;
 
1256
  if (toplevel->group_leader && !GDK_WINDOW_DESTROYED (toplevel->group_leader))
 
1257
    {
 
1258
      wm_hints.flags |= WindowGroupHint;
 
1259
      wm_hints.window_group = GDK_WINDOW_XID (toplevel->group_leader);
 
1260
    }
 
1261
  else
 
1262
    wm_hints.window_group = GDK_DISPLAY_X11 (display)->leader_window;
 
1263
 
 
1264
  if (toplevel->urgency_hint)
 
1265
    wm_hints.flags |= XUrgencyHint;
 
1266
  
 
1267
  XSetWMHints (GDK_WINDOW_XDISPLAY (window),
 
1268
               GDK_WINDOW_XID (window),
 
1269
               &wm_hints);
 
1270
}
 
1271
 
 
1272
static void
 
1273
set_initial_hints (GdkWindow *window)
 
1274
{
 
1275
  GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
 
1276
  Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
 
1277
  Window xwindow = GDK_WINDOW_XID (window);  
 
1278
  GdkWindowObject *private;
 
1279
  GdkToplevelX11 *toplevel;
 
1280
  Atom atoms[9];
 
1281
  gint i;
 
1282
 
 
1283
  private = (GdkWindowObject*) window;
 
1284
  toplevel = _gdk_x11_window_get_toplevel (window);
 
1285
 
 
1286
  if (!toplevel)
 
1287
    return;
 
1288
 
 
1289
  update_wm_hints (window, TRUE);
 
1290
  
 
1291
  /* We set the spec hints regardless of whether the spec is supported,
 
1292
   * since it can't hurt and it's kind of expensive to check whether
 
1293
   * it's supported.
 
1294
   */
 
1295
  
 
1296
  i = 0;
 
1297
 
 
1298
  if (private->state & GDK_WINDOW_STATE_MAXIMIZED)
 
1299
    {
 
1300
      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
 
1301
                                                        "_NET_WM_STATE_MAXIMIZED_VERT");
 
1302
      ++i;
 
1303
      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
 
1304
                                                        "_NET_WM_STATE_MAXIMIZED_HORZ");
 
1305
      ++i;
 
1306
    }
 
1307
 
 
1308
  if (private->state & GDK_WINDOW_STATE_ABOVE)
 
1309
    {
 
1310
      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
 
1311
                                                        "_NET_WM_STATE_ABOVE");
 
1312
      ++i;
 
1313
    }
 
1314
  
 
1315
  if (private->state & GDK_WINDOW_STATE_BELOW)
 
1316
    {
 
1317
      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
 
1318
                                                        "_NET_WM_STATE_BELOW");
 
1319
      ++i;
 
1320
    }
 
1321
  
 
1322
  if (private->state & GDK_WINDOW_STATE_STICKY)
 
1323
    {
 
1324
      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
 
1325
                                                        "_NET_WM_STATE_STICKY");
 
1326
      ++i;
 
1327
    }
 
1328
 
 
1329
  if (private->state & GDK_WINDOW_STATE_FULLSCREEN)
 
1330
    {
 
1331
      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
 
1332
                                                        "_NET_WM_STATE_FULLSCREEN");
 
1333
      ++i;
 
1334
    }
 
1335
 
 
1336
  if (private->modal_hint)
 
1337
    {
 
1338
      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
 
1339
                                                        "_NET_WM_STATE_MODAL");
 
1340
      ++i;
 
1341
    }
 
1342
 
 
1343
  if (toplevel->skip_taskbar_hint)
 
1344
    {
 
1345
      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
 
1346
                                                        "_NET_WM_STATE_SKIP_TASKBAR");
 
1347
      ++i;
 
1348
    }
 
1349
 
 
1350
  if (toplevel->skip_pager_hint)
 
1351
    {
 
1352
      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
 
1353
                                                        "_NET_WM_STATE_SKIP_PAGER");
 
1354
      ++i;
 
1355
    }
 
1356
 
 
1357
  if (i > 0)
 
1358
    {
 
1359
      XChangeProperty (xdisplay,
 
1360
                       xwindow,
 
1361
                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
 
1362
                       XA_ATOM, 32, PropModeReplace,
 
1363
                       (guchar*) atoms, i);
 
1364
    }
 
1365
  else 
 
1366
    {
 
1367
      XDeleteProperty (xdisplay,
 
1368
                       xwindow,
 
1369
                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"));
 
1370
    }
 
1371
 
 
1372
  if (private->state & GDK_WINDOW_STATE_STICKY)
 
1373
    {
 
1374
      atoms[0] = 0xFFFFFFFF;
 
1375
      XChangeProperty (xdisplay,
 
1376
                       xwindow,
 
1377
                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
 
1378
                       XA_CARDINAL, 32, PropModeReplace,
 
1379
                       (guchar*) atoms, 1);
 
1380
    }
 
1381
  else
 
1382
    {
 
1383
      XDeleteProperty (xdisplay,
 
1384
                       xwindow,
 
1385
                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"));
 
1386
    }
 
1387
 
 
1388
  toplevel->map_serial = NextRequest (xdisplay);
 
1389
}
 
1390
 
 
1391
static void
 
1392
show_window_internal (GdkWindow *window,
 
1393
                      gboolean   raise)
 
1394
{
 
1395
  GdkWindowObject *private;
 
1396
  GdkDisplay *display;
 
1397
  GdkDisplayX11 *display_x11;
 
1398
  GdkToplevelX11 *toplevel;
 
1399
  
 
1400
  g_return_if_fail (GDK_IS_WINDOW (window));
 
1401
  
 
1402
  private = (GdkWindowObject*) window;
 
1403
  if (!private->destroyed)
 
1404
    {
 
1405
      GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
 
1406
      Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
 
1407
      Window xwindow = GDK_WINDOW_XID (window);
 
1408
      
 
1409
      if (raise)
 
1410
        XRaiseWindow (xdisplay, xwindow);
 
1411
 
 
1412
      if (!GDK_WINDOW_IS_MAPPED (window))
 
1413
        {
 
1414
          set_initial_hints (window);
 
1415
          
 
1416
          gdk_synthesize_window_state (window,
 
1417
                                       GDK_WINDOW_STATE_WITHDRAWN,
 
1418
                                       0);
 
1419
        }
 
1420
      
 
1421
      g_assert (GDK_WINDOW_IS_MAPPED (window));
 
1422
 
 
1423
      if (WINDOW_IS_TOPLEVEL (window))
 
1424
        {
 
1425
          display = gdk_drawable_get_display (window);
 
1426
          display_x11 = GDK_DISPLAY_X11 (display);
 
1427
          toplevel = _gdk_x11_window_get_toplevel (window);
 
1428
 
 
1429
          if (toplevel->user_time != 0 &&
 
1430
              display_x11->user_time != 0 &&
 
1431
              XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
 
1432
            gdk_x11_window_set_user_time (window, display_x11->user_time);
 
1433
        }
 
1434
 
 
1435
      if (impl->position_info.mapped)
 
1436
        {
 
1437
          gboolean unset_bg = !private->input_only &&
 
1438
            (private->window_type == GDK_WINDOW_CHILD ||
 
1439
             impl->override_redirect) &&
 
1440
            gdk_window_is_viewable (window);
 
1441
 
 
1442
          if (unset_bg)
 
1443
            _gdk_x11_window_tmp_unset_bg (window, TRUE);
 
1444
          
 
1445
          XMapWindow (xdisplay, xwindow);
 
1446
 
 
1447
          if (unset_bg)
 
1448
            {
 
1449
              _gdk_x11_window_tmp_reset_bg (window, TRUE);
 
1450
              gdk_window_invalidate_rect (window, NULL, TRUE);
 
1451
            }
 
1452
        }
 
1453
    }
 
1454
}
 
1455
 
 
1456
/**
 
1457
 * gdk_window_show_unraised:
 
1458
 * @window: a #GdkWindow
 
1459
 *
 
1460
 * Shows a #GdkWindow onscreen, but does not modify its stacking
 
1461
 * order. In contrast, gdk_window_show() will raise the window
 
1462
 * to the top of the window stack.
 
1463
 *
 
1464
 * On the X11 platform, in Xlib terms, this function calls
 
1465
 * XMapWindow() (it also updates some internal GDK state, which means
 
1466
 * that you can't really use XMapWindow() directly on a GDK window).
 
1467
 * 
 
1468
 **/
 
1469
void
 
1470
gdk_window_show_unraised (GdkWindow *window)
 
1471
{
 
1472
  g_return_if_fail (GDK_IS_WINDOW (window));
 
1473
  
 
1474
  show_window_internal (window, FALSE);
 
1475
}
 
1476
 
 
1477
/**
 
1478
 * gdk_window_show:
 
1479
 * @window: a #GdkWindow
 
1480
 *
 
1481
 * Like gdk_window_show_unraised(), but also raises the window to the
 
1482
 * top of the window stack (moves the window to the front of the
 
1483
 * Z-order).
 
1484
 *
 
1485
 * This function maps a window so it's visible onscreen. Its opposite
 
1486
 * is gdk_window_hide().
 
1487
 *
 
1488
 * When implementing a #GtkWidget, you should call this function on the widget's
 
1489
 * #GdkWindow as part of the "map" method.
 
1490
 * 
 
1491
 **/
 
1492
void
 
1493
gdk_window_show (GdkWindow *window)
 
1494
{
 
1495
  g_return_if_fail (GDK_IS_WINDOW (window));
 
1496
 
 
1497
  show_window_internal (window, TRUE);
 
1498
}
 
1499
 
 
1500
static void
 
1501
pre_unmap (GdkWindow *window)
 
1502
{
 
1503
  GdkWindow *start_window = NULL;
 
1504
  GdkWindowObject *private = (GdkWindowObject *)window;
 
1505
 
 
1506
  if (private->input_only)
 
1507
    return;
 
1508
 
 
1509
  if (private->window_type == GDK_WINDOW_CHILD)
 
1510
    start_window = (GdkWindow *)private->parent;
 
1511
  else if (private->window_type == GDK_WINDOW_TEMP)
 
1512
    start_window = get_root (window);
 
1513
 
 
1514
  if (start_window)
 
1515
    _gdk_x11_window_tmp_unset_bg (start_window, TRUE);
 
1516
}
 
1517
 
 
1518
static void
 
1519
post_unmap (GdkWindow *window)
 
1520
{
 
1521
  GdkWindow *start_window = NULL;
 
1522
  GdkWindowObject *private = (GdkWindowObject *)window;
 
1523
  
 
1524
  if (private->input_only)
 
1525
    return;
 
1526
 
 
1527
  if (private->window_type == GDK_WINDOW_CHILD)
 
1528
    start_window = (GdkWindow *)private->parent;
 
1529
  else if (private->window_type == GDK_WINDOW_TEMP)
 
1530
    start_window = get_root (window);
 
1531
 
 
1532
  if (start_window)
 
1533
    {
 
1534
      _gdk_x11_window_tmp_reset_bg (start_window, TRUE);
 
1535
 
 
1536
      if (private->window_type == GDK_WINDOW_CHILD && private->parent)
 
1537
        {
 
1538
          GdkRectangle invalid_rect;
 
1539
      
 
1540
          gdk_window_get_position (window, &invalid_rect.x, &invalid_rect.y);
 
1541
          gdk_drawable_get_size (GDK_DRAWABLE (window),
 
1542
                                 &invalid_rect.width, &invalid_rect.height);
 
1543
          gdk_window_invalidate_rect ((GdkWindow *)private->parent,
 
1544
                                      &invalid_rect, TRUE);
 
1545
        }
 
1546
    }
 
1547
}
 
1548
 
 
1549
/**
 
1550
 * gdk_window_hide:
 
1551
 * @window: a #GdkWindow
 
1552
 *
 
1553
 * For toplevel windows, withdraws them, so they will no longer be
 
1554
 * known to the window manager; for all windows, unmaps them, so
 
1555
 * they won't be displayed. Normally done automatically as
 
1556
 * part of gtk_widget_hide().
 
1557
 * 
 
1558
 **/
 
1559
void
 
1560
gdk_window_hide (GdkWindow *window)
 
1561
{
 
1562
  GdkWindowObject *private;
 
1563
  
 
1564
  g_return_if_fail (GDK_IS_WINDOW (window));
 
1565
 
 
1566
  private = (GdkWindowObject*) window;
 
1567
 
 
1568
  /* We'll get the unmap notify eventually, and handle it then,
 
1569
   * but checking here makes things more consistent if we are
 
1570
   * just doing stuff ourself.
 
1571
   */
 
1572
  _gdk_xgrab_check_unmap (window,
 
1573
                          NextRequest (GDK_WINDOW_XDISPLAY (window)));
 
1574
 
 
1575
  /* You can't simply unmap toplevel windows. */
 
1576
  switch (private->window_type)
 
1577
    {
 
1578
    case GDK_WINDOW_TOPLEVEL:
 
1579
    case GDK_WINDOW_DIALOG:
 
1580
    case GDK_WINDOW_TEMP: /* ? */
 
1581
      gdk_window_withdraw (window);
 
1582
      return;
 
1583
      break;
 
1584
      
 
1585
    case GDK_WINDOW_FOREIGN:
 
1586
    case GDK_WINDOW_ROOT:
 
1587
    case GDK_WINDOW_CHILD:
 
1588
      break;
 
1589
    }
 
1590
  
 
1591
  if (!private->destroyed)
 
1592
    {
 
1593
      if (GDK_WINDOW_IS_MAPPED (window))
 
1594
        gdk_synthesize_window_state (window,
 
1595
                                     0,
 
1596
                                     GDK_WINDOW_STATE_WITHDRAWN);
 
1597
 
 
1598
      g_assert (!GDK_WINDOW_IS_MAPPED (window));
 
1599
      
 
1600
      _gdk_window_clear_update_area (window);
 
1601
 
 
1602
      pre_unmap (window);
 
1603
      
 
1604
      XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
 
1605
                    GDK_WINDOW_XID (window));
 
1606
 
 
1607
      post_unmap (window);
 
1608
    }
 
1609
}
 
1610
 
 
1611
/**
 
1612
 * gdk_window_withdraw:
 
1613
 * @window: a toplevel #GdkWindow
 
1614
 * 
 
1615
 * Withdraws a window (unmaps it and asks the window manager to forget about it).
 
1616
 * This function is not really useful as gdk_window_hide() automatically
 
1617
 * withdraws toplevel windows before hiding them.
 
1618
 * 
 
1619
 **/
 
1620
void
 
1621
gdk_window_withdraw (GdkWindow *window)
 
1622
{
 
1623
  GdkWindowObject *private;
 
1624
  
 
1625
  g_return_if_fail (GDK_IS_WINDOW (window));
 
1626
  
 
1627
  private = (GdkWindowObject*) window;
 
1628
  if (!private->destroyed)
 
1629
    {
 
1630
      if (GDK_WINDOW_IS_MAPPED (window))
 
1631
        gdk_synthesize_window_state (window,
 
1632
                                     0,
 
1633
                                     GDK_WINDOW_STATE_WITHDRAWN);
 
1634
 
 
1635
      g_assert (!GDK_WINDOW_IS_MAPPED (window));
 
1636
 
 
1637
      pre_unmap (window);
 
1638
      
 
1639
      XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
 
1640
                       GDK_WINDOW_XID (window), 0);
 
1641
 
 
1642
      post_unmap (window);
 
1643
    }
 
1644
}
 
1645
 
 
1646
/**
 
1647
 * gdk_window_move:
 
1648
 * @window: a #GdkWindow
 
1649
 * @x: X coordinate relative to window's parent
 
1650
 * @y: Y coordinate relative to window's parent
 
1651
 *
 
1652
 * Repositions a window relative to its parent window.
 
1653
 * For toplevel windows, window managers may ignore or modify the move;
 
1654
 * you should probably use gtk_window_move() on a #GtkWindow widget
 
1655
 * anyway, instead of using GDK functions. For child windows,
 
1656
 * the move will reliably succeed.
 
1657
 *
 
1658
 * If you're also planning to resize the window, use gdk_window_move_resize()
 
1659
 * to both move and resize simultaneously, for a nicer visual effect.
 
1660
 **/
 
1661
void
 
1662
gdk_window_move (GdkWindow *window,
 
1663
                 gint       x,
 
1664
                 gint       y)
 
1665
{
 
1666
  GdkWindowObject *private = (GdkWindowObject *)window;
 
1667
  GdkWindowImplX11 *impl;
 
1668
 
 
1669
  g_return_if_fail (GDK_IS_WINDOW (window));
 
1670
 
 
1671
  impl = GDK_WINDOW_IMPL_X11 (private->impl);
 
1672
          
 
1673
  if (!GDK_WINDOW_DESTROYED (window))
 
1674
    {
 
1675
      if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
 
1676
        {
 
1677
          _gdk_window_move_resize_child (window, x, y,
 
1678
                                         impl->width, impl->height);
 
1679
        }
 
1680
      else
 
1681
        {
 
1682
          XMoveWindow (GDK_WINDOW_XDISPLAY (window),
 
1683
                       GDK_WINDOW_XID (window),
 
1684
                       x, y);
 
1685
 
 
1686
          if (impl->override_redirect)
 
1687
            {
 
1688
              private->x = x;
 
1689
              private->y = y;
 
1690
            }
 
1691
        }
 
1692
    }
 
1693
}
 
1694
 
 
1695
/**
 
1696
 * gdk_window_resize:
 
1697
 * @window: a #GdkWindow
 
1698
 * @width: new width of the window
 
1699
 * @height: new height of the window
 
1700
 *
 
1701
 * Resizes @window; for toplevel windows, asks the window manager to resize
 
1702
 * the window. The window manager may not allow the resize. When using GTK+,
 
1703
 * use gtk_window_resize() instead of this low-level GDK function.
 
1704
 *
 
1705
 * Windows may not be resized below 1x1.
 
1706
 * 
 
1707
 * If you're also planning to move the window, use gdk_window_move_resize()
 
1708
 * to both move and resize simultaneously, for a nicer visual effect.
 
1709
 **/
 
1710
void
 
1711
gdk_window_resize (GdkWindow *window,
 
1712
                   gint       width,
 
1713
                   gint       height)
 
1714
{
 
1715
  GdkWindowObject *private;
 
1716
  
 
1717
  g_return_if_fail (GDK_IS_WINDOW (window));
 
1718
  
 
1719
  if (width < 1)
 
1720
    width = 1;
 
1721
  if (height < 1)
 
1722
    height = 1;
 
1723
 
 
1724
  private = (GdkWindowObject*) window;
 
1725
  
 
1726
  if (!GDK_WINDOW_DESTROYED (window))
 
1727
    {
 
1728
      if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
 
1729
        {
 
1730
          _gdk_window_move_resize_child (window, private->x, private->y,
 
1731
                                         width, height);
 
1732
          _gdk_x11_drawable_update_size (private->impl);
 
1733
        }
 
1734
      else
 
1735
        {
 
1736
          GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
 
1737
 
 
1738
          XResizeWindow (GDK_WINDOW_XDISPLAY (window),
 
1739
                         GDK_WINDOW_XID (window),
 
1740
                         width, height);
 
1741
 
 
1742
          if (impl->override_redirect)
 
1743
            {
 
1744
              impl->width = width;
 
1745
              impl->height = height;
 
1746
              _gdk_x11_drawable_update_size (private->impl);
 
1747
            }
 
1748
          else
 
1749
            {
 
1750
              if (width != impl->width || height != impl->height)
 
1751
                private->resize_count += 1;
 
1752
            }
 
1753
        }
 
1754
 
 
1755
      _gdk_x11_drawable_update_size (private->impl);
 
1756
    }
 
1757
}
 
1758
 
 
1759
/**
 
1760
 * gdk_window_move_resize:
 
1761
 * @window: a #GdkWindow
 
1762
 * @x: new X position relative to window's parent
 
1763
 * @y: new Y position relative to window's parent
 
1764
 * @width: new width
 
1765
 * @height: new height
 
1766
 *
 
1767
 * Equivalent to calling gdk_window_move() and gdk_window_resize(),
 
1768
 * except that both operations are performed at once, avoiding strange
 
1769
 * visual effects. (i.e. the user may be able to see the window first
 
1770
 * move, then resize, if you don't use gdk_window_move_resize().)
 
1771
 **/
 
1772
void
 
1773
gdk_window_move_resize (GdkWindow *window,
 
1774
                        gint       x,
 
1775
                        gint       y,
 
1776
                        gint       width,
 
1777
                        gint       height)
 
1778
{
 
1779
  GdkWindowObject *private;
 
1780
  
 
1781
  g_return_if_fail (GDK_IS_WINDOW (window));
 
1782
 
 
1783
  if (width < 1)
 
1784
    width = 1;
 
1785
  if (height < 1)
 
1786
    height = 1;
 
1787
  
 
1788
  private = (GdkWindowObject*) window;
 
1789
 
 
1790
  if (!GDK_WINDOW_DESTROYED (window))
 
1791
    {
 
1792
      if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
 
1793
        {
 
1794
          _gdk_window_move_resize_child (window, x, y, width, height);
 
1795
          _gdk_x11_drawable_update_size (private->impl);
 
1796
        }
 
1797
      else
 
1798
        {
 
1799
          GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
 
1800
 
 
1801
          XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
 
1802
                             GDK_WINDOW_XID (window),
 
1803
                             x, y, width, height);
 
1804
          if (impl->override_redirect)
 
1805
            {
 
1806
              private->x = x;
 
1807
              private->y = y;
 
1808
              impl->width = width;
 
1809
              impl->height = height;
 
1810
 
 
1811
              _gdk_x11_drawable_update_size (private->impl);
 
1812
            }
 
1813
          else
 
1814
            {
 
1815
              if (width != impl->width || height != impl->height)
 
1816
                private->resize_count += 1;
 
1817
            }
 
1818
        }
 
1819
    }
 
1820
}
 
1821
 
 
1822
/**
 
1823
 * gdk_window_reparent:
 
1824
 * @window: a #GdkWindow
 
1825
 * @new_parent: new parent to move @window into
 
1826
 * @x: X location inside the new parent
 
1827
 * @y: Y location inside the new parent
 
1828
 *
 
1829
 * Reparents @window into the given @new_parent. The window being
 
1830
 * reparented will be unmapped as a side effect.
 
1831
 * 
 
1832
 **/
 
1833
void
 
1834
gdk_window_reparent (GdkWindow *window,
 
1835
                     GdkWindow *new_parent,
 
1836
                     gint       x,
 
1837
                     gint       y)
 
1838
{
 
1839
  GdkWindowObject *window_private;
 
1840
  GdkWindowObject *parent_private;
 
1841
  GdkWindowObject *old_parent_private;
 
1842
  GdkWindowImplX11 *impl;
 
1843
  gboolean was_toplevel;
 
1844
  
 
1845
  g_return_if_fail (GDK_IS_WINDOW (window));
 
1846
  g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
 
1847
  g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
 
1848
 
 
1849
  if (GDK_WINDOW_DESTROYED (window) ||
 
1850
      (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
 
1851
    {
 
1852
      return;
 
1853
    }
 
1854
  
 
1855
  if (!new_parent)
 
1856
    new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
 
1857
 
 
1858
  window_private = (GdkWindowObject*) window;
 
1859
  old_parent_private = (GdkWindowObject*)window_private->parent;
 
1860
  parent_private = (GdkWindowObject*) new_parent;
 
1861
  impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
 
1862
  
 
1863
  XReparentWindow (GDK_WINDOW_XDISPLAY (window),
 
1864
                   GDK_WINDOW_XID (window),
 
1865
                   GDK_WINDOW_XID (new_parent),
 
1866
                   x, y);
 
1867
 
 
1868
  window_private->x = x;
 
1869
  window_private->y = y;
 
1870
  
 
1871
  /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
 
1872
   * the root window
 
1873
   */
 
1874
  if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
 
1875
    new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
 
1876
  
 
1877
  window_private->parent = (GdkWindowObject *)new_parent;
 
1878
 
 
1879
  /* Switch the window type as appropriate */
 
1880
 
 
1881
  switch (GDK_WINDOW_TYPE (new_parent))
 
1882
    {
 
1883
    case GDK_WINDOW_ROOT:
 
1884
    case GDK_WINDOW_FOREIGN:
 
1885
      was_toplevel = WINDOW_IS_TOPLEVEL (window);
 
1886
      
 
1887
      if (impl->toplevel_window_type != -1)
 
1888
        GDK_WINDOW_TYPE (window) = impl->toplevel_window_type;
 
1889
      else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
 
1890
        GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
 
1891
 
 
1892
      if (WINDOW_IS_TOPLEVEL (window) && !was_toplevel)
 
1893
        setup_toplevel_window (window, new_parent);
 
1894
      break;
 
1895
    case GDK_WINDOW_TOPLEVEL:
 
1896
    case GDK_WINDOW_CHILD:
 
1897
    case GDK_WINDOW_DIALOG:
 
1898
    case GDK_WINDOW_TEMP:
 
1899
      if (WINDOW_IS_TOPLEVEL (window))
 
1900
        {
 
1901
          /* Save the original window type so we can restore it if the
 
1902
           * window is reparented back to be a toplevel
 
1903
           */
 
1904
          impl->toplevel_window_type = GDK_WINDOW_TYPE (window);
 
1905
          GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
 
1906
          if (impl->toplevel)
 
1907
            {
 
1908
              if (impl->toplevel->focus_window)
 
1909
                {
 
1910
                  XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
 
1911
                  _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
 
1912
                }
 
1913
                
 
1914
              gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), 
 
1915
                                              impl->toplevel);
 
1916
              g_free (impl->toplevel);
 
1917
              impl->toplevel = NULL;
 
1918
            }
 
1919
        }
 
1920
    }
 
1921
 
 
1922
  if (old_parent_private)
 
1923
    old_parent_private->children = g_list_remove (old_parent_private->children, window);
 
1924
  
 
1925
  if ((old_parent_private &&
 
1926
       (!old_parent_private->guffaw_gravity != !parent_private->guffaw_gravity)) ||
 
1927
      (!old_parent_private && parent_private->guffaw_gravity))
 
1928
    gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
 
1929
  
 
1930
  parent_private->children = g_list_prepend (parent_private->children, window);
 
1931
  _gdk_window_init_position (GDK_WINDOW (window_private));
 
1932
}
 
1933
 
 
1934
void
 
1935
_gdk_windowing_window_clear_area (GdkWindow *window,
 
1936
                                  gint       x,
 
1937
                                  gint       y,
 
1938
                                  gint       width,
 
1939
                                  gint       height)
 
1940
{
 
1941
  g_return_if_fail (GDK_IS_WINDOW (window));
 
1942
  
 
1943
  if (!GDK_WINDOW_DESTROYED (window))
 
1944
    XClearArea (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
 
1945
                x, y, width, height, False);
 
1946
}
 
1947
 
 
1948
void
 
1949
_gdk_windowing_window_clear_area_e (GdkWindow *window,
 
1950
                                    gint       x,
 
1951
                                    gint       y,
 
1952
                                    gint       width,
 
1953
                                    gint       height)
 
1954
{
 
1955
  g_return_if_fail (GDK_IS_WINDOW (window));
 
1956
  
 
1957
  if (!GDK_WINDOW_DESTROYED (window))
 
1958
    XClearArea (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
 
1959
                x, y, width, height, True);
 
1960
}
 
1961
 
 
1962
 
 
1963
/**
 
1964
 * gdk_window_raise:
 
1965
 * @window: a #GdkWindow
 
1966
 * 
 
1967
 * Raises @window to the top of the Z-order (stacking order), so that
 
1968
 * other windows with the same parent window appear below @window.
 
1969
 * This is true whether or not the windows are visible.
 
1970
 *
 
1971
 * If @window is a toplevel, the window manager may choose to deny the
 
1972
 * request to move the window in the Z-order, gdk_window_raise() only
 
1973
 * requests the restack, does not guarantee it.
 
1974
 * 
 
1975
 **/
 
1976
void
 
1977
gdk_window_raise (GdkWindow *window)
 
1978
{
 
1979
  g_return_if_fail (GDK_IS_WINDOW (window));
 
1980
  
 
1981
  if (!GDK_WINDOW_DESTROYED (window))
 
1982
    XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
 
1983
}
 
1984
 
 
1985
/**
 
1986
 * gdk_window_lower:
 
1987
 * @window: a #GdkWindow
 
1988
 * 
 
1989
 * Lowers @window to the bottom of the Z-order (stacking order), so that
 
1990
 * other windows with the same parent window appear above @window.
 
1991
 * This is true whether or not the other windows are visible.
 
1992
 *
 
1993
 * If @window is a toplevel, the window manager may choose to deny the
 
1994
 * request to move the window in the Z-order, gdk_window_lower() only
 
1995
 * requests the restack, does not guarantee it.
 
1996
 *
 
1997
 * Note that gdk_window_show() raises the window again, so don't call this
 
1998
 * function before gdk_window_show(). (Try gdk_window_show_unraised().)
 
1999
 * 
 
2000
 **/
 
2001
void
 
2002
gdk_window_lower (GdkWindow *window)
 
2003
{
 
2004
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2005
  
 
2006
  if (!GDK_WINDOW_DESTROYED (window))
 
2007
    XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
 
2008
}
 
2009
 
 
2010
/**
 
2011
 * gdk_x11_window_move_to_current_desktop:
 
2012
 * @window: a #GdkWindow
 
2013
 * 
 
2014
 * Moves the window to the correct workspace when running under a 
 
2015
 * window manager that supports multiple workspaces, as described
 
2016
 * in the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended 
 
2017
 * Window Manager Hints</ulink>.  Will not do anything if the
 
2018
 * window is already on all workspaces.
 
2019
 * 
 
2020
 * Since: 2.8
 
2021
 */
 
2022
void
 
2023
gdk_x11_window_move_to_current_desktop (GdkWindow *window)
 
2024
{
 
2025
  GdkToplevelX11 *toplevel;
 
2026
 
 
2027
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2028
  g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
 
2029
 
 
2030
  toplevel = _gdk_x11_window_get_toplevel (window);
 
2031
 
 
2032
  if (toplevel->on_all_desktops)
 
2033
    return;
 
2034
  
 
2035
  move_to_current_desktop (window);
 
2036
}
 
2037
 
 
2038
static void
 
2039
move_to_current_desktop (GdkWindow *window)
 
2040
{
 
2041
  if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
 
2042
                                           gdk_atom_intern_static_string ("_NET_WM_DESKTOP")))
 
2043
    {
 
2044
      Atom type;
 
2045
      gint format;
 
2046
      gulong nitems;
 
2047
      gulong bytes_after;
 
2048
      guchar *data;
 
2049
      gulong *current_desktop;
 
2050
      GdkDisplay *display;
 
2051
      
 
2052
      display = gdk_drawable_get_display (window);
 
2053
 
 
2054
      /* Get current desktop, then set it; this is a race, but not
 
2055
       * one that matters much in practice.
 
2056
       */
 
2057
      XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), 
 
2058
                          GDK_WINDOW_XROOTWIN (window),
 
2059
                          gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"),
 
2060
                          0, G_MAXLONG,
 
2061
                          False, XA_CARDINAL, &type, &format, &nitems,
 
2062
                          &bytes_after, &data);
 
2063
 
 
2064
      if (type == XA_CARDINAL)
 
2065
        {
 
2066
          XClientMessageEvent xclient;
 
2067
          current_desktop = (gulong *)data;
 
2068
          
 
2069
          memset (&xclient, 0, sizeof (xclient));
 
2070
          xclient.type = ClientMessage;
 
2071
          xclient.serial = 0;
 
2072
          xclient.send_event = True;
 
2073
          xclient.window = GDK_WINDOW_XWINDOW (window);
 
2074
          xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP");
 
2075
          xclient.format = 32;
 
2076
 
 
2077
          xclient.data.l[0] = *current_desktop;
 
2078
          xclient.data.l[1] = 0;
 
2079
          xclient.data.l[2] = 0;
 
2080
          xclient.data.l[3] = 0;
 
2081
          xclient.data.l[4] = 0;
 
2082
      
 
2083
          XSendEvent (GDK_DISPLAY_XDISPLAY (display), 
 
2084
                      GDK_WINDOW_XROOTWIN (window), 
 
2085
                      False,
 
2086
                      SubstructureRedirectMask | SubstructureNotifyMask,
 
2087
                      (XEvent *)&xclient);
 
2088
 
 
2089
          XFree (current_desktop);
 
2090
        }
 
2091
    }
 
2092
}
 
2093
 
 
2094
/**
 
2095
 * gdk_window_focus:
 
2096
 * @window: a #GdkWindow
 
2097
 * @timestamp: timestamp of the event triggering the window focus
 
2098
 *
 
2099
 * Sets keyboard focus to @window. In most cases, gtk_window_present() 
 
2100
 * should be used on a #GtkWindow, rather than calling this function.
 
2101
 * 
 
2102
 **/
 
2103
void
 
2104
gdk_window_focus (GdkWindow *window,
 
2105
                  guint32    timestamp)
 
2106
{
 
2107
  GdkDisplay *display;
 
2108
  
 
2109
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2110
 
 
2111
  if (GDK_WINDOW_DESTROYED (window))
 
2112
    return;
 
2113
 
 
2114
  display = GDK_WINDOW_DISPLAY (window);
 
2115
 
 
2116
  if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
 
2117
                                           gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
 
2118
    {
 
2119
      XClientMessageEvent xclient;
 
2120
 
 
2121
      memset (&xclient, 0, sizeof (xclient));
 
2122
      xclient.type = ClientMessage;
 
2123
      xclient.window = GDK_WINDOW_XWINDOW (window);
 
2124
      xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
 
2125
                                                                        "_NET_ACTIVE_WINDOW");
 
2126
      xclient.format = 32;
 
2127
      xclient.data.l[0] = 1; /* requestor type; we're an app */
 
2128
      xclient.data.l[1] = timestamp;
 
2129
      xclient.data.l[2] = None; /* currently active window */
 
2130
      xclient.data.l[3] = 0;
 
2131
      xclient.data.l[4] = 0;
 
2132
      
 
2133
      XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
 
2134
                  SubstructureRedirectMask | SubstructureNotifyMask,
 
2135
                  (XEvent *)&xclient);
 
2136
    }
 
2137
  else
 
2138
    {
 
2139
      XRaiseWindow (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window));
 
2140
 
 
2141
      /* There is no way of knowing reliably whether we are viewable;
 
2142
       * _gdk_x11_set_input_focus_safe() traps errors asynchronously.
 
2143
       */
 
2144
      _gdk_x11_set_input_focus_safe (display, GDK_WINDOW_XID (window),
 
2145
                                     RevertToParent,
 
2146
                                     timestamp);
 
2147
    }
 
2148
}
 
2149
 
 
2150
/**
 
2151
 * gdk_window_set_hints:
 
2152
 * @window: a #GdkWindow
 
2153
 * @x: ignored field, does not matter
 
2154
 * @y: ignored field, does not matter
 
2155
 * @min_width: minimum width hint
 
2156
 * @min_height: minimum height hint
 
2157
 * @max_width: max width hint
 
2158
 * @max_height: max height hint
 
2159
 * @flags: logical OR of GDK_HINT_POS, GDK_HINT_MIN_SIZE, and/or GDK_HINT_MAX_SIZE
 
2160
 *
 
2161
 * This function is broken and useless and you should ignore it.
 
2162
 * If using GTK+, use functions such as gtk_window_resize(), gtk_window_set_size_request(),
 
2163
 * gtk_window_move(), gtk_window_parse_geometry(), and gtk_window_set_geometry_hints(),
 
2164
 * depending on what you're trying to do.
 
2165
 *
 
2166
 * If using GDK directly, use gdk_window_set_geometry_hints().
 
2167
 * 
 
2168
 **/
 
2169
void
 
2170
gdk_window_set_hints (GdkWindow *window,
 
2171
                      gint       x,
 
2172
                      gint       y,
 
2173
                      gint       min_width,
 
2174
                      gint       min_height,
 
2175
                      gint       max_width,
 
2176
                      gint       max_height,
 
2177
                      gint       flags)
 
2178
{
 
2179
  XSizeHints size_hints;
 
2180
  
 
2181
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2182
  
 
2183
  if (GDK_WINDOW_DESTROYED (window))
 
2184
    return;
 
2185
  
 
2186
  size_hints.flags = 0;
 
2187
  
 
2188
  if (flags & GDK_HINT_POS)
 
2189
    {
 
2190
      size_hints.flags |= PPosition;
 
2191
      size_hints.x = x;
 
2192
      size_hints.y = y;
 
2193
    }
 
2194
  
 
2195
  if (flags & GDK_HINT_MIN_SIZE)
 
2196
    {
 
2197
      size_hints.flags |= PMinSize;
 
2198
      size_hints.min_width = min_width;
 
2199
      size_hints.min_height = min_height;
 
2200
    }
 
2201
  
 
2202
  if (flags & GDK_HINT_MAX_SIZE)
 
2203
    {
 
2204
      size_hints.flags |= PMaxSize;
 
2205
      size_hints.max_width = max_width;
 
2206
      size_hints.max_height = max_height;
 
2207
    }
 
2208
  
 
2209
  /* FIXME: Would it be better to delete this property if
 
2210
   *        flags == 0? It would save space on the server
 
2211
   */
 
2212
  XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
 
2213
                     GDK_WINDOW_XID (window),
 
2214
                     &size_hints);
 
2215
}
 
2216
 
 
2217
/**
 
2218
 * gdk_window_set_type_hint:
 
2219
 * @window: A toplevel #GdkWindow
 
2220
 * @hint: A hint of the function this window will have
 
2221
 *
 
2222
 * The application can use this call to provide a hint to the window
 
2223
 * manager about the functionality of a window. The window manager
 
2224
 * can use this information when determining the decoration and behaviour
 
2225
 * of the window.
 
2226
 *
 
2227
 * The hint must be set before the window is mapped.
 
2228
 **/
 
2229
void
 
2230
gdk_window_set_type_hint (GdkWindow        *window,
 
2231
                          GdkWindowTypeHint hint)
 
2232
{
 
2233
  GdkDisplay *display;
 
2234
  Atom atom;
 
2235
  
 
2236
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2237
  
 
2238
  if (GDK_WINDOW_DESTROYED (window))
 
2239
    return;
 
2240
 
 
2241
  display = gdk_drawable_get_display (window);
 
2242
 
 
2243
  switch (hint)
 
2244
    {
 
2245
    case GDK_WINDOW_TYPE_HINT_DIALOG:
 
2246
      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG");
 
2247
      break;
 
2248
    case GDK_WINDOW_TYPE_HINT_MENU:
 
2249
      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU");
 
2250
      break;
 
2251
    case GDK_WINDOW_TYPE_HINT_TOOLBAR:
 
2252
      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR");
 
2253
      break;
 
2254
    case GDK_WINDOW_TYPE_HINT_UTILITY:
 
2255
      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY");
 
2256
      break;
 
2257
    case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
 
2258
      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH");
 
2259
      break;
 
2260
    case GDK_WINDOW_TYPE_HINT_DOCK:
 
2261
      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK");
 
2262
      break;
 
2263
    case GDK_WINDOW_TYPE_HINT_DESKTOP:
 
2264
      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP");
 
2265
      break;
 
2266
    case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
 
2267
      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU");
 
2268
      break;
 
2269
    case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
 
2270
      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU");
 
2271
      break;
 
2272
    case GDK_WINDOW_TYPE_HINT_TOOLTIP:
 
2273
      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP");
 
2274
      break;
 
2275
    case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
 
2276
      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION");
 
2277
      break;
 
2278
    case GDK_WINDOW_TYPE_HINT_COMBO:
 
2279
      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO");
 
2280
      break;
 
2281
    case GDK_WINDOW_TYPE_HINT_DND:
 
2282
      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND");
 
2283
      break;
 
2284
    default:
 
2285
      g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
 
2286
      /* Fall thru */
 
2287
    case GDK_WINDOW_TYPE_HINT_NORMAL:
 
2288
      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NORMAL");
 
2289
      break;
 
2290
    }
 
2291
 
 
2292
  XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
 
2293
                   gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
 
2294
                   XA_ATOM, 32, PropModeReplace,
 
2295
                   (guchar *)&atom, 1);
 
2296
}
 
2297
 
 
2298
/**
 
2299
 * gdk_window_get_type_hint:
 
2300
 * @window: A toplevel #GdkWindow
 
2301
 *
 
2302
 * This function returns the type hint set for a window.
 
2303
 *
 
2304
 * Return value: The type hint set for @window
 
2305
 *
 
2306
 * Since: 2.10
 
2307
 **/
 
2308
GdkWindowTypeHint
 
2309
gdk_window_get_type_hint (GdkWindow *window)
 
2310
{
 
2311
  GdkDisplay *display;
 
2312
  GdkWindowTypeHint type;
 
2313
  Atom type_return;
 
2314
  gint format_return;
 
2315
  gulong nitems_return;
 
2316
  gulong bytes_after_return;
 
2317
  guchar *data = NULL;
 
2318
 
 
2319
  g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
 
2320
 
 
2321
  if (GDK_WINDOW_DESTROYED (window))
 
2322
    return GDK_WINDOW_TYPE_HINT_NORMAL;
 
2323
 
 
2324
  type = GDK_WINDOW_TYPE_HINT_NORMAL;
 
2325
 
 
2326
  display = gdk_drawable_get_display (window);
 
2327
 
 
2328
  if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
 
2329
                          gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
 
2330
                          0, G_MAXLONG, False, XA_ATOM, &type_return,
 
2331
                          &format_return, &nitems_return, &bytes_after_return,
 
2332
                          &data) == Success)
 
2333
    {
 
2334
      if ((type_return == XA_ATOM) && (format_return == 32) &&
 
2335
          (data) && (nitems_return == 1))
 
2336
        {
 
2337
          Atom atom = *(Atom*)data;
 
2338
 
 
2339
          if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG"))
 
2340
            type = GDK_WINDOW_TYPE_HINT_DIALOG;
 
2341
          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU"))
 
2342
            type = GDK_WINDOW_TYPE_HINT_MENU;
 
2343
          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR"))
 
2344
            type = GDK_WINDOW_TYPE_HINT_TOOLBAR;
 
2345
          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY"))
 
2346
            type = GDK_WINDOW_TYPE_HINT_UTILITY;
 
2347
          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH"))
 
2348
            type = GDK_WINDOW_TYPE_HINT_SPLASHSCREEN;
 
2349
          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK"))
 
2350
            type = GDK_WINDOW_TYPE_HINT_DOCK;
 
2351
          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP"))
 
2352
            type = GDK_WINDOW_TYPE_HINT_DESKTOP;
 
2353
          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"))
 
2354
            type = GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU;
 
2355
          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU"))
 
2356
            type = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
 
2357
          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP"))
 
2358
            type = GDK_WINDOW_TYPE_HINT_TOOLTIP;
 
2359
          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION"))
 
2360
            type = GDK_WINDOW_TYPE_HINT_NOTIFICATION;
 
2361
          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO"))
 
2362
            type = GDK_WINDOW_TYPE_HINT_COMBO;
 
2363
          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND"))
 
2364
            type = GDK_WINDOW_TYPE_HINT_DND;
 
2365
        }
 
2366
 
 
2367
      if (type_return != None && data != NULL)
 
2368
        XFree (data);
 
2369
    }
 
2370
 
 
2371
  return type;
 
2372
}
 
2373
 
 
2374
static void
 
2375
gdk_wmspec_change_state (gboolean   add,
 
2376
                         GdkWindow *window,
 
2377
                         GdkAtom    state1,
 
2378
                         GdkAtom    state2)
 
2379
{
 
2380
  GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
 
2381
  XClientMessageEvent xclient;
 
2382
  
 
2383
#define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
 
2384
#define _NET_WM_STATE_ADD           1    /* add/set property */
 
2385
#define _NET_WM_STATE_TOGGLE        2    /* toggle property  */  
 
2386
  
 
2387
  memset (&xclient, 0, sizeof (xclient));
 
2388
  xclient.type = ClientMessage;
 
2389
  xclient.window = GDK_WINDOW_XID (window);
 
2390
  xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE");
 
2391
  xclient.format = 32;
 
2392
  xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
 
2393
  xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
 
2394
  xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
 
2395
  xclient.data.l[3] = 0;
 
2396
  xclient.data.l[4] = 0;
 
2397
  
 
2398
  XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
 
2399
              SubstructureRedirectMask | SubstructureNotifyMask,
 
2400
              (XEvent *)&xclient);
 
2401
}
 
2402
 
 
2403
/**
 
2404
 * gdk_window_set_modal_hint:
 
2405
 * @window: A toplevel #GdkWindow
 
2406
 * @modal: %TRUE if the window is modal, %FALSE otherwise.
 
2407
 *
 
2408
 * The application can use this hint to tell the window manager
 
2409
 * that a certain window has modal behaviour. The window manager
 
2410
 * can use this information to handle modal windows in a special
 
2411
 * way.
 
2412
 *
 
2413
 * You should only use this on windows for which you have
 
2414
 * previously called gdk_window_set_transient_for()
 
2415
 **/
 
2416
void
 
2417
gdk_window_set_modal_hint (GdkWindow *window,
 
2418
                           gboolean   modal)
 
2419
{
 
2420
  GdkWindowObject *private;
 
2421
 
 
2422
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2423
  
 
2424
  if (GDK_WINDOW_DESTROYED (window))
 
2425
    return;
 
2426
 
 
2427
  private = (GdkWindowObject*) window;
 
2428
 
 
2429
  private->modal_hint = modal;
 
2430
 
 
2431
  if (GDK_WINDOW_IS_MAPPED (window))
 
2432
    gdk_wmspec_change_state (modal, window,
 
2433
                             gdk_atom_intern_static_string ("_NET_WM_STATE_MODAL"), 
 
2434
                             NULL);
 
2435
}
 
2436
 
 
2437
/**
 
2438
 * gdk_window_set_skip_taskbar_hint:
 
2439
 * @window: a toplevel #GdkWindow
 
2440
 * @skips_taskbar: %TRUE to skip the taskbar
 
2441
 * 
 
2442
 * Toggles whether a window should appear in a task list or window
 
2443
 * list. If a window's semantic type as specified with
 
2444
 * gdk_window_set_type_hint() already fully describes the window, this
 
2445
 * function should <emphasis>not</emphasis> be called in addition, 
 
2446
 * instead you should allow the window to be treated according to 
 
2447
 * standard policy for its semantic type.
 
2448
 *
 
2449
 * Since: 2.2
 
2450
 **/
 
2451
void
 
2452
gdk_window_set_skip_taskbar_hint (GdkWindow *window,
 
2453
                                  gboolean   skips_taskbar)
 
2454
{
 
2455
  GdkToplevelX11 *toplevel;
 
2456
  
 
2457
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2458
  g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
 
2459
  
 
2460
  if (GDK_WINDOW_DESTROYED (window))
 
2461
    return;
 
2462
 
 
2463
  toplevel = _gdk_x11_window_get_toplevel (window);
 
2464
  toplevel->skip_taskbar_hint = skips_taskbar;
 
2465
 
 
2466
  if (GDK_WINDOW_IS_MAPPED (window))
 
2467
    gdk_wmspec_change_state (skips_taskbar, window,
 
2468
                             gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_TASKBAR"), 
 
2469
                             NULL);
 
2470
}
 
2471
 
 
2472
/**
 
2473
 * gdk_window_set_skip_pager_hint:
 
2474
 * @window: a toplevel #GdkWindow
 
2475
 * @skips_pager: %TRUE to skip the pager
 
2476
 * 
 
2477
 * Toggles whether a window should appear in a pager (workspace
 
2478
 * switcher, or other desktop utility program that displays a small
 
2479
 * thumbnail representation of the windows on the desktop). If a
 
2480
 * window's semantic type as specified with gdk_window_set_type_hint()
 
2481
 * already fully describes the window, this function should 
 
2482
 * <emphasis>not</emphasis> be called in addition, instead you should 
 
2483
 * allow the window to be treated according to standard policy for 
 
2484
 * its semantic type.
 
2485
 *
 
2486
 * Since: 2.2
 
2487
 **/
 
2488
void
 
2489
gdk_window_set_skip_pager_hint (GdkWindow *window,
 
2490
                                gboolean   skips_pager)
 
2491
{
 
2492
  GdkToplevelX11 *toplevel;
 
2493
    
 
2494
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2495
  g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
 
2496
  
 
2497
  if (GDK_WINDOW_DESTROYED (window))
 
2498
    return;
 
2499
 
 
2500
  toplevel = _gdk_x11_window_get_toplevel (window);
 
2501
  toplevel->skip_pager_hint = skips_pager;
 
2502
  
 
2503
  if (GDK_WINDOW_IS_MAPPED (window))
 
2504
    gdk_wmspec_change_state (skips_pager, window,
 
2505
                             gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_PAGER"), 
 
2506
                             NULL);
 
2507
}
 
2508
 
 
2509
/**
 
2510
 * gdk_window_set_urgency_hint:
 
2511
 * @window: a toplevel #GdkWindow
 
2512
 * @urgent: %TRUE if the window is urgent
 
2513
 * 
 
2514
 * Toggles whether a window needs the user's
 
2515
 * urgent attention.
 
2516
 *
 
2517
 * Since: 2.8
 
2518
 **/
 
2519
void
 
2520
gdk_window_set_urgency_hint (GdkWindow *window,
 
2521
                             gboolean   urgent)
 
2522
{
 
2523
  GdkToplevelX11 *toplevel;
 
2524
    
 
2525
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2526
  g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
 
2527
  
 
2528
  if (GDK_WINDOW_DESTROYED (window))
 
2529
    return;
 
2530
 
 
2531
  toplevel = _gdk_x11_window_get_toplevel (window);
 
2532
  toplevel->urgency_hint = urgent;
 
2533
  
 
2534
  update_wm_hints (window, FALSE);
 
2535
}
 
2536
 
 
2537
/**
 
2538
 * gdk_window_set_geometry_hints:
 
2539
 * @window: a toplevel #GdkWindow
 
2540
 * @geometry: geometry hints
 
2541
 * @geom_mask: bitmask indicating fields of @geometry to pay attention to
 
2542
 *
 
2543
 * Sets the geometry hints for @window. Hints flagged in @geom_mask
 
2544
 * are set, hints not flagged in @geom_mask are unset.
 
2545
 * To unset all hints, use a @geom_mask of 0 and a @geometry of %NULL.
 
2546
 *
 
2547
 * This function provides hints to the windowing system about
 
2548
 * acceptable sizes for a toplevel window. The purpose of 
 
2549
 * this is to constrain user resizing, but the windowing system
 
2550
 * will typically  (but is not required to) also constrain the
 
2551
 * current size of the window to the provided values and
 
2552
 * constrain programatic resizing via gdk_window_resize() or
 
2553
 * gdk_window_move_resize().
 
2554
 * 
 
2555
 * Note that on X11, this effect has no effect on windows
 
2556
 * of type %GDK_WINDOW_TEMP or windows where override redirect
 
2557
 * has been turned on via gdk_window_set_override_redirect()
 
2558
 * since these windows are not resizable by the user.
 
2559
 * 
 
2560
 * Since you can't count on the windowing system doing the
 
2561
 * constraints for programmatic resizes, you should generally
 
2562
 * call gdk_window_constrain_size() yourself to determine
 
2563
 * appropriate sizes.
 
2564
 *
 
2565
 **/
 
2566
void 
 
2567
gdk_window_set_geometry_hints (GdkWindow      *window,
 
2568
                               GdkGeometry    *geometry,
 
2569
                               GdkWindowHints  geom_mask)
 
2570
{
 
2571
  XSizeHints size_hints;
 
2572
  
 
2573
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2574
  
 
2575
  if (GDK_WINDOW_DESTROYED (window))
 
2576
    return;
 
2577
  
 
2578
  size_hints.flags = 0;
 
2579
  
 
2580
  if (geom_mask & GDK_HINT_POS)
 
2581
    {
 
2582
      size_hints.flags |= PPosition;
 
2583
      /* We need to initialize the following obsolete fields because KWM 
 
2584
       * apparently uses these fields if they are non-zero.
 
2585
       * #@#!#!$!.
 
2586
       */
 
2587
      size_hints.x = 0;
 
2588
      size_hints.y = 0;
 
2589
    }
 
2590
 
 
2591
  if (geom_mask & GDK_HINT_USER_POS)
 
2592
    {
 
2593
      size_hints.flags |= USPosition;
 
2594
    }
 
2595
 
 
2596
  if (geom_mask & GDK_HINT_USER_SIZE)
 
2597
    {
 
2598
      size_hints.flags |= USSize;
 
2599
    }
 
2600
  
 
2601
  if (geom_mask & GDK_HINT_MIN_SIZE)
 
2602
    {
 
2603
      size_hints.flags |= PMinSize;
 
2604
      size_hints.min_width = geometry->min_width;
 
2605
      size_hints.min_height = geometry->min_height;
 
2606
    }
 
2607
  
 
2608
  if (geom_mask & GDK_HINT_MAX_SIZE)
 
2609
    {
 
2610
      size_hints.flags |= PMaxSize;
 
2611
      size_hints.max_width = MAX (geometry->max_width, 1);
 
2612
      size_hints.max_height = MAX (geometry->max_height, 1);
 
2613
    }
 
2614
  
 
2615
  if (geom_mask & GDK_HINT_BASE_SIZE)
 
2616
    {
 
2617
      size_hints.flags |= PBaseSize;
 
2618
      size_hints.base_width = geometry->base_width;
 
2619
      size_hints.base_height = geometry->base_height;
 
2620
    }
 
2621
  
 
2622
  if (geom_mask & GDK_HINT_RESIZE_INC)
 
2623
    {
 
2624
      size_hints.flags |= PResizeInc;
 
2625
      size_hints.width_inc = geometry->width_inc;
 
2626
      size_hints.height_inc = geometry->height_inc;
 
2627
    }
 
2628
  
 
2629
  if (geom_mask & GDK_HINT_ASPECT)
 
2630
    {
 
2631
      size_hints.flags |= PAspect;
 
2632
      if (geometry->min_aspect <= 1)
 
2633
        {
 
2634
          size_hints.min_aspect.x = 65536 * geometry->min_aspect;
 
2635
          size_hints.min_aspect.y = 65536;
 
2636
        }
 
2637
      else
 
2638
        {
 
2639
          size_hints.min_aspect.x = 65536;
 
2640
          size_hints.min_aspect.y = 65536 / geometry->min_aspect;;
 
2641
        }
 
2642
      if (geometry->max_aspect <= 1)
 
2643
        {
 
2644
          size_hints.max_aspect.x = 65536 * geometry->max_aspect;
 
2645
          size_hints.max_aspect.y = 65536;
 
2646
        }
 
2647
      else
 
2648
        {
 
2649
          size_hints.max_aspect.x = 65536;
 
2650
          size_hints.max_aspect.y = 65536 / geometry->max_aspect;;
 
2651
        }
 
2652
    }
 
2653
 
 
2654
  if (geom_mask & GDK_HINT_WIN_GRAVITY)
 
2655
    {
 
2656
      size_hints.flags |= PWinGravity;
 
2657
      size_hints.win_gravity = geometry->win_gravity;
 
2658
    }
 
2659
  
 
2660
  /* FIXME: Would it be better to delete this property if
 
2661
   *        geom_mask == 0? It would save space on the server
 
2662
   */
 
2663
  XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
 
2664
                     GDK_WINDOW_XID (window),
 
2665
                     &size_hints);
 
2666
}
 
2667
 
 
2668
static void
 
2669
gdk_window_get_geometry_hints (GdkWindow      *window,
 
2670
                               GdkGeometry    *geometry,
 
2671
                               GdkWindowHints *geom_mask)
 
2672
{
 
2673
  XSizeHints *size_hints;  
 
2674
  glong junk_supplied_mask = 0;
 
2675
 
 
2676
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2677
  g_return_if_fail (geometry != NULL);
 
2678
  g_return_if_fail (geom_mask != NULL);
 
2679
 
 
2680
  *geom_mask = 0;
 
2681
  
 
2682
  if (GDK_WINDOW_DESTROYED (window))
 
2683
    return;
 
2684
 
 
2685
  size_hints = XAllocSizeHints ();
 
2686
  if (!size_hints)
 
2687
    return;
 
2688
  
 
2689
  if (!XGetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
 
2690
                          GDK_WINDOW_XID (window),
 
2691
                          size_hints,
 
2692
                          &junk_supplied_mask))
 
2693
    size_hints->flags = 0;
 
2694
 
 
2695
  if (size_hints->flags & PMinSize)
 
2696
    {
 
2697
      *geom_mask |= GDK_HINT_MIN_SIZE;
 
2698
      geometry->min_width = size_hints->min_width;
 
2699
      geometry->min_height = size_hints->min_height;
 
2700
    }
 
2701
 
 
2702
  if (size_hints->flags & PMaxSize)
 
2703
    {
 
2704
      *geom_mask |= GDK_HINT_MAX_SIZE;
 
2705
      geometry->max_width = MAX (size_hints->max_width, 1);
 
2706
      geometry->max_height = MAX (size_hints->max_height, 1);
 
2707
    }
 
2708
 
 
2709
  if (size_hints->flags & PResizeInc)
 
2710
    {
 
2711
      *geom_mask |= GDK_HINT_RESIZE_INC;
 
2712
      geometry->width_inc = size_hints->width_inc;
 
2713
      geometry->height_inc = size_hints->height_inc;
 
2714
    }
 
2715
 
 
2716
  if (size_hints->flags & PAspect)
 
2717
    {
 
2718
      *geom_mask |= GDK_HINT_ASPECT;
 
2719
 
 
2720
      geometry->min_aspect = (gdouble) size_hints->min_aspect.x / (gdouble) size_hints->min_aspect.y;
 
2721
      geometry->max_aspect = (gdouble) size_hints->max_aspect.x / (gdouble) size_hints->max_aspect.y;
 
2722
    }
 
2723
 
 
2724
  if (size_hints->flags & PWinGravity)
 
2725
    {
 
2726
      *geom_mask |= GDK_HINT_WIN_GRAVITY;
 
2727
      geometry->win_gravity = size_hints->win_gravity;
 
2728
    }
 
2729
 
 
2730
  XFree (size_hints);
 
2731
}
 
2732
 
 
2733
static gboolean
 
2734
utf8_is_latin1 (const gchar *str)
 
2735
{
 
2736
  const char *p = str;
 
2737
 
 
2738
  while (*p)
 
2739
    {
 
2740
      gunichar ch = g_utf8_get_char (p);
 
2741
 
 
2742
      if (ch > 0xff)
 
2743
        return FALSE;
 
2744
      
 
2745
      p = g_utf8_next_char (p);
 
2746
    }
 
2747
 
 
2748
  return TRUE;
 
2749
}
 
2750
 
 
2751
/* Set the property to @utf8_str as STRING if the @utf8_str is fully
 
2752
 * convertable to STRING, otherwise, set it as compound text
 
2753
 */
 
2754
static void
 
2755
set_text_property (GdkDisplay  *display,
 
2756
                   Window       xwindow,
 
2757
                   Atom         property,
 
2758
                   const gchar *utf8_str)
 
2759
{
 
2760
  gchar *prop_text = NULL;
 
2761
  Atom prop_type;
 
2762
  gint prop_length;
 
2763
  gint prop_format;
 
2764
  gboolean is_compound_text;
 
2765
  
 
2766
  if (utf8_is_latin1 (utf8_str))
 
2767
    {
 
2768
      prop_type = XA_STRING;
 
2769
      prop_text = gdk_utf8_to_string_target (utf8_str);
 
2770
      prop_length = prop_text ? strlen (prop_text) : 0;
 
2771
      prop_format = 8;
 
2772
      is_compound_text = FALSE;
 
2773
    }
 
2774
  else
 
2775
    {
 
2776
      GdkAtom gdk_type;
 
2777
      
 
2778
      gdk_utf8_to_compound_text_for_display (display,
 
2779
                                             utf8_str, &gdk_type, &prop_format,
 
2780
                                             (guchar **)&prop_text, &prop_length);
 
2781
      prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
 
2782
      is_compound_text = TRUE;
 
2783
    }
 
2784
 
 
2785
  if (prop_text)
 
2786
    {
 
2787
      XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
 
2788
                       xwindow,
 
2789
                       property,
 
2790
                       prop_type, prop_format,
 
2791
                       PropModeReplace, (guchar *)prop_text,
 
2792
                       prop_length);
 
2793
 
 
2794
      if (is_compound_text)
 
2795
        gdk_free_compound_text ((guchar *)prop_text);
 
2796
      else
 
2797
        g_free (prop_text);
 
2798
    }
 
2799
}
 
2800
 
 
2801
/* Set WM_NAME and _NET_WM_NAME
 
2802
 */
 
2803
static void
 
2804
set_wm_name (GdkDisplay  *display,
 
2805
             Window       xwindow,
 
2806
             const gchar *name)
 
2807
{
 
2808
  XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
 
2809
                   gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
 
2810
                   gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
 
2811
                   PropModeReplace, (guchar *)name, strlen (name));
 
2812
  
 
2813
  set_text_property (display, xwindow,
 
2814
                     gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
 
2815
                     name);
 
2816
}
 
2817
 
 
2818
/**
 
2819
 * gdk_window_set_title:
 
2820
 * @window: a toplevel #GdkWindow
 
2821
 * @title: title of @window
 
2822
 *
 
2823
 * Sets the title of a toplevel window, to be displayed in the titlebar.
 
2824
 * If you haven't explicitly set the icon name for the window
 
2825
 * (using gdk_window_set_icon_name()), the icon name will be set to
 
2826
 * @title as well. @title must be in UTF-8 encoding (as with all
 
2827
 * user-readable strings in GDK/GTK+). @title may not be %NULL.
 
2828
 **/
 
2829
void
 
2830
gdk_window_set_title (GdkWindow   *window,
 
2831
                      const gchar *title)
 
2832
{
 
2833
  GdkDisplay *display;
 
2834
  Display *xdisplay;
 
2835
  Window xwindow;
 
2836
  
 
2837
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2838
  g_return_if_fail (title != NULL);
 
2839
 
 
2840
  if (GDK_WINDOW_DESTROYED (window))
 
2841
    return;
 
2842
  
 
2843
  display = gdk_drawable_get_display (window);
 
2844
  xdisplay = GDK_DISPLAY_XDISPLAY (display);
 
2845
  xwindow = GDK_WINDOW_XID (window);
 
2846
 
 
2847
  set_wm_name (display, xwindow, title);
 
2848
  
 
2849
  if (!gdk_window_icon_name_set (window))
 
2850
    {
 
2851
      XChangeProperty (xdisplay, xwindow,
 
2852
                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
 
2853
                       gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
 
2854
                       PropModeReplace, (guchar *)title, strlen (title));
 
2855
      
 
2856
      set_text_property (display, xwindow,
 
2857
                         gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
 
2858
                         title);
 
2859
    }
 
2860
}
 
2861
 
 
2862
/**
 
2863
 * gdk_window_set_role:
 
2864
 * @window: a toplevel #GdkWindow
 
2865
 * @role: a string indicating its role
 
2866
 *
 
2867
 * When using GTK+, typically you should use gtk_window_set_role() instead
 
2868
 * of this low-level function.
 
2869
 * 
 
2870
 * The window manager and session manager use a window's role to
 
2871
 * distinguish it from other kinds of window in the same application.
 
2872
 * When an application is restarted after being saved in a previous
 
2873
 * session, all windows with the same title and role are treated as
 
2874
 * interchangeable.  So if you have two windows with the same title
 
2875
 * that should be distinguished for session management purposes, you
 
2876
 * should set the role on those windows. It doesn't matter what string
 
2877
 * you use for the role, as long as you have a different role for each
 
2878
 * non-interchangeable kind of window.
 
2879
 * 
 
2880
 **/
 
2881
void          
 
2882
gdk_window_set_role (GdkWindow   *window,
 
2883
                     const gchar *role)
 
2884
{
 
2885
  GdkDisplay *display;
 
2886
  
 
2887
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2888
 
 
2889
  display = gdk_drawable_get_display (window);
 
2890
 
 
2891
  if (!GDK_WINDOW_DESTROYED (window))
 
2892
    {
 
2893
      if (role)
 
2894
        XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
 
2895
                         gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"),
 
2896
                         XA_STRING, 8, PropModeReplace, (guchar *)role, strlen (role));
 
2897
      else
 
2898
        XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
 
2899
                         gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"));
 
2900
    }
 
2901
}
 
2902
 
 
2903
/**
 
2904
 * gdk_window_set_transient_for:
 
2905
 * @window: a toplevel #GdkWindow
 
2906
 * @parent: another toplevel #GdkWindow
 
2907
 *
 
2908
 * Indicates to the window manager that @window is a transient dialog
 
2909
 * associated with the application window @parent. This allows the
 
2910
 * window manager to do things like center @window on @parent and
 
2911
 * keep @window above @parent.
 
2912
 *
 
2913
 * See gtk_window_set_transient_for() if you're using #GtkWindow or
 
2914
 * #GtkDialog.
 
2915
 * 
 
2916
 **/
 
2917
void          
 
2918
gdk_window_set_transient_for (GdkWindow *window, 
 
2919
                              GdkWindow *parent)
 
2920
{
 
2921
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2922
  
 
2923
  if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent))
 
2924
    XSetTransientForHint (GDK_WINDOW_XDISPLAY (window), 
 
2925
                          GDK_WINDOW_XID (window),
 
2926
                          GDK_WINDOW_XID (parent));
 
2927
}
 
2928
 
 
2929
/**
 
2930
 * gdk_window_set_background:
 
2931
 * @window: a #GdkWindow
 
2932
 * @color: an allocated #GdkColor
 
2933
 *
 
2934
 * Sets the background color of @window. (However, when using GTK+,
 
2935
 * set the background of a widget with gtk_widget_modify_bg() - if
 
2936
 * you're an application - or gtk_style_set_background() - if you're
 
2937
 * implementing a custom widget.)
 
2938
 *
 
2939
 * The @color must be allocated; gdk_rgb_find_color() is the best way
 
2940
 * to allocate a color.
 
2941
 *
 
2942
 * See also gdk_window_set_back_pixmap().
 
2943
 * 
 
2944
 **/
 
2945
void
 
2946
gdk_window_set_background (GdkWindow      *window,
 
2947
                           const GdkColor *color)
 
2948
{
 
2949
  GdkWindowObject *private = (GdkWindowObject *)window;
 
2950
  GdkColormap *colormap = gdk_drawable_get_colormap (window);
 
2951
  
 
2952
  g_return_if_fail (GDK_IS_WINDOW (window));
 
2953
  
 
2954
  if (!GDK_WINDOW_DESTROYED (window))
 
2955
    XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
 
2956
                          GDK_WINDOW_XID (window), color->pixel);
 
2957
 
 
2958
  private->bg_color = *color;
 
2959
  gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
 
2960
 
 
2961
  if (private->bg_pixmap &&
 
2962
      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
 
2963
      private->bg_pixmap != GDK_NO_BG)
 
2964
    g_object_unref (private->bg_pixmap);
 
2965
  
 
2966
  private->bg_pixmap = NULL;
 
2967
}
 
2968
 
 
2969
/**
 
2970
 * gdk_window_set_back_pixmap:
 
2971
 * @window: a #GdkWindow
 
2972
 * @pixmap: a #GdkPixmap, or %NULL
 
2973
 * @parent_relative: whether the tiling origin is at the origin of @window's parent
 
2974
 *
 
2975
 * Sets the background pixmap of @window. May also be used to set a background of
 
2976
 * "None" on @window, by setting a background pixmap of %NULL.
 
2977
 * A background pixmap will be tiled, positioning the first tile at the origin of
 
2978
 * @window, or if @parent_relative is %TRUE, the tiling will be done based on the
 
2979
 * origin of the parent window (useful to align tiles in a parent with tiles
 
2980
 * in a child).
 
2981
 *
 
2982
 * A background pixmap of %NULL means that the window will have no
 
2983
 * background.  A window with no background will never have its
 
2984
 * background filled by the windowing system, instead the window will
 
2985
 * contain whatever pixels were already in the corresponding area of
 
2986
 * the display.
 
2987
 *
 
2988
 * The windowing system will normally fill a window with its background
 
2989
 * when the window is obscured then exposed, and when you call
 
2990
 * gdk_window_clear().
 
2991
 * 
 
2992
 **/
 
2993
void
 
2994
gdk_window_set_back_pixmap (GdkWindow *window,
 
2995
                            GdkPixmap *pixmap,
 
2996
                            gboolean   parent_relative)
 
2997
{
 
2998
  GdkWindowObject *private = (GdkWindowObject *)window;
 
2999
  Pixmap xpixmap;
 
3000
  
 
3001
  g_return_if_fail (GDK_IS_WINDOW (window));
 
3002
  g_return_if_fail (pixmap == NULL || !parent_relative);
 
3003
  g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
 
3004
 
 
3005
  if (pixmap && !gdk_drawable_get_colormap (pixmap))
 
3006
    {
 
3007
      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
 
3008
      return;
 
3009
    }
 
3010
  
 
3011
  if (private->bg_pixmap &&
 
3012
      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
 
3013
      private->bg_pixmap != GDK_NO_BG)
 
3014
    g_object_unref (private->bg_pixmap);
 
3015
 
 
3016
  if (parent_relative)
 
3017
    {
 
3018
      xpixmap = ParentRelative;
 
3019
      private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
 
3020
    }
 
3021
  else
 
3022
    {
 
3023
      if (pixmap)
 
3024
        {
 
3025
          g_object_ref (pixmap);
 
3026
          private->bg_pixmap = pixmap;
 
3027
          xpixmap = GDK_PIXMAP_XID (pixmap);
 
3028
        }
 
3029
      else
 
3030
        {
 
3031
          xpixmap = None;
 
3032
          private->bg_pixmap = GDK_NO_BG;
 
3033
        }
 
3034
    }
 
3035
  
 
3036
  if (!GDK_WINDOW_DESTROYED (window))
 
3037
    XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
 
3038
                                GDK_WINDOW_XID (window), xpixmap);
 
3039
}
 
3040
 
 
3041
/**
 
3042
 * gdk_window_set_cursor:
 
3043
 * @window: a #GdkWindow
 
3044
 * @cursor: a cursor
 
3045
 *
 
3046
 * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new() or
 
3047
 * gdk_cursor_new_from_pixmap() to create the cursor.
 
3048
 * To make the cursor invisible, use gdk_cursor_new_from_pixmap() to create
 
3049
 * a cursor with no pixels in it. Passing %NULL for the @cursor argument
 
3050
 * to gdk_window_set_cursor() means that @window will use the cursor of
 
3051
 * its parent window. Most windows should use this default.
 
3052
 * 
 
3053
 **/
 
3054
void
 
3055
gdk_window_set_cursor (GdkWindow *window,
 
3056
                       GdkCursor *cursor)
 
3057
{
 
3058
  GdkWindowObject *private;
 
3059
  GdkWindowImplX11 *impl;
 
3060
  GdkCursorPrivate *cursor_private;
 
3061
  Cursor xcursor;
 
3062
  
 
3063
  g_return_if_fail (GDK_IS_WINDOW (window));
 
3064
    
 
3065
  private = (GdkWindowObject *)window;
 
3066
  impl = GDK_WINDOW_IMPL_X11 (private->impl);
 
3067
  cursor_private = (GdkCursorPrivate*) cursor;
 
3068
 
 
3069
  if (impl->cursor)
 
3070
    {
 
3071
      gdk_cursor_unref (impl->cursor);
 
3072
      impl->cursor = NULL;
 
3073
    }
 
3074
 
 
3075
  if (!cursor)
 
3076
    xcursor = None;
 
3077
  else
 
3078
    {
 
3079
      _gdk_x11_cursor_update_theme (cursor);
 
3080
      xcursor = cursor_private->xcursor;
 
3081
    }
 
3082
  
 
3083
  if (!GDK_WINDOW_DESTROYED (window))
 
3084
    {
 
3085
      XDefineCursor (GDK_WINDOW_XDISPLAY (window),
 
3086
                     GDK_WINDOW_XID (window),
 
3087
                     xcursor);
 
3088
      
 
3089
      if (cursor)
 
3090
        impl->cursor = gdk_cursor_ref (cursor);
 
3091
    }
 
3092
}
 
3093
 
 
3094
GdkCursor *
 
3095
_gdk_x11_window_get_cursor (GdkWindow *window)
 
3096
{
 
3097
  GdkWindowObject *private;
 
3098
  GdkWindowImplX11 *impl;
 
3099
  
 
3100
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
3101
    
 
3102
  private = (GdkWindowObject *)window;
 
3103
  impl = GDK_WINDOW_IMPL_X11 (private->impl);
 
3104
 
 
3105
  return impl->cursor;
 
3106
}
 
3107
 
 
3108
/**
 
3109
 * gdk_window_get_geometry:
 
3110
 * @window: a #GdkWindow
 
3111
 * @x: return location for X coordinate of window (relative to its parent)
 
3112
 * @y: return location for Y coordinate of window (relative to its parent)
 
3113
 * @width: return location for width of window
 
3114
 * @height: return location for height of window
 
3115
 * @depth: return location for bit depth of window
 
3116
 *
 
3117
 * Any of the return location arguments to this function may be %NULL,
 
3118
 * if you aren't interested in getting the value of that field.
 
3119
 *
 
3120
 * The X and Y coordinates returned are relative to the parent window
 
3121
 * of @window, which for toplevels usually means relative to the
 
3122
 * window decorations (titlebar, etc.) rather than relative to the
 
3123
 * root window (screen-size background window).
 
3124
 *
 
3125
 * On the X11 platform, the geometry is obtained from the X server,
 
3126
 * so reflects the latest position of @window; this may be out-of-sync
 
3127
 * with the position of @window delivered in the most-recently-processed
 
3128
 * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
 
3129
 * position from the most recent configure event.
 
3130
 * 
 
3131
 * <note>
 
3132
 * If @window is not a toplevel, it is <emphasis>much</emphasis> better 
 
3133
 * to call gdk_window_get_position() and gdk_drawable_get_size() instead, 
 
3134
 * because it avoids the roundtrip to the X server and because 
 
3135
 * gdk_drawable_get_size() supports the full 32-bit coordinate space,
 
3136
 * whereas gdk_window_get_geometry() is restricted to the 16-bit
 
3137
 * coordinates of X11.
 
3138
 *</note>
 
3139
 **/
 
3140
void
 
3141
gdk_window_get_geometry (GdkWindow *window,
 
3142
                         gint      *x,
 
3143
                         gint      *y,
 
3144
                         gint      *width,
 
3145
                         gint      *height,
 
3146
                         gint      *depth)
 
3147
{
 
3148
  Window root;
 
3149
  gint tx;
 
3150
  gint ty;
 
3151
  guint twidth;
 
3152
  guint theight;
 
3153
  guint tborder_width;
 
3154
  guint tdepth;
 
3155
  
 
3156
  g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
 
3157
  
 
3158
  if (!window)
 
3159
    {
 
3160
      GDK_NOTE (MULTIHEAD,
 
3161
                g_message ("gdk_window_get_geometry(): Window needs to be non-NULL to be multi head safe"));
 
3162
      window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
 
3163
    }
 
3164
 
 
3165
  if (!GDK_WINDOW_DESTROYED (window))
 
3166
    {
 
3167
      XGetGeometry (GDK_WINDOW_XDISPLAY (window),
 
3168
                    GDK_WINDOW_XID (window),
 
3169
                    &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
 
3170
      
 
3171
      if (x)
 
3172
        *x = tx;
 
3173
      if (y)
 
3174
        *y = ty;
 
3175
      if (width)
 
3176
        *width = twidth;
 
3177
      if (height)
 
3178
        *height = theight;
 
3179
      if (depth)
 
3180
        *depth = tdepth;
 
3181
    }
 
3182
}
 
3183
 
 
3184
/**
 
3185
 * gdk_window_get_origin:
 
3186
 * @window: a #GdkWindow
 
3187
 * @x: return location for X coordinate
 
3188
 * @y: return location for Y coordinate
 
3189
 * 
 
3190
 * Obtains the position of a window in root window coordinates.
 
3191
 * (Compare with gdk_window_get_position() and
 
3192
 * gdk_window_get_geometry() which return the position of a window
 
3193
 * relative to its parent window.)
 
3194
 * 
 
3195
 * Return value: not meaningful, ignore
 
3196
 **/
 
3197
gint
 
3198
gdk_window_get_origin (GdkWindow *window,
 
3199
                       gint      *x,
 
3200
                       gint      *y)
 
3201
{
 
3202
  gint return_val;
 
3203
  Window child;
 
3204
  gint tx = 0;
 
3205
  gint ty = 0;
 
3206
  
 
3207
  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
3208
  
 
3209
  if (!GDK_WINDOW_DESTROYED (window))
 
3210
    {
 
3211
      return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
 
3212
                                          GDK_WINDOW_XID (window),
 
3213
                                          GDK_WINDOW_XROOTWIN (window),
 
3214
                                          0, 0, &tx, &ty,
 
3215
                                          &child);
 
3216
    }
 
3217
  else
 
3218
    return_val = 0;
 
3219
  
 
3220
  if (x)
 
3221
    *x = tx;
 
3222
  if (y)
 
3223
    *y = ty;
 
3224
  
 
3225
  return return_val;
 
3226
}
 
3227
 
 
3228
/**
 
3229
 * gdk_window_get_deskrelative_origin:
 
3230
 * @window: a toplevel #GdkWindow
 
3231
 * @x: return location for X coordinate
 
3232
 * @y: return location for Y coordinate
 
3233
 * 
 
3234
 * This gets the origin of a #GdkWindow relative to
 
3235
 * an Enlightenment-window-manager desktop. As long as you don't
 
3236
 * assume that the user's desktop/workspace covers the entire
 
3237
 * root window (i.e. you don't assume that the desktop begins
 
3238
 * at root window coordinate 0,0) this function is not necessary.
 
3239
 * It's deprecated for that reason.
 
3240
 * 
 
3241
 * Return value: not meaningful
 
3242
 **/
 
3243
gboolean
 
3244
gdk_window_get_deskrelative_origin (GdkWindow *window,
 
3245
                                    gint      *x,
 
3246
                                    gint      *y)
 
3247
{
 
3248
  gboolean return_val = FALSE;
 
3249
  gint num_children, format_return;
 
3250
  Window win, *child, parent, root;
 
3251
  gint tx = 0;
 
3252
  gint ty = 0;
 
3253
  Atom type_return;
 
3254
  Atom atom;
 
3255
  gulong number_return, bytes_after_return;
 
3256
  guchar *data_return;
 
3257
  
 
3258
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
3259
  
 
3260
  if (!GDK_WINDOW_DESTROYED (window))
 
3261
    {
 
3262
      atom = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
 
3263
                                                    "ENLIGHTENMENT_DESKTOP");
 
3264
      win = GDK_WINDOW_XID (window);
 
3265
      
 
3266
      while (XQueryTree (GDK_WINDOW_XDISPLAY (window), win, &root, &parent,
 
3267
                         &child, (unsigned int *)&num_children))
 
3268
        {
 
3269
          if ((child) && (num_children > 0))
 
3270
            XFree (child);
 
3271
          
 
3272
          if (!parent)
 
3273
            break;
 
3274
          else
 
3275
            win = parent;
 
3276
          
 
3277
          if (win == root)
 
3278
            break;
 
3279
          
 
3280
          data_return = NULL;
 
3281
          XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), win, atom, 0, 0,
 
3282
                              False, XA_CARDINAL, &type_return, &format_return,
 
3283
                              &number_return, &bytes_after_return, &data_return);
 
3284
 
 
3285
          if (type_return == XA_CARDINAL)
 
3286
            {
 
3287
              XFree (data_return);
 
3288
              break;
 
3289
            }
 
3290
        }
 
3291
      
 
3292
      return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
 
3293
                                          GDK_WINDOW_XID (window),
 
3294
                                          win,
 
3295
                                          0, 0, &tx, &ty,
 
3296
                                          &root);
 
3297
      if (x)
 
3298
        *x = tx;
 
3299
      if (y)
 
3300
        *y = ty;
 
3301
    }
 
3302
  
 
3303
  
 
3304
  return return_val;
 
3305
}
 
3306
 
 
3307
/**
 
3308
 * gdk_window_get_root_origin:
 
3309
 * @window: a toplevel #GdkWindow
 
3310
 * @x: return location for X position of window frame
 
3311
 * @y: return location for Y position of window frame
 
3312
 *
 
3313
 * Obtains the top-left corner of the window manager frame in root
 
3314
 * window coordinates.
 
3315
 * 
 
3316
 **/
 
3317
void
 
3318
gdk_window_get_root_origin (GdkWindow *window,
 
3319
                            gint      *x,
 
3320
                            gint      *y)
 
3321
{
 
3322
  GdkRectangle rect;
 
3323
 
 
3324
  g_return_if_fail (GDK_IS_WINDOW (window));
 
3325
 
 
3326
  gdk_window_get_frame_extents (window, &rect);
 
3327
 
 
3328
  if (x)
 
3329
    *x = rect.x;
 
3330
 
 
3331
  if (y)
 
3332
    *y = rect.y;
 
3333
}
 
3334
 
 
3335
/**
 
3336
 * gdk_window_get_frame_extents:
 
3337
 * @window: a toplevel #GdkWindow
 
3338
 * @rect: rectangle to fill with bounding box of the window frame
 
3339
 *
 
3340
 * Obtains the bounding box of the window, including window manager
 
3341
 * titlebar/borders if any. The frame position is given in root window
 
3342
 * coordinates. To get the position of the window itself (rather than
 
3343
 * the frame) in root window coordinates, use gdk_window_get_origin().
 
3344
 * 
 
3345
 **/
 
3346
void
 
3347
gdk_window_get_frame_extents (GdkWindow    *window,
 
3348
                              GdkRectangle *rect)
 
3349
{
 
3350
  GdkDisplay *display;
 
3351
  GdkWindowObject *private;
 
3352
  Window xwindow;
 
3353
  Window xparent;
 
3354
  Window root;
 
3355
  Window *children;
 
3356
  guchar *data;
 
3357
  Window *vroots;
 
3358
  Atom type_return;
 
3359
  guint nchildren;
 
3360
  guint nvroots;
 
3361
  gulong nitems_return;
 
3362
  gulong bytes_after_return;
 
3363
  gint format_return;
 
3364
  gint i;
 
3365
  guint ww, wh, wb, wd;
 
3366
  gint wx, wy;
 
3367
  
 
3368
  g_return_if_fail (GDK_IS_WINDOW (window));
 
3369
  g_return_if_fail (rect != NULL);
 
3370
  
 
3371
  private = (GdkWindowObject*) window;
 
3372
  
 
3373
  rect->x = 0;
 
3374
  rect->y = 0;
 
3375
  rect->width = 1;
 
3376
  rect->height = 1;
 
3377
  
 
3378
  if (GDK_WINDOW_DESTROYED (window))
 
3379
    return;
 
3380
  
 
3381
  while (private->parent && ((GdkWindowObject*) private->parent)->parent)
 
3382
    private = (GdkWindowObject*) private->parent;
 
3383
 
 
3384
  /* Refine our fallback answer a bit using local information */
 
3385
  rect->x = private->x;
 
3386
  rect->y = private->y;
 
3387
  gdk_drawable_get_size ((GdkDrawable *)private, &rect->width, &rect->height);
 
3388
 
 
3389
  if (GDK_WINDOW_DESTROYED (private))
 
3390
    return;
 
3391
 
 
3392
  gdk_error_trap_push();
 
3393
  
 
3394
  /* use NETWM_VIRTUAL_ROOTS if available */
 
3395
  display = gdk_drawable_get_display (window);
 
3396
  root = GDK_WINDOW_XROOTWIN (window);
 
3397
 
 
3398
  nvroots = 0;
 
3399
  vroots = NULL;
 
3400
 
 
3401
  if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), root,
 
3402
                          gdk_x11_get_xatom_by_name_for_display (display, 
 
3403
                                                                 "_NET_VIRTUAL_ROOTS"),
 
3404
                          0, G_MAXLONG, False, XA_WINDOW, &type_return,
 
3405
                          &format_return, &nitems_return, &bytes_after_return,
 
3406
                          &data)
 
3407
      == Success)
 
3408
    {
 
3409
      if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
 
3410
        {
 
3411
          nvroots = nitems_return;
 
3412
          vroots = (Window *)data;
 
3413
        }
 
3414
    }
 
3415
 
 
3416
  xparent = GDK_WINDOW_XID (window);
 
3417
 
 
3418
  do
 
3419
    {
 
3420
      xwindow = xparent;
 
3421
 
 
3422
      if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xwindow,
 
3423
                       &root, &xparent,
 
3424
                       &children, &nchildren))
 
3425
        goto fail;
 
3426
      
 
3427
      if (children)
 
3428
        XFree (children);
 
3429
 
 
3430
      /* check virtual roots */
 
3431
      for (i = 0; i < nvroots; i++)
 
3432
        {
 
3433
          if (xparent == vroots[i])
 
3434
            {
 
3435
              root = xparent;
 
3436
              break;
 
3437
           }
 
3438
        }
 
3439
    }
 
3440
  while (xparent != root);
 
3441
  
 
3442
  if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow, 
 
3443
                    &root, &wx, &wy, &ww, &wh, &wb, &wd))
 
3444
    {
 
3445
      rect->x = wx;
 
3446
      rect->y = wy;
 
3447
      rect->width = ww;
 
3448
      rect->height = wh;
 
3449
    }
 
3450
 
 
3451
 fail:
 
3452
  if (vroots)
 
3453
    XFree (vroots);
 
3454
 
 
3455
  gdk_error_trap_pop ();
 
3456
}
 
3457
 
 
3458
void
 
3459
_gdk_windowing_get_pointer (GdkDisplay       *display,
 
3460
                            GdkScreen       **screen,
 
3461
                            gint             *x,
 
3462
                            gint             *y,
 
3463
                            GdkModifierType  *mask)
 
3464
{
 
3465
  GdkScreen *default_screen;
 
3466
  Display *xdisplay;
 
3467
  Window xwindow;
 
3468
  Window root = None;
 
3469
  Window child;
 
3470
  int rootx, rooty;
 
3471
  int winx;
 
3472
  int winy;
 
3473
  unsigned int xmask;
 
3474
 
 
3475
  if (display->closed)
 
3476
    return;
 
3477
 
 
3478
  default_screen = gdk_display_get_default_screen (display);
 
3479
 
 
3480
  xdisplay = GDK_SCREEN_XDISPLAY (default_screen);
 
3481
  xwindow = GDK_SCREEN_XROOTWIN (default_screen);
 
3482
  
 
3483
  if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) 
 
3484
    {
 
3485
      XQueryPointer (xdisplay, xwindow,
 
3486
                     &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
 
3487
    } 
 
3488
  else 
 
3489
    {
 
3490
      XSetWindowAttributes attributes;
 
3491
      Window w;
 
3492
      
 
3493
      w = XCreateWindow (xdisplay, xwindow, 0, 0, 1, 1, 0, 
 
3494
                         CopyFromParent, InputOnly, CopyFromParent, 
 
3495
                         0, &attributes);
 
3496
      XQueryPointer (xdisplay, w, 
 
3497
                     &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
 
3498
      XDestroyWindow (xdisplay, w);
 
3499
    }
 
3500
  
 
3501
  if (root != None)
 
3502
    {
 
3503
      GdkWindow *gdk_root = gdk_window_lookup_for_display (display, root);
 
3504
      *screen = gdk_drawable_get_screen (gdk_root);
 
3505
    }
 
3506
  
 
3507
  *x = rootx;
 
3508
  *y = rooty;
 
3509
  *mask = xmask;
 
3510
}
 
3511
 
 
3512
GdkWindow*
 
3513
_gdk_windowing_window_get_pointer (GdkDisplay      *display,
 
3514
                                   GdkWindow       *window,
 
3515
                                   gint            *x,
 
3516
                                   gint            *y,
 
3517
                                   GdkModifierType *mask)
 
3518
{
 
3519
  GdkWindow *return_val;
 
3520
  Window root;
 
3521
  Window child;
 
3522
  int rootx, rooty;
 
3523
  int winx = 0;
 
3524
  int winy = 0;
 
3525
  unsigned int xmask = 0;
 
3526
  gint xoffset, yoffset;
 
3527
 
 
3528
  g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
 
3529
  
 
3530
  _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
 
3531
 
 
3532
  return_val = NULL;
 
3533
  if (!GDK_WINDOW_DESTROYED (window)) 
 
3534
    {
 
3535
      if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) 
 
3536
        {
 
3537
          if (XQueryPointer (GDK_WINDOW_XDISPLAY (window),
 
3538
                             GDK_WINDOW_XID (window),
 
3539
                             &root, &child, &rootx, &rooty, &winx, &winy, &xmask))
 
3540
            {
 
3541
              if (child)
 
3542
                return_val = gdk_window_lookup_for_display (GDK_WINDOW_DISPLAY (window), child);
 
3543
            }
 
3544
        } 
 
3545
      else 
 
3546
        {
 
3547
          GdkScreen *screen;
 
3548
          int originx, originy;
 
3549
          _gdk_windowing_get_pointer (gdk_drawable_get_display (window), &screen, 
 
3550
                                      &rootx, &rooty, &xmask);
 
3551
          gdk_window_get_origin (window, &originx, &originy);
 
3552
          winx = rootx - originx;
 
3553
          winy = rooty - originy;
 
3554
        }
 
3555
    }
 
3556
  
 
3557
  *x = winx + xoffset;
 
3558
  *y = winy + yoffset;
 
3559
  *mask = xmask;
 
3560
  
 
3561
  return return_val;
 
3562
}
 
3563
 
 
3564
/**
 
3565
 * gdk_display_warp_pointer:
 
3566
 * @display: a #GdkDisplay
 
3567
 * @screen: the screen of @display to warp the pointer to
 
3568
 * @x: the x coordinate of the destination
 
3569
 * @y: the y coordinate of the destination
 
3570
 * 
 
3571
 * Warps the pointer of @display to the point @x,@y on 
 
3572
 * the screen @screen, unless the pointer is confined
 
3573
 * to a window by a grab, in which case it will be moved
 
3574
 * as far as allowed by the grab. Warping the pointer 
 
3575
 * creates events as if the user had moved the mouse 
 
3576
 * instantaneously to the destination.
 
3577
 * 
 
3578
 * Note that the pointer should normally be under the
 
3579
 * control of the user. This function was added to cover
 
3580
 * some rare use cases like keyboard navigation support
 
3581
 * for the color picker in the #GtkColorSelectionDialog.
 
3582
 *
 
3583
 * Since: 2.8
 
3584
 */ 
 
3585
void
 
3586
gdk_display_warp_pointer (GdkDisplay *display,
 
3587
                          GdkScreen  *screen,
 
3588
                          gint        x,
 
3589
                          gint        y)
 
3590
{
 
3591
  Display *xdisplay;
 
3592
  Window dest;
 
3593
 
 
3594
  xdisplay = GDK_DISPLAY_XDISPLAY (display);
 
3595
  dest = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
 
3596
 
 
3597
  XWarpPointer (xdisplay, None, dest, 0, 0, 0, 0, x, y);  
 
3598
}
 
3599
 
 
3600
GdkWindow*
 
3601
_gdk_windowing_window_at_pointer (GdkDisplay *display,
 
3602
                                  gint       *win_x,
 
3603
                                  gint       *win_y)
 
3604
{
 
3605
  GdkWindow *window;
 
3606
  GdkScreen *screen;
 
3607
  Window root;
 
3608
  Window xwindow;
 
3609
  Window child;
 
3610
  Window xwindow_last = 0;
 
3611
  Display *xdisplay;
 
3612
  int rootx = -1, rooty = -1;
 
3613
  int winx, winy;
 
3614
  unsigned int xmask;
 
3615
 
 
3616
  screen = gdk_display_get_default_screen (display);
 
3617
  
 
3618
  xwindow = GDK_SCREEN_XROOTWIN (screen);
 
3619
  xdisplay = GDK_SCREEN_XDISPLAY (screen);
 
3620
 
 
3621
  /* This function really only works if the mouse pointer is held still
 
3622
   * during its operation. If it moves from one leaf window to another
 
3623
   * than we'll end up with inaccurate values for win_x, win_y
 
3624
   * and the result.
 
3625
   */
 
3626
  gdk_x11_display_grab (display);
 
3627
  if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) 
 
3628
    {
 
3629
      XQueryPointer (xdisplay, xwindow,
 
3630
                     &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
 
3631
      if (root == xwindow)
 
3632
        xwindow = child;
 
3633
      else
 
3634
        xwindow = root;
 
3635
      
 
3636
      while (xwindow)
 
3637
        {
 
3638
          xwindow_last = xwindow;
 
3639
          XQueryPointer (xdisplay, xwindow,
 
3640
                         &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
 
3641
        }
 
3642
    } 
 
3643
  else 
 
3644
    {
 
3645
      gint i, screens, width, height;
 
3646
      GList *toplevels, *list;
 
3647
      Window pointer_window;
 
3648
      
 
3649
      pointer_window = None;
 
3650
      screens = gdk_display_get_n_screens (display);
 
3651
      for (i = 0; i < screens; ++i) {
 
3652
        screen = gdk_display_get_screen (display, i);
 
3653
        toplevels = gdk_screen_get_toplevel_windows (screen);
 
3654
        for (list = toplevels; list != NULL; list = g_list_next (list)) {
 
3655
          window = GDK_WINDOW (list->data);
 
3656
          xwindow = GDK_WINDOW_XWINDOW (window);
 
3657
          gdk_error_trap_push ();
 
3658
          XQueryPointer (xdisplay, xwindow,
 
3659
                         &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
 
3660
          gdk_flush ();
 
3661
          if (gdk_error_trap_pop ())
 
3662
            continue;
 
3663
          if (child != None) 
 
3664
            {
 
3665
              pointer_window = child;
 
3666
              break;
 
3667
            }
 
3668
          gdk_window_get_geometry (window, NULL, NULL, &width, &height, NULL);
 
3669
          if (winx >= 0 && winy >= 0 && winx < width && winy < height) 
 
3670
            {
 
3671
              /* A childless toplevel, or below another window? */
 
3672
              XSetWindowAttributes attributes;
 
3673
              Window w;
 
3674
              
 
3675
              w = XCreateWindow (xdisplay, xwindow, winx, winy, 1, 1, 0, 
 
3676
                                 CopyFromParent, InputOnly, CopyFromParent, 
 
3677
                                 0, &attributes);
 
3678
              XMapWindow (xdisplay, w);
 
3679
              XQueryPointer (xdisplay, xwindow, 
 
3680
                             &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
 
3681
              XDestroyWindow (xdisplay, w);
 
3682
              if (child == w) 
 
3683
                {
 
3684
                  pointer_window = xwindow;
 
3685
                  break;
 
3686
                }
 
3687
            }
 
3688
        }
 
3689
        g_list_free (toplevels);
 
3690
        if (pointer_window != None)
 
3691
          break;
 
3692
      }
 
3693
      xwindow = pointer_window;
 
3694
 
 
3695
      while (xwindow)
 
3696
        {
 
3697
          xwindow_last = xwindow;
 
3698
          gdk_error_trap_push ();
 
3699
          XQueryPointer (xdisplay, xwindow,
 
3700
                         &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
 
3701
          gdk_flush ();
 
3702
          if (gdk_error_trap_pop ())
 
3703
            break;
 
3704
        }
 
3705
    }
 
3706
  
 
3707
  gdk_x11_display_ungrab (display);
 
3708
 
 
3709
  window = gdk_window_lookup_for_display (display, xwindow_last);
 
3710
  *win_x = window ? winx : -1;
 
3711
  *win_y = window ? winy : -1;
 
3712
 
 
3713
  return window;
 
3714
}
 
3715
 
 
3716
/**
 
3717
 * gdk_window_get_events:
 
3718
 * @window: a #GdkWindow
 
3719
 * 
 
3720
 * Gets the event mask for @window. See gdk_window_set_events().
 
3721
 * 
 
3722
 * Return value: event mask for @window
 
3723
 **/
 
3724
GdkEventMask  
 
3725
gdk_window_get_events (GdkWindow *window)
 
3726
{
 
3727
  XWindowAttributes attrs;
 
3728
  GdkEventMask event_mask;
 
3729
  
 
3730
  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
3731
 
 
3732
  if (GDK_WINDOW_DESTROYED (window))
 
3733
    return 0;
 
3734
  else
 
3735
    {
 
3736
      XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
 
3737
                            GDK_WINDOW_XID (window), 
 
3738
                            &attrs);
 
3739
      
 
3740
      event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
 
3741
      GDK_WINDOW_OBJECT (window)->event_mask = event_mask;
 
3742
  
 
3743
      return event_mask;
 
3744
    }
 
3745
}
 
3746
 
 
3747
/**
 
3748
 * gdk_window_set_events:
 
3749
 * @window: a #GdkWindow
 
3750
 * @event_mask: event mask for @window
 
3751
 *
 
3752
 * The event mask for a window determines which events will be reported
 
3753
 * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
 
3754
 * means the window should report button press events. The event mask
 
3755
 * is the bitwise OR of values from the #GdkEventMask enumeration.
 
3756
 * 
 
3757
 **/
 
3758
void          
 
3759
gdk_window_set_events (GdkWindow       *window,
 
3760
                       GdkEventMask     event_mask)
 
3761
{
 
3762
  long xevent_mask;
 
3763
  int i;
 
3764
  
 
3765
  g_return_if_fail (GDK_IS_WINDOW (window));
 
3766
  
 
3767
  if (!GDK_WINDOW_DESTROYED (window))
 
3768
    {
 
3769
      GDK_WINDOW_OBJECT (window)->event_mask = event_mask;
 
3770
      xevent_mask = StructureNotifyMask | PropertyChangeMask;
 
3771
      for (i = 0; i < _gdk_nenvent_masks; i++)
 
3772
        {
 
3773
          if (event_mask & (1 << (i + 1)))
 
3774
            xevent_mask |= _gdk_event_mask_table[i];
 
3775
        }
 
3776
      
 
3777
      XSelectInput (GDK_WINDOW_XDISPLAY (window),
 
3778
                    GDK_WINDOW_XID (window),
 
3779
                    xevent_mask);
 
3780
    }
 
3781
}
 
3782
 
 
3783
static void
 
3784
gdk_window_add_colormap_windows (GdkWindow *window)
 
3785
{
 
3786
  GdkWindow *toplevel;
 
3787
  Window *old_windows;
 
3788
  Window *new_windows;
 
3789
  int i, count;
 
3790
  
 
3791
  g_return_if_fail (GDK_IS_WINDOW (window));
 
3792
 
 
3793
  if (GDK_WINDOW_DESTROYED (window))
 
3794
    return;
 
3795
 
 
3796
  toplevel = gdk_window_get_toplevel (window);
 
3797
  
 
3798
  old_windows = NULL;
 
3799
  if (!XGetWMColormapWindows (GDK_WINDOW_XDISPLAY (toplevel),
 
3800
                              GDK_WINDOW_XID (toplevel),
 
3801
                              &old_windows, &count))
 
3802
    {
 
3803
      count = 0;
 
3804
    }
 
3805
  
 
3806
  for (i = 0; i < count; i++)
 
3807
    if (old_windows[i] == GDK_WINDOW_XID (window))
 
3808
      {
 
3809
        XFree (old_windows);
 
3810
        return;
 
3811
      }
 
3812
  
 
3813
  new_windows = g_new (Window, count + 1);
 
3814
  
 
3815
  for (i = 0; i < count; i++)
 
3816
    new_windows[i] = old_windows[i];
 
3817
  new_windows[count] = GDK_WINDOW_XID (window);
 
3818
  
 
3819
  XSetWMColormapWindows (GDK_WINDOW_XDISPLAY (toplevel),
 
3820
                         GDK_WINDOW_XID (toplevel),
 
3821
                         new_windows, count + 1);
 
3822
  
 
3823
  g_free (new_windows);
 
3824
  if (old_windows)
 
3825
    XFree (old_windows);
 
3826
}
 
3827
 
 
3828
#define WARN_SHAPE_TOO_BIG() g_warning ("GdkWindow is too large to allow the use of shape masks or shape regions.")
 
3829
 
 
3830
/*
 
3831
 * This needs the X11 shape extension.
 
3832
 * If not available, shaped windows will look
 
3833
 * ugly, but programs still work.    Stefan Wille
 
3834
 */
 
3835
static void
 
3836
do_shape_combine_mask (GdkWindow *window,
 
3837
                       GdkBitmap *mask,
 
3838
                       gint       x, 
 
3839
                       gint       y,
 
3840
                       gint       shape)
 
3841
{
 
3842
  GdkWindowObject *private = (GdkWindowObject *)window;
 
3843
  Pixmap pixmap;
 
3844
  gint xoffset, yoffset;
 
3845
  
 
3846
  g_return_if_fail (GDK_IS_WINDOW (window));
 
3847
  
 
3848
#ifdef HAVE_SHAPE_EXT
 
3849
  if (GDK_WINDOW_DESTROYED (window))
 
3850
    return;
 
3851
 
 
3852
  _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
 
3853
 
 
3854
  if (xoffset != 0 || yoffset != 0)
 
3855
    {
 
3856
      WARN_SHAPE_TOO_BIG ();
 
3857
      return;
 
3858
    }
 
3859
  
 
3860
  if (shape == ShapeBounding
 
3861
      ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
 
3862
      : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
 
3863
    {
 
3864
      if (mask)
 
3865
        {
 
3866
          pixmap = GDK_PIXMAP_XID (mask);
 
3867
          
 
3868
          private->shaped = (shape == ShapeBounding);
 
3869
        }
 
3870
      else
 
3871
        {
 
3872
          x = 0;
 
3873
          y = 0;
 
3874
          pixmap = None;
 
3875
 
 
3876
          private->shaped = FALSE;
 
3877
        }
 
3878
      
 
3879
      XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
 
3880
                         GDK_WINDOW_XID (window),
 
3881
                         shape,
 
3882
                         x, y,
 
3883
                         pixmap,
 
3884
                         ShapeSet);
 
3885
    }
 
3886
#endif /* HAVE_SHAPE_EXT */
 
3887
}
 
3888
 
 
3889
/**
 
3890
 * gdk_window_shape_combine_mask:
 
3891
 * @window: a #GdkWindow
 
3892
 * @mask: shape mask
 
3893
 * @x: X position of shape mask with respect to @window
 
3894
 * @y: Y position of shape mask with respect to @window
 
3895
 *
 
3896
 * Applies a shape mask to @window. Pixels in @window corresponding to
 
3897
 * set bits in the @mask will be visible; pixels in @window
 
3898
 * corresponding to unset bits in the @mask will be transparent. This
 
3899
 * gives a non-rectangular window.
 
3900
 *
 
3901
 * If @mask is %NULL, the shape mask will be unset, and the @x/@y
 
3902
 * parameters are not used.
 
3903
 *
 
3904
 * On the X11 platform, this uses an X server extension which is
 
3905
 * widely available on most common platforms, but not available on
 
3906
 * very old X servers, and occasionally the implementation will be
 
3907
 * buggy. On servers without the shape extension, this function
 
3908
 * will do nothing.
 
3909
 *
 
3910
 * On the Win32 platform the functionality is always present.
 
3911
 *
 
3912
 * This function works on both toplevel and child windows.
 
3913
 * 
 
3914
 **/
 
3915
void
 
3916
gdk_window_shape_combine_mask (GdkWindow *window,
 
3917
                               GdkBitmap *mask,
 
3918
                               gint       x, 
 
3919
                               gint       y)
 
3920
{
 
3921
  do_shape_combine_mask (window, mask, x, y, ShapeBounding);
 
3922
}
 
3923
 
 
3924
/**
 
3925
 * gdk_window_input_shape_combine_mask:
 
3926
 * @window: a #GdkWindow
 
3927
 * @mask: shape mask
 
3928
 * @x: X position of shape mask with respect to @window
 
3929
 * @y: Y position of shape mask with respect to @window
 
3930
 * 
 
3931
 * Like gdk_window_shape_combine_mask(), but the shape applies
 
3932
 * only to event handling. Mouse events which happen while
 
3933
 * the pointer position corresponds to an unset bit in the 
 
3934
 * mask will be passed on the window below @window.
 
3935
 *
 
3936
 * An input shape is typically used with RGBA windows.
 
3937
 * The alpha channel of the window defines which pixels are 
 
3938
 * invisible and allows for nicely antialiased borders,
 
3939
 * and the input shape controls where the window is
 
3940
 * "clickable".
 
3941
 *
 
3942
 * On the X11 platform, this requires version 1.1 of the
 
3943
 * shape extension.
 
3944
 *
 
3945
 * On the Win32 platform, this functionality is not present and the
 
3946
 * function does nothing.
 
3947
 *
 
3948
 * Since: 2.10
 
3949
 */
 
3950
void 
 
3951
gdk_window_input_shape_combine_mask (GdkWindow *window,
 
3952
                                     GdkBitmap *mask,
 
3953
                                     gint       x,
 
3954
                                     gint       y)
 
3955
{
 
3956
#ifdef ShapeInput
 
3957
  do_shape_combine_mask (window, mask, x, y, ShapeInput);
 
3958
#endif
 
3959
}
 
3960
 
 
3961
 
 
3962
static void
 
3963
do_shape_combine_region (GdkWindow *window,
 
3964
                         GdkRegion *shape_region,
 
3965
                         gint       offset_x,
 
3966
                         gint       offset_y,
 
3967
                         gint       shape)
 
3968
{
 
3969
  GdkWindowObject *private = (GdkWindowObject *)window;
 
3970
  gint xoffset, yoffset;
 
3971
  
 
3972
  g_return_if_fail (GDK_IS_WINDOW (window));
 
3973
  
 
3974
#ifdef HAVE_SHAPE_EXT
 
3975
  if (GDK_WINDOW_DESTROYED (window))
 
3976
    return;
 
3977
 
 
3978
  _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
 
3979
 
 
3980
  if (xoffset != 0 || yoffset != 0)
 
3981
    {
 
3982
      WARN_SHAPE_TOO_BIG ();
 
3983
      return;
 
3984
    }
 
3985
  
 
3986
  if (shape_region == NULL)
 
3987
    {
 
3988
      /* Use NULL mask to unset the shape */
 
3989
      gdk_window_shape_combine_mask (window, NULL, 0, 0);
 
3990
      return;
 
3991
    }
 
3992
  
 
3993
  if (shape == ShapeBounding
 
3994
      ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
 
3995
      : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
 
3996
    {
 
3997
      gint n_rects = 0;
 
3998
      XRectangle *xrects = NULL;
 
3999
 
 
4000
      private->shaped = shape == ShapeBounding;
 
4001
 
 
4002
      _gdk_region_get_xrectangles (shape_region,
 
4003
                                   0, 0,
 
4004
                                   &xrects, &n_rects);
 
4005
      
 
4006
      XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
 
4007
                               GDK_WINDOW_XID (window),
 
4008
                               shape,
 
4009
                               offset_x, offset_y,
 
4010
                               xrects, n_rects,
 
4011
                               ShapeSet,
 
4012
                               YXBanded);
 
4013
 
 
4014
      g_free (xrects);
 
4015
    }
 
4016
#endif /* HAVE_SHAPE_EXT */
 
4017
}
 
4018
 
 
4019
/**
 
4020
 * gdk_window_shape_combine_region:
 
4021
 * @window: a #GdkWindow
 
4022
 * @shape_region: region of window to be non-transparent
 
4023
 * @offset_x: X position of @shape_region in @window coordinates
 
4024
 * @offset_y: Y position of @shape_region in @window coordinates
 
4025
 *
 
4026
 * Makes pixels in @window outside @shape_region be transparent,
 
4027
 * so that the window may be nonrectangular. See also
 
4028
 * gdk_window_shape_combine_mask() to use a bitmap as the mask.
 
4029
 *
 
4030
 * If @shape_region is %NULL, the shape will be unset, so the whole
 
4031
 * window will be opaque again. @offset_x and @offset_y are ignored
 
4032
 * if @shape_region is %NULL.
 
4033
 * 
 
4034
 * On the X11 platform, this uses an X server extension which is
 
4035
 * widely available on most common platforms, but not available on
 
4036
 * very old X servers, and occasionally the implementation will be
 
4037
 * buggy. On servers without the shape extension, this function
 
4038
 * will do nothing.
 
4039
 *
 
4040
 * On the Win32 platform, this functionality is always present.
 
4041
 *
 
4042
 * This function works on both toplevel and child windows.
 
4043
 * 
 
4044
 **/
 
4045
void
 
4046
gdk_window_shape_combine_region (GdkWindow *window,
 
4047
                                 GdkRegion *shape_region,
 
4048
                                 gint       offset_x,
 
4049
                                 gint       offset_y)
 
4050
 
4051
  do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
 
4052
}
 
4053
 
 
4054
/**
 
4055
 * gdk_window_input_shape_combine_region:
 
4056
 * @window: a #GdkWindow
 
4057
 * @shape_region: region of window to be non-transparent
 
4058
 * @offset_x: X position of @shape_region in @window coordinates
 
4059
 * @offset_y: Y position of @shape_region in @window coordinates
 
4060
 * 
 
4061
 * Like gdk_window_shape_combine_region(), but the shape applies
 
4062
 * only to event handling. Mouse events which happen while
 
4063
 * the pointer position corresponds to an unset bit in the 
 
4064
 * mask will be passed on the window below @window.
 
4065
 *
 
4066
 * An input shape is typically used with RGBA windows.
 
4067
 * The alpha channel of the window defines which pixels are 
 
4068
 * invisible and allows for nicely antialiased borders,
 
4069
 * and the input shape controls where the window is
 
4070
 * "clickable".
 
4071
 *
 
4072
 * On the X11 platform, this requires version 1.1 of the
 
4073
 * shape extension.
 
4074
 *
 
4075
 * On the Win32 platform, this functionality is not present and the
 
4076
 * function does nothing.
 
4077
 *
 
4078
 * Since: 2.10
 
4079
 */
 
4080
void 
 
4081
gdk_window_input_shape_combine_region (GdkWindow *window,
 
4082
                                       GdkRegion *shape_region,
 
4083
                                       gint       offset_x,
 
4084
                                       gint       offset_y)
 
4085
{
 
4086
#ifdef ShapeInput
 
4087
  do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
 
4088
#endif
 
4089
}
 
4090
 
 
4091
 
 
4092
/**
 
4093
 * gdk_window_set_override_redirect:
 
4094
 * @window: a toplevel #GdkWindow
 
4095
 * @override_redirect: %TRUE if window should be override redirect
 
4096
 *
 
4097
 * An override redirect window is not under the control of the window manager.
 
4098
 * This means it won't have a titlebar, won't be minimizable, etc. - it will
 
4099
 * be entirely under the control of the application. The window manager
 
4100
 * can't see the override redirect window at all.
 
4101
 *
 
4102
 * Override redirect should only be used for short-lived temporary
 
4103
 * windows, such as popup menus. #GtkMenu uses an override redirect
 
4104
 * window in its implementation, for example.
 
4105
 * 
 
4106
 **/
 
4107
void
 
4108
gdk_window_set_override_redirect (GdkWindow *window,
 
4109
                                  gboolean override_redirect)
 
4110
{
 
4111
  XSetWindowAttributes attr;
 
4112
  
 
4113
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4114
 
 
4115
  if (!GDK_WINDOW_DESTROYED (window))
 
4116
    {
 
4117
      GdkWindowObject *private = (GdkWindowObject *)window;
 
4118
      GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
 
4119
 
 
4120
      attr.override_redirect = (override_redirect? True : False);
 
4121
      XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
 
4122
                               GDK_WINDOW_XID (window),
 
4123
                               CWOverrideRedirect,
 
4124
                               &attr);
 
4125
 
 
4126
      impl->override_redirect = attr.override_redirect;
 
4127
    }
 
4128
}
 
4129
 
 
4130
/**
 
4131
 * gdk_window_set_accept_focus:
 
4132
 * @window: a toplevel #GdkWindow
 
4133
 * @accept_focus: %TRUE if the window should receive input focus
 
4134
 *
 
4135
 * Setting @accept_focus to %FALSE hints the desktop environment that the
 
4136
 * window doesn't want to receive input focus. 
 
4137
 *
 
4138
 * On X, it is the responsibility of the window manager to interpret this 
 
4139
 * hint. ICCCM-compliant window manager usually respect it.
 
4140
 *
 
4141
 * Since: 2.4 
 
4142
 **/
 
4143
void
 
4144
gdk_window_set_accept_focus (GdkWindow *window,
 
4145
                             gboolean accept_focus)
 
4146
{
 
4147
  GdkWindowObject *private;
 
4148
 
 
4149
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4150
 
 
4151
  private = (GdkWindowObject *)window;  
 
4152
  
 
4153
  accept_focus = accept_focus != FALSE;
 
4154
 
 
4155
  if (private->accept_focus != accept_focus)
 
4156
    {
 
4157
      private->accept_focus = accept_focus;
 
4158
 
 
4159
      if (!GDK_WINDOW_DESTROYED (window))
 
4160
        update_wm_hints (window, FALSE);
 
4161
    }
 
4162
}
 
4163
 
 
4164
/**
 
4165
 * gdk_window_set_focus_on_map:
 
4166
 * @window: a toplevel #GdkWindow
 
4167
 * @focus_on_map: %TRUE if the window should receive input focus when mapped
 
4168
 *
 
4169
 * Setting @focus_on_map to %FALSE hints the desktop environment that the
 
4170
 * window doesn't want to receive input focus when it is mapped.  
 
4171
 * focus_on_map should be turned off for windows that aren't triggered
 
4172
 * interactively (such as popups from network activity).
 
4173
 *
 
4174
 * On X, it is the responsibility of the window manager to interpret
 
4175
 * this hint. Window managers following the freedesktop.org window
 
4176
 * manager extension specification should respect it.
 
4177
 *
 
4178
 * Since: 2.6 
 
4179
 **/
 
4180
void
 
4181
gdk_window_set_focus_on_map (GdkWindow *window,
 
4182
                             gboolean focus_on_map)
 
4183
{
 
4184
  GdkWindowObject *private;
 
4185
 
 
4186
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4187
 
 
4188
  private = (GdkWindowObject *)window;  
 
4189
  
 
4190
  focus_on_map = focus_on_map != FALSE;
 
4191
 
 
4192
  if (private->focus_on_map != focus_on_map)
 
4193
    {
 
4194
      private->focus_on_map = focus_on_map;
 
4195
 
 
4196
      if ((!GDK_WINDOW_DESTROYED (window)) && (!private->focus_on_map))
 
4197
        gdk_x11_window_set_user_time (window, 0);
 
4198
    }
 
4199
}
 
4200
 
 
4201
/**
 
4202
 * gdk_x11_window_set_user_time:
 
4203
 * @window: A toplevel #GdkWindow
 
4204
 * @timestamp: An XServer timestamp to which the property should be set
 
4205
 *
 
4206
 * The application can use this call to update the _NET_WM_USER_TIME
 
4207
 * property on a toplevel window.  This property stores an Xserver
 
4208
 * time which represents the time of the last user input event
 
4209
 * received for this window.  This property may be used by the window
 
4210
 * manager to alter the focus, stacking, and/or placement behavior of
 
4211
 * windows when they are mapped depending on whether the new window
 
4212
 * was created by a user action or is a "pop-up" window activated by a
 
4213
 * timer or some other event.
 
4214
 *
 
4215
 * Note that this property is automatically updated by GDK, so this
 
4216
 * function should only be used by applications which handle input
 
4217
 * events bypassing GDK.
 
4218
 *
 
4219
 * Since: 2.6
 
4220
 **/
 
4221
void
 
4222
gdk_x11_window_set_user_time (GdkWindow *window,
 
4223
                              guint32    timestamp)
 
4224
{
 
4225
  GdkDisplay *display;
 
4226
  GdkDisplayX11 *display_x11;
 
4227
  GdkToplevelX11 *toplevel;
 
4228
  glong timestamp_long = (glong)timestamp;
 
4229
 
 
4230
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4231
 
 
4232
  if (GDK_WINDOW_DESTROYED (window))
 
4233
    return;
 
4234
 
 
4235
  display = gdk_drawable_get_display (window);
 
4236
  display_x11 = GDK_DISPLAY_X11 (display);
 
4237
  toplevel = _gdk_x11_window_get_toplevel (window);
 
4238
 
 
4239
  XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
 
4240
                   gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"),
 
4241
                   XA_CARDINAL, 32, PropModeReplace,
 
4242
                   (guchar *)&timestamp_long, 1);
 
4243
 
 
4244
  if (timestamp_long != GDK_CURRENT_TIME)
 
4245
    display_x11->user_time = timestamp_long;
 
4246
 
 
4247
  if (toplevel)
 
4248
    toplevel->user_time = timestamp_long;
 
4249
}
 
4250
 
 
4251
#define GDK_SELECTION_MAX_SIZE(display)                                 \
 
4252
  MIN(262144,                                                           \
 
4253
      XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0     \
 
4254
       ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100         \
 
4255
       : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
 
4256
 
 
4257
/**
 
4258
 * gdk_window_set_icon_list:
 
4259
 * @window: The #GdkWindow toplevel window to set the icon of.
 
4260
 * @pixbufs: A list of pixbufs, of different sizes.
 
4261
 *
 
4262
 * Sets a list of icons for the window. One of these will be used
 
4263
 * to represent the window when it has been iconified. The icon is
 
4264
 * usually shown in an icon box or some sort of task bar. Which icon
 
4265
 * size is shown depends on the window manager. The window manager
 
4266
 * can scale the icon  but setting several size icons can give better
 
4267
 * image quality since the window manager may only need to scale the
 
4268
 * icon by a small amount or not at all.
 
4269
 *
 
4270
 **/
 
4271
void
 
4272
gdk_window_set_icon_list (GdkWindow *window,
 
4273
                          GList     *pixbufs)
 
4274
{
 
4275
  gulong *data;
 
4276
  guchar *pixels;
 
4277
  gulong *p;
 
4278
  gint size;
 
4279
  GList *l;
 
4280
  GdkPixbuf *pixbuf;
 
4281
  gint width, height, stride;
 
4282
  gint x, y;
 
4283
  gint n_channels;
 
4284
  GdkDisplay *display;
 
4285
  gint n;
 
4286
  
 
4287
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4288
 
 
4289
  if (GDK_WINDOW_DESTROYED (window))
 
4290
    return;
 
4291
 
 
4292
  display = gdk_drawable_get_display (window);
 
4293
  
 
4294
  l = pixbufs;
 
4295
  size = 0;
 
4296
  n = 0;
 
4297
  while (l)
 
4298
    {
 
4299
      pixbuf = l->data;
 
4300
      g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
 
4301
 
 
4302
      width = gdk_pixbuf_get_width (pixbuf);
 
4303
      height = gdk_pixbuf_get_height (pixbuf);
 
4304
      
 
4305
      /* silently ignore overlarge icons */
 
4306
      if (size + 2 + width * height > GDK_SELECTION_MAX_SIZE(display))
 
4307
        {
 
4308
          g_warning ("gdk_window_set_icon_list: icons too large");
 
4309
          break;
 
4310
        }
 
4311
     
 
4312
      n++;
 
4313
      size += 2 + width * height;
 
4314
      
 
4315
      l = g_list_next (l);
 
4316
    }
 
4317
 
 
4318
  data = g_malloc (size * sizeof (gulong));
 
4319
 
 
4320
  l = pixbufs;
 
4321
  p = data;
 
4322
  while (l && n > 0)
 
4323
    {
 
4324
      pixbuf = l->data;
 
4325
      
 
4326
      width = gdk_pixbuf_get_width (pixbuf);
 
4327
      height = gdk_pixbuf_get_height (pixbuf);
 
4328
      stride = gdk_pixbuf_get_rowstride (pixbuf);
 
4329
      n_channels = gdk_pixbuf_get_n_channels (pixbuf);
 
4330
      
 
4331
      *p++ = width;
 
4332
      *p++ = height;
 
4333
 
 
4334
      pixels = gdk_pixbuf_get_pixels (pixbuf);
 
4335
 
 
4336
      for (y = 0; y < height; y++)
 
4337
        {
 
4338
          for (x = 0; x < width; x++)
 
4339
            {
 
4340
              guchar r, g, b, a;
 
4341
              
 
4342
              r = pixels[y*stride + x*n_channels + 0];
 
4343
              g = pixels[y*stride + x*n_channels + 1];
 
4344
              b = pixels[y*stride + x*n_channels + 2];
 
4345
              if (n_channels >= 4)
 
4346
                a = pixels[y*stride + x*n_channels + 3];
 
4347
              else
 
4348
                a = 255;
 
4349
              
 
4350
              *p++ = a << 24 | r << 16 | g << 8 | b ;
 
4351
            }
 
4352
        }
 
4353
 
 
4354
      l = g_list_next (l);
 
4355
      n--;
 
4356
    }
 
4357
 
 
4358
  if (size > 0)
 
4359
    {
 
4360
      XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
 
4361
                       GDK_WINDOW_XID (window),
 
4362
                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"),
 
4363
                       XA_CARDINAL, 32,
 
4364
                       PropModeReplace,
 
4365
                       (guchar*) data, size);
 
4366
    }
 
4367
  else
 
4368
    {
 
4369
      XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
 
4370
                       GDK_WINDOW_XID (window),
 
4371
                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"));
 
4372
    }
 
4373
  
 
4374
  g_free (data);
 
4375
}
 
4376
 
 
4377
/**
 
4378
 * gdk_window_set_icon:
 
4379
 * @window: a toplevel #GdkWindow
 
4380
 * @icon_window: a #GdkWindow to use for the icon, or %NULL to unset
 
4381
 * @pixmap: a #GdkPixmap to use as the icon, or %NULL to unset
 
4382
 * @mask: a 1-bit pixmap (#GdkBitmap) to use as mask for @pixmap, or %NULL to have none
 
4383
 *
 
4384
 * Sets the icon of @window as a pixmap or window. If using GTK+, investigate
 
4385
 * gtk_window_set_default_icon_list() first, and then gtk_window_set_icon_list()
 
4386
 * and gtk_window_set_icon(). If those don't meet your needs, look at
 
4387
 * gdk_window_set_icon_list(). Only if all those are too high-level do you
 
4388
 * want to fall back to gdk_window_set_icon().
 
4389
 * 
 
4390
 **/
 
4391
void          
 
4392
gdk_window_set_icon (GdkWindow *window, 
 
4393
                     GdkWindow *icon_window,
 
4394
                     GdkPixmap *pixmap,
 
4395
                     GdkBitmap *mask)
 
4396
{
 
4397
  GdkToplevelX11 *toplevel;
 
4398
 
 
4399
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4400
  g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
 
4401
  
 
4402
  if (GDK_WINDOW_DESTROYED (window))
 
4403
    return;
 
4404
 
 
4405
  toplevel = _gdk_x11_window_get_toplevel (window);
 
4406
 
 
4407
  if (toplevel->icon_window != icon_window)
 
4408
    {
 
4409
      if (toplevel->icon_window)
 
4410
        g_object_unref (toplevel->icon_window);
 
4411
      toplevel->icon_window = g_object_ref (icon_window);
 
4412
    }
 
4413
  
 
4414
  if (toplevel->icon_pixmap != pixmap)
 
4415
    {
 
4416
      if (pixmap)
 
4417
        g_object_ref (pixmap);
 
4418
      if (toplevel->icon_pixmap)
 
4419
        g_object_unref (toplevel->icon_pixmap);
 
4420
      toplevel->icon_pixmap = pixmap;
 
4421
    }
 
4422
  
 
4423
  if (toplevel->icon_mask != mask)
 
4424
    {
 
4425
      if (mask)
 
4426
        g_object_ref (mask);
 
4427
      if (toplevel->icon_mask)
 
4428
        g_object_unref (toplevel->icon_mask);
 
4429
      toplevel->icon_mask = mask;
 
4430
    }
 
4431
  
 
4432
  update_wm_hints (window, FALSE);
 
4433
}
 
4434
 
 
4435
static gboolean
 
4436
gdk_window_icon_name_set (GdkWindow *window)
 
4437
{
 
4438
  return GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (window),
 
4439
                                               g_quark_from_static_string ("gdk-icon-name-set")));
 
4440
}
 
4441
 
 
4442
/**
 
4443
 * gdk_window_set_icon_name:
 
4444
 * @window: a toplevel #GdkWindow
 
4445
 * @name: name of window while iconified (minimized)
 
4446
 *
 
4447
 * Windows may have a name used while minimized, distinct from the
 
4448
 * name they display in their titlebar. Most of the time this is a bad
 
4449
 * idea from a user interface standpoint. But you can set such a name
 
4450
 * with this function, if you like.
 
4451
 *
 
4452
 **/
 
4453
void          
 
4454
gdk_window_set_icon_name (GdkWindow   *window, 
 
4455
                          const gchar *name)
 
4456
{
 
4457
  GdkDisplay *display;
 
4458
  
 
4459
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4460
 
 
4461
  if (GDK_WINDOW_DESTROYED (window))
 
4462
    return;
 
4463
 
 
4464
  display = gdk_drawable_get_display (window);
 
4465
 
 
4466
  g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
 
4467
                      GUINT_TO_POINTER (TRUE));
 
4468
 
 
4469
  XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
 
4470
                   GDK_WINDOW_XID (window),
 
4471
                   gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
 
4472
                   gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
 
4473
                   PropModeReplace, (guchar *)name, strlen (name));
 
4474
  
 
4475
  set_text_property (display, GDK_WINDOW_XID (window),
 
4476
                     gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
 
4477
                     name);
 
4478
}
 
4479
 
 
4480
/**
 
4481
 * gdk_window_iconify:
 
4482
 * @window: a toplevel #GdkWindow
 
4483
 * 
 
4484
 * Asks to iconify (minimize) @window. The window manager may choose
 
4485
 * to ignore the request, but normally will honor it. Using
 
4486
 * gtk_window_iconify() is preferred, if you have a #GtkWindow widget.
 
4487
 *
 
4488
 * This function only makes sense when @window is a toplevel window.
 
4489
 *
 
4490
 **/
 
4491
void
 
4492
gdk_window_iconify (GdkWindow *window)
 
4493
{
 
4494
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4495
 
 
4496
  if (GDK_WINDOW_DESTROYED (window))
 
4497
    return;
 
4498
 
 
4499
  if (GDK_WINDOW_IS_MAPPED (window))
 
4500
    {  
 
4501
      XIconifyWindow (GDK_WINDOW_XDISPLAY (window),
 
4502
                      GDK_WINDOW_XWINDOW (window),
 
4503
                      gdk_screen_get_number (GDK_WINDOW_SCREEN (window)));
 
4504
    }
 
4505
  else
 
4506
    {
 
4507
      /* Flip our client side flag, the real work happens on map. */
 
4508
      gdk_synthesize_window_state (window,
 
4509
                                   0,
 
4510
                                   GDK_WINDOW_STATE_ICONIFIED);
 
4511
    }
 
4512
}
 
4513
 
 
4514
/**
 
4515
 * gdk_window_deiconify:
 
4516
 * @window: a toplevel #GdkWindow
 
4517
 *
 
4518
 * Attempt to deiconify (unminimize) @window. On X11 the window manager may
 
4519
 * choose to ignore the request to deiconify. When using GTK+,
 
4520
 * use gtk_window_deiconify() instead of the #GdkWindow variant. Or better yet,
 
4521
 * you probably want to use gtk_window_present(), which raises the window, focuses it,
 
4522
 * unminimizes it, and puts it on the current desktop.
 
4523
 *
 
4524
 **/
 
4525
void
 
4526
gdk_window_deiconify (GdkWindow *window)
 
4527
{
 
4528
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4529
 
 
4530
  if (GDK_WINDOW_DESTROYED (window))
 
4531
    return;
 
4532
 
 
4533
  if (GDK_WINDOW_IS_MAPPED (window))
 
4534
    {  
 
4535
      gdk_window_show (window);
 
4536
    }
 
4537
  else
 
4538
    {
 
4539
      /* Flip our client side flag, the real work happens on map. */
 
4540
      gdk_synthesize_window_state (window,
 
4541
                                   GDK_WINDOW_STATE_ICONIFIED,
 
4542
                                   0);
 
4543
    }
 
4544
}
 
4545
 
 
4546
/**
 
4547
 * gdk_window_stick:
 
4548
 * @window: a toplevel #GdkWindow
 
4549
 *
 
4550
 * "Pins" a window such that it's on all workspaces and does not scroll
 
4551
 * with viewports, for window managers that have scrollable viewports.
 
4552
 * (When using #GtkWindow, gtk_window_stick() may be more useful.)
 
4553
 *
 
4554
 * On the X11 platform, this function depends on window manager
 
4555
 * support, so may have no effect with many window managers. However,
 
4556
 * GDK will do the best it can to convince the window manager to stick
 
4557
 * the window. For window managers that don't support this operation,
 
4558
 * there's nothing you can do to force it to happen.
 
4559
 * 
 
4560
 **/
 
4561
void
 
4562
gdk_window_stick (GdkWindow *window)
 
4563
{
 
4564
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4565
 
 
4566
  if (GDK_WINDOW_DESTROYED (window))
 
4567
    return;
 
4568
 
 
4569
  if (GDK_WINDOW_IS_MAPPED (window))
 
4570
    {
 
4571
      /* "stick" means stick to all desktops _and_ do not scroll with the
 
4572
       * viewport. i.e. glue to the monitor glass in all cases.
 
4573
       */
 
4574
      
 
4575
      XClientMessageEvent xclient;
 
4576
 
 
4577
      /* Request stick during viewport scroll */
 
4578
      gdk_wmspec_change_state (TRUE, window,
 
4579
                               gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
 
4580
                               NULL);
 
4581
 
 
4582
      /* Request desktop 0xFFFFFFFF */
 
4583
      memset (&xclient, 0, sizeof (xclient));
 
4584
      xclient.type = ClientMessage;
 
4585
      xclient.window = GDK_WINDOW_XWINDOW (window);
 
4586
      xclient.display = GDK_WINDOW_XDISPLAY (window);
 
4587
      xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), 
 
4588
                                                                        "_NET_WM_DESKTOP");
 
4589
      xclient.format = 32;
 
4590
 
 
4591
      xclient.data.l[0] = 0xFFFFFFFF;
 
4592
      xclient.data.l[1] = 0;
 
4593
      xclient.data.l[2] = 0;
 
4594
      xclient.data.l[3] = 0;
 
4595
      xclient.data.l[4] = 0;
 
4596
 
 
4597
      XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
 
4598
                  SubstructureRedirectMask | SubstructureNotifyMask,
 
4599
                  (XEvent *)&xclient);
 
4600
    }
 
4601
  else
 
4602
    {
 
4603
      /* Flip our client side flag, the real work happens on map. */
 
4604
      gdk_synthesize_window_state (window,
 
4605
                                   0,
 
4606
                                   GDK_WINDOW_STATE_STICKY);
 
4607
    }
 
4608
}
 
4609
 
 
4610
/**
 
4611
 * gdk_window_unstick:
 
4612
 * @window: a toplevel #GdkWindow
 
4613
 *
 
4614
 * Reverse operation for gdk_window_stick(); see gdk_window_stick(),
 
4615
 * and gtk_window_unstick().
 
4616
 * 
 
4617
 **/
 
4618
void
 
4619
gdk_window_unstick (GdkWindow *window)
 
4620
{
 
4621
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4622
 
 
4623
  if (GDK_WINDOW_DESTROYED (window))
 
4624
    return;
 
4625
 
 
4626
  if (GDK_WINDOW_IS_MAPPED (window))
 
4627
    {
 
4628
      /* Request unstick from viewport */
 
4629
      gdk_wmspec_change_state (FALSE, window,
 
4630
                               gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
 
4631
                               NULL);
 
4632
 
 
4633
      move_to_current_desktop (window);
 
4634
    }
 
4635
  else
 
4636
    {
 
4637
      /* Flip our client side flag, the real work happens on map. */
 
4638
      gdk_synthesize_window_state (window,
 
4639
                                   GDK_WINDOW_STATE_STICKY,
 
4640
                                   0);
 
4641
 
 
4642
    }
 
4643
}
 
4644
 
 
4645
/**
 
4646
 * gdk_window_maximize:
 
4647
 * @window: a toplevel #GdkWindow
 
4648
 *
 
4649
 * Maximizes the window. If the window was already maximized, then
 
4650
 * this function does nothing.
 
4651
 * 
 
4652
 * On X11, asks the window manager to maximize @window, if the window
 
4653
 * manager supports this operation. Not all window managers support
 
4654
 * this, and some deliberately ignore it or don't have a concept of
 
4655
 * "maximized"; so you can't rely on the maximization actually
 
4656
 * happening. But it will happen with most standard window managers,
 
4657
 * and GDK makes a best effort to get it to happen.
 
4658
 *
 
4659
 * On Windows, reliably maximizes the window.
 
4660
 * 
 
4661
 **/
 
4662
void
 
4663
gdk_window_maximize (GdkWindow *window)
 
4664
{
 
4665
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4666
 
 
4667
  if (GDK_WINDOW_DESTROYED (window))
 
4668
    return;
 
4669
 
 
4670
  if (GDK_WINDOW_IS_MAPPED (window))
 
4671
    gdk_wmspec_change_state (TRUE, window,
 
4672
                             gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
 
4673
                             gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
 
4674
  else
 
4675
    gdk_synthesize_window_state (window,
 
4676
                                 0,
 
4677
                                 GDK_WINDOW_STATE_MAXIMIZED);
 
4678
}
 
4679
 
 
4680
/**
 
4681
 * gdk_window_unmaximize:
 
4682
 * @window: a toplevel #GdkWindow
 
4683
 *
 
4684
 * Unmaximizes the window. If the window wasn't maximized, then this
 
4685
 * function does nothing.
 
4686
 * 
 
4687
 * On X11, asks the window manager to unmaximize @window, if the
 
4688
 * window manager supports this operation. Not all window managers
 
4689
 * support this, and some deliberately ignore it or don't have a
 
4690
 * concept of "maximized"; so you can't rely on the unmaximization
 
4691
 * actually happening. But it will happen with most standard window
 
4692
 * managers, and GDK makes a best effort to get it to happen.
 
4693
 *
 
4694
 * On Windows, reliably unmaximizes the window.
 
4695
 * 
 
4696
 **/
 
4697
void
 
4698
gdk_window_unmaximize (GdkWindow *window)
 
4699
{
 
4700
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4701
 
 
4702
  if (GDK_WINDOW_DESTROYED (window))
 
4703
    return;
 
4704
 
 
4705
  if (GDK_WINDOW_IS_MAPPED (window))
 
4706
    gdk_wmspec_change_state (FALSE, window,
 
4707
                             gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
 
4708
                             gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
 
4709
  else
 
4710
    gdk_synthesize_window_state (window,
 
4711
                                 GDK_WINDOW_STATE_MAXIMIZED,
 
4712
                                 0);
 
4713
}
 
4714
 
 
4715
/**
 
4716
 * gdk_window_fullscreen:
 
4717
 * @window: a toplevel #GdkWindow
 
4718
 *
 
4719
 * Moves the window into fullscreen mode. This means the
 
4720
 * window covers the entire screen and is above any panels
 
4721
 * or task bars.
 
4722
 *
 
4723
 * If the window was already fullscreen, then this function does nothing.
 
4724
 * 
 
4725
 * On X11, asks the window manager to put @window in a fullscreen
 
4726
 * state, if the window manager supports this operation. Not all
 
4727
 * window managers support this, and some deliberately ignore it or
 
4728
 * don't have a concept of "fullscreen"; so you can't rely on the
 
4729
 * fullscreenification actually happening. But it will happen with
 
4730
 * most standard window managers, and GDK makes a best effort to get
 
4731
 * it to happen.
 
4732
 *
 
4733
 * Since: 2.2
 
4734
 **/
 
4735
void
 
4736
gdk_window_fullscreen (GdkWindow *window)
 
4737
{
 
4738
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4739
 
 
4740
  if (GDK_WINDOW_DESTROYED (window))
 
4741
    return;
 
4742
 
 
4743
  if (GDK_WINDOW_IS_MAPPED (window))
 
4744
    gdk_wmspec_change_state (TRUE, window,
 
4745
                             gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
 
4746
                             GDK_NONE);
 
4747
 
 
4748
  else
 
4749
    gdk_synthesize_window_state (window,
 
4750
                                 0,
 
4751
                                 GDK_WINDOW_STATE_FULLSCREEN);
 
4752
}
 
4753
 
 
4754
/**
 
4755
 * gdk_window_unfullscreen:
 
4756
 * @window: a toplevel #GdkWindow
 
4757
 *
 
4758
 * Moves the window out of fullscreen mode. If the window was not
 
4759
 * fullscreen, does nothing.
 
4760
 * 
 
4761
 * On X11, asks the window manager to move @window out of the fullscreen
 
4762
 * state, if the window manager supports this operation. Not all
 
4763
 * window managers support this, and some deliberately ignore it or
 
4764
 * don't have a concept of "fullscreen"; so you can't rely on the
 
4765
 * unfullscreenification actually happening. But it will happen with
 
4766
 * most standard window managers, and GDK makes a best effort to get
 
4767
 * it to happen. 
 
4768
 *
 
4769
 * Since: 2.2
 
4770
 **/
 
4771
void
 
4772
gdk_window_unfullscreen (GdkWindow *window)
 
4773
{
 
4774
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4775
 
 
4776
  if (GDK_WINDOW_DESTROYED (window))
 
4777
    return;
 
4778
 
 
4779
  if (GDK_WINDOW_IS_MAPPED (window))
 
4780
    gdk_wmspec_change_state (FALSE, window,
 
4781
                             gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
 
4782
                             GDK_NONE);
 
4783
 
 
4784
  else
 
4785
    gdk_synthesize_window_state (window,
 
4786
                                 GDK_WINDOW_STATE_FULLSCREEN,
 
4787
                                 0);
 
4788
}
 
4789
 
 
4790
/**
 
4791
 * gdk_window_set_keep_above:
 
4792
 * @window: a toplevel #GdkWindow
 
4793
 * @setting: whether to keep @window above other windows
 
4794
 *
 
4795
 * Set if @window must be kept above other windows. If the
 
4796
 * window was already above, then this function does nothing.
 
4797
 * 
 
4798
 * On X11, asks the window manager to keep @window above, if the window
 
4799
 * manager supports this operation. Not all window managers support
 
4800
 * this, and some deliberately ignore it or don't have a concept of
 
4801
 * "keep above"; so you can't rely on the window being kept above.
 
4802
 * But it will happen with most standard window managers,
 
4803
 * and GDK makes a best effort to get it to happen.
 
4804
 *
 
4805
 * Since: 2.4
 
4806
 **/
 
4807
void
 
4808
gdk_window_set_keep_above (GdkWindow *window, gboolean setting)
 
4809
{
 
4810
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4811
 
 
4812
  if (GDK_WINDOW_DESTROYED (window))
 
4813
    return;
 
4814
 
 
4815
  if (GDK_WINDOW_IS_MAPPED (window))
 
4816
    {
 
4817
      if (setting)
 
4818
        gdk_wmspec_change_state (FALSE, window,
 
4819
                                 gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
 
4820
                                 GDK_NONE);
 
4821
      gdk_wmspec_change_state (setting, window,
 
4822
                               gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
 
4823
                               GDK_NONE);
 
4824
    }
 
4825
  else
 
4826
    gdk_synthesize_window_state (window,
 
4827
                                 setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
 
4828
                                 setting ? GDK_WINDOW_STATE_ABOVE : 0);
 
4829
}
 
4830
 
 
4831
/**
 
4832
 * gdk_window_set_keep_below:
 
4833
 * @window: a toplevel #GdkWindow
 
4834
 * @setting: whether to keep @window below other windows
 
4835
 *
 
4836
 * Set if @window must be kept below other windows. If the
 
4837
 * window was already below, then this function does nothing.
 
4838
 * 
 
4839
 * On X11, asks the window manager to keep @window below, if the window
 
4840
 * manager supports this operation. Not all window managers support
 
4841
 * this, and some deliberately ignore it or don't have a concept of
 
4842
 * "keep below"; so you can't rely on the window being kept below.
 
4843
 * But it will happen with most standard window managers,
 
4844
 * and GDK makes a best effort to get it to happen.
 
4845
 *
 
4846
 * Since: 2.4
 
4847
 **/
 
4848
void
 
4849
gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
 
4850
{
 
4851
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4852
 
 
4853
  if (GDK_WINDOW_DESTROYED (window))
 
4854
    return;
 
4855
 
 
4856
  if (GDK_WINDOW_IS_MAPPED (window))
 
4857
    {
 
4858
      if (setting)
 
4859
        gdk_wmspec_change_state (FALSE, window,
 
4860
                                 gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
 
4861
                                 GDK_NONE);
 
4862
      gdk_wmspec_change_state (setting, window,
 
4863
                               gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
 
4864
                               GDK_NONE);
 
4865
    }
 
4866
  else
 
4867
    gdk_synthesize_window_state (window,
 
4868
                                 setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
 
4869
                                 setting ? GDK_WINDOW_STATE_BELOW : 0);
 
4870
}
 
4871
 
 
4872
/**
 
4873
 * gdk_window_get_group:
 
4874
 * @window: a toplevel #GdkWindow
 
4875
 * 
 
4876
 * Returns the group leader window for @window. See gdk_window_set_group().
 
4877
 * 
 
4878
 * Return value: the group leader window for @window
 
4879
 *
 
4880
 * Since: 2.4
 
4881
 **/
 
4882
GdkWindow *
 
4883
gdk_window_get_group (GdkWindow *window)
 
4884
{
 
4885
  GdkToplevelX11 *toplevel;
 
4886
  
 
4887
  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
4888
  g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
 
4889
 
 
4890
  if (GDK_WINDOW_DESTROYED (window))
 
4891
    return NULL;
 
4892
  
 
4893
  toplevel = _gdk_x11_window_get_toplevel (window);
 
4894
 
 
4895
  return toplevel->group_leader;
 
4896
}
 
4897
 
 
4898
/**
 
4899
 * gdk_window_set_group:
 
4900
 * @window: a toplevel #GdkWindow
 
4901
 * @leader: group leader window, or %NULL to restore the default group leader window
 
4902
 *
 
4903
 * Sets the group leader window for @window. By default,
 
4904
 * GDK sets the group leader for all toplevel windows
 
4905
 * to a global window implicitly created by GDK. With this function
 
4906
 * you can override this default.
 
4907
 *
 
4908
 * The group leader window allows the window manager to distinguish
 
4909
 * all windows that belong to a single application. It may for example
 
4910
 * allow users to minimize/unminimize all windows belonging to an
 
4911
 * application at once. You should only set a non-default group window
 
4912
 * if your application pretends to be multiple applications.
 
4913
 **/
 
4914
void          
 
4915
gdk_window_set_group (GdkWindow *window, 
 
4916
                      GdkWindow *leader)
 
4917
{
 
4918
  GdkToplevelX11 *toplevel;
 
4919
  
 
4920
  g_return_if_fail (GDK_IS_WINDOW (window));
 
4921
  g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
 
4922
  g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
 
4923
 
 
4924
  if (GDK_WINDOW_DESTROYED (window) || (leader != NULL && GDK_WINDOW_DESTROYED (leader)))
 
4925
    return;
 
4926
 
 
4927
  toplevel = _gdk_x11_window_get_toplevel (window);
 
4928
 
 
4929
  if (leader == NULL) 
 
4930
    leader = gdk_display_get_default_group (gdk_drawable_get_display (window));
 
4931
  
 
4932
  if (toplevel->group_leader != leader)
 
4933
    {
 
4934
      if (toplevel->group_leader)
 
4935
        g_object_unref (toplevel->group_leader);
 
4936
      toplevel->group_leader = g_object_ref (leader);
 
4937
      (_gdk_x11_window_get_toplevel (leader))->is_leader = TRUE;      
 
4938
    }
 
4939
 
 
4940
  update_wm_hints (window, FALSE);
 
4941
}
 
4942
 
 
4943
static MotifWmHints *
 
4944
gdk_window_get_mwm_hints (GdkWindow *window)
 
4945
{
 
4946
  GdkDisplay *display;
 
4947
  Atom hints_atom = None;
 
4948
  guchar *data;
 
4949
  Atom type;
 
4950
  gint format;
 
4951
  gulong nitems;
 
4952
  gulong bytes_after;
 
4953
  
 
4954
  if (GDK_WINDOW_DESTROYED (window))
 
4955
    return NULL;
 
4956
 
 
4957
  display = gdk_drawable_get_display (window);
 
4958
  
 
4959
  hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
 
4960
 
 
4961
  XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
 
4962
                      hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
 
4963
                      False, AnyPropertyType, &type, &format, &nitems,
 
4964
                      &bytes_after, &data);
 
4965
 
 
4966
  if (type == None)
 
4967
    return NULL;
 
4968
  
 
4969
  return (MotifWmHints *)data;
 
4970
}
 
4971
 
 
4972
static void
 
4973
gdk_window_set_mwm_hints (GdkWindow *window,
 
4974
                          MotifWmHints *new_hints)
 
4975
{
 
4976
  GdkDisplay *display;
 
4977
  Atom hints_atom = None;
 
4978
  guchar *data;
 
4979
  MotifWmHints *hints;
 
4980
  Atom type;
 
4981
  gint format;
 
4982
  gulong nitems;
 
4983
  gulong bytes_after;
 
4984
  
 
4985
  if (GDK_WINDOW_DESTROYED (window))
 
4986
    return;
 
4987
  
 
4988
  display = gdk_drawable_get_display (window);
 
4989
  
 
4990
  hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
 
4991
 
 
4992
  XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
 
4993
                      hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
 
4994
                      False, AnyPropertyType, &type, &format, &nitems,
 
4995
                      &bytes_after, &data);
 
4996
  
 
4997
  if (type == None)
 
4998
    hints = new_hints;
 
4999
  else
 
5000
    {
 
5001
      hints = (MotifWmHints *)data;
 
5002
        
 
5003
      if (new_hints->flags & MWM_HINTS_FUNCTIONS)
 
5004
        {
 
5005
          hints->flags |= MWM_HINTS_FUNCTIONS;
 
5006
          hints->functions = new_hints->functions;
 
5007
        }
 
5008
      if (new_hints->flags & MWM_HINTS_DECORATIONS)
 
5009
        {
 
5010
          hints->flags |= MWM_HINTS_DECORATIONS;
 
5011
          hints->decorations = new_hints->decorations;
 
5012
        }
 
5013
    }
 
5014
  
 
5015
  XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
 
5016
                   hints_atom, hints_atom, 32, PropModeReplace,
 
5017
                   (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
 
5018
  
 
5019
  if (hints != new_hints)
 
5020
    XFree (hints);
 
5021
}
 
5022
 
 
5023
/**
 
5024
 * gdk_window_set_decorations:
 
5025
 * @window: a toplevel #GdkWindow
 
5026
 * @decorations: decoration hint mask
 
5027
 *
 
5028
 * "Decorations" are the features the window manager adds to a toplevel #GdkWindow.
 
5029
 * This function sets the traditional Motif window manager hints that tell the
 
5030
 * window manager which decorations you would like your window to have.
 
5031
 * Usually you should use gtk_window_set_decorated() on a #GtkWindow instead of
 
5032
 * using the GDK function directly.
 
5033
 *
 
5034
 * The @decorations argument is the logical OR of the fields in
 
5035
 * the #GdkWMDecoration enumeration. If #GDK_DECOR_ALL is included in the
 
5036
 * mask, the other bits indicate which decorations should be turned off.
 
5037
 * If #GDK_DECOR_ALL is not included, then the other bits indicate
 
5038
 * which decorations should be turned on.
 
5039
 *
 
5040
 * Most window managers honor a decorations hint of 0 to disable all decorations,
 
5041
 * but very few honor all possible combinations of bits.
 
5042
 * 
 
5043
 **/
 
5044
void
 
5045
gdk_window_set_decorations (GdkWindow      *window,
 
5046
                            GdkWMDecoration decorations)
 
5047
{
 
5048
  MotifWmHints hints;
 
5049
  
 
5050
  g_return_if_fail (GDK_IS_WINDOW (window));
 
5051
  
 
5052
  /* initialize to zero to avoid writing uninitialized data to socket */
 
5053
  memset(&hints, 0, sizeof(hints));
 
5054
  hints.flags = MWM_HINTS_DECORATIONS;
 
5055
  hints.decorations = decorations;
 
5056
  
 
5057
  gdk_window_set_mwm_hints (window, &hints);
 
5058
}
 
5059
 
 
5060
/**
 
5061
 * gdk_window_get_decorations:
 
5062
 * @window: The toplevel #GdkWindow to get the decorations from
 
5063
 * @decorations: The window decorations will be written here
 
5064
 *
 
5065
 * Returns the decorations set on the GdkWindow with #gdk_window_set_decorations
 
5066
 * Returns: TRUE if the window has decorations set, FALSE otherwise.
 
5067
 **/
 
5068
gboolean
 
5069
gdk_window_get_decorations(GdkWindow       *window,
 
5070
                           GdkWMDecoration *decorations)
 
5071
{
 
5072
  MotifWmHints *hints;
 
5073
  gboolean result = FALSE;
 
5074
 
 
5075
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
5076
 
 
5077
  hints = gdk_window_get_mwm_hints (window);
 
5078
  
 
5079
  if (hints)
 
5080
    {
 
5081
      if (hints->flags & MWM_HINTS_DECORATIONS)
 
5082
        {
 
5083
          if (decorations)
 
5084
            *decorations = hints->decorations;
 
5085
          result = TRUE;
 
5086
        }
 
5087
      
 
5088
      XFree (hints);
 
5089
    }
 
5090
 
 
5091
  return result;
 
5092
}
 
5093
 
 
5094
/**
 
5095
 * gdk_window_set_functions:
 
5096
 * @window: a toplevel #GdkWindow
 
5097
 * @functions: bitmask of operations to allow on @window
 
5098
 *
 
5099
 * Sets hints about the window management functions to make available
 
5100
 * via buttons on the window frame.
 
5101
 * 
 
5102
 * On the X backend, this function sets the traditional Motif window 
 
5103
 * manager hint for this purpose. However, few window managers do
 
5104
 * anything reliable or interesting with this hint. Many ignore it
 
5105
 * entirely.
 
5106
 *
 
5107
 * The @functions argument is the logical OR of values from the
 
5108
 * #GdkWMFunction enumeration. If the bitmask includes #GDK_FUNC_ALL,
 
5109
 * then the other bits indicate which functions to disable; if
 
5110
 * it doesn't include #GDK_FUNC_ALL, it indicates which functions to
 
5111
 * enable.
 
5112
 * 
 
5113
 **/
 
5114
void
 
5115
gdk_window_set_functions (GdkWindow    *window,
 
5116
                          GdkWMFunction functions)
 
5117
{
 
5118
  MotifWmHints hints;
 
5119
  
 
5120
  g_return_if_fail (GDK_IS_WINDOW (window));
 
5121
  
 
5122
  /* initialize to zero to avoid writing uninitialized data to socket */
 
5123
  memset(&hints, 0, sizeof(hints));
 
5124
  hints.flags = MWM_HINTS_FUNCTIONS;
 
5125
  hints.functions = functions;
 
5126
  
 
5127
  gdk_window_set_mwm_hints (window, &hints);
 
5128
}
 
5129
 
 
5130
#ifdef HAVE_SHAPE_EXT
 
5131
 
 
5132
/* 
 
5133
 * propagate the shapes from all child windows of a GDK window to the parent 
 
5134
 * window. Shamelessly ripped from Enlightenment's code
 
5135
 * 
 
5136
 * - Raster
 
5137
 */
 
5138
struct _gdk_span
 
5139
{
 
5140
  gint                start;
 
5141
  gint                end;
 
5142
  struct _gdk_span    *next;
 
5143
};
 
5144
 
 
5145
static void
 
5146
gdk_add_to_span (struct _gdk_span **s,
 
5147
                 gint               x,
 
5148
                 gint               xx)
 
5149
{
 
5150
  struct _gdk_span *ptr1, *ptr2, *noo, *ss;
 
5151
  gchar             spanning;
 
5152
  
 
5153
  ptr2 = NULL;
 
5154
  ptr1 = *s;
 
5155
  spanning = 0;
 
5156
  ss = NULL;
 
5157
  /* scan the spans for this line */
 
5158
  while (ptr1)
 
5159
    {
 
5160
      /* -- -> new span */
 
5161
      /* == -> existing span */
 
5162
      /* ## -> spans intersect */
 
5163
      /* if we are in the middle of spanning the span into the line */
 
5164
      if (spanning)
 
5165
        {
 
5166
          /* case: ---- ==== */
 
5167
          if (xx < ptr1->start - 1)
 
5168
            {
 
5169
              /* ends before next span - extend to here */
 
5170
              ss->end = xx;
 
5171
              return;
 
5172
            }
 
5173
          /* case: ----##=== */
 
5174
          else if (xx <= ptr1->end)
 
5175
            {
 
5176
              /* crosses into next span - delete next span and append */
 
5177
              ss->end = ptr1->end;
 
5178
              ss->next = ptr1->next;
 
5179
              g_free (ptr1);
 
5180
              return;
 
5181
            }
 
5182
          /* case: ---###--- */
 
5183
          else
 
5184
            {
 
5185
              /* overlaps next span - delete and keep checking */
 
5186
              ss->next = ptr1->next;
 
5187
              g_free (ptr1);
 
5188
              ptr1 = ss;
 
5189
            }
 
5190
        }
 
5191
      /* otherwise havent started spanning it in yet */
 
5192
      else
 
5193
        {
 
5194
          /* case: ---- ==== */
 
5195
          if (xx < ptr1->start - 1)
 
5196
            {
 
5197
              /* insert span here in list */
 
5198
              noo = g_malloc (sizeof (struct _gdk_span));
 
5199
              
 
5200
              if (noo)
 
5201
                {
 
5202
                  noo->start = x;
 
5203
                  noo->end = xx;
 
5204
                  noo->next = ptr1;
 
5205
                  if (ptr2)
 
5206
                    ptr2->next = noo;
 
5207
                  else
 
5208
                    *s = noo;
 
5209
                }
 
5210
              return;
 
5211
            }
 
5212
          /* case: ----##=== */
 
5213
          else if ((x < ptr1->start) && (xx <= ptr1->end))
 
5214
            {
 
5215
              /* expand this span to the left point of the new one */
 
5216
              ptr1->start = x;
 
5217
              return;
 
5218
            }
 
5219
          /* case: ===###=== */
 
5220
          else if ((x >= ptr1->start) && (xx <= ptr1->end))
 
5221
            {
 
5222
              /* throw the span away */
 
5223
              return;
 
5224
            }
 
5225
          /* case: ---###--- */
 
5226
          else if ((x < ptr1->start) && (xx > ptr1->end))
 
5227
            {
 
5228
              ss = ptr1;
 
5229
              spanning = 1;
 
5230
              ptr1->start = x;
 
5231
              ptr1->end = xx;
 
5232
            }
 
5233
          /* case: ===##---- */
 
5234
          else if ((x >= ptr1->start) && (x <= ptr1->end + 1) && (xx > ptr1->end))
 
5235
            {
 
5236
              ss = ptr1;
 
5237
              spanning = 1;
 
5238
              ptr1->end = xx;
 
5239
            }
 
5240
          /* case: ==== ---- */
 
5241
          /* case handled by next loop iteration - first case */
 
5242
        }
 
5243
      ptr2 = ptr1;
 
5244
      ptr1 = ptr1->next;
 
5245
    }
 
5246
  /* it started in the middle but spans beyond your current list */
 
5247
  if (spanning)
 
5248
    {
 
5249
      ptr2->end = xx;
 
5250
      return;
 
5251
    }
 
5252
  /* it does not start inside a span or in the middle, so add it to the end */
 
5253
  noo = g_malloc (sizeof (struct _gdk_span));
 
5254
  
 
5255
  if (noo)
 
5256
    {
 
5257
      noo->start = x;
 
5258
      noo->end = xx;
 
5259
      if (ptr2)
 
5260
        {
 
5261
          noo->next = ptr2->next;
 
5262
          ptr2->next = noo;
 
5263
        }
 
5264
      else
 
5265
        {
 
5266
          noo->next = NULL;
 
5267
          *s = noo;
 
5268
        }
 
5269
    }
 
5270
  return;
 
5271
}
 
5272
 
 
5273
static void
 
5274
gdk_add_rectangles (Display           *disp,
 
5275
                    Window             win,
 
5276
                    struct _gdk_span **spans,
 
5277
                    gint               basew,
 
5278
                    gint               baseh,
 
5279
                    gint               x,
 
5280
                    gint               y)
 
5281
{
 
5282
  gint a, k;
 
5283
  gint x1, y1, x2, y2;
 
5284
  gint rn, ord;
 
5285
  XRectangle *rl;
 
5286
  
 
5287
  rl = XShapeGetRectangles (disp, win, ShapeBounding, &rn, &ord);
 
5288
  if (rl)
 
5289
    {
 
5290
      /* go through all clip rects in this window's shape */
 
5291
      for (k = 0; k < rn; k++)
 
5292
        {
 
5293
          /* for each clip rect, add it to each line's spans */
 
5294
          x1 = x + rl[k].x;
 
5295
          x2 = x + rl[k].x + (rl[k].width - 1);
 
5296
          y1 = y + rl[k].y;
 
5297
          y2 = y + rl[k].y + (rl[k].height - 1);
 
5298
          if (x1 < 0)
 
5299
            x1 = 0;
 
5300
          if (y1 < 0)
 
5301
            y1 = 0;
 
5302
          if (x2 >= basew)
 
5303
            x2 = basew - 1;
 
5304
          if (y2 >= baseh)
 
5305
            y2 = baseh - 1;
 
5306
          for (a = y1; a <= y2; a++)
 
5307
            {
 
5308
              if ((x2 - x1) >= 0)
 
5309
                gdk_add_to_span (&spans[a], x1, x2);
 
5310
            }
 
5311
        }
 
5312
      XFree (rl);
 
5313
    }
 
5314
}
 
5315
 
 
5316
static void
 
5317
gdk_propagate_shapes (Display *disp,
 
5318
                      Window   win,
 
5319
                      gboolean merge,
 
5320
                      int      shape)
 
5321
{
 
5322
  Window              rt, par, *list = NULL;
 
5323
  gint                i, j, num = 0, num_rects = 0;
 
5324
  gint                x, y, contig;
 
5325
  guint               w, h, d;
 
5326
  gint                baseh, basew;
 
5327
  XRectangle         *rects = NULL;
 
5328
  struct _gdk_span  **spans = NULL, *ptr1, *ptr2, *ptr3;
 
5329
  XWindowAttributes   xatt;
 
5330
  
 
5331
  XGetGeometry (disp, win, &rt, &x, &y, &w, &h, &d, &d);
 
5332
  if (h <= 0)
 
5333
    return;
 
5334
  basew = w;
 
5335
  baseh = h;
 
5336
  spans = g_malloc (sizeof (struct _gdk_span *) * h);
 
5337
  
 
5338
  for (i = 0; i < h; i++)
 
5339
    spans[i] = NULL;
 
5340
  XQueryTree (disp, win, &rt, &par, &list, (unsigned int *)&num);
 
5341
  if (list)
 
5342
    {
 
5343
      /* go through all child windows and create/insert spans */
 
5344
      for (i = 0; i < num; i++)
 
5345
        {
 
5346
          if (XGetWindowAttributes (disp, list[i], &xatt) && (xatt.map_state != IsUnmapped))
 
5347
            if (XGetGeometry (disp, list[i], &rt, &x, &y, &w, &h, &d, &d))
 
5348
              gdk_add_rectangles (disp, list[i], spans, basew, baseh, x, y);
 
5349
        }
 
5350
      if (merge)
 
5351
        gdk_add_rectangles (disp, win, spans, basew, baseh, x, y);
 
5352
      
 
5353
      /* go through the spans list and build a list of rects */
 
5354
      rects = g_malloc (sizeof (XRectangle) * 256);
 
5355
      num_rects = 0;
 
5356
      for (i = 0; i < baseh; i++)
 
5357
        {
 
5358
          ptr1 = spans[i];
 
5359
          /* go through the line for all spans */
 
5360
          while (ptr1)
 
5361
            {
 
5362
              rects[num_rects].x = ptr1->start;
 
5363
              rects[num_rects].y = i;
 
5364
              rects[num_rects].width = ptr1->end - ptr1->start + 1;
 
5365
              rects[num_rects].height = 1;
 
5366
              j = i + 1;
 
5367
              /* if there are more lines */
 
5368
              contig = 1;
 
5369
              /* while contigous rects (same start/end coords) exist */
 
5370
              while ((contig) && (j < baseh))
 
5371
                {
 
5372
                  /* search next line for spans matching this one */
 
5373
                  contig = 0;
 
5374
                  ptr2 = spans[j];
 
5375
                  ptr3 = NULL;
 
5376
                  while (ptr2)
 
5377
                    {
 
5378
                      /* if we have an exact span match set contig */
 
5379
                      if ((ptr2->start == ptr1->start) &&
 
5380
                          (ptr2->end == ptr1->end))
 
5381
                        {
 
5382
                          contig = 1;
 
5383
                          /* remove the span - not needed */
 
5384
                          if (ptr3)
 
5385
                            {
 
5386
                              ptr3->next = ptr2->next;
 
5387
                              g_free (ptr2);
 
5388
                              ptr2 = NULL;
 
5389
                            }
 
5390
                          else
 
5391
                            {
 
5392
                              spans[j] = ptr2->next;
 
5393
                              g_free (ptr2);
 
5394
                              ptr2 = NULL;
 
5395
                            }
 
5396
                          break;
 
5397
                        }
 
5398
                      /* gone past the span point no point looking */
 
5399
                      else if (ptr2->start < ptr1->start)
 
5400
                        break;
 
5401
                      if (ptr2)
 
5402
                        {
 
5403
                          ptr3 = ptr2;
 
5404
                          ptr2 = ptr2->next;
 
5405
                        }
 
5406
                    }
 
5407
                  /* if a contiguous span was found increase the rect h */
 
5408
                  if (contig)
 
5409
                    {
 
5410
                      rects[num_rects].height++;
 
5411
                      j++;
 
5412
                    }
 
5413
                }
 
5414
              /* up the rect count */
 
5415
              num_rects++;
 
5416
              /* every 256 new rects increase the rect array */
 
5417
              if ((num_rects % 256) == 0)
 
5418
                rects = g_realloc (rects, sizeof (XRectangle) * (num_rects + 256));
 
5419
              ptr1 = ptr1->next;
 
5420
            }
 
5421
        }
 
5422
      /* set the rects as the shape mask */
 
5423
      if (rects)
 
5424
        {
 
5425
          XShapeCombineRectangles (disp, win, shape, 0, 0, rects, num_rects,
 
5426
                                   ShapeSet, YXSorted);
 
5427
          g_free (rects);
 
5428
        }
 
5429
      XFree (list);
 
5430
    }
 
5431
  /* free up all the spans we made */
 
5432
  for (i = 0; i < baseh; i++)
 
5433
    {
 
5434
      ptr1 = spans[i];
 
5435
      while (ptr1)
 
5436
        {
 
5437
          ptr2 = ptr1;
 
5438
          ptr1 = ptr1->next;
 
5439
          g_free (ptr2);
 
5440
        }
 
5441
    }
 
5442
  g_free (spans);
 
5443
}
 
5444
 
 
5445
#endif /* HAVE_SHAPE_EXT */
 
5446
 
 
5447
/**
 
5448
 * gdk_window_set_child_shapes:
 
5449
 * @window: a #GdkWindow
 
5450
 * 
 
5451
 * Sets the shape mask of @window to the union of shape masks
 
5452
 * for all children of @window, ignoring the shape mask of @window
 
5453
 * itself. Contrast with gdk_window_merge_child_shapes() which includes
 
5454
 * the shape mask of @window in the masks to be merged.
 
5455
 **/
 
5456
void
 
5457
gdk_window_set_child_shapes (GdkWindow *window)
 
5458
{
 
5459
  g_return_if_fail (GDK_IS_WINDOW (window));
 
5460
  
 
5461
  
 
5462
#ifdef HAVE_SHAPE_EXT
 
5463
  if (!GDK_WINDOW_DESTROYED (window) &&
 
5464
      gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
 
5465
    gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
 
5466
                          GDK_WINDOW_XID (window), FALSE, ShapeBounding);
 
5467
#endif   
 
5468
}
 
5469
 
 
5470
/**
 
5471
 * gdk_window_merge_child_shapes:
 
5472
 * @window: a #GdkWindow
 
5473
 * 
 
5474
 * Merges the shape masks for any child windows into the
 
5475
 * shape mask for @window. i.e. the union of all masks
 
5476
 * for @window and its children will become the new mask
 
5477
 * for @window. See gdk_window_shape_combine_mask().
 
5478
 *
 
5479
 * This function is distinct from gdk_window_set_child_shapes()
 
5480
 * because it includes @window's shape mask in the set of shapes to
 
5481
 * be merged.
 
5482
 **/
 
5483
void
 
5484
gdk_window_merge_child_shapes (GdkWindow *window)
 
5485
{
 
5486
  g_return_if_fail (GDK_IS_WINDOW (window));
 
5487
  
 
5488
#ifdef HAVE_SHAPE_EXT
 
5489
  if (!GDK_WINDOW_DESTROYED (window) &&
 
5490
      gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
 
5491
    gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
 
5492
                          GDK_WINDOW_XID (window), TRUE, ShapeBounding);
 
5493
#endif   
 
5494
}
 
5495
 
 
5496
/**
 
5497
 * gdk_window_set_child_input_shapes:
 
5498
 * @window: a #GdkWindow
 
5499
 * 
 
5500
 * Sets the input shape mask of @window to the union of input shape masks
 
5501
 * for all children of @window, ignoring the input shape mask of @window
 
5502
 * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
 
5503
 * the input shape mask of @window in the masks to be merged.
 
5504
 *
 
5505
 * Since: 2.10
 
5506
 **/
 
5507
void 
 
5508
gdk_window_set_child_input_shapes (GdkWindow *window)
 
5509
{
 
5510
  g_return_if_fail (GDK_IS_WINDOW (window));
 
5511
  
 
5512
#ifdef HAVE_SHAPE_EXT
 
5513
#ifdef ShapeInput
 
5514
  if (!GDK_WINDOW_DESTROYED (window) &&
 
5515
      gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
 
5516
    gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
 
5517
                          GDK_WINDOW_XID (window), FALSE, ShapeInput);
 
5518
#endif
 
5519
#endif   
 
5520
}
 
5521
 
 
5522
/**
 
5523
 * gdk_window_merge_child_input_shapes:
 
5524
 * @window: a #GdkWindow
 
5525
 * 
 
5526
 * Merges the input shape masks for any child windows into the
 
5527
 * input shape mask for @window. i.e. the union of all input masks
 
5528
 * for @window and its children will become the new input mask
 
5529
 * for @window. See gdk_window_input_shape_combine_mask().
 
5530
 *
 
5531
 * This function is distinct from gdk_window_set_child_input_shapes()
 
5532
 * because it includes @window's input shape mask in the set of 
 
5533
 * shapes to be merged.
 
5534
 *
 
5535
 * Since: 2.10
 
5536
 **/
 
5537
void 
 
5538
gdk_window_merge_child_input_shapes (GdkWindow *window)
 
5539
{
 
5540
  g_return_if_fail (GDK_IS_WINDOW (window));
 
5541
  
 
5542
#ifdef HAVE_SHAPE_EXT
 
5543
#ifdef ShapeInput
 
5544
  if (!GDK_WINDOW_DESTROYED (window) &&
 
5545
      gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
 
5546
    gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
 
5547
                          GDK_WINDOW_XID (window), TRUE, ShapeInput);
 
5548
#endif
 
5549
#endif   
 
5550
}
 
5551
 
 
5552
 
 
5553
static void
 
5554
gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
 
5555
{
 
5556
  XSetWindowAttributes xattributes;
 
5557
  GdkWindowObject *private;
 
5558
  guint xattributes_mask = 0;
 
5559
  
 
5560
  g_return_if_fail (GDK_IS_WINDOW (window));
 
5561
 
 
5562
  private = GDK_WINDOW_OBJECT (window);
 
5563
  if (private->input_only)
 
5564
    return;
 
5565
  
 
5566
  xattributes.bit_gravity = StaticGravity;
 
5567
  xattributes_mask |= CWBitGravity;
 
5568
  xattributes.bit_gravity = on ? StaticGravity : ForgetGravity;
 
5569
  XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
 
5570
                           GDK_WINDOW_XID (window),
 
5571
                           CWBitGravity,  &xattributes);
 
5572
}
 
5573
 
 
5574
static void
 
5575
gdk_window_set_static_win_gravity (GdkWindow *window, gboolean on)
 
5576
{
 
5577
  XSetWindowAttributes xattributes;
 
5578
  
 
5579
  g_return_if_fail (GDK_IS_WINDOW (window));
 
5580
  
 
5581
  xattributes.win_gravity = on ? StaticGravity : NorthWestGravity;
 
5582
  
 
5583
  XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
 
5584
                           GDK_WINDOW_XID (window),
 
5585
                           CWWinGravity,  &xattributes);
 
5586
}
 
5587
 
 
5588
/**
 
5589
 * gdk_window_set_static_gravities:
 
5590
 * @window: a #GdkWindow
 
5591
 * @use_static: %TRUE to turn on static gravity
 
5592
 *
 
5593
 * Set the bit gravity of the given window to static, and flag it so
 
5594
 * all children get static subwindow gravity. This is used if you are
 
5595
 * implementing scary features that involve deep knowledge of the
 
5596
 * windowing system. Don't worry about it unless you have to.
 
5597
 * 
 
5598
 * Return value: %TRUE if the server supports static gravity
 
5599
 **/
 
5600
gboolean 
 
5601
gdk_window_set_static_gravities (GdkWindow *window,
 
5602
                                 gboolean   use_static)
 
5603
{
 
5604
  GdkWindowObject *private = (GdkWindowObject *)window;
 
5605
  GList *tmp_list;
 
5606
  
 
5607
  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
5608
 
 
5609
  if (!use_static == !private->guffaw_gravity)
 
5610
    return TRUE;
 
5611
 
 
5612
  private->guffaw_gravity = use_static;
 
5613
  
 
5614
  if (!GDK_WINDOW_DESTROYED (window))
 
5615
    {
 
5616
      gdk_window_set_static_bit_gravity (window, use_static);
 
5617
      
 
5618
      tmp_list = private->children;
 
5619
      while (tmp_list)
 
5620
        {
 
5621
          gdk_window_set_static_win_gravity (tmp_list->data, use_static);
 
5622
          
 
5623
          tmp_list = tmp_list->next;
 
5624
        }
 
5625
    }
 
5626
  
 
5627
  return TRUE;
 
5628
}
 
5629
 
 
5630
static void
 
5631
wmspec_moveresize (GdkWindow *window,
 
5632
                   gint       direction,
 
5633
                   gint       root_x,
 
5634
                   gint       root_y,
 
5635
                   guint32    timestamp)     
 
5636
{
 
5637
  GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
 
5638
  
 
5639
  XClientMessageEvent xclient;
 
5640
 
 
5641
  /* Release passive grab */
 
5642
  gdk_display_pointer_ungrab (display, timestamp);
 
5643
 
 
5644
  memset (&xclient, 0, sizeof (xclient));
 
5645
  xclient.type = ClientMessage;
 
5646
  xclient.window = GDK_WINDOW_XID (window);
 
5647
  xclient.message_type =
 
5648
    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_MOVERESIZE");
 
5649
  xclient.format = 32;
 
5650
  xclient.data.l[0] = root_x;
 
5651
  xclient.data.l[1] = root_y;
 
5652
  xclient.data.l[2] = direction;
 
5653
  xclient.data.l[3] = 0;
 
5654
  xclient.data.l[4] = 0;
 
5655
  
 
5656
  XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
 
5657
              SubstructureRedirectMask | SubstructureNotifyMask,
 
5658
              (XEvent *)&xclient);
 
5659
}
 
5660
 
 
5661
typedef struct _MoveResizeData MoveResizeData;
 
5662
 
 
5663
struct _MoveResizeData
 
5664
{
 
5665
  GdkDisplay *display;
 
5666
  
 
5667
  GdkWindow *moveresize_window;
 
5668
  GdkWindow *moveresize_emulation_window;
 
5669
  gboolean is_resize;
 
5670
  GdkWindowEdge resize_edge;
 
5671
  gint moveresize_button;
 
5672
  gint moveresize_x;
 
5673
  gint moveresize_y;
 
5674
  gint moveresize_orig_x;
 
5675
  gint moveresize_orig_y;
 
5676
  gint moveresize_orig_width;
 
5677
  gint moveresize_orig_height;
 
5678
  GdkWindowHints moveresize_geom_mask;
 
5679
  GdkGeometry moveresize_geometry;
 
5680
  Time moveresize_process_time;
 
5681
  XEvent *moveresize_pending_event;
 
5682
};
 
5683
 
 
5684
/* From the WM spec */
 
5685
#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT      0
 
5686
#define _NET_WM_MOVERESIZE_SIZE_TOP          1
 
5687
#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT     2
 
5688
#define _NET_WM_MOVERESIZE_SIZE_RIGHT        3
 
5689
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT  4
 
5690
#define _NET_WM_MOVERESIZE_SIZE_BOTTOM       5
 
5691
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT   6
 
5692
#define _NET_WM_MOVERESIZE_SIZE_LEFT         7
 
5693
#define _NET_WM_MOVERESIZE_MOVE              8
 
5694
 
 
5695
static void
 
5696
wmspec_resize_drag (GdkWindow     *window,
 
5697
                    GdkWindowEdge  edge,
 
5698
                    gint           button,
 
5699
                    gint           root_x,
 
5700
                    gint           root_y,
 
5701
                    guint32        timestamp)
 
5702
{
 
5703
  gint direction;
 
5704
  
 
5705
  /* Let the compiler turn a switch into a table, instead
 
5706
   * of doing the table manually, this way is easier to verify.
 
5707
   */
 
5708
  switch (edge)
 
5709
    {
 
5710
    case GDK_WINDOW_EDGE_NORTH_WEST:
 
5711
      direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
 
5712
      break;
 
5713
 
 
5714
    case GDK_WINDOW_EDGE_NORTH:
 
5715
      direction = _NET_WM_MOVERESIZE_SIZE_TOP;
 
5716
      break;
 
5717
 
 
5718
    case GDK_WINDOW_EDGE_NORTH_EAST:
 
5719
      direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
 
5720
      break;
 
5721
 
 
5722
    case GDK_WINDOW_EDGE_WEST:
 
5723
      direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
 
5724
      break;
 
5725
 
 
5726
    case GDK_WINDOW_EDGE_EAST:
 
5727
      direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
 
5728
      break;
 
5729
 
 
5730
    case GDK_WINDOW_EDGE_SOUTH_WEST:
 
5731
      direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
 
5732
      break;
 
5733
 
 
5734
    case GDK_WINDOW_EDGE_SOUTH:
 
5735
      direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
 
5736
      break;
 
5737
 
 
5738
    case GDK_WINDOW_EDGE_SOUTH_EAST:
 
5739
      direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
 
5740
      break;
 
5741
 
 
5742
    default:
 
5743
      g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
 
5744
                 edge);
 
5745
      return;
 
5746
      break;
 
5747
    }
 
5748
  
 
5749
  wmspec_moveresize (window, direction, root_x, root_y, timestamp);
 
5750
}
 
5751
 
 
5752
static MoveResizeData *
 
5753
get_move_resize_data (GdkDisplay *display,
 
5754
                      gboolean    create)
 
5755
{
 
5756
  MoveResizeData *mv_resize;
 
5757
  static GQuark move_resize_quark = 0;
 
5758
 
 
5759
  if (!move_resize_quark)
 
5760
    move_resize_quark = g_quark_from_static_string ("gdk-window-moveresize");
 
5761
  
 
5762
  mv_resize = g_object_get_qdata (G_OBJECT (display), move_resize_quark);
 
5763
 
 
5764
  if (!mv_resize && create)
 
5765
    {
 
5766
      mv_resize = g_new0 (MoveResizeData, 1);
 
5767
      mv_resize->display = display;
 
5768
      
 
5769
      g_object_set_qdata (G_OBJECT (display), move_resize_quark, mv_resize);
 
5770
    }
 
5771
 
 
5772
  return mv_resize;
 
5773
}
 
5774
 
 
5775
static void
 
5776
update_pos (MoveResizeData *mv_resize,
 
5777
            gint            new_root_x,
 
5778
            gint            new_root_y)
 
5779
{
 
5780
  gint dx, dy;
 
5781
 
 
5782
  dx = new_root_x - mv_resize->moveresize_x;
 
5783
  dy = new_root_y - mv_resize->moveresize_y;
 
5784
 
 
5785
  if (mv_resize->is_resize)
 
5786
    {
 
5787
      gint x, y, w, h;
 
5788
 
 
5789
      x = mv_resize->moveresize_orig_x;
 
5790
      y = mv_resize->moveresize_orig_y;
 
5791
 
 
5792
      w = mv_resize->moveresize_orig_width;
 
5793
      h = mv_resize->moveresize_orig_height;
 
5794
 
 
5795
      switch (mv_resize->resize_edge)
 
5796
        {
 
5797
        case GDK_WINDOW_EDGE_NORTH_WEST:
 
5798
          x += dx;
 
5799
          y += dy;
 
5800
          w -= dx;
 
5801
          h -= dy;
 
5802
          break;
 
5803
        case GDK_WINDOW_EDGE_NORTH:
 
5804
          y += dy;
 
5805
          h -= dy;
 
5806
          break;
 
5807
        case GDK_WINDOW_EDGE_NORTH_EAST:
 
5808
          y += dy;
 
5809
          h -= dy;
 
5810
          w += dx;
 
5811
          break;
 
5812
        case GDK_WINDOW_EDGE_SOUTH_WEST:
 
5813
          h += dy;
 
5814
          x += dx;
 
5815
          w -= dx;
 
5816
          break;
 
5817
        case GDK_WINDOW_EDGE_SOUTH_EAST:
 
5818
          w += dx;
 
5819
          h += dy;
 
5820
          break;
 
5821
        case GDK_WINDOW_EDGE_SOUTH:
 
5822
          h += dy;
 
5823
          break;
 
5824
        case GDK_WINDOW_EDGE_EAST:
 
5825
          w += dx;
 
5826
          break;
 
5827
        case GDK_WINDOW_EDGE_WEST:
 
5828
          x += dx;
 
5829
          w -= dx;
 
5830
          break;
 
5831
        }
 
5832
 
 
5833
      x = MAX (x, 0);
 
5834
      y = MAX (y, 0);
 
5835
      w = MAX (w, 1);
 
5836
      h = MAX (h, 1);
 
5837
 
 
5838
      if (mv_resize->moveresize_geom_mask)
 
5839
        {
 
5840
          gdk_window_constrain_size (&mv_resize->moveresize_geometry,
 
5841
                                     mv_resize->moveresize_geom_mask,
 
5842
                                     w, h, &w, &h);
 
5843
        }
 
5844
 
 
5845
      gdk_window_move_resize (mv_resize->moveresize_window, x, y, w, h);
 
5846
    }
 
5847
  else
 
5848
    {
 
5849
      gint x, y;
 
5850
 
 
5851
      x = mv_resize->moveresize_orig_x + dx;
 
5852
      y = mv_resize->moveresize_orig_y + dy;
 
5853
 
 
5854
      gdk_window_move (mv_resize->moveresize_window, x, y);
 
5855
    }
 
5856
}
 
5857
 
 
5858
static void
 
5859
finish_drag (MoveResizeData *mv_resize)
 
5860
{
 
5861
  gdk_window_destroy (mv_resize->moveresize_emulation_window);
 
5862
  mv_resize->moveresize_emulation_window = NULL;
 
5863
  g_object_unref (mv_resize->moveresize_window);
 
5864
  mv_resize->moveresize_window = NULL;
 
5865
 
 
5866
  if (mv_resize->moveresize_pending_event)
 
5867
    {
 
5868
      g_free (mv_resize->moveresize_pending_event);
 
5869
      mv_resize->moveresize_pending_event = NULL;
 
5870
    }
 
5871
}
 
5872
 
 
5873
static int
 
5874
lookahead_motion_predicate (Display *xdisplay,
 
5875
                            XEvent  *event,
 
5876
                            XPointer arg)
 
5877
{
 
5878
  gboolean *seen_release = (gboolean *)arg;
 
5879
  GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
 
5880
  MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
 
5881
 
 
5882
  if (*seen_release)
 
5883
    return False;
 
5884
 
 
5885
  switch (event->xany.type)
 
5886
    {
 
5887
    case ButtonRelease:
 
5888
      *seen_release = TRUE;
 
5889
      break;
 
5890
    case MotionNotify:
 
5891
      mv_resize->moveresize_process_time = event->xmotion.time;
 
5892
      break;
 
5893
    default:
 
5894
      break;
 
5895
    }
 
5896
 
 
5897
  return False;
 
5898
}
 
5899
 
 
5900
static gboolean
 
5901
moveresize_lookahead (MoveResizeData *mv_resize,
 
5902
                      XEvent         *event)
 
5903
{
 
5904
  XEvent tmp_event;
 
5905
  gboolean seen_release = FALSE;
 
5906
 
 
5907
  if (mv_resize->moveresize_process_time)
 
5908
    {
 
5909
      if (event->xmotion.time == mv_resize->moveresize_process_time)
 
5910
        {
 
5911
          mv_resize->moveresize_process_time = 0;
 
5912
          return TRUE;
 
5913
        }
 
5914
      else
 
5915
        return FALSE;
 
5916
    }
 
5917
 
 
5918
  XCheckIfEvent (event->xany.display, &tmp_event,
 
5919
                 lookahead_motion_predicate, (XPointer) & seen_release);
 
5920
 
 
5921
  return mv_resize->moveresize_process_time == 0;
 
5922
}
 
5923
        
 
5924
gboolean
 
5925
_gdk_moveresize_handle_event (XEvent *event)
 
5926
{
 
5927
  guint button_mask = 0;
 
5928
  GdkWindowObject *window_private;
 
5929
  GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
 
5930
  MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
 
5931
 
 
5932
  if (!mv_resize || !mv_resize->moveresize_window)
 
5933
    return FALSE;
 
5934
 
 
5935
  window_private = (GdkWindowObject *) mv_resize->moveresize_window;
 
5936
 
 
5937
  button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
 
5938
 
 
5939
  switch (event->xany.type)
 
5940
    {
 
5941
    case MotionNotify:
 
5942
      if (window_private->resize_count > 0)
 
5943
        {
 
5944
          if (mv_resize->moveresize_pending_event)
 
5945
            *mv_resize->moveresize_pending_event = *event;
 
5946
          else
 
5947
            mv_resize->moveresize_pending_event =
 
5948
              g_memdup (event, sizeof (XEvent));
 
5949
 
 
5950
          break;
 
5951
        }
 
5952
      if (!moveresize_lookahead (mv_resize, event))
 
5953
        break;
 
5954
 
 
5955
      update_pos (mv_resize,
 
5956
                  event->xmotion.x_root,
 
5957
                  event->xmotion.y_root);
 
5958
 
 
5959
      /* This should never be triggered in normal cases, but in the
 
5960
       * case where the drag started without an implicit grab being
 
5961
       * in effect, we could miss the release if it occurs before
 
5962
       * we grab the pointer; this ensures that we will never
 
5963
       * get a permanently stuck grab.
 
5964
       */
 
5965
      if ((event->xmotion.state & button_mask) == 0)
 
5966
        finish_drag (mv_resize);
 
5967
      break;
 
5968
 
 
5969
    case ButtonRelease:
 
5970
      update_pos (mv_resize,
 
5971
                  event->xbutton.x_root,
 
5972
                  event->xbutton.y_root);
 
5973
 
 
5974
      if (event->xbutton.button == mv_resize->moveresize_button)
 
5975
        finish_drag (mv_resize);
 
5976
      break;
 
5977
    }
 
5978
  return TRUE;
 
5979
}
 
5980
 
 
5981
gboolean 
 
5982
_gdk_moveresize_configure_done (GdkDisplay *display,
 
5983
                                GdkWindow  *window)
 
5984
{
 
5985
  XEvent *tmp_event;
 
5986
  MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
 
5987
  
 
5988
  if (!mv_resize || window != mv_resize->moveresize_window)
 
5989
    return FALSE;
 
5990
 
 
5991
  if (mv_resize->moveresize_pending_event)
 
5992
    {
 
5993
      tmp_event = mv_resize->moveresize_pending_event;
 
5994
      mv_resize->moveresize_pending_event = NULL;
 
5995
      _gdk_moveresize_handle_event (tmp_event);
 
5996
      g_free (tmp_event);
 
5997
    }
 
5998
  
 
5999
  return TRUE;
 
6000
}
 
6001
 
 
6002
static void
 
6003
create_moveresize_window (MoveResizeData *mv_resize,
 
6004
                          guint32         timestamp)
 
6005
{
 
6006
  GdkWindowAttr attributes;
 
6007
  gint attributes_mask;
 
6008
  GdkGrabStatus status;
 
6009
 
 
6010
  g_assert (mv_resize->moveresize_emulation_window == NULL);
 
6011
 
 
6012
  attributes.x = -100;
 
6013
  attributes.y = -100;
 
6014
  attributes.width = 10;
 
6015
  attributes.height = 10;
 
6016
  attributes.window_type = GDK_WINDOW_TEMP;
 
6017
  attributes.wclass = GDK_INPUT_ONLY;
 
6018
  attributes.override_redirect = TRUE;
 
6019
  attributes.event_mask = 0;
 
6020
 
 
6021
  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
 
6022
 
 
6023
  mv_resize->moveresize_emulation_window = 
 
6024
    gdk_window_new (gdk_screen_get_root_window (gdk_display_get_default_screen (mv_resize->display)),
 
6025
                    &attributes,
 
6026
                    attributes_mask);
 
6027
 
 
6028
  gdk_window_show (mv_resize->moveresize_emulation_window);
 
6029
 
 
6030
  status = gdk_pointer_grab (mv_resize->moveresize_emulation_window,
 
6031
                             FALSE,
 
6032
                             GDK_BUTTON_RELEASE_MASK |
 
6033
                             GDK_POINTER_MOTION_MASK,
 
6034
                             NULL,
 
6035
                             NULL,
 
6036
                             timestamp);
 
6037
 
 
6038
  if (status != GDK_GRAB_SUCCESS)
 
6039
    {
 
6040
      /* If this fails, some other client has grabbed the window
 
6041
       * already.
 
6042
       */
 
6043
      finish_drag (mv_resize);
 
6044
    }
 
6045
 
 
6046
  mv_resize->moveresize_process_time = 0;
 
6047
}
 
6048
 
 
6049
/* 
 
6050
   Calculate mv_resize->moveresize_orig_x and mv_resize->moveresize_orig_y
 
6051
   so that calling XMoveWindow with these coordinates will not move the 
 
6052
   window.
 
6053
   Note that this depends on the WM to implement ICCCM-compliant reference
 
6054
   point handling.
 
6055
*/
 
6056
static void 
 
6057
calculate_unmoving_origin (MoveResizeData *mv_resize)
 
6058
{
 
6059
  GdkRectangle rect;
 
6060
  gint width, height;
 
6061
 
 
6062
  if (mv_resize->moveresize_geom_mask & GDK_HINT_WIN_GRAVITY &&
 
6063
      mv_resize->moveresize_geometry.win_gravity == GDK_GRAVITY_STATIC)
 
6064
    {
 
6065
      gdk_window_get_origin (mv_resize->moveresize_window,
 
6066
                             &mv_resize->moveresize_orig_x,
 
6067
                             &mv_resize->moveresize_orig_y);
 
6068
    }
 
6069
  else
 
6070
    {
 
6071
      gdk_window_get_frame_extents (mv_resize->moveresize_window, &rect);
 
6072
      gdk_window_get_geometry (mv_resize->moveresize_window, 
 
6073
                               NULL, NULL, &width, &height, NULL);
 
6074
      
 
6075
      switch (mv_resize->moveresize_geometry.win_gravity) 
 
6076
        {
 
6077
        case GDK_GRAVITY_NORTH_WEST:
 
6078
          mv_resize->moveresize_orig_x = rect.x;
 
6079
          mv_resize->moveresize_orig_y = rect.y;
 
6080
          break;
 
6081
        case GDK_GRAVITY_NORTH:
 
6082
          mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
 
6083
          mv_resize->moveresize_orig_y = rect.y;
 
6084
          break;          
 
6085
        case GDK_GRAVITY_NORTH_EAST:
 
6086
          mv_resize->moveresize_orig_x = rect.x + rect.width - width;
 
6087
          mv_resize->moveresize_orig_y = rect.y;
 
6088
          break;
 
6089
        case GDK_GRAVITY_WEST:
 
6090
          mv_resize->moveresize_orig_x = rect.x;
 
6091
          mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
 
6092
          break;
 
6093
        case GDK_GRAVITY_CENTER:
 
6094
          mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
 
6095
          mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
 
6096
          break;
 
6097
        case GDK_GRAVITY_EAST:
 
6098
          mv_resize->moveresize_orig_x = rect.x + rect.width - width;
 
6099
          mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
 
6100
          break;
 
6101
        case GDK_GRAVITY_SOUTH_WEST:
 
6102
          mv_resize->moveresize_orig_x = rect.x;
 
6103
          mv_resize->moveresize_orig_y = rect.y + rect.height - height;
 
6104
          break;
 
6105
        case GDK_GRAVITY_SOUTH:
 
6106
          mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
 
6107
          mv_resize->moveresize_orig_y = rect.y + rect.height - height;
 
6108
          break;
 
6109
        case GDK_GRAVITY_SOUTH_EAST:
 
6110
          mv_resize->moveresize_orig_x = rect.x + rect.width - width;
 
6111
          mv_resize->moveresize_orig_y = rect.y + rect.height - height;
 
6112
          break;
 
6113
        default:
 
6114
          mv_resize->moveresize_orig_x = rect.x;
 
6115
          mv_resize->moveresize_orig_y = rect.y;
 
6116
          break; 
 
6117
        }
 
6118
    }  
 
6119
}
 
6120
 
 
6121
static void
 
6122
emulate_resize_drag (GdkWindow     *window,
 
6123
                     GdkWindowEdge  edge,
 
6124
                     gint           button,
 
6125
                     gint           root_x,
 
6126
                     gint           root_y,
 
6127
                     guint32        timestamp)
 
6128
{
 
6129
  MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
 
6130
 
 
6131
  mv_resize->is_resize = TRUE;
 
6132
  mv_resize->moveresize_button = button;
 
6133
  mv_resize->resize_edge = edge;
 
6134
  mv_resize->moveresize_x = root_x;
 
6135
  mv_resize->moveresize_y = root_y;
 
6136
  mv_resize->moveresize_window = g_object_ref (window);
 
6137
 
 
6138
  gdk_drawable_get_size (window,
 
6139
                         &mv_resize->moveresize_orig_width,
 
6140
                         &mv_resize->moveresize_orig_height);
 
6141
 
 
6142
  mv_resize->moveresize_geom_mask = 0;
 
6143
  gdk_window_get_geometry_hints (window,
 
6144
                                 &mv_resize->moveresize_geometry,
 
6145
                                 &mv_resize->moveresize_geom_mask);
 
6146
 
 
6147
  calculate_unmoving_origin (mv_resize);
 
6148
 
 
6149
  create_moveresize_window (mv_resize, timestamp);
 
6150
}
 
6151
 
 
6152
static void
 
6153
emulate_move_drag (GdkWindow     *window,
 
6154
                   gint           button,
 
6155
                   gint           root_x,
 
6156
                   gint           root_y,
 
6157
                   guint32        timestamp)
 
6158
{
 
6159
  MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
 
6160
  
 
6161
  mv_resize->is_resize = FALSE;
 
6162
  mv_resize->moveresize_button = button;
 
6163
  mv_resize->moveresize_x = root_x;
 
6164
  mv_resize->moveresize_y = root_y;
 
6165
 
 
6166
  mv_resize->moveresize_window = g_object_ref (window);
 
6167
 
 
6168
  calculate_unmoving_origin (mv_resize);
 
6169
 
 
6170
  create_moveresize_window (mv_resize, timestamp);
 
6171
}
 
6172
 
 
6173
/**
 
6174
 * gdk_window_begin_resize_drag:
 
6175
 * @window: a toplevel #GdkWindow
 
6176
 * @edge: the edge or corner from which the drag is started
 
6177
 * @button: the button being used to drag
 
6178
 * @root_x: root window X coordinate of mouse click that began the drag
 
6179
 * @root_y: root window Y coordinate of mouse click that began the drag
 
6180
 * @timestamp: timestamp of mouse click that began the drag (use gdk_event_get_time())
 
6181
 *
 
6182
 * Begins a window resize operation (for a toplevel window).
 
6183
 * You might use this function to implement a "window resize grip," for
 
6184
 * example; in fact #GtkStatusbar uses it. The function works best
 
6185
 * with window managers that support the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended Window Manager Hints</ulink>, but has a 
 
6186
 * fallback implementation for other window managers.
 
6187
 * 
 
6188
 **/
 
6189
void
 
6190
gdk_window_begin_resize_drag (GdkWindow     *window,
 
6191
                              GdkWindowEdge  edge,
 
6192
                              gint           button,
 
6193
                              gint           root_x,
 
6194
                              gint           root_y,
 
6195
                              guint32        timestamp)
 
6196
{
 
6197
  g_return_if_fail (GDK_IS_WINDOW (window));
 
6198
 
 
6199
  if (GDK_WINDOW_DESTROYED (window))
 
6200
    return;
 
6201
 
 
6202
  if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
 
6203
                                           gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
 
6204
    wmspec_resize_drag (window, edge, button, root_x, root_y, timestamp);
 
6205
  else
 
6206
    emulate_resize_drag (window, edge, button, root_x, root_y, timestamp);
 
6207
}
 
6208
 
 
6209
/**
 
6210
 * gdk_window_begin_move_drag:
 
6211
 * @window: a toplevel #GdkWindow
 
6212
 * @button: the button being used to drag
 
6213
 * @root_x: root window X coordinate of mouse click that began the drag
 
6214
 * @root_y: root window Y coordinate of mouse click that began the drag
 
6215
 * @timestamp: timestamp of mouse click that began the drag
 
6216
 *
 
6217
 * Begins a window move operation (for a toplevel window).  You might
 
6218
 * use this function to implement a "window move grip," for
 
6219
 * example. The function works best with window managers that support
 
6220
 * the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended 
 
6221
 * Window Manager Hints</ulink>, but has a fallback implementation for
 
6222
 * other window managers.
 
6223
 * 
 
6224
 **/
 
6225
void
 
6226
gdk_window_begin_move_drag (GdkWindow *window,
 
6227
                            gint       button,
 
6228
                            gint       root_x,
 
6229
                            gint       root_y,
 
6230
                            guint32    timestamp)
 
6231
{
 
6232
  g_return_if_fail (GDK_IS_WINDOW (window));
 
6233
 
 
6234
  if (GDK_WINDOW_DESTROYED (window))
 
6235
    return;
 
6236
 
 
6237
  if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
 
6238
                                           gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
 
6239
    wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE, root_x, root_y,
 
6240
                       timestamp);
 
6241
  else
 
6242
    emulate_move_drag (window, button, root_x, root_y, timestamp);
 
6243
}
 
6244
 
 
6245
/**
 
6246
 * gdk_window_enable_synchronized_configure:
 
6247
 * @window: a toplevel #GdkWindow
 
6248
 * 
 
6249
 * Indicates that the application will cooperate with the window
 
6250
 * system in synchronizing the window repaint with the window
 
6251
 * manager during resizing operations. After an application calls
 
6252
 * this function, it must call gdk_window_configure_finished() every
 
6253
 * time it has finished all processing associated with a set of
 
6254
 * Configure events. Toplevel GTK+ windows automatically use this
 
6255
 * protocol.
 
6256
 * 
 
6257
 * On X, calling this function makes @window participate in the
 
6258
 * _NET_WM_SYNC_REQUEST window manager protocol.
 
6259
 * 
 
6260
 * Since: 2.6
 
6261
 **/
 
6262
void
 
6263
gdk_window_enable_synchronized_configure (GdkWindow *window)
 
6264
{
 
6265
  GdkWindowObject *private = (GdkWindowObject *)window;
 
6266
  GdkWindowImplX11 *impl;
 
6267
 
 
6268
  g_return_if_fail (GDK_IS_WINDOW (window));
 
6269
 
 
6270
  impl = GDK_WINDOW_IMPL_X11 (private->impl);
 
6271
          
 
6272
  if (!impl->use_synchronized_configure)
 
6273
    {
 
6274
      impl->use_synchronized_configure = TRUE;
 
6275
      ensure_sync_counter (window);
 
6276
    }
 
6277
}
 
6278
 
 
6279
/**
 
6280
 * gdk_window_configure_finished:
 
6281
 * @window: a toplevel #GdkWindow
 
6282
 * 
 
6283
 * Signal to the window system that the application has finished
 
6284
 * handling Configure events it has received. Window Managers can
 
6285
 * use this to better synchronize the frame repaint with the
 
6286
 * application. GTK+ applications will automatically call this
 
6287
 * function when appropriate.
 
6288
 *
 
6289
 * This function can only be called if gdk_window_enable_synchronized_configure()
 
6290
 * was called previously.
 
6291
 *
 
6292
 * Since: 2.6
 
6293
 **/
 
6294
void
 
6295
gdk_window_configure_finished (GdkWindow *window)
 
6296
{
 
6297
  GdkWindowImplX11 *impl;
 
6298
 
 
6299
  g_return_if_fail (GDK_IS_WINDOW (window));
 
6300
  
 
6301
  impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
 
6302
  if (!impl->use_synchronized_configure)
 
6303
    return;
 
6304
  
 
6305
#ifdef HAVE_XSYNC
 
6306
  if (!GDK_WINDOW_DESTROYED (window))
 
6307
    {
 
6308
      GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
 
6309
      GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
 
6310
 
 
6311
      if (toplevel && toplevel->update_counter != None &&
 
6312
          GDK_DISPLAY_X11 (display)->use_sync &&
 
6313
          !XSyncValueIsZero (toplevel->current_counter_value))
 
6314
        {
 
6315
          XSyncSetCounter (GDK_WINDOW_XDISPLAY (window), 
 
6316
                           toplevel->update_counter,
 
6317
                           toplevel->current_counter_value);
 
6318
          
 
6319
          XSyncIntToValue (&toplevel->current_counter_value, 0);
 
6320
        }
 
6321
    }
 
6322
#endif
 
6323
}
 
6324
 
 
6325
#define __GDK_WINDOW_X11_C__
 
6326
#include "gdkaliasdef.c"